【发布时间】:2017-12-11 17:14:39
【问题描述】:
问题:哪些因素会导致以下问题?
我们有一个存储过程,用于更新或将价格记录插入表中。非常直截了当。但是,有时我们会在尝试插入已经存在的行时遇到主键冲突。如您所见,我们正在检查记录是否存在,然后酌情更新或插入。
这种情况很少发生,但上一次发生时,我们在 3 分钟的时间内发生了 18 次。我们更新的行数比 18 行多得多,所以不是每次都更新。这个 SP 经常被调用。我们检查了一下,当时没有进行索引维护。调用此 SP 的应用程序只是循环通过一个队列来更新/插入这些价格,并且只有一个应用程序实例在运行。
这是在具有 3 台服务器的 2016 可用性组上运行的。
ALTER PROCEDURE [dbo].[mw_UpdatePrice] @CustTypeID INT
,@ID INT
,@Price MONEY
,@OldPrice MONEY
,@ExpirationDate DATETIME
,@PriceStatusID INT
,@PriceStatusDesc VARCHAR(80)
,@FreeFreightShipviaServiceLevelID INT = NULL
,@FreeFreightShipViaServiceLevelDescription VARCHAR(150) = NULL
,@FreeFreightShipViaServiceLevelRank INT = NULL
AS
BEGIN
SET NOCOUNT ON;
IF EXISTS (
SELECT 1
FROM dbo.Price
WHERE ID = @ID
AND CustTypeID = @CustTypeID
)
BEGIN
UPDATE dbo.Price
SET Price = @Price
,OldPrice = @OldPrice
,ExpirationDate = @ExpirationDate
,PriceStatusID = @PriceStatusID
,PriceStatusDescription = @PriceStatusDesc
,ServiceLevelName = @FreeFreightShipViaServiceLevelDescription
,ServiceLevelId = @FreeFreightShipviaServiceLevelID
,ServiceLevelRank = @FreeFreightShipViaServiceLevelRank
WHERE ID = @ID
AND CustTypeID = @CustTypeID
END
ELSE
BEGIN
INSERT dbo.Price (
ID
,CustTypeID
,Price
,OldPrice
,ExpirationDate
,PriceStatusID
,PriceStatusDescription
,ServiceLevelName
,ServiceLevelID
,ServiceLevelRank
)
VALUES (
@ID
,@CustTypeID
,@Price
,@OldPrice
,@ExpirationDate
,@PriceStatusID
,@PriceStatusDesc
,@FreeFreightShipViaServiceLevelDescription
,@FreeFreightShipviaServiceLevelID
,@FreeFreightShipViaServiceLevelRank
)
END
END
【问题讨论】:
-
你的主键是什么?是
ID和CustTypeID的复合键吗?您可以将表格的 DDL 编辑到您的帖子中吗?如果它不是复合键,那就是你的问题;您正在检查特定ID和CustTypeID的条目是否存在,因此如果ID存在但对于不同的CustTypeID,您将获得违规。 -
首先你必须在一个事务中做这种工作。第二:这类问题最适合使用 MERGE 语句。在这里查看red-gate.com/simple-talk/sql/learn-sql-server/…
-
@Larnu 这就是PK。我仔细检查了。
-
@SteveB 是什么?就
ID? -
@MihailShishkov 这已经存在了一段时间,所以我不知道为什么它使用它的结构。我确实记得在奇怪的情况下 MERGE 存在一些问题,所以这可能就是原因。我打赌这笔交易可能会解决问题。遗憾的是我没有想到这一点。
标签: sql-server sql-server-2016