Значение от последней вставленной строки в DB [дубликат]

Этот вопрос уже имеет ответ здесь:

Там некоторый путь состоит в том, чтобы получить значение от последней вставленной строки?

Я вставляю строку, где PK автоматически увеличится должный упорядочить созданный, и я хотел бы получить этот порядковый номер. Только PK, как гарантируют, будет уникален в таблице.

Я использую Java с JDBC и Oracle.

Я забыл добавлять, что я хотел бы получить это значение с помощью набора результатов ниже. (Я попробовал это mysql, и он работал успешно, но я должен был переключиться на Oracle, и теперь я получаю строковое представление идентификатора а не на самом деле порядкового номера),

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 таблице. Но так как я переключился на Oracle, возвращенное значение является теперь странным строковым значением.

10
задан Ruepen 29 December 2009 в 21:30
поделиться

3 ответа

Вы пытаетесь воспользоваться пунктом 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);
10
ответ дан 3 December 2019 в 22:00
поделиться

Это не согласуется с другими базами данных, но при использовании Oracle, getGeneratedKeys() возвращает ROWID для вставленной строки при использовании Statement.RETURN_GENERATEDKEYS. Поэтому вам необходимо использовать 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); 

Но это не даст вам сгенерированный ID PK. При работе с 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 (как упоминалось здесь), так что, ну, я думаю, что это не может быть полностью неправильным. Но, к сожалению, на самом деле она не портативна и может не работать на других платформах.

.
4
ответ дан 3 December 2019 в 22:00
поделиться

Вместо этого следует использовать ResultSet#getLong(). Напрасно попробуйте ResultSet#getRowId() и в конце концов произнесите его на oracle.sql.ROWID. Если возвращаемая шестнадцатеричная строка на самом деле является идентификатором в шестнадцатеричном представлении, то можно попробовать преобразовать её в десятичную с помощью Long#valueOf() или Integer#valueOf().

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

Тем не менее, JDBC драйвер Oracle долгое время не поддерживал ResultSet#getGeneratedKeys() и до сих пор вызывает некоторые затруднения. Если вы не можете получить это право, то вы должны выполнить SELECT CURRVAL (имя последовательности) на том же заявлении, как вы сделали вставить, или новое заявление внутри той же операции, если это было 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().

.
2
ответ дан 3 December 2019 в 22:00
поделиться
Другие вопросы по тегам:

Похожие вопросы: