SSMSのコンテキストを動的SQLで指定されたデータベースに動的に変更しようとすると問題が発生します。
EXEC sys.sp_executesql N'USE db1 ' ;
正常に実行されますが、SSMSのデータベースコンテキストは変更されません。
上記のように少し変更してみました
DECLARE @sql NVARCHAR(100) DECLARE @db NVARCHAR(50)
SET @db = N'db1' SET @sql = N'Use ' + @db
EXEC sp_executesql @sql
繰り返しになりますが、正常に実行されますが、データベースは変更されません。
選択したデータベース内で他の動的SQLを実行することが最終的な目標である場合、これは十分簡単です。
DECLARE @db sysname = N'db1';
DECLARE @exec nvarchar(max) = QUOTENAME(@db) + N'.sys.sp_executesql',
@sql nvarchar(max) = N'SELECT DB_NAME();';
EXEC @exec @sql;
パラメータを渡す必要がある場合、問題ありません:
DECLARE @db sysname = N'db1', @i int = 1;
DECLARE @exec nvarchar(max) = QUOTENAME(@db) + N'.sys.sp_executesql',
@sql nvarchar(max) = N'SELECT DB_NAME(), @i;';
EXEC @exec @sql, N'@i int', @i;
選択したデータベース内で静的 SQLを実行することが目的である場合は、その静的SQLを各データベースのストアドプロシージャに格納し、次のように動的に呼び出すことを検討する必要があります。
DECLARE @db sysname = N'db1';
DECLARE @exec nvarchar(max) = QUOTENAME(@db) + N'.sys.sp_executesql',
@sql nvarchar(max) = N'EXEC dbo.procedurename;';
EXEC @exec @sql;
そして、うまくいけば、最終的な目標は、SSMSでこのコードをすべて実行することではなく、SSMSが@db
のコンテキストになるようにすることです。コメントも述べた。
DynamicSQLは、実際にはインラインであるかのように実行されますが、実際にはコードの残りの部分とは別のエンティティで具体的にインラインで実行されません。
次のコードを実行すると、現在のセットのSET @sql = N'Use ' + @db + '; select DB_NAME(); select @@spid'
の代わりに、アクティブデータベースを移動したことを示す結果が表示されますが、同じ接続で実行されています。
インラインデータベースの選択を変更する場合は、次のような方法が最適です。
IF @db = 'db1'
USE db1
ELSE IF @db = 'db2'
USE db2
それはナイスでもクリーンでもなく、潜在的なデータベースごとに2行が必要ですが、ジョブを実行します(動的SQLで実行しないと、メインスレッドが変更されないという同じ問題が発生します)。
ただし、USEコマンドの使用は、プロシージャ/関数では禁止されています。