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

PostgreSQL Discussion :

clé dupliquée dans une table


Sujet :

PostgreSQL

  1. #1
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    677
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 677
    Par défaut clé dupliquée dans une table
    Bonjour à tous !

    J'ai une table "inscrit_en_ligne" qui possède un index avec une contrainte d'unicité sur la colonne "inscrit_en_ligne_inscrit_id". Il faut absolument éviter les doublons.

    J'ai une fonction qui teste la présence d'un membre dans cette table. Si le membre est présent on fait un UPDATE dans le cas contraire, on fait un INSERT.

    malheureusement j'ai souvent un message d'erreur dans mes logs qui dit qu'une clé dupliquée rompt la contrainte unique. Ce qui veut dire que mon test INSERT ou UPDATE ne fonctionne pas.

    ERREUR: une cl? dupliqu?e rompt la contrainte unique << inscrit_en_ligne_idx_inscri_id >>\nCONTEXT
    J'ai beau regardé ma fonction dans tous les sens je ne vois pas où est le problème. Je me décide donc à vous la soumettre car je n'ai peut-être plus la clairvoyance nécessaire

    Voilà un extrait :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
     /* on verifie si l'inscrit est deja present dans la table inscrit_en_ligne */
            SELECT INTO nb_lignes count(*) FROM inscrit_en_ligne
            WHERE inscrit_en_ligne_inscrit_id = $1
            AND inscrit_en_ligne_inscrit_id_crypte = $2;
    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
     
      IF nb_lignes != 0  THEN
            /* inscrit deja present dans la table inscrit_en_ligne */
               /* maj */
               UPDATE inscrit_en_ligne
               SET inscrit_en_ligne_date_connexion = $4
               WHERE inscrit_en_ligne_inscrit_id = $1
                     AND inscrit_en_ligne_inscrit_id_crypte = $2;
     
       ELSIF nb_lignes = 0 THEN
            /* inscrit non present dans la table inscrit_en_ligne */
               /* insertion */
               INSERT INTO inscrit_en_ligne (inscrit_en_ligne_inscrit_id, inscrit_en_ligne_inscrit_id_crypte, inscrit_en_ligne_date_connexion)
               VALUES($1, $2, $4);
     
       END IF;

    Voici un autre message d'erreur lié à cette fonction apparu ce matin :
    ERREUR: Bloquage d?tect?\nDETAIL: Le processus 12476 attend ShareLock sur transaction 426219146 ; bloqu? par le processus 12485.\nLe processus 12485 attend ShareLock sur transaction 426219132 ;
    Merci à tous

  2. #2
    Membre émérite
    Homme Profil pro
    Inscrit en
    Janvier 2006
    Messages
    491
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Corse (Corse)

    Informations forums :
    Inscription : Janvier 2006
    Messages : 491
    Par défaut
    bonsoir ,essaie une fonction de ce type là:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    CREATE OR REPLACE FUNCTION verif() returns opaque AS $body$
    begin
    IF NEW.id  IN ( SELECT id FROM ma_table ) THEN
        UPDATE ma_table SET ma_colonne =NEW.ma_valeur
        WHERE id=NEW.id;
        RETURN NULL;
    END IF;
    RETURN NEW;
    END;
    $body$
     LANGUAGE 'plpgsql';
    puis tu crées le trigger
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    CREATE TRIGGER tr_verif BEFORE INSERT ON ma_table
    FOR each row execute procedure verif();

  3. #3
    Membre confirmé
    Inscrit en
    Avril 2008
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 89
    Par défaut
    Salut,

    se peut-il que l'ID soit présent dans la table mais pas l'ID cripté auquel cas tu crois qu'il faut faire un INSERT (ton nb_count vaut 0) et là boum !!! L'ID est déjà présent (mais pas l'ID cripté) !!!

    Si c'est le cas :
    1°) tu peux faire un test pour remplir nb_count en testant uniquement la clé primaire soit ID (tu enlèves le AND ID cripté ...)

    2°) ou mieux définir une PK double sur ID et ID cripté ainsi si l'ID existe mais pas l'ID cripté ton insert ne fera pas planter le truc.

    Si ce n'est pas le cas je ne sais pas....

    Cordialement,

  4. #4
    Membre éclairé
    Profil pro
    Inscrit en
    Mai 2002
    Messages
    677
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mai 2002
    Messages : 677
    Par défaut
    malheureusement non l'id crypté est obligatoirement dans la table

  5. #5
    Membre confirmé
    Inscrit en
    Avril 2008
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 89
    Par défaut Sur ?
    Clairement,
    ton message d'erreur vient de l'insert (et pas de l'update).

    Ce qui signifie que $1 est déjà présent dans la table.

    Or ton test (nb_count) t'indiques que le couple ($1,$2) n'est pas présent.

    Donc il y a bien un ($1,xx) présent dans ta table... non ?

    Où alors (en supposant que ceci est impossible ou que tu as fait le test de manière explicite) l'enchainement des deux parties du code (et ce qu'il manque peut-être entre les deux) fait que ton $1 n'est pas le même dans le test et dans l'insert (mets l'ensemble du code dans le post s'il le faut).

    Même si par exemple tu utilises une méthode bijective qui fait que 1 seul ID cripté est (normalement) associé à 1 seul ID, je te conseilles de vérifier à la main lors de l'update si l'ID n'est pas présent et de ne pas simplement de te dire que ta méthode te le garantis.

    On ne sait jamais...

    Sinon je ne vois pas ce qui plante dans le code et je ne saurais que te conseiller de mettre des RAISE NOTICE au niveau de l'INSERT. Quand ça plante tu pourras alors t'assurer que l'ID n'est effectivement pas présent dans ta table.

  6. #6
    Membre confirmé
    Inscrit en
    Avril 2008
    Messages
    89
    Détails du profil
    Informations forums :
    Inscription : Avril 2008
    Messages : 89
    Par défaut De plus
    Si tu es sûr que l'association ID / ID cripté est unique pourquoi fais-tu le test sur :

    where id not in ma_table AND id_cripte not ....

    Si cette relation est sûr fais juste

    where id not in ma_table

    Et si là ça plante on sera fixé....

Discussions similaires

  1. Déterminer la Valeur la plus grande dans une table
    Par arnaud_verlaine dans le forum Langage SQL
    Réponses: 9
    Dernier message: 22/08/2014, 23h35
  2. [WD17] Dupliquer une ligne dans une table windev 17
    Par lafif50 dans le forum WinDev
    Réponses: 2
    Dernier message: 16/02/2013, 12h08
  3. [WD15E] Dupliquer des enregistrements dans une table mémoire
    Par Totik dans le forum WinDev
    Réponses: 4
    Dernier message: 16/01/2012, 08h30
  4. Dupliquer données dans une table
    Par LegendPC dans le forum Access
    Réponses: 6
    Dernier message: 24/05/2011, 15h18
  5. Comment stocker un ficher dans une table postgres
    Par josoft dans le forum Requêtes
    Réponses: 3
    Dernier message: 23/06/2003, 16h41

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