代码之家  ›  专栏  ›  技术社区  ›  Haoest

plsqljdbc:如何获取最后一行ID?

  •  18
  • Haoest  · 技术社区  · 14 年前

    PLSQL(Oracle)与这个sqlserver片段的等价物是什么?

    BEGIN TRAN
    INSERT INTO mytable(content) VALUES ("test") -- assume there's an ID column that is autoincrement
    SELECT @@IDENTITY
    COMMIT TRAN
    

    如何在Oracle中插入新行,并让JDBC获得新id的副本?

    编辑: 巴鲁斯克提供了一个非常好的起点。由于某些原因,JDBC不喜欢命名参数绑定。这会导致“参数设置或注册不正确”SQLException。为什么会这样?

            OracleConnection conn = getAppConnection();
            String q = "BEGIN INSERT INTO tb (id) values (claim_seq.nextval) returning id into :newId; end;" ;
            CallableStatement cs = (OracleCallableStatement) conn.prepareCall(q);
            cs.registerOutParameter("newId", OracleTypes.NUMBER);
            cs.execute();
            int newId = cs.getInt("newId");
    
    3 回复  |  直到 14 年前
        1
  •  37
  •   Community CDub    8 年前

    正常情况下 你会用 Statement#getGeneratedKeys() 为此(另请参见 this answer 但是到目前为止(仍然)oraclejdbc驱动程序不支持这一点。

    你最好的办法就是 利用 CallableStatement RETURNING 条款:

    String sql = "BEGIN INSERT INTO mytable(id, content) VALUES (seq_mytable.NEXTVAL(), ?) RETURNING id INTO ?; END;";
    
    Connection connection = null;
    CallableStatement statement = null;
    
    try {
        connection = database.getConnection();
        statement = connection.prepareCall(sql);
        statement.setString(1, "test");
        statement.registerOutParameter(2, Types.NUMERIC);
        statement.execute();
        int id = statement.getInt(2);
        // ...
    

    或者 SELECT sequencename.CURRVAL INSERT 在同一交易中:

    String sql_insert = "INSERT INTO mytable(content) VALUES (?)";
    String sql_currval = "SELECT seq_mytable.CURRVAL FROM dual";
    
    Connection connection = null;
    PreparedStatement statement = null;
    Statement currvalStatement = null;
    ResultSet currvalResultSet = null;
    
    try {
        connection = database.getConnection();
        connection.setAutoCommit(false);
        statement = connection.prepareStatement(sql_insert);
        statement.setString(1, "test");
        statement.executeUpdate();
        currvalStatement = connection.createStatement();
        currvalResultSet = currvalStatement.executeQuery(sql_currval);
        if (currvalResultSet.next()) {
            int id = currvalResultSet.getInt(1);
        }
        connection.commit();
        // ...
    
        2
  •  8
  •   Pablo Santa Cruz    14 年前

    你可以用甲骨文的 returning 条款。

    insert into mytable(content) values ('test') returning your_id into :var;
    

    this link 对于代码示例。您需要oracle10g或更高版本,以及新版本的JDBC驱动程序。

        3
  •  2
  •   finejustice    11 年前

    下面是一个片段:

        // change the string to your connection string
        Connection connection = DriverManager.getConnection("connection string");
    
        // assume that the field "id" is PK, and PK-trigger exists 
        String sql = "insert into my_table(id) values (default)";
        // you can select key field by field index
        int[] colIdxes = { 1 };
        // or by field name
        String[] colNames = { "id" };
    
        // Java 1.7 syntax; try-finally for older versions
        try (PreparedStatement preparedStatement = connection.prepareStatement(sql, colNames))
        {
            // note: oracle JDBC driver do not support auto-generated key feature with batch update
            //          // insert 5 rows
            //          for (int i = 0; i < 5; i++)
            //          {
            //              preparedStatement.addBatch();
            //          }
            //          
            //          int[] batch = preparedStatement.executeBatch();
            preparedStatement.executeUpdate();
    
            // get generated keys
            try (ResultSet resultSet = preparedStatement.getGeneratedKeys())
            {
                while (resultSet.next())
                {
                    // assume that the key's type is BIGINT
                    long id = resultSet.getLong(1);
                    assertTrue(id != 0);
    
                    System.out.println(id);
                }
            }
        }
    

    http://docs.oracle.com/cd/E16655_01/java.121/e17657/jdbcvers.htm#CHDEGDHJ

        4
  •  0
  •   seregamorph    5 年前

    万一你用 spring-jdbc 对于数据库,您可以考虑从 morejdbc ,它将如下所示:

    import static org.morejdbc.SqlTypes.BIGINT;
    import static org.morejdbc.JdbcCall.callSql;
    import static org.morejdbc.*;
    ...
    
    Out<Long> idOut = Out.of(BIGINT);
    jdbcTemplate.execute(callSql("BEGIN INSERT INTO mytable(id, content) VALUES (seq_mytable.NEXTVAL(), ?) "
            + "RETURNING id INTO ?; END;")
            .in(content)
            .out(BIGINT, idOut));
    System.out.println("Id is " + idOut.get());
    

    如果你有一个像

    @lombok.Data
    public class Entity {
        private long id;
        private String content;
    }
    

    Entity entity = ;
    
    jdbcTemplate.execute(callSql("BEGIN INSERT INTO mytable(id, content) VALUES (seq_mytable.NEXTVAL(), ?) "
            + "RETURNING id INTO ?; END;")
            .in(entity.getContent())
            .out(BIGINT, entity::setId));
    System.out.println("Id is " + entity.get());