SQL Server 如何编写防死锁的upsert T-SQL?[已关闭]

anauzrmj  于 2023-01-20  发布在  其他
关注(0)|答案(1)|浏览(146)
    • 已关闭**。此问题为opinion-based。当前不接受答案。
    • 想要改进此问题吗?**请更新此问题,以便editing this post可以用事实和引文来回答。

昨天关门了。
这篇文章是昨天编辑并提交审查的。
Improve this question
对于针对数据库执行标准CRUD操作的Web API:
对于DML CUD操作,我可以在端点看到两种策略:
策略一:CUD SP接受表键的参数,首先调用读SP以确定相关记录是否存在;如果没有找到,则返回401;如果找到,则继续SP插入、更新、删除、传递相关密钥。
示例:为客户添加新自动的端点。自动表具有FK到客户表的PK。首先调用自动读取SP(名字、姓氏、电话等)。如果没有找到行,则返回401+自定义消息。如果找到行,则调用自动更新SP,传递客户键。
策略二:CUD SP接受属性参数和到其他表的SQL连接(如果相关)。
示例:相同端点。使用参数auto make、model、year + customer name、phone对自动插入SP进行单次调用。如果失败,则返回500 + SQL错误消息。
策略一的优势:为最终用户提供更好的体验(自定义友好的错误消息),并且如果由于所需记录不存在而预先确定失败,则从不尝试调用CUD操作。
策略2的优势:每次调用web端点时对数据库的调用更少。这通常有多重要?是否有其他优点?
编辑:我正在尝试Aaron Bertrands upsert,并尝试检索插入的新行的标识,但始终为零:

BEGIN TRAN

INSERT [dbo].[Auto]
([Make],[Model],[Year],[Customer]) 
SELECT @make, @model, @year, @customerId
WHERE NOT EXISTS
(SELECT 1 
FROM [dbo].[Auto] WITH (UPDLOCK, SERIALIZABLE)
WHERE [Make] = @make
AND [Model] = @model
AND [Year] = @year
AND [Customer] = customerId)

IF @@ROWCOUNT = 0
BEGIN
  UPDATE [dbo].[Auto] 
  SET [Make] = @make
     ,[Model] = @model
     ,[Year] = @year
     ,[Customer] = @customerId
WHERE [Make] = @make
AND [Model] = @model
AND [Year] = @year
AND [Customer] = @customerId)
END

SET @id = SCOPE_IDENTITY()

COMMIT
hmmo2u0o

hmmo2u0o1#

如果不是因为策略1绝对没有好处,这个问题将是基于观点的。
不需要多次调用就可以得到友好的错误消息。只需调用存储过程(或临时SQL批处理)。如果失败,则捕获异常并发送适当且有用的HTTP响应。
如果需要额外的逻辑,请将其放在存储过程的 * 内部 *。

相关问题