PLSQL JDBC: как получить идентификатор последней строки?
Что такое PLSQL (Oracle) эквивалент этого фрагмента SQL-сервера?
BEGIN TRAN
INSERT INTO mytable(content) VALUES ("test") -- assume there an ID column that is autoincrement
SELECT @@IDENTITY
COMMIT TRAN
В С# вы можете вызвать myCommand.ExecuteScalar(), чтобы получить идентификатор новой строки.
Как я могу вставить новую строку в Oracle и получить JDBC копию нового идентификатора?
EDIT:
BalusC обеспечил очень хорошую отправную точку. По какой-то причине 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");
Ответы
Ответ 1
Обычно вы использовали Statement#getGeneratedKeys()
для этого (см. также этот ответ для примера), но это так далеко (по-прежнему) не поддерживается драйвером JDBC Oracle.
Лучше всего либо использовать 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
Вы можете использовать Oracle возврат.
insert into mytable(content) values ('test') returning your_id into :var;
Отметьте эту ссылку для образца кода. Вам нужен Oracle 10g или более поздняя версия и новая версия драйвера JDBC.
Ответ 3
Вы можете использовать getGeneratedKeys(), путем явного выбора ключевого поля.
Вот фрагмент:
// 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 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