DB中最后一行插入的值

有没有办法从最后插入的行中获取值?

我正在插入一行,由于创建序列,PK将自动增加,我想得到这个序列号。 只有PK才能保证在表中是唯一的。

我正在使用Java和JDBC和Oracle。

我忘了添加我想使用下面的结果集检索此值。 (我用mysql尝试了这个并且它成功运行了,但我不得不切换到Oracle,现在我得到了ID的字符串表示而不是实际的序列号)

Statement stmt = conn.createStatement(); stmt.executeUpdate(insertCmd, Statement.RETURN_GENERATED_KEYS); stmt.RETURN_GENERATED_KEYS; ResultSet rs = stmt.getGeneratedKeys(); if(rs.next()){ log.info("Successful insert"); id = rs.getString(1); } 

上面的代码片段将返回存储在mysql表中的列int值。 但是由于我已经切换到Oracle,返回的值现在是一个奇怪的字符串值。

您要做的是利用RETURNING子句。 让我们设置一个示例表和序列:

 CREATE TABLE "TEST" ( "ID" NUMBER NOT NULL ENABLE, "NAME" VARCHAR2(100 CHAR) NOT NULL ENABLE, CONSTRAINT "PK_TEST" PRIMARY KEY ("ID") ); CREATE SEQUENCE SEQ_TEST; 

现在,您的Java代码应如下所示:

 String insertSql = "BEGIN INSERT INTO TEST (ID, NAME) VALUES (SEQ_TEST.NEXTVAL(), ?) RETURNING ID INTO ?; END;"; java.sql.CallableStatement stmt = conn.prepareCall(insertSql); stmt.setString(1, "John Smith"); stmt.registerOutParameter(2, java.sql.Types.VARCHAR); stmt.execute(); int id = stmt.getInt(2); 

这与其他数据库不一致,但在使用Oracle时, getGeneratedKeys()在使用Statement.RETURN_GENERATEDKEYS时返回插入行的ROWID。 所以你需要使用oracle.sql.ROWID专有类型来“读取”它:

 Statement stmt = connection.createStatement(); stmt.executeUpdate(insertCmd, Statement.RETURN_GENERATED_KEYS); ResultSet rs = stmt.getGeneratedKeys(); oracle.sql.ROWID rid = (oracle.sql.ROWID) rs.getObject(1); 

但是这不会给你生成PK的ID。 使用Oracle时,您应该使用方法executeUpdate(String sql, int[] columnIndexes)executeUpdate(String sql, String[] columnNames)而不是executeUpdate(String sql, int autoGeneratedKeys)来获取生成的序列值。 像这样的东西(调整值以匹配索引或主键列的名称):

 stmt.executeUpdate(INSERT_SQL, new int[] {1}); ResultSet rs = stmt.getGeneratedKeys(); 

要么

 stmt.executeUpdate(INSERT_SQL, new String[] {"ID"}); ResultSet rs = stmt.getGeneratedKeys(); 

虽然在这方面进行了更多的研究,但似乎这种方法在Spring文档中显示 (如此处所述),所以,我想这不是完全错误的。 但是,不幸的是,它不是真正可移植的,它可能无法在其他平台上运行。

您应该使用ResultSet#getLong()代替。 如果徒劳,请尝试ResultSet#getRowId()并最终将其转换为oracle.sql.ROWID 。 如果返回的hex字符串实际上是hex风格的ID,那么您可以尝试通过Long#valueOf()Integer#valueOf()将其转换为十进制。

 Long id = Long.valueOf(hexId, 16); 

也就是说,Oracle的JDBC驱动程序长时间不支持ResultSet#getGeneratedKeys() ,并且仍然有点麻烦。 如果你无法做到这一点,那么你需要在insert时在同一语句上执行SELECT CURRVAL(sequencename) ,或者在同一事务中执行一个新语句(如果它是PreparedStatement 。 基本示例:

 public void create(User user) throws SQLException { Connection connection = null; PreparedStatement preparedStatement = null; Statement statement = null; ResultSet generatedKeys = null; try { connection = daoFactory.getConnection(); preparedStatement = connection.prepareStatement(SQL_INSERT); preparedStatement.setValue(1, user.getName()); // Set more values here. int affectedRows = preparedStatement.executeUpdate(); if (affectedRows == 0) { throw new SQLException("Creating user failed, no rows affected."); } statement = connection.createStatement(); generatedKeys = statement.executeQuery(SQL_CURRVAL); if (generatedKeys.next()) { user.setId(generatedKeys.getLong(1)); } else { throw new SQLException("Creating user failed, no generated key obtained."); } } finally { close(generatedKeys); close(statement); close(preparedStatement); close(connection); } } 

哦,从您的代码示例,以下行

 stmt.RETURN_GENERATED_KEYS; 

完全是多余的。 去掉它。

你可以在这里找到我之前发布的关于获取生成的密钥的另一个例子,它使用正常的getGeneratedKeys()方法。