PreparedStatement:查询还是更新?

PreparedStatement: Query, or Update?

给定 java.sql.PreparedStatement 的实例 stmt,我可以执行 stmt.executeQuery(),如果我的 SQL 语句是 SELECT,那么 returns 结果,或者我可以为 INSERT 或 UPDATE 做 stmt.executeUpdate()

现在,提出我不知道的情况,正在执行哪种 SQL 语句?我希望有一些方便的东西,比如 stmt.hasResultSet(),但那不存在。解析 SQL 语句似乎不是一个好的选择。

你总是可以做一个 executeQuery() 但传递给一个结果集,比如:

ResultSet rs = ps.executeQuery();

获得结果集后,您可以获取其元数据:

ResultSetMetaData rsmd = rs.getMetaData();

在此元数据中,您可以检查 getColumnCount() 是否为零或更多,这样您甚至可以获得返回的精确列数以使用循环执行一般解析:

final ResultSetMetaData rsmd = rs.getMetaData();
final int columnCount = rsmd.getColumnCount();

if (columnCount > 0) {
    while (rs.next()) {
        final StringBuilder sb = new StringBuilder();
        
        for (int i = 1 ; i <= columnCount ; i++) {
            sb.append(rs.getString(i));
            if (i < columnCount) {
                sb.append(", ");
            }
        }
        
        temp.add(sb.toString());
    }
}

JDBC API 提供 PreparedStatement.execute() method (and Statement.execute(String)) 正是为此目的:

Executes the SQL statement in this PreparedStatement object, which may be any kind of SQL statement. Some prepared statements return multiple results; the execute method handles these complex statements as well as the simpler form of statements handled by the methods executeQuery and executeUpdate.

The execute method returns a boolean to indicate the form of the first result. You must call either the method getResultSet or getUpdateCount to retrieve the result; you must call getMoreResults to move to any subsequent result(s).

Returns:
 true if the first result is a ResultSet object; false if the first result is an update count or there is no result

因此,要执行未知语句,您需要执行以下操作:

try (PreparedStatement pstmt = connection.prepareStatement(unknownStatement)) {
    // set variables ...

    boolean currentResult = pstmt.execute();
    while (true) {
        if (currentResult) {
            try (ResultSet rs = pstmt.getResultSet()) {
                // process result set
            }
        } else {
            int updateCount = pstmt.getUpdateCount();
            if (updateCount == -1) {
                // no more results
                break;
            }
            // do something with update count
        }
        currentResult = pstmt.getMoreResults();
    }
}

之所以存在循环,是因为某些数据库系统(例如 SQL 服务器)可以生成多个结果集和多个更新计数,而这将处理所有这些。