使用Java应用程序中的List数组运行多个插入和更新SQL语句的DB2存储过程

mwg9r5ms  于 2023-04-04  发布在  Java
关注(0)|答案(1)|浏览(82)

我想使用DB2存储过程从我的Java应用程序中运行多个插入和更新SQL语句。我准备了以下包含错误的过程。
在这个实现中,我首先要创建一个临时表来存储SQL语句。然后使用一个循环,使用一个准备好的语句将SQL语句插入临时表。最后,我们以批处理模式执行SQL语句。
为了从Java应用程序调用这个存储过程,我希望将SQL语句列表作为字符串的List数组传递。
下面是我的步骤:

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();
    }
}

由于错误,过程无法执行

muk1a3rh

muk1a3rh1#

有趣的过程。我假设你的用法是这样的,你不担心什么SQL被注入的Java程序?
最近我经常使用数组,通常是与行类型一起使用。
注意第116行:

Struct[] attributeStructs = new Struct[sessionAttributes.size()];

第141行:

attributeArray = connection.createArrayOf(schemaName + "ATTRIBUTES.SESSION_ATTRIBUTE", attributeStructs);

你看,这就是我传递给createArrayOf(...)的东西,Struct[] * 而不是 * Object[]。在JDBC中,任何行类型都是Struct,所以行类型的数组是Struct[]。
在你的例子中,VARCHAR是一个String,所以对于VARCHAR数组,你应该传递String[]。
希望这个有用。

相关问题