Mon objectif est d'insérer automatiquement un champ de clé primaire lors de l'insertion d'une nouvelle ligne dans le tableau.
Comment faire passer une séquence de session en session dans PostgreSQL?
doubleemploi@hanbei:/home/yves$ psql -d test
Mot de passe :
psql (8.4.13)
Saisissez « help » pour l''aide.
test=> create sequence test001 start 10;
CREATE SEQUENCE
test=> select currval('test001');
ERREUR: la valeur courante (currval) de la séquence « test00 » n''est pas encore définie dans cette session
--- current value not yet defined this session (???)
test=> select setval('test001', 10);
setval
--------
10
(1 ligne)
test=> select currval('test00');
currval
---------
10
(1 ligne)
test=> \q
test@hanbei:/home/yves$ psql -d test
Mot de passe :
psql (8.4.13)
Saisissez « help » pour l''aide.
test=> select currval('test001');
ERREUR: la valeur courante (currval) de la séquence « test00 » n''est pas encore définie dans cette session
Cela peut être plus simple que vous ne le pensez ...
Mon objectif est d'insérer automatiquement un champ de clé primaire lors de l'insertion d'une nouvelle ligne dans le tableau.
Définissez simplement la valeur par défaut de la colonne:
ALTER TABLE tbl ALTER COLUMN tbl_id SET DEFAULT nextval('my_seq'::regclass);
Ou encore plus simple, créez la table avec un type serial
pour la clé primaire pour commencer:
CREATE TABLE tbl(
tbl_id serial PRIMARY KEY
,col1 txt
-- more columns
);
Il crée une séquence dédiée et définit automatiquement la valeur par défaut pour tbl_id.
Par ici tbl_id
est automatiquement affectée à la prochaine valeur de la séquence jointe si vous ne la mentionnez pas dans INSERT
. Fonctionne avec any session, simultanée ou non.
INSERT INTO tbl(col1) VALUES ('foo');
Si vous voulez le nouveau tbl_id
retour pour en faire quelque chose:
INSERT INTO tbl(col1) VALUES ('foo') RETURNING tbl_id;
currval
renverra la dernière valeur générée pour la séquence dans la session en cours. Donc, si une autre session génère une nouvelle valeur pour la séquence, vous pouvez toujours récupérer la dernière valeur générée par VOTRE session, en évitant les erreurs.
Mais, pour obtenir la dernière valeur générée sur toutes les sessions, vous pouvez utiliser ce qui précède:
SELECT last_value FROM your_sequence_name;
Attention, si la valeur a été utilisée par une autre session avec une transaction non validée (ou abandonnée) et que vous utilisez cette valeur comme référence, vous pouvez obtenir une erreur. Généralement, les gens ont juste besoin du currval
ou même du retour de setval
.
Je donnerai une réponse pratique à ce sujet. Mon serveur de base de données est utilisé par mes programmes et mon terminal psql; il y a donc plusieurs sessions. actuellement je suis dans mon terminal psql:
fooserver=> select currval('fusion_id_seq');
ERROR: currval of sequence "fusion_id_seq" is not yet defined in this session
fooserver=> select nextval('fusion_id_seq');
nextval
---------
320032
(1 row)
fooserver=> select currval('fusion_id_seq');
currval
---------
320032
(1 row)
Il semble que vous ne puissiez voir les valeurs que dans votre propre session. Cela affectera également le currval d'une autre session. Ceci est probablement lié au multi-threading du serveur pour isoler différentes sessions. Le compteur (série en psql) est un objet partagé. À mon avis, cette session devrait être en mesure d'obtenir la valeur actuelle du compteur tant que le compteur est correctement verrouillé pour garantir qu'un seul thread (session) puisse l'incrémenter (opération atomique). Mais je peux me tromper ici (pas un expert en écriture de serveur de base de données).
En fait nextval fera avancer la séquence et renverra la nouvelle valeur, ce serait donc la réponse à votre question.
currval renverra la valeur la plus récemment obtenue avec nextval pour la séquence spécifiée (cela pourrait cependant échouer s'il n'y avait pas nextval utilisé dans la session en cours).
Ce problème semble être intermittent, pour des raisons de cohérence, utilisez CTE pour obtenir la séquence insérée pour la session en cours
AVEC AS inséré (INSERT INTO notifn_main (notifn_dt, stat_id) SELECT now (), 22 FROM notifn RETURNING id) SELECT id from inséré INTO tmp_id;