在SQL中,我希望得到并删除符合特定条件的表的下一行。但是,我想阻止执行相同SQL的其他服务返回同一行。我在考虑交易或行锁,但看不出任何人会帮助我。
DECLARE @tblTempRow TABLE(intUserID int, intBlobID int)
-- Get the next match and remember in temp table. I want to prevent that other processes return the same row.
INSERT INTO @tblTempRow(intUserID, intBlobID)
SELECT TOP 1 intUserID, intBlobID FROM Schedule WHERE intScheduleType = @intScheduleType
-- Delete if requested.
IF(@intDeleteAfterGet = 1)
BEGIN
DELETE FROM
Schedule
WHERE
intUserID = (SELECT intUserID FROM @tblTempRow)
AND intBlobID = (SELECT intBlobID FROM @tblTempRow)
AND intScheduleType = @intScheduleType
END
-- Return the temp table.
SELECT intUserID, @intScheduleType, intBlobID FROM @tblTempRow
答案 0 :(得分:2)
您可以使用ROWLOCK,UPDLOCK,READPAST将表用作队列(这就是您正在做的事情)
SQL Server Process Queue Race Condition
DECLARE @tblTempRow TABLE(intUserID int, intBlobID int)
--no rollback needed now. will automatically roll back
SET XACT_ABORT ON
-- to span select and delete
BEGIN TRANSACTION
-- Get the next match and remember in temp table. I want to prevent that other processes return the same row.
INSERT INTO @tblTempRow(intUserID, intBlobID)
SELECT TOP 1 intUserID, intBlobID
--for hints, see link above
FROM Schedule WITH (ROWLOCK, READPAST, UPDLOCK)
WHERE intScheduleType = @intScheduleType
-- Delete if requested.
IF(@intDeleteAfterGet = 1)
BEGIN
DELETE
Schedule S
WHERE --yes, more elegant
EXISTS (SELECT * FROM
@tblTempRow T
WHERE
S.intUserID = T.intUserID AND
S.intBlobID = T.intBlobID)
AND
S.intScheduleType = @intScheduleType
END
COMMIT TRANSACTION
-- Return the temp table.
SELECT intUserID, @intScheduleType, intBlobID FROM @tblTempRow
答案 1 :(得分:2)
在这种情况下,您可以更好地直接发出删除,并使用OUTPUT clause填充表格。那应该自动为你管理锁。 TODO:处理没有匹配的行,但你已经遇到了这个问题。
DECLARE @tblTempRow TABLE(intUserID int, intBlobID int)
IF(@intDeleteAfterGet = 1)
begin
DELETE TOP 1 FROM Schedule WITH (READPAST) WHERE intScheduleType = @intScheduleType
OUTPUT deleted.intUserID,deleted.intBlobID INTO @tblTempRow
end
else
begin
INSERT INTO @tblTempRow(intUserID, intBlobID)
SELECT TOP 1 intUserID, intBlobID FROM Schedule WHERE intScheduleType = @intScheduleType
end
-- Return the temp table.
SELECT intUserID, @intScheduleType, intBlobID FROM @tblTempRow