该查询如何违反主键?

时间:2016-05-18 06:39:34

标签: sql sql-server database

假设我有一个空的ProductLocalizations表,其中复合主键由ProductIdLanguageCode字段组成,我执行以下查询。

INSERT INTO dbo.ProductLocalizations (ProductId, LanguageCode, Name, Description) 
SELECT ProductId, LanguageCode1, Name1, Description1 FROM dbo.BulkProducts 
WHERE ProductId NOT IN (SELECT ProductId FROM dbo.ProductLocalizations) UNION 
SELECT ProductId, LanguageCode2, Name2, Description2 FROM dbo.BulkProducts
WHERE ProductId NOT IN (SELECT ProductId FROM dbo.ProductLocalizations) UNION 
SELECT ProductId, LanguageCode3, Name3, Description3 FROM dbo.BulkProducts
WHERE ProductId NOT IN (SELECT ProductId FROM dbo.ProductLocalizations) UNION 
SELECT ProductId, LanguageCode4, Name4, Description4 FROM dbo.BulkProducts
WHERE ProductId NOT IN (SELECT ProductId FROM dbo.ProductLocalizations) 

从我的(有限的)SQL知识,因为查询包含

WHERE ProductId NOT IN (SELECT ProductId FROM dbo.ProductLocalizations)

子句,不应该以任何方式插入重复(无效)记录。但是,执行此操作时,我会收到

  

Msg 2627,Level 14,State 1,Line 1违反PRIMARY KEY   约束' PK_dbo.ProductLocalizations'。无法插入重复键   在对象&#d ;.ProductLocalizations'。重复的键值是   (29977,de)。声明已经终止。

我错过了什么?

2 个答案:

答案 0 :(得分:5)

您的表格中有一个由StringProductId组成的复合主键。您需要修改LanguageCode子句以使用WHERE。此外,seeing as you're unpivoting the table, you may want to use CROSS APPLY to improve the speed

NOT EXISTS

如果您无法使用INSERT INTO dbo.ProductLocalizations (ProductId, LanguageCode, Name, Description) SELECT bp.ProductId, t.LanguageCode, t.Name, t.Description FROM dbo.BulkProducts bp CROSS APPLY( VALUES (LanguageCode1, Name1, Description1), (LanguageCode2, Name2, Description2), (LanguageCode3, Name3, Description3), (LanguageCode4, Name4, Description4) ) t(LanguageCode, Name, Description) WHERE NOT EXISTS( SELECT 1 FROM dbo.ProductLocalizations p WHERE p.ProductId = bp.ProductId AND p.LanguageCode = t.LanguageCode ) ,则此处是改进的CROSS APPLY版本:

UNION ALL

答案 1 :(得分:0)

SELECT ProductId, LanguageCode1, Name1, Description1 FROM dbo.BulkProducts 
WHERE ProductId NOT IN (SELECT ProductId FROM dbo.ProductLocalizations) UNION 
SELECT ProductId, LanguageCode2, Name2, Description2 FROM dbo.BulkProdu
WHERE ProductId NOT IN (SELECT ProductId FROM dbo.ProductLocalizations) UNION 
SELECT ProductId, LanguageCode3, Name3, Description3 FROM dbo.BulkProdu
WHERE ProductId NOT IN (SELECT ProductId FROM dbo.ProductLocalizations) UNION 
SELECT ProductId, LanguageCode4, Name4, Description4 FROM dbo.BulkProdu
WHERE ProductId NOT IN (SELECT ProductId FROM dbo.ProductLocalizations) 

您的选择查询返回productID和languagecode列的重复值