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

MS SQL Server Discussion :

Violation de la contrainte PRIMARY KEY


Sujet :

MS SQL Server

  1. #1
    Membre émérite Avatar de franculo_caoulene
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 880
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 880
    Points : 2 953
    Points
    2 953
    Par défaut Violation de la contrainte PRIMARY KEY
    Salut,

    Je suis en train d'écrire une petite procédure stockée afin d'exporter des données d'une table à une autre.
    Lorsqu'une ligne est déjà insérée je souhaite faire une mise à jour d'un champ.
    Le problème est que la condition censée détecter le cas ne fonctionne pas.
    La condition :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    if (select count(COL_2) from TABLE_1 where COL_1 = @id and COL_2 = @2) = 0
    me retourne toujours 0 dans la procédure. Si j'exécute la requête à part, pour tester, j'ai bien un résultat cohérent.

    Je pense que la définition des tables n'est pas utile, mais je suis disposé à les donner si nécessaire.
    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
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    open CURS_TMP
    fetch next from CURS_TMP into @id, @p, @1, @2, @3, @4, @5, @6, @7, @8, @9
    while @@fetch_status = 0
    	begin
    		if isnull(charindex(';', @1), 0) <> 0
    		begin 
    			set @ideb = 0
    			set @ifin = 0
    			while (@ifin < len(@1))
    			begin
    				set @ideb = @ifin
    				set @ifin = charindex(';', @1, (@ideb+1))
    				if @ifin<>1 and @ifin<>len(@1)
    				begin
    					insert into TABLE_1 (COL_1, COL_2, COL_3) values (@id, substring(@1,(@ideb+1),(@ifin-@ideb-1)), 23)
    				end
    			end
    		end
    		if isnull(charindex(';', @2), 0) <> 0
    		begin 
    			set @ideb = 0
    			set @ifin = 0
    			while (@ifin < len(@2))
    			begin
    				set @ideb = @ifin
    				set @ifin = charindex(';', @2, (@ideb+1))
    				if @ifin<>1 and @ifin<>len(@2)
    				begin
    					if (select count(COL_2) from TABLE_1 where COL_1 = @id and COL_2 = @2) = 0
    						insert into TABLE_1 (COL_1, COL_2, COL_3) values (@id, substring(@2,(@ideb+1),(@ifin-@ideb-1)), 19)
    					else
    						update TABLE_1 set COL_3 = (COL_3*19) where COL_1 = @id and COL_2 = @2
    				end
    			end
    		end
    		fetch next from CURS_TMP into @id, @p, @1, @2, @3, @4, @5, @6, @7, @8, @9
    	end
    close CURS_TMP
    deallocate CURS_TMP
    Je pense que ça ne peut pas lire et compter les données déjà insérées dans ces conditions, mais je ne sais pas vraiment pourquoi (juste une idée floue), ni comment faire pour que je fasse le select sur les données déjà insérées.

    Merci par avance.

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 056
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 056
    Points : 1 216
    Points
    1 216
    Par défaut
    bonjour,

    est-ce que le curseur est sur TABLE_1 ? for readonly ou for update ?

    et quand vous lancez tout le code du curseur hors procédure, le résultat du select est bon ?

    désolé poour l'éventuelle redite, mais c'est pour avoir des certitudes :-)

    merci

  3. #3
    Membre émérite Avatar de franculo_caoulene
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 880
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 880
    Points : 2 953
    Points
    2 953
    Par défaut
    Je n'ai pas le code sous les yeux, je ne peux donc que fournir des réponses approximatives.
    Citation Envoyé par kagemaru Voir le message
    est-ce que le curseur est sur TABLE_1 ?
    Non le curseur est sur une autre table. Ce sont des données que "j'exporte" de TABLE_0 vers TABLE_1
    Citation Envoyé par kagemaru Voir le message
    for readonly ou for update ?
    Bonne question, on va dire par défaut. C'est la première fois que j'utilise vraiment les curseurs, pour des raisons historiques on va dire.
    Citation Envoyé par kagemaru Voir le message
    et quand vous lancez tout le code du curseur hors procédure, le résultat du select est bon ?
    C'est à dire? Ce n'est pas encore dans une procédure stockée mais un simple fichier SQL que j'exécute, je suis encore en phase de test. Quand j'exécute le SELECT, mais juste le select, j'ai bien le résultat attendu après l'exécution du code affiché, car TABLE_1 est vide à l'origine.
    Citation Envoyé par kagemaru Voir le message
    désolé poour l'éventuelle redite, mais c'est pour avoir des certitudes :-)
    Mais c'est plus que bienvenu, merci de t'intéresser à mon problème.

  4. #4
    Membre émérite Avatar de franculo_caoulene
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 880
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 880
    Points : 2 953
    Points
    2 953
    Par défaut
    En effet, j'ai oublié la déclaration du curseur :
    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
    declare CURS_TMP cursor for
    select
    	CH_ID,
    	CH_P,
    	CH_1, 
    	CH_2, 
    	CH_3, 
    	CH_4, 
    	CH_5, 
    	CH_6, 
    	CH_7, 
            CH_8, 
    	CH_9,
    	CH_A,
    	CH_T,
    	CH_F
    from TABLE_1
    where CH_P = 1
     
    open CURS_TMP
    -- code posté précédemment
    Le curseur est donc pour un simple select.

  5. #5
    Membre éprouvé
    Profil pro
    Inscrit en
    Juin 2007
    Messages
    1 056
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2007
    Messages : 1 056
    Points : 1 216
    Points
    1 216
    Par défaut
    Non le curseur est sur une autre table. Ce sont des données que "j'exporte" de TABLE_0 vers TABLE_1
    Pourtant la déclaration du curseur indique TABLE_1, sans vouloir abuser .... Parfois il vaut mieux citer les noms de tables tels quels...

    me retourne toujours 0 dans la procédure
    je pensais que vous êtiez dans une procédure ...

    Bonne question, on va dire par défaut
    Le mode par défaut est readonly (jeu d'enregistrement en lecture seule)
    Mais si de toute façon le curseur parcourt une table autre que celle mise à jour le problème ne vient pas du curseur.
    Les curseurs ont parfois des comportements différents en fonction du mode d'ouverture, des index placés sur la table (PK, ...).
    Mais dans votre cas, ce n'est pas lié.

    Votre problème est étrange en effet, la condition étant ok. Si vous n'avez pas déja trouvé, peut-être pourriez-vous décrire les premiers tours de boucle avec un enregistrement d'exemple ....

  6. #6
    Rédacteur

    Avatar de SQLpro
    Homme Profil pro
    Expert bases de données / SQL / MS SQL Server / Postgresql
    Inscrit en
    Mai 2002
    Messages
    21 888
    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 888
    Points : 53 122
    Points
    53 122
    Billets dans le blog
    6
    Par défaut
    Cette conditon n'a aucun sens :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    IF (SELECT count(COL_2) FROM TABLE_1 WHERE COL_1 = @id AND COL_2 = @2) = 0
    						INSERT INTO TABLE_1 (COL_1, COL_2, COL_3) VALUES (@id, substring(@2,(@ideb+1),(@ifin-@ideb-1)), 19)
    					else
    						UPDATE TABLE_1 SET COL_3 = (COL_3*19) WHERE COL_1 = @id AND COL_2 = @2
    En effet une requête renvoie une table non une valeur !

    Il faut faire quelque chose comme :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    IF EXISTS (SELECT count(COL_2) 
               FROM   TABLE_1 
               WHERE  COL_1 = @id 
                 AND  COL_2 = @2
               HAVING count(COL_2) = 0)
       INSERT INTO TABLE_1 (COL_1, COL_2, COL_3) 
              VALUES (@id, substring(@2,(@ideb+1),(@ifin-@ideb-1)), 19)
    ELSE
       UPDATE TABLE_1 
       SET    COL_3 = (COL_3*19) 
       WHERE  COL_1 = @id 
         AND  COL_2 = @2;
    A +

  7. #7
    Membre émérite Avatar de franculo_caoulene
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    2 880
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 2 880
    Points : 2 953
    Points
    2 953
    Par défaut
    Et bien l'erreur était bel et bien dans ma condition. Je l'avais testé mais mal testé! Au lieu de récupérer réellement la requête exécutée, je remplacais bêtement ma variable à la main par la valeur qu'elle devait avoir.

    Merci à vous, merci à kagemaru qui en me demandant plus d'infos m'a forcé à plus me plonger dans le code et non plus d'être sûr de ce que j'avais.

    SQLpro : c'est vrai qu'une requête retourne une table et non une valeur. Après quelques mois sans coder j'avais oublié "exists". Mais la condition comme je l'ai affiché ici fonctionne aussi. Je ne connais pas le coeur de MSSQL pour l'expliquer mais ça fonctionne.

    Merci encore à vous deux pour vous être intéressé à mon problème.

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

Discussions similaires

  1. Réponses: 3
    Dernier message: 27/02/2015, 13h23
  2. Probleme avec les contraintes primary key et foreign key
    Par haylox dans le forum MS SQL Server
    Réponses: 4
    Dernier message: 17/04/2013, 14h23
  3. Lenteur lors de Violation de la contrainte UNIQUE KEY
    Par ludo00002 dans le forum Firebird
    Réponses: 5
    Dernier message: 23/05/2012, 23h12
  4. [AJAX] Violation Primary Keys
    Par ririch dans le forum AJAX
    Réponses: 27
    Dernier message: 18/05/2009, 09h21
  5. Réponses: 3
    Dernier message: 10/08/2007, 16h17

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