IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Oracle Discussion :

Récupérer une clé primaire après insertion


Sujet :

SQL Oracle

  1. #1
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 66
    Par défaut Récupérer une clé primaire après insertion
    Bonjour,
    Je fouille depuis un moment pour trouver comment récupérer une valeur de clé primaire sous Oracle (10g me semble-t-il) et je ne suis pas un vieil habitué d'Oracle en général.

    Chacune de mes tables a une clé primaire assortie d'une séquence et d'un trigger pour une auto-incrémentation automatique.

    Mes insertions ne mentionnent donc pas la colonne de clé primaire. Ce faisant, je n'ai nul besoin d'indiquer de valeur de clé primaire avec <nom_sequence.nextval>. Ça fonctionne fort bien, mais je me heurte à un problème : mes insertions se font via des requêtes paramétrées dans des packages. J'ai donc dans mon package une procédure pour l'insertion. J'ai des paramètres de retour (OUT) ERRCODE et ERRMSG, mais je cherche surtout comment récupérer la valeur de clé primaire générée en étant sûr que, si une insertion concurrente à eu lieu en parallèle par un autre utilisateur, j'ai bien la clé correspondant à ma requête.

    Toute indication ou piste vers une doc appropriée sera grandement bienvenue.

    Merci d'avance.

  2. #2
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    insert into ... returning ... ou sequence.currval.

  3. #3
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 66
    Par défaut
    Merci pour la rapidité mnitu,
    Corrige moi si je me trompe :
    1. déclarer une variable OUT pour recevoir la valeur;
    2. Après la requête d'insertion, ajouter ce second INSERT pour récupérer seq.currval avant le END nom_procedure;

    Quelque chose dans ce goût-là :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
      -- -----------------------------------
      -- Ajout d'un centre
      -- -----------------------------------
      PROCEDURE insert_centre(
        ERRCODE             IN OUT NUMBER,
        ERRMSG              IN OUT NOCOPY VARCHAR2,
        ID_CENTRE           OUT NUMBER,
        -- reste de mes parametres ....
      ) AS
      BEGIN
        INSERT INTO LOG_CENTRE_CTR (
            -- colonnes à remplir
        )
        VALUES(
            -- valeurs correspondantes
        );
        ID_CENTRE := SEQ_PK_CTR.CURRVAL;
        RETURN ID_CENTRE;
      END insert_centre;
    ?

  4. #4
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    Plutôt ça
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    INSERT INTO employees 
          (employee_id, last_name, email, hire_date, job_id, salary)
       VALUES 
       (employees_seq.nextval, 'Doe', 'john.doe@oracle.com', 
           SYSDATE, 'SH_CLERK', 2400) 
       RETURNING salary*12, job_id INTO l_bnd1, l_bnd2

  5. #5
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 66
    Par défaut
    Ben alors mon trigger ne sert plus à rien si je dois indiquer explicitement la valeur de la clé primaire dans la requête. Or comme expliqué en préambule, je ne l'indique pas :
    -1- Pour ma table, j'ai une séquence pour la clé primaire, comme ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE SEQUENCE  "SEQ_PK_CTR"  
    MINVALUE 1 
    MAXVALUE 999999999999999999999999999 
    INCREMENT BY 1 
    START WITH 1 
    CACHE 20 
    NOORDER  
    NOCYCLE ;
    -2- Pour la table, j'ai un trigger comme celui-ci par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    create or replace TRIGGER "TIB_LOG_PK_CTR" 
    before insert on "LOG_CENTRE_CTR"   
    for each row 
    begin    
        if inserting then      
            if:NEW."CTR_ID" is null then         
                select SEQ_PK_CTR.nextval
                into :NEW."CTR_ID"
                from dual;      
            end if;   
        end if; 
    end;
    -3- ma requête d'insertion comprendra donc les noms des colonnes autres que la clé primaire et je n'indiquerai pas de valeur non plus, le trigger s'en charge.

    Donc le problème lors de l'appel de ma procédure consiste à récupérer la valeur générée. Voilà pourquoi j'ai songé à cette syntaxe pour le faire en assignant la valeur SEQ_PK_CTR.currval à ma variable déclarée OUT en début de procédure, un équivalent en quelque sorte d'un last_insert_id

    Faut que je fasse des tests, pour l'instant j'en suis à l'écriture des packages, je n'ai pas attaqué le code appelant qui enverra les données. Après réflexion, la formule serait probablement davantage sous la forme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    -- ... code de la procédure ...
      SELECT SEQ_PK_CTR.CURRVAL 
      INTO ID_CENTRE 
      FROM DUAL;
    END;
    Ce que je ne sais pas, c'est de savoir si ça me récupèrera la bonne valeur, ce qui impliquerait que ça prendrait en compte l'insertion juste avant et donc que l'incrémentation par le trigger aurait correctement été effectuée, et encore une fois qu'aucune insertion concurrente par un autre utilisateur ne risquerait de fausser le résultat.

  6. #6
    Expert confirmé Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Marne (Champagne Ardenne)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Octobre 2007
    Messages : 5 611
    Par défaut
    L'exemple c'était pour la syntaxe du insert ... returning et non pas pour supprimer le trigger.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    create table tutu (
      id    number primary key,
      txt   varchar2(10)
    )
    /
    create sequence seq_tutu_id
    /
    CREATE OR REPLACE TRIGGER "BI_TUTU" 
    before INSERT ON "TUTU"   
    FOR each row 
    begin
      if :new.id is null then
       select seq_tutu_id.nextval into :new.id from dual;
      end if;
    end;
    /
    SQL> variable n number;
    SQL> insert into tutu (txt) values ('test') returning id into :n;
     
    1 row inserted
    n
    ---------
    1
     
    SQL> print n
    n
    ---------
    1
    Bien sûr qu'à la place du n tu peux utiliser une variable pl_sql.

  7. #7
    Membre averti
    Profil pro
    Inscrit en
    Mars 2003
    Messages
    66
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2003
    Messages : 66
    Par défaut
    Ok, j'avais mal compris.

    C'est excellent, je te remercie

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 3
    Dernier message: 15/12/2011, 02h36
  2. Réponses: 3
    Dernier message: 10/03/2009, 13h09
  3. Existe-t'il une validation à demander apres INSERT ?
    Par colorid dans le forum Firebird
    Réponses: 7
    Dernier message: 28/11/2007, 20h10
  4. Réponses: 3
    Dernier message: 19/04/2007, 21h55
  5. Réponses: 4
    Dernier message: 30/03/2007, 19h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo