skip to main | skip to sidebar
Code 18
Manuel du savoir-faire à l'usage des geeks et des curieux
RSS
  • Accueil
  • Le web au Québec
  • Liens
  • Twitter
  • Facebook
  • À propos

dimanche 4 septembre 2011

Récupérer l'ID d'un enregistrement inséré sous Postgres

Publié par Infinite Loop, à 14 h 03 2 commentaires

En programmation, c'est une bonne stratégie de connaître des alternatives pour écrire du code qui fait le même travail. On se rend compte avec le temps qu'il n'y a pas de mauvaise façon de faire, juste des meilleures.

Quand j'ai écrit mes premières lignes de code pour des fonctions Postgres et que j'avais à insérer un enregistrement pour récupérer et retourner la valeur de l'identificateur unique (par sa séquence / clé primaire), j'ai pris l'habitude d'y aller en deux étapes : l'insertion d'abord, la récupération ensuite. Le tout étant encapsulé dans une fonction suivant les règles de transaction, ça fonctionnait bien.

CREATE OR REPLACE FUNCTION insert_something(fname character varying, lname character varying)

RETURNS integer AS
$BODY$
BEGIN
INSERT INTO artist (firstname, lastname)
VALUES (fname, lname);

RETURN currval('public.artist_id_artist_seq');
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
Avec ce code, il est impératif de connaître le nom de la séquence pour obtenir la valeur courante de l'insertion qui la précède. Et comme on utilise généralement le type SERIAL pour faciliter la création d'une clé primaire qui génère du même coup la séquence avec un nom générique, il faudra d'abord trouver ce nom.

L'énoncé pour obtenir le nom d'une séquence appliquée à une colonne d'une table :
SELECT pg_get_serial_sequence('artist', 'id_artist')

-- "public.t_artist_id_artist_seq"
Et on demande sa valeur par currval :
SELECT currval('public.artist_id_artist_seq') as id;


-- ou en l'assignant à une variable pl/pgsql

id := currval('public.artist_id_artist_seq');
La requête retournera l'ID généré par l'appel de la fonction :
SELECT insert_something('Jimi', 'Hendrix') // 4
Pour faire exactement la même chose, on pourrait réécrire le code en utilisant une particularité de Postgres pour demander à la requête SQL de retourner la valeur d'un champ dans le même énoncé en utilisant le mot clé RETURNING qui l'assignera à une variable déclarée.
CREATE OR REPLACE FUNCTION insert_something(fname character varying, lname character varying)

RETURNS integer AS
$BODY$
DECLARE
id integer; -- déclaration de la valeur de retour
BEGIN
INSERT INTO t_test (firstname, lastname)
VALUES (fname, lname)
RETURNING "id_record" INTO STRICT id;

RETURN id;
END;
$BODY$
LANGUAGE 'plpgsql' VOLATILE;
En fait, vous pouvez retourner n'importe quelle valeur de l'enregistrement venant d'être créé, que ce soit la valeur de la séquence ou la valeur par défaut définie dans un champ de la table (par exemple une date de création avec comme valeur par défaut "now()"). Cependant, si la valeur à retourner est insérée par un trigger de type AFTER INSERT, sa valeur sera nulle car Postgres fait appel au trigger uniquement après l'insertion (BEFORE INSERT ne présente pas de problème).

L'énoncé qui utilise RETURNING a l'avantage qu'on n'a pas à connaître le nom de la séquence et que ça fonctionnera quand même si son nom change dans le futur (tant que le nom du champ demandé reste inchangé!).


Tags: PostgreSQL

2 réponses à "Récupérer l'ID d'un enregistrement inséré sous Postgres"

  1. admin-for-pro a dit...
    27 mars 2012 à 08 h 22

    Perso j'utilise :
    select pg_get_serial_sequence('nom de la table',
    SELECT attname as primary_key FROM pg_constraint
    INNER JOIN pg_class ON (conrelid = relfilenode)
    INNER JOIN pg_attribute ON (conrelid = attrelid AND conkey[1] = attnum)
    WHERE contype = 'p' and relname = 'nom de la table'"
    ) as name_sequence

    pour connaitre le nom de la séquence de ma table.

    Donc j'arrivais à générer un insert pour n'importe quelle table, néanmoins je trouve ton histoire de returning beaucoup mais alors là beaucoup plus classe !
    Donc merci de l'avoir partagée !

    Jean Paul a dit...
    9 janvier 2014 à 06 h 56

    Salut,
    avec votre astuce j'ai pu récupérer un ID sans utiliser un trigger.
    Merci beaucoup.


Publier un commentaire

