针对不同服务器的条件SQL

时间:2012-05-01 15:33:32

标签: sql sql-server sql-server-2008

如何让一条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

我尝试使用变量@TGT并使用SQL devserver将其设置为testserverFROM [@TGT].[cases].[dbo].[sp_class],但收到错误Could not find server '@TGT' in sys.servers.

3 个答案:

答案 0 :(得分:6)

您需要使用动态SQL。此外,您不应该使用'single quotes'来分隔列别名;此语法已被弃用。您应该使用[square brackets]"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;

(事实上,你并不需要这里的别名,但你应该指定插入列列表。)

或者,如何使代码更稳定,就是在两个环境中使用同义词。在开发中:

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版本总是有用的!

答案 1 :(得分: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用于它自己的系统过程的前缀,这可能会让人非常困惑。

答案 2 :(得分:1)

正如Aaron Bertrand所指出的那样,动态SQL是一种选择,在The Curse and Blessings of Dynamic 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 

最后,特别是如果问题条件基于类似于运行的机器之类的东西,您可以使用同义词,但根据需要更改别名指向的内容。这可能是最复杂的选项,但它的优点是可以使存储过程更简单,更简单。