我想知道如何使用一个语句在SQL Server中使用UPSERT
或换句话说UPDATE if records exists Else enter new record
操作?
此示例显示了在Oracle Here中实现此目的的方法
但它使用了Dual
表,SQL Server
中没有。
那么,任何SQL Server替代(没有存储过程)请?
答案 0 :(得分:90)
很多人会建议你使用MERGE
,但我提醒你不要这样做。默认情况下,它不会保护您不受多个语句的并发和竞争条件的影响,但它确实会引入其他危险:
http://www.mssqltips.com/sqlservertip/3074/use-caution-with-sql-servers-merge-statement/
即使有这种“更简单”的语法,我仍然更喜欢这种方法(为简洁省略了错误处理):
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
UPDATE dbo.table SET ... WHERE PK = @PK;
IF @@ROWCOUNT = 0
BEGIN
INSERT dbo.table(PK, ...) SELECT @PK, ...;
END
COMMIT TRANSACTION;
很多人会这样建议:
SET TRANSACTION ISOLATION LEVEL SERIALIZABLE;
BEGIN TRANSACTION;
IF EXISTS (SELECT 1 FROM dbo.table WHERE PK = @PK)
BEGIN
UPDATE ...
END
ELSE
BEGIN
INSERT ...
END
COMMIT TRANSACTION;
但所有这一切都可以确保您可能需要两次读取表格以找到要更新的行。在第一个示例中,您只需要找到一次行。 (在这两种情况下,如果从初始读取中找不到行,则会发生插入。)
其他人会这样建议:
BEGIN TRY
INSERT ...
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 2627
UPDATE ...
END CATCH
但是,如果除了让几乎每个插入失败的罕见情况之外,除了让SQL Server捕获您可能首先阻止的异常之外没有其他原因,这是有问题的。我在这里证明了这一点:
通过单一陈述不确定您认为您获得了什么;我认为你没有任何收获。 MERGE
是一个单一的陈述,但它仍然必须真正执行多个操作 - 即使它让你认为它没有。