Récupérer une séquence, équivalence PostgreSQL vs MSSQL
Dans une fonction PostgreSQL ou une procédure stockée SQL Server, c'est assez commun de devoir récupérer la séquence courante suite à l'insertion d'un enregistrement. La plupart du temps, c'est pour la retourner comme valeur de retour ou encore pour s'en servir pour insérer des enregistrements dépendants dans une base de données modélisée en forme normale 3FN.
Juste pour vous situer, c'est comme dire qu'on doit conserver la trace d'un message et la liste des destinataires dans deux tables séparées. On récupérera l'ID du message pour ensuite l'utiliser dans l'insertion des destinataires, selon une relation 1 à plusieurs.
L'important, c'est de s'assurer que l'ID principal correspond à la bonne insertion. Si on faisait quelque chose comme ceci (pseudo-code) :
INSERT INTO messages (...) VALUES (...);Il y aurait de fortes chances pour que quelqu'un d'autre ait au même moment inséré un autre message, ce qui aurait pour conséquence qu'on récupérerait le mauvais ID.
-- conserver max(message_id) dans une variable
SELECT MAX(message_id) FROM messages);
INSERT INTO recipients (message_id, email)
VALUES ($id, 'lui@hotmail.com');
INSERT INTO recipients (message_id, email)
VALUES ($id, 'elle@hotmail.com');
Pour s'assurer qu'on récupère le bon, mieux vaut l'englober dans une procédure stockée. Avec SQL Server, immédiatement après l'insertion principale (message), on peut appeler la fonction T_SQL scope_identity() qui retournera le dernier ID inséré dans n'importe quelle table pour la session courante, selon la portée de la fonction/procédure/trigger qui l'appelle. D'où l'importance de l'appeler immédiatement après l'insertion.
DECLARE @id integerMais faites attention car il existe aussi @@identity mais celui-ci n'est pas limité à la portée.
INSERT INTO messages (...)
VALUES (...);
SET @id = SCOPE_IDENTITY()
INSERT INTO recipients (message_id, email)
VALUES (@id, 'lui@hotmail.com');
Avec PostgreSQL, on fait la même chose dans une fonction. Cependant, comme les séquences sont nommées, on les récupère avec la fonction currval() qui prend comme paramètre le nom de la séquence. Ici, il n'y a pas d'ambiguité, c'est la valeur courante qui est retournée.
DECLARE id integer;En utilisant cette technique, ça vous évitera de devoir chercher les incohérences dans l'intégrité de vos données.
INSERT INTO messages (...) VALUES (...);
id := currval('nom_de_la_sequence');
INSERT INTO recipients (message_id, email)
VALUES (id, 'lui@hotmail.com');
Finalement, je ne suis pas très connaisseur de MySQL mais je crois que son équivalent est la fonction last_insert_id(). Cependant, il faut faire attention si on insère en batch : la fonction de MySQL retournera l'ID du premier élément inséré dans la batch tandis que scope_identity() de MSSQL retournera le dernier.