2010-08-24 2 views
0

Je suis en train de développer une requête pour renvoyer seulement les enregistrements non-double pour que je puisse ajouter à ma base de données, mais je continue à obtenir cette erreur:Comment formuler T-SQL pour éviter une contrainte de clé primaire?

Msg 2627, Level 14, State 1, Line 1
Violation of PRIMARY KEY constraint 'PK_j5c_MasterMeasures'.
Cannot insert duplicate key in object 'dbo.j5c_MasterMeasures'.
The statement has been terminated.

Et voici ma dernière question que je utilise:

CREATE TABLE #GOOD_RECORDS3 (STUDENTID VARCHAR(50), MEASUREDATE SMALLDATETIME, 
measurename VARCHAR(100), LabelName VARCHAR(100), score_10 VARCHAR(100)) 
INSERT INTO #GOOD_RECORDS3 
select A.studentid, A.measuredate, B.measurename, B.LabelName, A.score_10 
from [J5C_Measures_Sys] A join [J5C_ListBoxMeasures_Sys] B on 
A.MeasureID = B.MeasureID 
where score_10 is not null and score_10 <> '0' 
except 
select A.studentid, A.measuredate, B.measurename, B.LabelName, A.score_10 
from [J5C_Measures_Sys] A join [J5C_ListBoxMeasures_Sys] B on 
A.MeasureID = B.MeasureID 
where score_10 is not null and score_10 <> '0' 
GROUP BY A.studentid, A.measuredate, B.measurename, B.LabelName, A.score_10 
having COUNT(A.score_10) > 1 

delete #GOOD_RECORDS3 
from #GOOD_RECORDS3 a 
join sysobjects so on so.name = 'J5C_Measures_Sys' AND so.type = 'u' 
join syscolumns sc on so.id = sc.id and sc.name = 'score_10' 
join [J5C_MeasureNamesV2_Sys] v on v.Score_field_id = sc.name 
WHERE A.SCORE_10 IS NOT NULL AND A.STUDENTID IS NOT NULL AND 
A.MEASUREID IS NOT NULL 
and exists (select 1 from J5C_MasterMeasures M 
where M.StudentID = A.StudentID 
and M.MeasureID = A.MeasureID) 

Insert into J5C_MasterMeasures (studentid, measuredate, measureid, nce) 
select A.studentid, A.measuredate, a.MEASUREID, A.score_10 
from #GOOD_RECORDS3 a 
join sysobjects so on so.name = 'J5C_Measures_Sys' AND so.type = 'u' 
join syscolumns sc on so.id = sc.id and sc.name = 'score_10' 
join [J5C_MeasureNamesV2_Sys] v on v.Score_field_id = sc.name 
WHERE A.SCORE_10 IS NOT NULL AND A.STUDENTID IS NOT NULL AND 
A.MEASUREID IS NOT NULL 

La partie source de confusion à ce sujet est que MeasureId de M5C_Measures_Sys = B.measurename + ' ' + B.Labelname. Ceci est quelques exemples de données de #GOOD_RECORDS3:

1 2006-03-01 00:00:00 ISAT Reading ISAT Reading 564 
10005 2003-11-17 00:00:00 TerraNova Reading TerraNova Reading  19 
10005 2003-11-17 00:00:00 TerraNova Science TerraNova Science  26 
10005 2003-11-17 00:00:00 TerraNova Total Battery TerraNova Total Battery  22 
10005 2003-11-17 00:00:00 TerraNova Total Language TerraNova Total Language 43 

vous pouvez donc voir que b.measurename = b.labelname. L'erreur ci-dessus se produit sur l'insertion.

Résultat de votre recherche de réponse ci-dessous:

1 2006-03-01 00:00:00 ISAT Reading ISAT Reading 564 
10005 2003-11-17 00:00:00 TerraNova Reading TerraNova Reading 19 
10005 2003-11-17 00:00:00 TerraNova Science TerraNova Science 26 
10005 2003-11-17 00:00:00 TerraNova Total Battery TerraNova Total Battery  22 
10005 2003-11-17 00:00:00 TerraNova Total Language TerraNova Total Language 43 
+0

Un peu confus Quelle est la clé primaire? – u07ch

+0

sont les enregistrements exactes en double ou est-ce juste les valeurs dans le champ PK qui sont similaires – zeocrash

Répondre

0

Un peu sur le sujet ...

Au lieu d'utiliser CREATE TABLE #GOOD_RECORDS3 vous pouvez faire DECLARE @Good_Records3 TABLE (FieldDefinition...).

