如何让一条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
将其设置为testserver
或FROM [@TGT].[cases].[dbo].[sp_class]
,但收到错误Could not find server '@TGT' in sys.servers.
答案 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
几点说明:
答案 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
最后,特别是如果问题条件基于类似于运行的机器之类的东西,您可以使用同义词,但根据需要更改别名指向的内容。这可能是最复杂的选项,但它的优点是可以使存储过程更简单,更简单。