Dans PostgreSQL, comment obtenir le dernier identifiant inséré dans une table?
Dans MS SQL, il y a SCOPE_IDENTITY ().
Veuillez ne pas me conseiller d'utiliser quelque chose comme ceci:
select max(id) from table
Dans PostgreSQL, comment obtenir le dernier identifiant inséré dans une table?
Dans MS SQL, il y a SCOPE_IDENTITY ().
Veuillez ne pas me conseiller d'utiliser quelque chose comme ceci:
select max(id) from table
Réponses:
(
tl;dr
: passez à l'option 3: INSÉRER avec RETOUR)Rappelons que dans postgresql, il n'y a pas de concept "id" pour les tables, juste des séquences (qui sont généralement mais pas nécessairement utilisées comme valeurs par défaut pour les clés primaires de substitution, avec le pseudo-type SERIAL ).
Si vous souhaitez obtenir l'ID d'une ligne nouvellement insérée, il existe plusieurs façons:
Option 1:
CURRVAL(<sequence name>);
.Par exemple:
Le nom de la séquence doit être connu, c'est vraiment arbitraire; dans cet exemple, nous supposons que la table
persons
a uneid
colonne créée avec leSERIAL
pseudo-type. Pour éviter de vous y fier et pour vous sentir plus propre, vous pouvez utiliser à la placepg_get_serial_sequence
:Avertissement:
currval()
ne fonctionne qu'après unINSERT
(qui s'est exécuténextval()
), dans la même session .Option 2:
LASTVAL();
Ceci est similaire au précédent, sauf que vous n'avez pas besoin de spécifier le nom de la séquence: il recherche la séquence modifiée la plus récente (toujours à l'intérieur de votre session, même mise en garde que ci-dessus).
Les deux
CURRVAL
etLASTVAL
sont totalement sûrs simultanément. Le comportement de la séquence dans PG est conçu pour que différentes sessions n'interfèrent pas, donc il n'y a aucun risque de conditions de course (si une autre session insère une autre ligne entre mon INSERT et mon SELECT, j'obtiens toujours ma valeur correcte).Cependant, ils ont un problème potentiel subtil. Si la base de données a un TRIGGER (ou RULE) qui, lors de l'insertion dans la
persons
table, fait des insertions supplémentaires dans d'autres tables ... alorsLASTVAL
nous donnera probablement la mauvaise valeur. Le problème peut même se produire avecCURRVAL
, si les insertions supplémentaires sont effectuées dans la mêmepersons
table (c'est beaucoup moins habituel, mais le risque existe toujours).Option 3:
INSERT
avecRETURNING
C'est le moyen le plus propre, efficace et sûr d'obtenir l'identifiant. Il n'a aucun des risques du précédent.
Désavantages? Presque aucun: vous devrez peut-être modifier la façon dont vous appelez votre instruction INSERT (dans le pire des cas, votre couche API ou DB ne s'attend pas à ce qu'un INSERT renvoie une valeur); ce n'est pas du SQL standard (peu importe); il est disponible depuis Postgresql 8.2 (déc 2006 ...)
Conclusion: si vous le pouvez, optez pour l'option 3. Ailleurs, préférez 1.
Remarque: toutes ces méthodes sont inutiles si vous avez l'intention d'obtenir le dernier identifiant inséré globalement (pas nécessairement par votre session). Pour cela, vous devez recourir à
SELECT max(id) FROM table
(bien sûr, cela ne lira pas les insertions non validées d'autres transactions).Inversement, vous ne devez jamais utiliser à la
SELECT max(id) FROM table
place l'une des 3 options ci-dessus, pour obtenir l'ID juste généré par votreINSERT
instruction, car (en dehors des performances), ce n'est pas sûr en même temps: entre votreINSERT
et votreSELECT
autre session peut avoir inséré un autre enregistrement.la source
SELECT max(id)
ne fait malheureusement pas le travail non plus dès que vous commencez à supprimer des lignes.1,2,3,4,5
et supprimez les lignes 4 et 5, le dernier ID inséré est toujours 5, maismax()
renvoie 3.RETURNING id;
pour insérer ceci dans un autre tableau serait le bienvenu!RETURNING id
un script SQL alimenté par l'psql
outil de ligne de commande?Voir la clause RETURNING de l' instruction INSERT . Fondamentalement, le INSERT se double d'une requête et vous renvoie la valeur qui a été insérée.
la source
insert into names (firstname, lastname) values ('john', 'smith') returning id;
simplement id comme si vous exécutiezselect id from names where id=$lastid
directement. Si vous souhaitez enregistrer le retour dans une variable aa , alorsinsert into names (firstname, lastname) values ('john', 'smith') returning id into other_variable;
si l'instruction contenant le retour est la dernière instruction d'une fonction , l'ID en coursreturning
de modification est renvoyé par la fonction dans son ensemble.vous pouvez utiliser la clause RETURNING dans l'instruction INSERT, tout comme la suivante
la source
La réponse de Leonbloy est assez complète. J'ajouterais seulement le cas spécial dans lequel on a besoin d'obtenir la dernière valeur insérée à partir d'une fonction PL / pgSQL où OPTION 3 ne correspond pas exactement.
Par exemple, si nous avons les tableaux suivants:
Si nous devons insérer un enregistrement client, nous devons nous référer à un enregistrement personne. Mais disons que nous voulons concevoir une fonction PL / pgSQL qui insère un nouvel enregistrement dans le client mais s'occupe également d'insérer le nouvel enregistrement de personne. Pour cela, nous devons utiliser une légère variation de l'OPTION 3 de leonbloy:
Notez qu'il existe deux clauses INTO. Par conséquent, la fonction PL / pgSQL serait définie comme:
Maintenant, nous pouvons insérer les nouvelles données en utilisant:
ou
Et nous obtenons l'ID nouvellement créé.
la source
Pour ceux qui ont besoin d'obtenir l'ensemble des données, vous pouvez ajouter
à la fin de votre requête pour obtenir l'objet all, y compris l'id.
la source
Voir l'exemple ci-dessous
Ensuite, pour obtenir le dernier identifiant inséré, utilisez ceci pour la table "utilisateur" nom de colonne seq "id"
la source
Vous devez bien sûr fournir le nom de la table et le nom de la colonne.
Ce sera pour la session / connexion actuelle http://www.postgresql.org/docs/8.3/static/functions-sequence.html
la source
Essaye ça:
Si cela retourne 1 (ou quelle que soit la valeur de début de votre séquence), réinitialisez la séquence à sa valeur d'origine, en passant le faux drapeau:
Autrement,
Cela restaurera la valeur de séquence à l'état d'origine et "setval" reviendra avec la valeur de séquence que vous recherchez.
la source
Postgres a un mécanisme intégré pour le même, qui dans la même requête renvoie l'ID ou tout ce que vous souhaitez que la requête retourne. Voici un exemple. Considérez que vous avez créé une table qui comporte 2 colonnes colonne1 et colonne2 et que vous souhaitez que la colonne1 soit renvoyée après chaque insertion.
la source
J'ai eu ce problème avec Java et Postgres. Je l'ai corrigé en mettant à jour une nouvelle version de Connector-J.
postgresql-9.2-1002.jdbc4.jar
https://jdbc.postgresql.org/download.html : version 42.2.12
https://jdbc.postgresql.org/download/postgresql-42.2.12.jar
la source