呼叫建立/刪除暫存表的存儲過程,CallableStatement.getUpdateCount() 回傳 -1,導致誤判為執行失敗。
getUpdateCount() 回傳值定義 (JDBC 規範):
>= 0:影響的行數 (DML: INSERT/UPDATE/DELETE)-1:非 DML 語句 (DDL: CREATE/DROP/ALTER、SET、CALL 等) 或 結果集 (SELECT)-2:未知 (批次執行、尚未完成)建立/刪除暫存表屬於 DDL,不產生「影響行數」,故回傳 -1 屬正常行為,不代表失敗。
CallableStatement cs = conn.prepareCall("{call PROC_TEMP}");
boolean hasResult = cs.execute(); // 執行,回傳 true 表示有 ResultSet
// 處理多重結果 (存儲過程可能回傳多個 ResultSet/更新計數)
while (true) {
int updateCount = cs.getUpdateCount();
if (updateCount != -1) {
// DML 更新計數
System.out.println("更新行數: " + updateCount);
} else {
// 可能是 ResultSet 或無結果
ResultSet rs = cs.getResultSet();
if (rs != null) {
// 處理結果集
while (rs.next()) { /* ... */ }
rs.close();
} else {
// 真正結束
break;
}
}
// 檢查是否還有下一個結果
if (!cs.getMoreResults()) {
break;
}
}
cs.close();
CREATE PROCEDURE PROC_TEMP
@ResultCode INT OUTPUT
AS
BEGIN
SET NOCOUNT ON; -- 關閉 DONE_IN_PROC 訊息,減少網路傳輸
BEGIN TRY
IF OBJECT_ID('tempdb..##temp') IS NOT NULL
DROP TABLE ##temp;
SELECT IDENTITY(INT) AS id, *
INTO ##temp
FROM AlarmRecordRe
ORDER BY [TIMESTAMP] DESC;
SET @ResultCode = 0; -- 成功
END TRY
BEGIN CATCH
SET @ResultCode = ERROR_NUMBER(); -- 失敗回傳錯誤碼
END CATCH
END
CallableStatement cs = conn.prepareCall("{call PROC_TEMP(?)}");
cs.registerOutParameter(1, Types.INTEGER);
cs.execute();
int resultCode = cs.getInt(1);
if (resultCode == 0) {
System.out.println("存儲過程執行成功");
} else {
System.out.println("存儲過程失敗,錯誤碼: " + resultCode);
}
| 資料庫 | 動態建表/刪表範例 |
|---|---|
| MySQL | PREPARE stmt FROM @sql; EXECUTE stmt; DEALLOCATE PREPARE stmt; |
| Oracle | EXECUTE IMMEDIATE 'DROP TABLE ' || table_name || ' PURGE'; |
| SQL Server | EXEC sp_executesql @sql; |
| PostgreSQL | EXECUTE format('DROP TABLE IF EXISTS %I', table_name); |
| 誤區 | 正確觀念 |
|---|---|
| getUpdateCount() == -1 表示失敗 | -1 表示非 DML 或結果集,DDL 正常回傳 -1 |
| execute() 回傳 false 表示失敗 | false 表示無 ResultSet (可能是更新計數或無結果) |
| 不需關閉 CallableStatement | 必須 close() 釋放資料庫游標與連線資源 |
// 開啟 JDBC 詳細日誌 (log4j2/logback)
// 或程式碼層面
cs.execute();
System.out.println("execute() 回傳: " + hasResult);
System.out.println("getUpdateCount(): " + cs.getUpdateCount());
ResultSet rs = cs.getResultSet();
System.out.println("getResultSet(): " + (rs != null ? "有結果集" : "無"));