Как получить значение из последней вставленной строки?[дубликат]

StackOverflow https://stackoverflow.com/questions/241003

Вопрос

На этот вопрос уже есть ответ здесь:

Есть ли какой-нибудь способ получить значение из последней вставленной строки?

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

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

Это было полезно?

Решение

С PostgreSQL вы можете сделать это с помощью ключевого слова RETURNING:

PostgresSQL - ВОЗВРАТ

INSERT INTO mytable( field_1, field_2,... )
VALUES ( value_1, value_2 ) RETURNING anyfield

Он вернет значение "anyfield"."любое поле" может быть последовательностью или нет.

Чтобы использовать его с JDBC, выполните:

ResultSet rs = statement.executeQuery("INSERT ... RETURNING ID");
rs.next();
rs.getInt(1);

Другие советы

Смотрите документы по API для java.sql.Оператор.

В принципе, когда вы звоните executeUpdate() или executeQuery(), используйте Statement.RETURN_GENERATED_KEYS постоянный.Затем вы можете позвонить getGeneratedKeys чтобы получить автоматически сгенерированные ключи всех строк, созданных этим выполнением.(Предполагая, что ваш драйвер JDBC предоставляет это.)

Это звучит примерно так:

Statement stmt = conn.createStatement();
stmt.execute(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet keyset = stmt.getGeneratedKeys();

Если вы используете JDBC 3.0, то вы можете получить значение PK, как только вы его вставили.

Вот статья, в которой рассказывается о том, как : https://www.ibm.com/developerworks/java/library/j-jdbcnew/

Statement stmt = conn.createStatement();
// Obtain the generated key that results from the query.
stmt.executeUpdate("INSERT INTO authors " +
                   "(first_name, last_name) " +
                   "VALUES ('George', 'Orwell')",
                   Statement.RETURN_GENERATED_KEYS);
ResultSet rs = stmt.getGeneratedKeys();
if ( rs.next() ) {
    // Retrieve the auto generated key(s).
    int key = rs.getInt(1);
}

Начиная с версии драйвера PostgreSQL JDBC 8.4-701 в PreparedStatement#getGeneratedKeys() наконец-то он полностью функционален.Мы используем его здесь почти год в производстве к нашему полному удовлетворению.

В "обычном JDBC" PreparedStatement необходимо создать следующим образом, чтобы заставить его возвращать ключи:

statement = connection.prepareStatement(SQL, Statement.RETURN_GENERATED_KEYS);

Вы можете загрузить текущую версию драйвера JDBC здесь (который на данный момент все еще составляет 8.4-701).

Последовательности в postgresql безопасны для транзакций.Таким образом, вы можете использовать

currval(sequence)

Цитата:

каррвал

Возвращает значение, самое последнее полученное nextval для этой последовательности в текущем сеансе.(Ошибка сообщается, если nextval никогда не был вызван для этой последовательности в этом сеансе.) Обратите внимание, что, поскольку это возвращает локальное значение сеанса, это дает предсказуемый ответ, даже если другие сеансы выполняются nextval тем временем.

Вот как я решил это, основываясь на приведенных здесь ответах:

Connection conn = ConnectToDB(); //ConnectToDB establishes a connection to the database.
String sql = "INSERT INTO \"TableName\"" +
        "(\"Column1\", \"Column2\",\"Column3\",\"Column4\")" +
        "VALUES ('value1',value2, 'value3', 'value4') RETURNING 
         \"TableName\".\"TableId\"";
PreparedStatement prpState = conn.prepareStatement(sql);
ResultSet rs = prpState.executeQuery();
if(rs.next()){
      System.out.println(rs.getInt(1));
        }

Если вы используете Statement, перейдите к следующему

//MY_NUMBER is the column name in the database 
String generatedColumns[] = {"MY_NUMBER"};
Statement stmt = conn.createStatement();

//String sql holds the insert query
stmt.executeUpdate(sql, generatedColumns);

ResultSet rs = stmt.getGeneratedKeys();

// The generated id

if(rs.next())
long key = rs.getLong(1);

Если вы используете PreparedStatement, перейдите к следующему

String generatedColumns[] = {"MY_NUMBER"};
PreparedStatement pstmt = conn.prepareStatement(sql,generatedColumns);
pstmt.setString(1, "qwerty");

pstmt.execute();
ResultSet rs = pstmt.getGeneratedKeys();
if(rs.next())
long key = rs.getLong(1);

Используйте последовательности в postgres для столбцов идентификаторов:

INSERT mytable(myid) VALUES (nextval('MySequence'));

SELECT currval('MySequence');

currval вернет текущее значение последовательности в том же сеансе.

(В MS SQL вы бы использовали @@identity или SCOPE_IDENTITY())

PreparedStatement stmt = getConnection(PROJECTDB + 2)
    .prepareStatement("INSERT INTO fonts (font_size) VALUES(?) RETURNING fonts.*");
stmt.setString(1, "986");
ResultSet res = stmt.executeQuery();
while (res.next()) {
    System.out.println("Generated key: " + res.getLong(1));
    System.out.println("Generated key: " + res.getInt(2));
    System.out.println("Generated key: " + res.getInt(3));
}
stmt.close();

Не используйте SELECT currval('MySequence') - значение увеличивается при неудачных вставках.

Для MyBatis 3.0.4 с аннотациями и драйвером Postgresql 9.0-801.jdbc4 вы определяете метод интерфейса в вашем Mapper следующим образом

public interface ObjectiveMapper {

@Select("insert into objectives" +
        " (code,title,description) values" +
        " (#{code}, #{title}, #{description}) returning id")
int insert(Objective anObjective);

Обратите внимание, что вместо @Insert используется @Select.

например:

 Connection conn = null;
            PreparedStatement sth = null;
            ResultSet rs =null;
            try {
                conn = delegate.getConnection();
                sth = conn.prepareStatement(INSERT_SQL);
                sth.setString(1, pais.getNombre());
                sth.executeUpdate();
                rs=sth.getGeneratedKeys();
                if(rs.next()){
                    Integer id = (Integer) rs.getInt(1);
                    pais.setId(id);
                }
            } 

с ,Statement.RETURN_GENERATED_KEYS);" не найдено.

Используйте этот простой код:

// Do your insert code

myDataBase.execSQL("INSERT INTO TABLE_NAME (FIELD_NAME1,FIELD_NAME2,...)VALUES (VALUE1,VALUE2,...)");

// Use the sqlite function "last_insert_rowid"

Cursor last_id_inserted = yourBD.rawQuery("SELECT last_insert_rowid()", null);

// Retrieve data from cursor.

last_id_inserted.moveToFirst(); // Don't forget that!

ultimo_id = last_id_inserted.getLong(0);  // For Java, the result is returned on Long type  (64)

Если вы участвуете в транзакции, вы можете использовать SELECT lastval() после вставки, чтобы получить последний сгенерированный идентификатор.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top