編集: MSSQL2005以降の方がはるかに優れているDavidTMacknetの回答を参照してください。ただし、この手法は、他のDBMSまたは以前のバージョンのSQLサーバーでも役立つ場合があります。
2番目のテーブルを使用してこれを実行し、テーブルがロックされているかどうかの事実を保持できます。
create table Notifications_Lock(
ix int primary key,
fLocked bit,
constraint Notifications_Lock_SingleRow check (ix = 1)
)
insert Notifications_Lock values( 1, 0, null)
go
create proc NotificationsLockTry
as
begin
update Notifications_Lock set fLocked = 1
from Notifications_Lock with (TABLOCKX)
where fLocked = 0
return @@rowcount
end
go
create proc NotificationsLockTimeout( @waitSeconds int)
as
begin
set @waitSeconds = isnull(@waitSeconds, 0)
declare @dtWaitTill datetime
set @dtWaitTill = dateadd(second, @waitSeconds, getutcdate())
declare @fLocked int
update Notifications_Lock set fLocked = 1
from Notifications_Lock with (TABLOCKX)
where fLocked = 0
set @fLocked = @@rowcount
if @fLocked > 0 return @fLocked
while @fLocked = 0 And @dtWaitTill > getutcdate()
begin
waitfor delay '00:00:01'
update Notifications_Lock set fLocked = 1
from Notifications_Lock with (TABLOCKX)
where fLocked = 0
set @fLocked = @@rowcount
if @fLocked > 0 return @fLocked
end
return @fLocked
end
go
create proc NotificationsUnlock
as
begin
update Notifications_Lock set fLocked = 0, dtLocked = null
from Notifications_Lock with (TABLOCKX)
where fLocked = 1
return @@rowcount
end
使用例:
declare @fLocked int
-- Wait up to 5 minutes for a lock
exec @fLocked = NotificationsLockTry 300
if @fLocked = 0
begin
raiserror('Unable to lock notifications table', 11,11)
return
end
-- Locked OK
-- INSERT NOTIFICATIONS HERE
-- CALL Send.cmd HERE
exec NotificationsUnlock
return
この方法を使用している場合、ジョブが終了または中断された場合は、通知テーブルのロックを手動で解除する必要がある場合があることに注意してください。
ロックされた日付をテーブルに追加してタイムアウトを追加することもできます。これを定期的に確認し、過去に遠すぎる場合は、ロックを解除するだけです。