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

时间:2021-11-26 22:56:16

I'm trying to insert into a table that has unique constraint on (ProductType, ProductOwnerid) in a way that when that key already exists that the contraint violation would not be triggered. So I have this SQL that works as intended:

我正在尝试插入一个对(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)

Is this decent SQL or how could I improve this? I'm not a big fan of the TOP 1, how can I make this more readable/better performing?

这是不错的SQL还是我怎么能改进这个?我不是TOP 1的忠实粉丝,我怎样才能让它更具可读性/表现更好?

2 个解决方案

#1


1  

The MERGE statement is the SQL standard way to handle such cases.

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

A relational database management system uses SQL MERGE (also called upsert) statements to INSERT new records or UPDATE existing records depending on whether or not a condition matches. It was officially introduced in the SQL:2003 standard, and expanded in the SQL:2008 standard.

关系数据库管理系统使用SQL MERGE(也称为upsert)语句来INSERT新记录或UPDATE现有记录,具体取决于条件是否匹配。它在SQL:2003标准中正式引入,并在SQL:2008标准中进行了扩展。

It is a little bit more verbose than your solution but I find it more readable. Also, the intention of the code is very clear since the MERGE statement is specialized in dealing with this exact scenario.

它比你的解决方案更冗长,但我觉得它更具可读性。此外,代码的意图非常明确,因为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.* ;

#2


0  

In this query, distinct will also work in place of top 1

在此查询中,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)

#1


1  

The MERGE statement is the SQL standard way to handle such cases.

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

A relational database management system uses SQL MERGE (also called upsert) statements to INSERT new records or UPDATE existing records depending on whether or not a condition matches. It was officially introduced in the SQL:2003 standard, and expanded in the SQL:2008 standard.

关系数据库管理系统使用SQL MERGE(也称为upsert)语句来INSERT新记录或UPDATE现有记录,具体取决于条件是否匹配。它在SQL:2003标准中正式引入,并在SQL:2008标准中进行了扩展。

It is a little bit more verbose than your solution but I find it more readable. Also, the intention of the code is very clear since the MERGE statement is specialized in dealing with this exact scenario.

它比你的解决方案更冗长,但我觉得它更具可读性。此外,代码的意图非常明确,因为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.* ;

#2


0  

In this query, distinct will also work in place of top 1

在此查询中,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)