Sql server 合并插入/更新是否防止PK冲突和死锁?
目前,我在一个表中有一个处理插入和更新事务的存储过程。我仍在测试这个解决方案是否存在任何潜在问题,以及如何改进流程。此SP接受少量参数,然后检查匹配的ID和预执行项插入或更新。我读过这篇关于Sql server 合并插入/更新是否防止PK冲突和死锁?,sql-server,sql-server-2008,stored-procedures,merge,sql-merge,Sql Server,Sql Server 2008,Stored Procedures,Merge,Sql Merge,目前,我在一个表中有一个处理插入和更新事务的存储过程。我仍在测试这个解决方案是否存在任何潜在问题,以及如何改进流程。此SP接受少量参数,然后检查匹配的ID和预执行项插入或更新。我读过这篇关于主键冲突错误的文章,它表明MERGE容易受到并发问题的影响,比如多语句条件插入/更新。似乎他们已经用和(HOLDLOCK)解决了一些问题。我是存储过程和合并领域的新手。我想在这里谈谈你的意见,如果这是可靠的应用程序代码与高交易?我可能有多个用户在同一个表中插入或同时运行Update语句。在这种情况下,参数嗅探
主键冲突错误的文章,它表明MERGE容易受到并发问题的影响,比如多语句条件插入/更新。似乎他们已经用和(HOLDLOCK)
解决了一些问题。我是存储过程和合并领域的新手。我想在这里谈谈你的意见,如果这是可靠的应用程序代码与高交易?我可能有多个用户在同一个表中插入或同时运行Update语句。在这种情况下,参数嗅探是否存在任何潜在问题?如果我应该考虑使用<代码>选项(重新编译)< /> >,或者只适用于选择搜索查询?下面是我的SQL代码示例:
USE [TestDB]
GO
/****** Object: StoredProcedure [dbo].[SaveMaster] Script Date: 08/21/2018 10:05:21 ******/
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
-- =============================================
-- Author: M, D
-- Create date: 08/21/2018
-- Description: Insert/Update Master table
-- =============================================
ALTER PROCEDURE [dbo].[SaveMaster]
@RecordID INT = NULL,
@Status BIT = NULL,
@Name VARCHAR(50) = NULL,
@Code CHAR(2) = NULL,
@ActionDt DATETIME = NULL,
@ActionID UNIQUEIDENTIFIER = NULL
AS
MERGE dbo.Master WITH (HOLDLOCK) AS Target
USING (SELECT @RecordID,@Status,@Name,@Code,@ActionDt,@ActionID)
AS Source (RecordID,Status,Name,Code,ActionDt,ActionID)
ON Target.RecID = Source.RecordID
WHEN MATCHED THEN
UPDATE
SET Target.Status = Source.Status,
Target.Name = Source.Name,
Target.Code = Source.Code,
Target.ActionDt = Source.ActionDt,
Target.ActionID = Source.ActionID
WHEN NOT MATCHED THEN
INSERT(
Status,Name,Code,ActionDt,ActionID
)VALUES(
Source.Status,
Source.Name,
Source.Code,
Source.ActionDt,
Source.ActionID
);
RETURN @@ERROR;
下面是我如何使用服务器端语言(ColdFusion 2016)调用存储过程的示例:
正如您所看到的,我希望存储过程返回应该返回的RecID
(与我在存储过程中为现有记录传递的ID相同,或者如果不存在,则将生成并返回InsertSELECT SCOPE\u IDENTITY()的ID作为RecID;
或像这样更新选择@RecordID作为RecID
)。如果有人有任何建议,并且知道从运行Insert/Update with Merge的SP返回RecID的最佳方法,请告诉我
如果有人有任何建议,并且知道从运行Insert/Update with Merge的SP返回RecID的最佳方法,请告诉我
您可以在MERGE
语句中添加一个。这将允许您返回一个包含新ID的结果集,如果您愿意,还可以返回它选择的操作:
MERGE dbo.Master WITH (HOLDLOCK) AS Target
USING (SELECT @RecordID,@Status,@Name,@Code,@ActionDt,@ActionID)
AS Source (RecordID,Status,Name,Code,ActionDt,ActionID)
ON Target.RecID = Source.RecordID
WHEN MATCHED THEN
UPDATE
SET Target.Status = Source.Status,
Target.Name = Source.Name,
Target.Code = Source.Code,
Target.ActionDt = Source.ActionDt,
Target.ActionID = Source.ActionID
WHEN NOT MATCHED THEN
INSERT(
Status,Name,Code,ActionDt,ActionID
)VALUES(
Source.Status,
Source.Name,
Source.Code,
Source.ActionDt,
Source.ActionID
)
OUTPUT inserted.RedIC,$action as Action;
我假设coldfusion能够使用这个结果集。如果没有,请切换到OUTPUT
变量,该变量将填充一个表变量(OUTPUT…INTO
),并使用该变量设置添加到过程中的OUTPUT
参数。我已经测试过,并且OUTPUT
执行了返回RecID
和操作的技巧。你对这个过程有什么想法吗?此交易方法是否有任何缺点?谢谢。我发现顶部的叙述有点难以分清,所以我看不出是否有问题(如果有,你能更清楚地把事情分成几段,清楚地说明你在问什么)。我已经解决了你在底部的问题。如果顶部实际上是一个问题,与底部的问题无关,我建议将其分为两个问题。(请将这一部分作为底部,因为我已经回答了)
MERGE dbo.Master WITH (HOLDLOCK) AS Target
USING (SELECT @RecordID,@Status,@Name,@Code,@ActionDt,@ActionID)
AS Source (RecordID,Status,Name,Code,ActionDt,ActionID)
ON Target.RecID = Source.RecordID
WHEN MATCHED THEN
UPDATE
SET Target.Status = Source.Status,
Target.Name = Source.Name,
Target.Code = Source.Code,
Target.ActionDt = Source.ActionDt,
Target.ActionID = Source.ActionID
WHEN NOT MATCHED THEN
INSERT(
Status,Name,Code,ActionDt,ActionID
)VALUES(
Source.Status,
Source.Name,
Source.Code,
Source.ActionDt,
Source.ActionID
)
OUTPUT inserted.RedIC,$action as Action;