とにかくSET LOCK_TIMEOUT
でストアドプロシージャを明示的に実行する方法はありますか?
例えば。 dbo.LoadData
というsprocがあります。テーブルdbo.Abc
からデータを取得し、テーブルdbo.Xyz
に挿入するだけです。
ここで、sproc dbo.LoadData
を実行したいのですが、テーブルdbo.Abc
がlocked
の場合、 10秒を超える場合は、ストアドプロシージャの実行を停止します。
オプションSET LOCK_TIMEOUT
はsproc dbo.LoadData
自体に実装できることは知っていますが、明示的に呼び出す方法があるかどうか(=ストアドプロシージャ自体にオプションを実装していない)。
LOCK_TIMEOUT
は、セッションレベルの設定であるだけでなく、別のバッチで設定する必要もあります。ただし、変数を介して設定することはできません。したがって、これは、「マスター」ストアドプロシージャで動的SQLを使用することで実現できます。これにより、LOCK_TIMEOUT
次に、この特定の設定内で実行する必要がある他のストアドプロシージャを実行します。設定は最上位/最外部のプロセスの値に戻るため、動的SQLを1回実行する必要があります。例えば:
これをSSMSの1つのクエリタブで実行します。
GO
CREATE PROCEDURE ##ShouldTimeout
AS
INSERT INTO ##LockedTable ([ID]) VALUES (1);
GO
GO
CREATE PROCEDURE ##TimeoutTest
(
@SecondsUntilTimeout INT = 2
)
AS
SET NOCOUNT ON;
SET @SecondsUntilTimeout = ISNULL(@SecondsUntilTimeout, 2); -- enforce default
DECLARE @SQL NVARCHAR(MAX) = N'SET LOCK_TIMEOUT ';
SET @SQL += CONVERT(NVARCHAR(MAX), @SecondsUntilTimeout * 1000) + N';
';
SET @SQL += N'EXEC ##ShouldTimeout;'; -- use CASE / IF to decide what to exec
RAISERROR(@SQL, 10, 1) WITH NOWAIT; -- print Dynamic SQL in "Messages" tab
EXEC (@SQL);
GO
SSMSの別のクエリタブで次を実行します。
BEGIN TRAN;
CREATE TABLE ##LockedTable (ID INT);
-- ROLLBACK
次に、最初のクエリタブ(2つの一時ストアドプロシージャを作成した場所)に戻り、次の2つのテストを実行します。
EXEC ##TimeoutTest;
-- this will timeout after 2 seconds (the default)
EXEC ##TimeoutTest 5;
-- this will timeout after 5 seconds
次に、2番目のクエリタブに戻り、ROLLBACK
;-)を実行します。
いいえ、それはできません。これは接続のプロパティです。
オンライン書籍:
接続の開始時、この設定の値は-1です。変更後、新しい設定は残りの接続で有効になります。 SET LOCK_TIMEOUTの設定は、実行時または実行時に設定され、解析時ではありません。
それがどのように使用できるかのいくつかの例と議論: