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 Firebird Discussion :

Simulation INSERT IGNORE avec WHEN SQLCODE -803 DO


Sujet :

SQL Firebird

  1. #1
    Membre régulier
    Simulation INSERT IGNORE avec WHEN SQLCODE -803 DO
    Bonjour,

    Je voudrais simuler le comportement de l'instruction INSERT IGNORE de MySQL dans Firebird.

    J'ai une table qui contient un id auto incrémenté et 2 champs entier, value_A et value_B. J'ai définie une contrainte d'unicité sur {valeur_A , valeur_B}.

    Le comportement souhaité est le suivant :
    J’insère respectivement les valeurs 2 et 5 dans les champs valeur_A et valeur_B et je retourne l'id créé. Si la requête provoque une violation de la contrainte d'unicité (erreur 803), alors je sélectionne l'id dont les champs valeur_A et valeur_B valent respectivement 2 et 5.

    Concrètement, j'en arrives à la requête suivante :
    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
    EXECUTE block AS BEGIN
        INSERT
        INTO "table"(
            "valeur_A", 
            "valeur_B"
        )VALUES(
            2, 
            5
        )RETURNING "id";
        WHEN SQLCODE -803 DO
            SELECT "id"
            FROM "table"
            WHERE "valeur_A"=2
            AND "valeur_B"=5;
    END


    Problème, il me dit
    "SQL error code = -104. Token unknown - line 14, column 27. ;."
    Et je ne comprends pas pourquoi il me dit que le dernier ; est invalide (et si je l'enlève, il me dit que c'est END qui est invalide, ce qui me parait logique).


    Merci ^^

  2. #2
    Rédacteur/Modérateur

    Bonjour,

    Ce qui me choque : l'utilisation des " " normalement inutiles, le fait que si le bloc doit renvoyer des données il n'y ait pas de déclaration en ce sens (RETURNS) et qu'il n'y ait pas de SUSPEND

    Pour en avoir le cœur net j'ai donc créé la table
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    CREATE TABLE TEST_1
    (
      ID Bigint NOT NULL,
      COLA Integer NOT NULL,
      COLB Integer NOT NULL,
      PRIMARY KEY (ID),
      CONSTRAINT UNQ_TEST_1_1 UNIQUE (COLA,COLB)
    );

    et testé ce bloc (fonctionnel, avec flamerobin)
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
    SET TERM $ ;
    EXECUTE BLOCK RETURNS (PID BIGINT)
    AS BEGIN
    INSERT INTO TEST_1(COLA,COLB) VALUES (2,5) RETURNING ID INTO <img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />ID;
    SUSPEND;
    WHEN SQLCODE -803 DO
      begin
            SELECT id  FROM TEST_1 WHERE COLA=2 AND COLB=5 INTO <img src="images/smilies/icon_razz.gif" border="0" alt="" title=":P" class="inlineimg" />ID;     
            SUSPEND;
      end      
    END$
    SET TERM ; $
    La seule chose absolue dans un monde comme le nôtre, c'est l'humour. » Albert Einstein

    Delphi installés : D3,D7,D2010,XE4,XE7,D10 (Tokyo, Rio, Sidney) et peut être quelques autres
    SGBD : Firebird 2.5, 3, SQLite
    générateurs Etats : FastReport, Rave, QuickReport
    OS : Window Vista, Windows 10, Ubuntu, Androïd

  3. #3
    Membre régulier
    Pour les guillemets, c'est parce que le driver PHP capitalise automatiquement les noms de tables et champs alors qu'ils sont en minuscules dans la base. Donc je suis obligé de les protéger à l'écriture de la requête. Et j'ai pas pensé à les retirer pour l'exemple.

    Effectivement, en rajoutant la déclaration de retours et l'instruction SUSPEND, ça fonctionne mieux ^^

    Je m'étais essentiellement basé sur cet article qui utilises des SELECT sans utiliser de RETURN, du coup je me suis dit que ça devait être implicite en P-SQL. Manque d’expérience, quoi.

    Au final, la requête donne ça :

    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
    EXECUTE block RETURNS (id INTEGER) AS BEGIN
        INSERT
        INTO "table"(
            "valeur_A", 
            "valeur_B"
        )VALUES(
            2, 
            5
        )RETURNING "id" INTO :id;
        SUSPEND;
     
        WHEN SQLCODE -803 DO BEGIN
            SELECT "id"
            FROM "table"
            WHERE "valeur_A"=2
            AND "valeur_B"=5 INTO :id;
            SUSPEND;
        END
    END


    J'ai dû retirer les lignes
    Code :Sélectionner tout -Visualiser dans une fenêtre à part
    SET TERM $ ; et $ SET TERM ; $
    qui ne semblaient pas être reconnues.


    Merci pour la réponses (et au modo pour avoir ajouter les balises idoine ^^').

###raw>template_hook.ano_emploi###