Message plus récent Messages plus anciens Accueil
S'abonner à : Publier des commentaires (Atom)
    Suivre @code18 sur Twitter

    Catégories

    • Apache (21)
    • Citations (167)
    • Club Vidéo (24)
    • Coffre à outils (56)
    • CSS (8)
    • Curiosités (117)
    • Design Pattern (2)
    • Drupal (8)
    • Easter Eggs (22)
    • Extensions Firefox (20)
    • GIMP (7)
    • Histoire (21)
    • HTML (32)
    • Humour (57)
    • Intégration (34)
    • iPod (12)
    • JavaScript (110)
    • Jeu de combat (6)
    • Le coin du geek (128)
    • Liens (12)
    • Linux (56)
    • Livres (78)
    • Lois et principes (46)
    • Marché des saveurs (26)
    • Mathématique (18)
    • Mobile (5)
    • Montréal (32)
    • Musique (112)
    • Pancartes et écriteaux (16)
    • Perl (8)
    • Pérou (1)
    • PHP (130)
    • PostgreSQL (44)
    • Programmation (105)
    • Saviez-vous que (55)
    • Sécurité (22)
    • SEO (5)
    • SQL Server (22)
    • Vieilles publicités (6)
    • Virtualisation (8)
    • Voyages (1)
    • Zend Framework (26)

    Divers

    Archives

    • ►  2015 (6)
      • ►  août 2015 (1)
      • ►  juillet 2015 (1)
      • ►  février 2015 (3)
      • ►  janvier 2015 (1)
    • ►  2014 (8)
      • ►  décembre 2014 (1)
      • ►  novembre 2014 (1)
      • ►  octobre 2014 (1)
      • ►  août 2014 (2)
      • ►  juillet 2014 (2)
      • ►  janvier 2014 (1)
    • ►  2013 (53)
      • ►  décembre 2013 (2)
      • ►  novembre 2013 (1)
      • ►  octobre 2013 (3)
      • ►  septembre 2013 (2)
      • ►  août 2013 (5)
      • ►  juillet 2013 (3)
      • ►  juin 2013 (5)
      • ►  mai 2013 (3)
      • ►  avril 2013 (7)
      • ►  mars 2013 (7)
      • ►  février 2013 (11)
      • ►  janvier 2013 (4)
    • ►  2012 (105)
      • ►  décembre 2012 (8)
      • ►  novembre 2012 (5)
      • ►  octobre 2012 (4)
      • ►  septembre 2012 (1)
      • ►  août 2012 (8)
      • ►  juillet 2012 (7)
      • ►  juin 2012 (7)
      • ►  mai 2012 (10)
      • ►  avril 2012 (13)
      • ►  mars 2012 (15)
      • ►  février 2012 (15)
      • ►  janvier 2012 (12)
    • ▼  2011 (146)
      • ►  décembre 2011 (14)
      • ►  novembre 2011 (11)
      • ►  octobre 2011 (12)
      • ▼  septembre 2011 (13)
        • Vérifier si une table existe dans Postgres
        • Devant une bibliothèque imposante
        • Les jeunes condamnés à la location perpétuelle ?
        • Citation no. 135 sur les grands penseurs
        • Tri conditionnel dans un énoncé SQL
        • Bouton personnalisé dans un datepicker jQueryUI
        • Mon top 3 photos du 11 septembre 2011
        • Citation no. 134 sur le mensonge
        • Sélectionner le 1er enregistrement de chaque group...
        • La réponse sera toujours 8
        • Récupérer l'ID d'un enregistrement inséré sous Pos...
        • Citation no. 133 sur l'art d'être bien informé
        • La survie du petit commerce
      • ►  août 2011 (15)
      • ►  juillet 2011 (17)
      • ►  juin 2011 (18)
      • ►  mai 2011 (15)
      • ►  avril 2011 (9)
      • ►  mars 2011 (7)
      • ►  février 2011 (3)
      • ►  janvier 2011 (12)
    • ►  2010 (398)
      • ►  décembre 2010 (29)
      • ►  novembre 2010 (28)
      • ►  octobre 2010 (32)
      • ►  septembre 2010 (34)
      • ►  août 2010 (22)
      • ►  juillet 2010 (35)
      • ►  juin 2010 (42)
      • ►  mai 2010 (36)
      • ►  avril 2010 (37)
      • ►  mars 2010 (34)
      • ►  février 2010 (32)
      • ►  janvier 2010 (37)
    • ►  2009 (430)
      • ►  décembre 2009 (32)
      • ►  novembre 2009 (34)
      • ►  octobre 2009 (33)
      • ►  septembre 2009 (37)
      • ►  août 2009 (37)
      • ►  juillet 2009 (39)
      • ►  juin 2009 (38)
      • ►  mai 2009 (37)
      • ►  avril 2009 (35)
      • ►  mars 2009 (37)
      • ►  février 2009 (32)
      • ►  janvier 2009 (39)
    • ►  2008 (84)
      • ►  décembre 2008 (34)
      • ►  novembre 2008 (39)
      • ►  octobre 2008 (11)

    Abonnés

Copyright © All Rights Reserved. Code 18 | Converted into Blogger Templates by Theme Craft