我想知道如何使用一条语句在SQL Server中使用UPSERT
或换句话说UPDATE if records exists Else enter new record
操作?
此示例显示了在Oracle Here中实现此目标的方法但它使用了CCD_ 3表,而CCD_。
那么,是否有SQL Server替代方案(无存储过程)?
很多人会建议你使用MERGE
,但我提醒你不要使用它。默认情况下,它不会像多个语句那样保护你免受并发和竞争条件的影响,但它确实会引入其他危险:
- 对SQL Server的MERGE语句使用"小心">
- 如果你想使用MERGE,应该避免什么
- SQL Server UPSERT模式和反模式
即使有了这个";"更简单";语法可用,我仍然更喜欢这种方法(为了简洁起见,省略了错误处理):
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;
关于UPSERT
方法的更多信息,请点击此处:
- 请停止使用此UPSERT反模式
很多人会这样建议:
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捕获您本来可以阻止的异常要昂贵得多之外,这是有问题的,除非在几乎每个插入都失败的罕见情况下。我在这里证明了这一点:
- 在输入TRY/CATCH之前检查潜在的约束冲突
- 不同错误处理技术对性能的影响
不确定你认为自己通过一句话得到了什么;我认为你没有任何收获。MERGE
是一个单独的语句,但无论如何,它仍然必须执行多个操作——即使它让你认为它不是。