У меня есть простая таблица в Sybase, скажем, она выглядит следующим образом:
CREATE TABLE T
(
name VARCHAR(10),
entry_date datetime,
in_use CHAR(1)
)
Я хочу получить следующую запись в порядке «entry_date» и немедленно обновить «in_use» до «Y», чтобы указать, что запись недоступна для следующего входящего запроса. Кикер в том, что если два выполнения пути пытаются выполнить запрос одновременно, я хочу, чтобы второй блок заблокировал, чтобы он не захватывал одну и ту же запись.
Проблема в том, что я обнаружил, что вы не можете выполнить «SELECT FOR UPDATE» в Sybase, если у вас есть предложение ORDER BY, поэтому следующий сохраненный процесс не может быть создан из-за следующей ошибки из-за предложения ORDER BY в select - "FOR UPDATE" неправильно указан при использовании курсора READ ONLY.
Есть ли лучший способ получить следующую запись, заблокировать ее и обновить все за один атомный шаг?
CREATE PROCEDURE dbo.sp_getnextrecord
@out1 varchar(10) out,
@out2 datetime out
AS
DECLARE @outOne varchar(10), @outTwo datetime
BEGIN TRANSACTION
-- Here is the problem area Sybase does not like the
-- combination of 'ORDER BY' and 'FOR UPDATE'
DECLARE myCursor CURSOR FOR
SELECT TOP 1 name, entry_date FROM T
WHERE in_use = 'N'
ORDER BY entry_Date asc FOR UPDATE OF in_use
OPEN myCursor
FETCH NEXT FROM myCursor
INTO @outOne, @outOne
-- Check @@FETCH_STATUS to see if there are any more rows to fetch.
WHILE @@FETCH_STATUS = 0
BEGIN
UPDATE t SET IN_USE = 'Y' WHERE
name = @outOne AND entry_date = @outTwo
SELECT @out1 = @outOne
SELECT @out2 = @outTwo
-- This is executed as long as the previous fetch succeeds.
FETCH NEXT FROM myCursor
INTO @outOne, @outTwo
END
CLOSE myCursor
DEALLOCATE myCursor
COMMIT TRANSACTION