web-dev-qa-db-fra.com

Comment obtenir une valeur de la dernière ligne insérée?

Est-il possible d'obtenir une valeur à partir de la dernière ligne insérée?

J'insère une ligne où la PK augmentera automatiquement et j'aimerais obtenir cette PK. Seul le PK est garanti d'être unique dans la table.

J'utilise Java avec JDBC et PostgreSQL.

51
eflles

Avec PostgreSQL, vous pouvez le faire via le mot-clé RETURNING:

PostgresSQL - RETOURNER

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

Il retournera la valeur de "anyfield". "anyfield" peut être une séquence ou non.

Pour l'utiliser avec JDBC, faites:

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

Voir la documentation de l'API pour Java.sql.Statement .

En gros, lorsque vous appelez executeUpdate() ou executeQuery(), utilisez la constante Statement.RETURN_GENERATED_KEYS. Vous pouvez ensuite appeler getGeneratedKeys pour obtenir les clés générées automatiquement de toutes les lignes créées par cette exécution. (En supposant que votre pilote JDBC le fournisse.)

Cela va dans le sens de ceci:

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

Si vous utilisez JDBC 3.0, vous pouvez obtenir la valeur du PK dès que vous l’avez insérée. 

Voici un article qui explique comment: 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);
}
16
anjanb

Depuis la version du pilote PostgreSQL JDBC 8.4-701 la PreparedStatement#getGeneratedKeys() est enfin pleinement fonctionnelle. Nous l'utilisons ici depuis presque un an en production à notre entière satisfaction.

Dans "JDBC simple", la PreparedStatement doit être créée comme suit pour pouvoir renvoyer les clés:

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

Vous pouvez télécharger la version actuelle du pilote JDBC ici (qui est encore à l’heure actuelle 8.4-701).

10
BalusC

Les séquences dans postgresql sont sécurisées pour les transactions. Afin que vous puissiez utiliser le 

currval(sequence)

Citation:

currval

Renvoie la valeur la plus récente obtenue par nextval pour cette séquence dans la session en cours. (Une erreur est signalée. Si. Nextval n'a jamais été appelé Appelé pour cette séquence dans cette session ) Notez que, car il s'agit de. renvoyer une valeur de session-local, it donne une réponse prévisible même si d'autres sessions sont en cours d'exécution nextval pendant ce temps.

8
svrist

Voici comment je l'ai résolu, basé sur les réponses ici:

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));
        }
7
eflles

Si vous utilisez Statement, optez pour ce qui suit

//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);

Si vous utilisez PreparedStatement, optez pour ce qui suit

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);
4
Priyadharshani

Utilisez les séquences dans postgres pour les colonnes id:

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

SELECT currval('MySequence');

currval renverra la valeur actuelle de la séquence dans la même session.

(Dans MS SQL, vous utiliseriez @@ identity ou SCOPE_IDENTITY ())

1
BradC
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();
1

Pour MyBatis 3.0.4 avec Annotations et le pilote Postgresql 9.0-801.jdbc4, vous définissez une méthode d’interface dans votre mappeur, telle que

public interface ObjectiveMapper {

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

Notez que @Select est utilisé à la place de @Insert.

0
emicklei

N'utilisez pas SELECT currval ('MySequence') - la valeur est incrémentée lorsque les insertions échouent.

0
smilek

Si vous êtes dans une transaction, vous pouvez utiliser SELECT lastval() après une insertion pour obtenir le dernier identifiant généré.

0
mihu86

par exemple:

 Connexion conn = null; 
 PreparedStatement sth = null; 
 ResultSet rs = null; 
 essayez {
 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); 
 } 
 } 

avec ,Statement.RETURN_GENERATED_KEYS);" non trouvé.

0
fernando

Utilisez ce code simple:

// 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)
0
danigonlinea