Si le primarykey est sur la colonne measureid alors vous avez encore des ID dupliqués retournés à partir de la requête.

Qu'est-ce que la requête

select A.studentid, A.measuredate, a.MEASUREID, A.score_10 
from #GOOD_RECORDS3 a 
join sysobjects so on so.name = 'J5C_Measures_Sys' AND so.type = 'u' 
join syscolumns sc on so.id = sc.id and sc.name = 'score_10' 
join [J5C_MeasureNamesV2_Sys] v on v.Score_field_id = sc.name 
WHERE A.SCORE_10 IS NOT NULL AND A.STUDENTID IS NOT NULL AND A.MEASUREID IS NOT NULL 

retour? Aucun doublon MEASUREID-values?

+0

Désolé, vous pouvez regarder ma requête mise à jour s'il vous plaît? Maintenant, ma table # GOOD_RECORDS3 a des colonnes measurename et labelname à la place de measureID – salvationishere

+0

Je viens d'ajouter la sortie de votre requête à ma description à la fin. – salvationishere

+0

Hmm. Etes-vous sûr que la table J5C_MasterMeasures est vide avant d'y insérer les enregistrements? –

0

Je considère que le problème survient lors de l'insertion dans la table J5C_MasterMeasures des enregistrements récupérés dans la table # GOOD_RECORDS3. S'il vous plaît assurez-vous que J5C_MasterMeasures PRIMARY KEY est. Ensuite, imprimez les enregistrements # GOOD_RECORDS3 pour rechercher d'éventuels doublons susceptibles de violer la contrainte de clé primaire J5C_MasterMeasures.

Espoir qui aide,

+0

en quelque sorte mais pouvez-vous recommander la syntaxe pour cela? PK = StudentID, MeasureDate, (MeasureName + '' + LabelName) – salvationishere

0

d'abord déclarer une table pour stocker les détails en double dans

declare @dupetable table(did int, dcount int) 

ensuite déclarer deux variables, l'un pour stocker le nombre total d'enregistrements avec doublons et un comme un compteur de boucle:

declare @dupecount int, @loopcounter int 

remplir ensuite la table en double avec une liste d'enregistrements qui ont des doublons et le nombre de doublons chacun a:

insert into @dupetable --Populate duplicate table 
(did, dcount) 
select id, COUNT(*) 
from #GOOD_RECORDS3 
group by id     --Replace ID with whatever the primary key is 
having COUNT(*) > 1 

Ensuite, obtenir le nombre total d'enregistrements avec doublons:

select @dupecount = COUNT(*)  
from @dupetable 

initialize le compteur de boucle:

set @loopcounter = 0 

Le code devrait ensuite en boucle à travers la table des doublons, la sélection l'enregistrement supérieur, en supprimant toutes les entrées en double pour lui puis en le supprimant du fichier temporaire @dupetable:

while @loopcounter < @dupecount --Loop through duplicate records 
begin 
select * from @dupetable 
set @loopcounter = @loopcounter + 1 --Increase the counter by 1 
Declare @ldid int, @ldcount int   --Declare variables for storing the duplicate id and the number of dupes 
select top 1 @ldid = did, @ldcount = dcount --Populate those variables 
from @dupetable 
delete from @dupetable  --Remove record from dupe table 
where did = @ldid 
declare @rcval int  --Declare variable for setting rowcount 
set @rcval = @ldcount - 1 --Set the rowcount val to the number of duplicate rows -1 
set rowcount @rcval  --Set the rowcount val to the number of duplicate rows -1 
delete from @testtbl  --Delete the duplicate records from the table 
where id = @ldid 
end  --End loop 

Ce n'est pas trop élégant, mais je crois que cela fonctionne.

+0

grands commentaires, cependant, tous mes champs dans @dupetable sont varchars donc je ne peux pas convertir d'erreur de chaîne. Et mon ID est un PK composite de 3 colonnes. Et cette identification ne ressemble pas toujours à un nombre. La plupart des entrées sont des chaînes comme '2009456', mais quelques-unes sont comme 'L' – salvationishere

+0

vous devrez déclarer @ldid comme un varchar puis au lieu d'un int. Le type de données de votre PK ne devrait pas avoir d'importance, ce script trouve les enregistrements qui ont des valeurs PK correspondantes et supprime tout sauf 1. Vous avez juste besoin de changer les types de données de @dupetable et @ldid en conséquence – zeocrash

+0

pourquoi cela a-t-il juste obtenu un downvote? ? – zeocrash

Questions connexes