避免插入SQL SERVER上的唯一冲突

时间:2015-05-18 10:05:03

标签: sql sql-server performance database-performance

我试图插入一个对(ProductType,ProductOwnerid)具有唯一约束的表,其方式是当该键已存在时,不会触发约束违规。所以我有这个按预期工作的SQL:

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的忠实粉丝,我怎样才能让它更具可读性/更好的表现呢?

2 个答案:

答案 0 :(得分:1)

MERGE语句是处理此类情况的SQL标准方法。

  

关系数据库管理系统使用SQL MERGE(也称为   upsert)语句来INSERT新记录或UPDATE现有记录   取决于条件是否匹配。这是正式的   在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.* ;

答案 1 :(得分:0)

在此查询中,distinct也可以代替top 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)