Come ottenere un valore dall'ultima riga inserita? [duplicare]
-
04-07-2019 - |
Domanda
Questa domanda ha già una risposta qui:
- Come ottenere l'ID di inserimento in JDBC? 12 risposte
C'è un modo per ottenere un valore dall'ultima riga inserita?
Sto inserendo una riga in cui il PK aumenterà automaticamente e vorrei ottenere questo PK. Solo il PK è garantito per essere unico nella tabella.
Sto usando Java con un JDBC e PostgreSQL.
Soluzione
Con PostgreSQL puoi farlo tramite la parola chiave RETURNING:
INSERT INTO mytable( field_1, field_2,... )
VALUES ( value_1, value_2 ) RETURNING anyfield
Restituirà il valore di " anyfield " ;. & Quot; anyfield " può essere una sequenza o no.
Per usarlo con JDBC, fai:
ResultSet rs = statement.executeQuery("INSERT ... RETURNING ID");
rs.next();
rs.getInt(1);
Altri suggerimenti
Consulta i documenti API per java.sql.Statement .
Fondamentalmente, quando chiami executeUpdate ()
o executeQuery ()
, usa la costante Statement.RETURN_GENERATED_KEYS
. È quindi possibile chiamare getGeneratedKeys
per ottenere le chiavi generate automaticamente di tutte le righe create da tale esecuzione. (Supponendo che il driver JDBC lo fornisca.)
Va ??qualcosa del genere:
Statement stmt = conn.createStatement();
stmt.execute(sql, Statement.RETURN_GENERATED_KEYS);
ResultSet keyset = stmt.getGeneratedKeys();
Se stai usando JDBC 3.0, puoi ottenere il valore del PK non appena lo hai inserito.
Ecco un articolo che parla di come: 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);
}
Dalla versione del driver PostgreSQL JDBC 8.4-701 the PreparedStatement # getGeneratedKeys ()
è finalmente perfettamente funzionante. Lo usiamo qui quasi un anno di produzione per la nostra piena soddisfazione.
In "semplice JDBC" PreparedStatement
deve essere creato come segue per renderlo in grado di restituire le chiavi:
statement = connection.prepareStatement(SQL, Statement.RETURN_GENERATED_KEYS);
Puoi scaricare la versione corrente del driver JDBC qui (che al momento è ancora 8,4-701).
Le sequenze in postgresql sono sicure per le transazioni. Quindi puoi usare
currval(sequence)
currval
Restituisce il valore ottenuto più recentemente da nextval per questa sequenza nella sessione corrente. (Un errore è segnalato se nextval non è mai stato ha chiesto questa sequenza in questo sessione.) Notare che perché questo è restituendo un valore locale di sessione, esso dà una risposta prevedibile anche se altre sessioni stanno eseguendo nextval nel frattempo.
Ecco come l'ho risolto, in base alle risposte qui:
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));
}
Se si utilizza Statement
, selezionare quanto segue
//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);
Se si utilizza PreparedStatement
, procedere come segue
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);
Usa sequenze in postgres per colonne id:
INSERT mytable(myid) VALUES (nextval('MySequence'));
SELECT currval('MySequence');
currval restituirà il valore corrente della sequenza nella stessa sessione.
(In MS SQL, useresti @@ identity o 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();
Non usare SELECT currval ('MySequence') - il valore viene incrementato sugli inserti che falliscono.
Per MyBatis 3.0.4 con Annotations e Postgresql driver 9.0-801.jdbc4 definisci un metodo di interfaccia nel tuo Mapper come
public interface ObjectiveMapper {
@Select("insert into objectives" +
" (code,title,description) values" +
" (#{code}, #{title}, #{description}) returning id")
int insert(Objective anObjective);
Nota che @Select è usato al posto di @Insert.
ad esempio:
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); } }
con , Statement.RETURN_GENERATED_KEYS); "
non trovato.
Usa quel semplice codice:
// 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)
Se sei in una transazione puoi usare SELECT lastval ()
dopo un inserimento per ottenere l'ultimo ID generato.