2010-08-24 51 views
0

我試圖建立一個查詢只返回非重複記錄,這樣我可以把它們添加到我的數據庫,但我不斷收到此錯誤:如何制定T-SQL以避免主鍵約束?

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.

這是我用我的最新查詢:

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 

關於這個混淆的部分是從M5C_Measures_Sys = B.measurename + ' ' + B.Labelname該MeasureId。這是一些示例數據從#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 

所以你可以看到,b.measurename = b.labelname。上面的錯誤發生在插入。

結果低於你的答案查詢:

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

有點困惑什麼是主鍵? – u07ch 2010-08-24 15:32:37

+0

是記錄確切的重複,或者它只是在PK領域的價值是相似的 – zeocrash 2010-08-24 15:33:25

回答

0

出題目有點...

而不是使用CREATE TABLE #GOOD_RECORDS3你可以做DECLARE @Good_Records3 TABLE (FieldDefinition...).

如果PrimaryKey的是在列measureid那麼你仍然重複從查詢中返回的id。

什麼查詢

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 

回報?沒有重複MEASUREID-values

+0

對不起,你可以看看我更新的查詢嗎?現在我的#GOOD_RECORDS3表的measurename和labelname列代替了measureID – salvationishere 2010-08-24 15:32:56

+0

我剛剛在最後將查詢的輸出添加到我的描述中。 – salvationishere 2010-08-24 15:37:14

+0

嗯。在將記錄插入到表之前,您確定表J5C_MasterMeasures爲空嗎? – 2010-08-24 15:51:36

0

我認爲插入到J5C_MasterMeasures表時將記錄提取到#GOOD_RECORDS3表中。請確定J5C_MasterMeasures PRIMARY KEY是什麼。然後打印#GOOD_RECORDS3記錄以查找可能違反J5C_MasterMeasures主鍵約束的重複項。

希望幫助,

+0

有點類似,但你能推薦這個語法嗎? PK = StudentID,MeasureDate,(MeasureName +''+ LabelName) – salvationishere 2010-08-24 15:39:33

0

首先聲明一個表中

declare @dupetable table(did int, dcount int) 

存儲重複細節然後聲明兩個變量,一個用於存儲記錄有重複的總數,一個作爲循環計數器:

declare @dupecount int, @loopcounter int 

然後用有重複記錄的列表,而且每一個都有重複的次數填充重複表:

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 

接下來,得到的記錄有重複總數:

select @dupecount = COUNT(*)  
from @dupetable 

然後初始化循環計數器:

set @loopcounter = 0 

代碼應該然後通過重複的表圈,選擇頂部記錄,刪除所有重複條目,然後從臨時文件刪除它@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 

這不是太優雅,但我相信它的工作原理。

+0

很棒的評論,但是,@dupetable中的所有字段都是varchars,所以我得到不能從字符串錯誤轉換。而我的身份證是3列的複合PK。這個ID並不總是看起來像一個數字。大多數條目都是字符串'2009456',但有一些像'L' – salvationishere 2010-08-24 18:57:56

+0

您需要將@ldid聲明爲varchar,而不是int。 您的PK的數據類型應該沒關係,該腳本查找具有匹配的PK值並刪除除1以外的所有記錄。您只需要相應地更改@dupetable和@ldid的數據類型 – zeocrash 2010-09-02 10:20:21

+0

爲什麼這只是得到一個downvote? ? – zeocrash 2012-03-13 11:44:57