3

1つのSQLでターゲットサーバーを条件付きで変更するにはどうすればよいですか?

したがって、ローカルの開発マシンでは、それを実行してコマンドを実行できます...

INSERT  INTO [sds].[dbo].[Team_Email_Addresses]
        SELECT  [class] AS 'Team number' ,
                [description] AS 'Team name' ,
                [DutyEmail] AS 'Team email address'
        FROM    [DEVSERVER].[cases].[dbo].[sp_class]
        WHERE   [status] = 1

しかし、テストマシンでは、同じSQLを実行して、コマンドを実行する必要があります...

INSERT  INTO [sds].[dbo].[Team_Email_Addresses]
        SELECT  [class] AS 'Team number' ,
                [description] AS 'Team name' ,
                [DutyEmail] AS 'Team email address'
        FROM    [TESTSERVER].[cases].[dbo].[sp_class]
        WHERE   [status] = 1

変数を使用して、またはSQLを使用@TGTして設定しようとしましたが、エラーが発生しますdevservertestserverFROM [@TGT].[cases].[dbo].[sp_class]Could not find server '@TGT' in sys.servers.

4

3 に答える 3

6

動的 SQL を使用する必要があります。'single quotes'また、列のエイリアスを区切るために使用しないでください。この構文は廃止されました。[square brackets]orを使用する必要があります"double quotes"(一般的に前者が推奨されます)。

DECLARE @sql NVARCHAR(MAX), @TGT SYSNAME;

SET @TGT = N'[TESTSERVER]';

SET @sql = N'INSERT  INTO [sds].[dbo].[Team_Email_Addresses]
        SELECT  [class] AS [Team number] ,
                [description] AS [Team name] ,
                [DutyEmail] AS [Team email address]
        FROM    ' + @TGT + '.[cases].[dbo].[sp_class]
        WHERE   [status] = 1;';

PRINT @sql;
EXEC sp_executesql @sql;

(実際には、挿入列リストを指定する必要がありますが、ここではエイリアスは必要ありません。)

または、コードをより安定させるためにできることは、2 つの環境で同義語を使用することです。開発中:

CREATE SYNONYM dbo.sp_class FOR DEVSERVER.cases.dbo.sp_class;

テスト中:

CREATE SYNONYM dbo.sp_class FOR TESTSERVER.cases.dbo.sp_class;

これで、クエリは次のようになります。

INSERT  INTO [sds].[dbo].[Team_Email_Addresses]
        SELECT  [class],
                [description],
                [DutyEmail]
        FROM    [dbo].[sp_class]
        WHERE   [status] = 1;

もちろん、シノニムは SQL Server 2005 以降を使用している場合にのみ機能します。使用している SQL Server のバージョンを指定すると便利です。

于 2012-05-01T15:35:58.660 に答える
2

私は通常、この種の状況に同義語を使用します。これは2つの異なる場所から実行しているため、それぞれの場所でシノニムを適切に定義する必要があります。

ローカル開発マシン:

CREATE SYNONYM dbo.Cases_sp_class FOR [DEVSERVER].[cases].[dbo].[sp_class]

そしてあなたのテストマシンで:

CREATE SYNONYM dbo.Cases_sp_class FOR [TESTSERVER].[cases].[dbo].[sp_class]

次に、すべての環境でSQLをこれに変更する必要があります。

INSERT  INTO [sds].[dbo].[Team_Email_Addresses]
        SELECT  [class] AS 'Team number' ,
                [description] AS 'Team name' ,
                [DutyEmail] AS 'Team email address'
        FROM    [dbo].[Cases_sp_class]
        WHERE   [status] = 1

いくつかのメモ:

  1. TESTSERVERおよび/またはDEVSERVERは、リンクサーバーとして定義する必要があります
  2. [sp_class]が実際にストアドプロシージャである場合は、これらすべてを少し異なる方法で実行する必要があります。そうでない場合は、「sp_」プレフィックスを使用しないでください。これは、MSが独自のシステムプロシージャに使用するプレフィックスであり、非常に混乱する可能性があります。
于 2012-05-01T15:43:04.237 に答える
1

Aaron Bertrand が指摘しているように、動的 SQL は 1 つの選択肢であり、動的 SQLの呪いと祝福で動的 SQLに関する適切な議論があります。

動的 sql オプションに加えて、単純に両方を if ステートメントに含めることができます。

If <insert condition> then
INSERT  INTO [sds].[dbo].[Team_Email_Addresses]         SELECT  [class] AS 'Team number' ,                 [description] AS 'Team name' ,                 [DutyEmail] AS 'Team email address'         FROM    [DEVSERVER].[cases].[dbo].[sp_class]         WHERE   [status] = 1 
else
INSERT  INTO [sds].[dbo].[Team_Email_Addresses]         SELECT  [class] AS 'Team number' ,                 [description] AS 'Team name' ,                 [DutyEmail] AS 'Team email address'         FROM    [TESTSERVER].[cases].[dbo].[sp_class]         WHERE   [status] = 1 

最後に、特に質問の条件が、これが実行されているマシンのようなものに基づいている場合は、同義語を使用できますが、必要に応じてエイリアスが指すものを変更できます。これはおそらく最も複雑なオプションですが、問題のストアド プロシージャをより短くシンプルに保つことができるという利点があります。

于 2012-05-01T15:44:53.383 に答える