Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sql-server/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Sql server 合并插入/更新是否防止PK冲突和死锁?_Sql Server_Sql Server 2008_Stored Procedures_Merge_Sql Merge - Fatal编程技术网

Sql server 合并插入/更新是否防止PK冲突和死锁?

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语句。在这种情况下,参数嗅探

目前,我在一个表中有一个处理插入和更新事务的存储过程。我仍在测试这个解决方案是否存在任何潜在问题,以及如何改进流程。此SP接受少量参数,然后检查匹配的ID和预执行项插入或更新。我读过这篇关于
主键冲突错误的文章,它表明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相同,或者如果不存在,则将生成并返回Insert
SELECT 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;