2015-05-18 166 views
0

上的唯一衝突我試圖插入到具有唯一約束(ProductType,ProductOwnerid)的表中,當該鍵已經存在時,將不會觸發違反違規行爲。所以我有這個SQL按預期工作:避免在插入SQL SERVER

INSERT INTO dbo.Products (ProductType, ProductOwnerId) 
SELECT TOP 1 22, 44 FROM dbo.products prods 
WHERE NOT EXISTS (
    SELECT prods2.ProductType FROM dbo.products prods2 
    WHERE prods2.ProductType = 22 AND prods2.ProductOwnerId = 44) 

這是不錯的SQL,或者我該如何改進?我不是TOP 1的忠實粉絲,我怎樣才能讓這個更具可讀性/更好的表現?

+0

工作僅用於演示22和44或者在查詢中始終是這兩個人?否則這沒有任何意義。 –

+0

爲什麼你想要一個永遠不會開火的約束。然後刪除它。 –

+1

改爲使用MERGE。 – dnoeth

回答

1

MERGE語句是處理這種情況的SQL標準方法。

關係數據庫管理系統採用SQL MERGE(也稱爲 UPSERT)語句來插入新記錄或更新現有記錄 取決於條件是否匹配與否。它是在SQL:2003標準中引入的正式 ,並在SQL:2008 標準中進行了擴展。

這比你的解決方案稍微冗長些,但我覺得它更具可讀性。此外,代碼的意圖非常明確,因爲MERGE聲明專門處理這種確切的情況。

CREATE TABLE products (
    ProductId INT IDENTITY(1, 1), 
    ProductType int, ProductOwnerId INT, 

    CONSTRAINT [unq_type_owner] UNIQUE (ProductType, ProductOwnerId) 
); 

MERGE INTO dbo.products p 
USING (VALUES (22, 44)) AS source(ProductType, ProductOwnerId) 
ON p.ProductType = source.ProductType AND p.ProductOwnerId = source.ProductOwnerId 

WHEN NOT MATCHED THEN 
    INSERT (ProductType, ProductOwnerId) 
    VALUES (source.ProductType, source.ProductOwnerId) 

-- OPTIONAL OUTPUT 
OUTPUT $action, Inserted.* ; 
0

在此查詢中,不同的也將代替前1

INSERT INTO dbo.Products (ProductType, ProductOwnerId) 
    SELECT DISTINCT 22, 44 
    FROM dbo.products prods 
    WHERE NOT EXISTS (SELECT prods2.ProductType 
         FROM dbo.products prods2 
         WHERE prods2.ProductType = 22 AND prods2.ProductOwnerId = 44)