Search code examples
javaoracleinsert

statement.executeUpdate() can't be used to insert multiple records in Oracle


With below code I am able to insert multiple Records in H2 Database. But with Oracle this doesn't work. Is there any other way to use normal SQL to INSERT multiple statements like that.

    //INSERT RECORDS
String    sql       = "INSERT INTO PERSON (NAME, AGE) VALUES ('"+name+"',+"+age+");" +
                      "INSERT INTO PERSON (NAME, AGE) VALUES ('Susan'   ,20      )";
Statement statement = connection.createStatement();
int       success   = statement.executeUpdate(sql);

Solution

  • Use a PreparedStatement and do not include the ; terminator in the SQL statement (as it is not part of the SQL statement and is not valid syntax):

    connection con.setAutoCommit(false);   
    PreparedStatement ps=connection.prepareStatement(
      "INSERT INTO PERSON (NAME, AGE) VALUES (?,?)"
    );
    ps.setString(1, "Susan");
    ps.setInt(2, 20);
    ps.addBatch();
    ps.setString(1, "Alice");
    ps.setInt(2, 21);
    ps.addBatch();
    int [] numInserts = ps.executeBatch();
    connection.commit();
    

    Note: In Oracle, you cannot have more than one statement in a command so trying to pass INSERT INTO t VALUES('X'); INSERT INTO t VALUES('Y') will fail with a syntax error even if the statements are individually syntactically valid (this helps to prevent SQL injection attacks). You need to either (1) send them individually as two commands or (2) wrap them in a PL/SQL block so that they become a single command. In your case, just use a batch of statements.


    Is there any other way to use normal SQL to INSERT multiple statements like that.

    There are multiple ways to insert multiple rows in a single statement:

    • Using an INSERT ALL statement:

      INSERT ALL
        INTO person (name, age) VALUES ('Susan', 20)
        INTO person (name, age) VALUES ('Alice', 21)
      SELECT 1 FROM DUAL
      
    • Using INSERT INTO ... SELECT ...:

      INSERT INTO person (name, age) 
        SELECT 'Susan', 20 FROM DUAL UNION ALL
        SELECT 'Alice', 21 FROM DUAL
      
    • Mureinik's answer shows how to use INSERT INTO with multiple VALUES clauses, which is available from Oracle 23.

    • Using PL/SQL to wrap multiple individual INSERTs:

      BEGIN
        INSERT INTO person (name, age) VALUES ('Susan', 20);
        INSERT INTO person (name, age) VALUES ('Alice', 21);
      END;
      

    You can parameterise all of those queries by replacing 'Susan', 'Alice', 20 and 21 with ? and then pass the values as bind parameters using Java.

    Note: The first three do not include a trailing ; but the PL/SQL solution would include the trailing ; to terminate the END statement (but not a trailing / as the terminator for the PL/SQL block).