Mav*_*ven 39 sql sql-server sql-server-2008
我想知道如何使用一个语句在SQL Server中使用UPSERT
或换句话说UPDATE if records exists Else enter new record
操作?
这个例子显示了在Oracle中实现这一目标的方式在这里
,但它使用Dual
表,它这不存在SQL Server
.
那么,任何SQL Server替代品(没有存储过程)好吗?
Aar*_*and 91
很多人会建议你使用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;
Run Code Online (Sandbox Code Playgroud)
很多人会这样建议:
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;
Run Code Online (Sandbox Code Playgroud)
但所有这一切都可以确保您可能需要两次读取表以找到要更新的行.在第一个示例中,您只需要找到一次行.(在这两种情况下,如果从初始读取中找不到行,则会发生插入.)
其他人会建议这样:
BEGIN TRY
INSERT ...
END TRY
BEGIN CATCH
IF ERROR_NUMBER() = 2627
UPDATE ...
END CATCH
Run Code Online (Sandbox Code Playgroud)
但是,如果除了在几乎每个插入失败的罕见情况下,除了让SQL Server捕获您可能首先阻止的异常之外没有其他原因,这是有问题的.我在这里证明了这一点:
通过单一陈述不确定您认为您获得了什么; 我认为你没有任何收获.MERGE
是一个单一的声明,但它仍然必须真正执行多个操作 - 即使它让你认为它没有.
归档时间: |
|
查看次数: |
217277 次 |
最近记录: |