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

Langage SQL Discussion :

INSERT IF NOT EXISTS


Sujet :

Langage SQL

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Par défaut INSERT IF NOT EXISTS
    Bonjour,
    J'essaie de comprendre une astuce permettant l'insertion uniquement si la clé primaire est absente (afin de ne pas déclencher l'inévitable erreur de clé dupliquée).
    Dans l'exemple donné sur ce post, il est bien précisé de faire le "WHERE NOT EXISTS" sur une table bidon :
    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
    INSERT INTO
        matable
        (   maclefprimaire
        ,   maclefetrangere
        ,   monattribut
        ) 
    SELECT  1
        ,   1
        ,   'valeurtexte'
    FROM    tablebidon
    WHERE   NOT EXISTS
            (   SELECT  0
                FROM    matable
                WHERE   maclefprimaire = 1
            )
    ;
    Effectivement, si on utilise matable au lieu de tablebidon:
    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
    INSERT INTO
        matable
        (   maclefprimaire
        ,   maclefetrangere
        ,   monattribut
        ) 
    SELECT  1
        ,   1
        ,   'valeurtexte'
    FROM    matable
    WHERE   NOT EXISTS
            (   SELECT  0
                FROM    matable
                WHERE   maclefprimaire = 1
            )
    ;
    ... on obtient une erreur de clé dupliquée si la clé en question n'est pas présente (par contre, cela fonctionne bien si la clé est présente).

    Pourquoi ?

  2. #2
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Par défaut
    bonjour,

    quel est votre sgbd ?

  3. #3
    Modérateur
    Avatar de al1_24
    Homme Profil pro
    Retraité
    Inscrit en
    Mai 2002
    Messages
    9 135
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 64
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Retraité
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Mai 2002
    Messages : 9 135
    Par défaut
    Relis bien ce qui était écrit dans le message auquel tu fais référence :
    Citation Envoyé par al1_24 Voir le message
    Il te suffit d'une table bidon contenant un enregistrement (comme dual sous Oracle, ou une table quelconque sur laquelle tu sélectionnes un enregistrement et un seul).
    Modérateur Langage SQL
    Règles du forum Langage SQL à lire par tous, N'hésitez pas à consulter les cours SQL
    N'oubliez pas le bouton et pensez aux balises
    [code]
    Si une réponse vous a aidé à résoudre votre problème, n'oubliez pas de voter pour elle en cliquant sur
    Aide-toi et le forum t'aidera : Un problème exposé sans mentionner les tentatives de résolution infructueuses peut laisser supposer que le posteur attend qu'on fasse son travail à sa place... et ne donne pas envie d'y répondre.

  4. #4
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Citation Envoyé par spirzouf Voir le message

    Pourquoi ?
    Dans le lien que vous citez, il est bien précisé que la "table bidon" doit contenir une (et une seule) ligne.

    Là vous essayez d'insérer autant de fois la même ligne qu'il y en a dans la table... d'où le message indiquant la violation de la contriainte

  5. #5
    Membre confirmé
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Par défaut
    Merci pour vos réponses !

    Citation Envoyé par aieeeuuuuu Voir le message
    Là vous essayez d'insérer autant de fois la même ligne qu'il y en a dans la table... d'où le message indiquant la violation de la contrainte
    D'accord, déjà, en terme de performance, je vois bien l'intérêt d'une et une seule ligne.

    Mais alors concernant la condition, elle devrait si la clé n'est PAS présente :
    - déclencher l'insertion lors de la 1ère ligne,
    - passer outre les fois suivantes,

    Sauf s'il s'agit du COMMIT qui ne se fait qu'à la fin, du coup, à la 2nde ligne, l'insertion est faite mais non détectable par la condition, et on entre en conflit avec l'insertion que l'on vient juste de faire ? Ce qui expliquerait l'autre cas de la clé présente dès le début, où aucune erreur
    n'est levée, car dès la première ligne, la condition empêche l'insertion et idem les lignes suivantes.

    Pour info, j'utilise postgreSQL 9.2

    (On est bien d'accord que c'est du triturage de cervelle, mais c'est juste pour comprendre comment cela fonctionne)

  6. #6
    Expert confirmé
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    3 173
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Mai 2002
    Messages : 3 173
    Par défaut
    Ceci serait vrai si vous effectuiez une deuxième requête dans la même transaction (sans commit intermédiaire).

    Dans votre cas, la requête de sélection s’exécute dans un premier temps, puis vient l'insert.

  7. #7
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Citation Envoyé par spirzouf Voir le message

    Mais alors concernant la condition, elle devrait si la clé n'est PAS présente :
    - déclencher l'insertion lors de la 1ère ligne,
    - passer outre les fois suivantes,
    Non, car le SQL est ensembliste : toutes les lignes sont insérées d'un coup.

    Essayez simplement la partie SELECT de votre deuxième requête (sans le INSERT) et vous verrez ce que vous êtes en train d'essayer d'insérer.

  8. #8
    Modérateur

    Profil pro
    dba
    Inscrit en
    Janvier 2010
    Messages
    5 643
    Détails du profil
    Informations personnelles :
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : dba

    Informations forums :
    Inscription : Janvier 2010
    Messages : 5 643
    Par défaut
    Citation Envoyé par spirzouf Voir le message
    Pour info, j'utilise postgreSQL 9.2
    Alors vous n'avez même pas besoin de table bidon, faites simplement


    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
     
    INSERT INTO
        matable
        (   maclefprimaire
        ,   maclefetrangere
        ,   monattribut
        ) 
    SELECT  1
        ,   1
        ,   'valeurtexte'
    WHERE   NOT EXISTS
            (   SELECT  0
                FROM    matable
                WHERE   maclefprimaire = 1
            )
    ;

  9. #9
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 999
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Expert bases de données / SQL / MS SQL Server / Postgresql
    Secteur : Conseil

    Informations forums :
    Inscription : Mai 2002
    Messages : 21 999
    Billets dans le blog
    6
    Par défaut
    cela dit en terme de performances, la solution lambda en force brut sans sous requête sera notablement plus rapide et surtout, la durée du verrouillage étant moins longue donc on y gagnera en concurrence !

    Pourquoi est-ce que les développeurs aiment faire des usines à gaz là ou des choses simples sont naturellement performantes ?


    A +
    Frédéric Brouard - SQLpro - ARCHITECTE DE DONNÉES - expert SGBDR et langage SQL
    Le site sur les SGBD relationnels et le langage SQL: http://sqlpro.developpez.com/
    Blog SQL, SQL Server, SGBDR : http://blog.developpez.com/sqlpro
    Expert Microsoft SQL Server - M.V.P. (Most valuable Professional) MS Corp.
    Entreprise SQL SPOT : modélisation, conseils, audit, optimisation, formation...
    * * * * * Expertise SQL Server : http://mssqlserver.fr/ * * * * *

  10. #10
    Membre confirmé
    Homme Profil pro
    Etudiant CNAM (DIE20)
    Inscrit en
    Janvier 2010
    Messages
    151
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant CNAM (DIE20)

    Informations forums :
    Inscription : Janvier 2010
    Messages : 151
    Par défaut
    Citation Envoyé par SQLpro Voir le message
    cela dit en terme de performances, la solution lambda en force brut sans sous requête sera notablement plus rapide et surtout, la durée du verrouillage étant moins longue donc on y gagnera en concurrence !
    Vous voulez dire une fonction anonyme PLPGSQL dans ce style (vous me faites découvrir ce concept sous postgreSQL) ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    DO LANGUAGE PLPGSQL $$
    DECLARE id_en retour INTEGER;
    BEGIN
        SELECT id FROM matable WHERE id = XXX RETURNING INTO id_en retour;
        IF id_en retour IS NULL THEN
            INSERT INTO matable ... ;
        ELSE 
            UPDATE matable ... ;
        END IF;
    END;
    $$;
    J'avais pensé faire une fonction enregistrée au début, mais laissé tomber pensant que justement, cela faisait plus usine à gaz qu'une sous-requête... Ce serait encore plus performant qu'une fonction lambda que l'on redéclare à chaque fois, non ?

    Mais j'ai dû comprendre de travers, car là aussi, on a un SELECT avant l'INSERT, donc ce doit être similaire à la sous-requête en terme de performances ?

    Citation Envoyé par SQLpro Voir le message
    Pourquoi est-ce que les développeurs aiment faire des usines à gaz là ou des choses simples sont naturellement performantes ?
    Je suis en pleine formation, alors je ne me sens pas (encore) visé

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

Discussions similaires

  1. INSERT IF NOT EXISTS
    Par finiderire dans le forum Langage SQL
    Réponses: 12
    Dernier message: 27/03/2012, 17h44
  2. [MySQL] INSERT IF NOT EXISTS
    Par Iloyo dans le forum MySQL
    Réponses: 7
    Dernier message: 17/03/2010, 15h26
  3. Sunopsis ODI: Insertion if not exists
    Par Marie-Thérèse dans le forum ODI (ex-Sunopsis)
    Réponses: 1
    Dernier message: 06/08/2009, 10h43
  4. insert et not exists
    Par farenheiit dans le forum SQL
    Réponses: 3
    Dernier message: 10/07/2009, 16h45
  5. Insert .. where not exists
    Par Zolex dans le forum SQL Procédural
    Réponses: 11
    Dernier message: 02/03/2007, 11h26

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