1

なぜこれが機能しないのか誰か教えてもらえますか?

if ((select @@servername) = 'ServerA')
begin
    use DatabaseA
    select top 5 * from dbo.SignUPRequest
end
else if ((select @@servername) = 'ServerB')
begin
    use DatabaseB
    select top 5 * from dbo.SignUPRequest
end

これをServerAで実行すると、DatabaseBがServerAに存在しないというメッセージが表示されますが、それは存在しませんが、falseと評価された場合に2番目が読み取ろうとしている理由がわかりません。

メッセージ911、レベル16、状態1、行8
データベース'DatabaseB'は存在しません。名前が正しく入力されていることを確認してください。

4

2 に答える 2

2

コードは実行前に解析されます。解析されると、SQL Serverはコード内のすべてにアクセスできることを確認しますが、他のサーバーに存在するデータベースにアクセスできないため、コードを実行する解析手順は失敗します。その結果、表示したエラーメッセージが表示されます。

それを回避したい場合は、動的に実行されるコードとしてIFブロックにコードを配置できます(これはちょっとしたハック/回避策だといつも感じています)。

DECLARE @sql NVARCHAR(4000);
if ((select @@servername) = 'ServerA')
begin
    SET @sql = 'use DatabaseA; select top 5 * from dbo.SignUPRequest;'
end
else if ((select @@servername) = 'ServerB')
begin
    SET @sql = 'use DatabaseB; select top 5 * from dbo.SignUPRequest'
end

EXEC (@sql)

したがって、ここで行われるのは、サーバーの実行時に適切なデータベースを使用するコードの解析と実行を、最後のEXECステートメントと同じように延期することです。

アップデート

以下の追加コメントに基づいて、これを次のように書き直すこともできます。

DECLARE @sql NVARCHAR(4000);
if ((select @@servername) = 'ServerA')
begin
    select top 5 * from DatabaseA.dbo.SignUPRequest;
end
else if ((select @@servername) = 'ServerB')
begin
    select top 5 * from DatabaseB.dbo.SignUPRequest;
end

したがって、USE <database-name>先頭にを入力する代わりに、selectステートメントでテーブルの名前をより完全に修飾することもできます。これを処理するSQLが1行しかない場合は、より効果的です。

于 2012-08-04T21:11:49.973 に答える
1

クエリの実行時ではなく、コンパイル時にエラーが発生します。でステートメントを実行してexec、データベースが存在する場合にのみコンパイルされるバッチでステートメントを取得できます。

if ((select @@servername) = 'ServerA')
begin
   exec(N'use DatabaseA
          select top 5 * from dbo.SignUPRequest')
end
else if ((select @@servername) = 'ServerB')
begin
   exec(N'use DatabaseB
          select top 5 * from dbo.SignUPRequest')
end
于 2012-08-04T21:10:11.027 に答える