Блокировка строки для чтения на SQL Server? - PullRequest
1 голос
/ 07 марта 2011

В кусочке SQL down я хотел бы получить и удалить следующую строку таблицы, соответствующую определенным критериям.Однако я хочу запретить другим службам, выполняющим тот же бит 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

Ответы [ 2 ]

2 голосов
/ 07 марта 2011

В этом случае вам может быть лучше выполнить удаление напрямую и использовать предложение OUTPUT для заполнения таблицы.Это должно автоматически управлять замками.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
2 голосов
/ 07 марта 2011

Вы можете использовать ROWLOCK, UPDLOCK, READPAST, чтобы использовать таблицу в качестве очереди (что вы и делаете)

Состояние гонки очереди процесса SQL Server

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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...