我想使用 DB2 存储过程从我的 Java 应用程序运行多插入和更新 SQL 语句。我准备了以下包含错误的程序。
在这个实现中,我首先要创建一个临时表来存储SQL语句。然后使用循环将 SQL 语句插入到使用准备好的语句的临时表中。最后,我们以批处理模式执行 SQL 语句。
要从我的 Java 应用程序调用此存储过程,我想将 SQL 语句列表作为字符串列表数组传递。
这是我的程序:
CREATE OR REPLACE PROCEDURE multiInsertAndUpdate(IN sqlStatements VARCHAR(2000) ARRAY)
BEGIN
DECLARE batchStmt VARCHAR(2000);
DECLARE i INTEGER DEFAULT 0;
-- Create a temporary table to store the SQL statements
CREATE TEMPORARY TABLE temp_sql_statements (
id INTEGER GENERATED ALWAYS AS IDENTITY,
statement VARCHAR(2000)
);
-- Insert the SQL statements into the temporary table using a prepared statement
DECLARE insertStmt STATEMENT;
SET insertStmt = 'INSERT INTO temp_sql_statements(statement) VALUES(?)';
FOR i IN 1..CARDINALITY(sqlStatements) DO
EXECUTE IMMEDIATE insertStmt USING sqlStatements[i];
END FOR;
-- Execute the SQL statements in batches of 1000
SET i = 0;
WHILE i >= 0 DO
DECLARE stmtCursor CURSOR WITH HOLD FOR
SELECT statement FROM temp_sql_statements ORDER BY id FOR UPDATE SKIP LOCKED FETCH FIRST 1000 ROWS ONLY;
OPEN stmtCursor;
FETCH FROM stmtCursor INTO batchStmt;
IF batchStmt IS NOT NULL THEN
DECLARE batchStmts VARCHAR(20000);
SET batchStmts = batchStmt;
SET i = i + 1;
WHILE FETCH FROM stmtCursor INTO batchStmt DO
SET batchStmts = batchStmts || batchStmt || ';';
SET i = i + 1;
IF i % 1000 = 0 THEN
EXECUTE IMMEDIATE batchStmts;
SET batchStmts = '';
END IF;
END WHILE;
IF batchStmts <> '' THEN
EXECUTE IMMEDIATE batchStmts;
END IF;
ELSE
SET i = -1;
END IF;
CLOSE stmtCursor;
END WHILE;
-- Drop the temporary table
DROP TABLE temp_sql_statements;
END
请协助对齐程序
// JAVA用SQL语句数组调用存储过程
static void executeStatements(Connection conn, List<String> sqlStatements)
{
try {
CallableStatement cstmt = conn.prepareCall("{CALL multiInsertAndUpdate(?)}");
// Convert the List<String> to a SQL Array
Array sqlArray = conn.createArrayOf("VARCHAR", sqlStatements.toArray());
cstmt.setArray(1, sqlArray);
cstmt.execute();
sqlArray.free();
cstmt.close();
} catch (SQLException e) {
e.printStackTrace();
}
}
程序因错误无法执行
有趣的程序。我假设您的用法是这样的,您不担心 Java 程序注入了什么 SQL?
我最近经常使用数组,通常是行类型。有关工作(但更复杂)的示例,请参阅我在 https://github.com/easydataservices/db2-auth/blob/main/db2/schema/module_attributes.sql 的 SAVE_ATTRIBUTES 过程,然后查看 Java 代码saveAttributes(String sessionId, List sessionAttributes) 在https://github.com/easydataservices/db2-auth/blob/main/java/src/open/auth/AuthAttributesDao.java
注意第 116 行:
Struct[] attributeStructs = new Struct[sessionAttributes.size()];
还有第141行:
attributeArray = connection.createArrayOf(schemaName + "ATTRIBUTES.SESSION_ATTRIBUTE", attributeStructs);
你看这就是我传递给 createArrayOf(...), Struct[] not Object[] 的内容。在 JDBC 中,任何行类型都是 Struct,因此行类型的数组是 Struct[]。
在您的情况下,VARCHAR 是一个字符串,因此对于 VARCHAR 数组,您应该传递 String[].
希望这有帮助。