使用“使用”命令或等效命令指向其他服务器

时间:2014-06-17 15:30:17

标签: sql-server

我有一个大型动态SQL语句,我需要在多个数据库上执行,并且可能在将来在多个服务器上执行。

在动态SQL开始时我可以使用

USE Database1

一切正常。但我想知道是否有一种方法可以指定链接服务器的服务器名称?例如

USE Server1.Database1

我知道我可以在查询中使用完全限定名称,但这会使sql更难阅读。有没有办法可以避免完全合格的名字?

总结一下我想要实现的目标 - 我有一个带有存储过程的中央数据库,可以将来自多个数据库的数据提取并处理到一个位置,以便客户端可以轻松地报告它。

3 个答案:

答案 0 :(得分:1)

我会考虑使用sqlcmd,而不是用于此目的。您可以在脚本顶部指定变量,如下所示:

:setvar MyLinkedServer "MyLinkedServerName"
:setvar DatabaseName "MyDb"

然后在脚本中调用它:

[$(MyLinkedServer)].[$(DatabaseName)].SomeSchema.SomeTable

在执行脚本之前,sqlcmd将替换值,即使它是在文本字符串中,也就像动态sql中的情况一样。通过使用sqlcmd.exe执行脚本,还可以将变量设置为脚本文件的参数。这应该有助于保持代码看起来更清洁。

答案 1 :(得分:1)

由于您提到可读性不仅仅是使用完全限定名称的原因,并且还提到您不熟悉别名,我还是假设您的查询看起来像这样。

select
    serverA.Database1.dbo.TableName.ColumnExample,
    serverB.Database2.dbo.TableName.SecondExample
from serverA.Database1.dbo.TableName
inner join serverB.Database2.dbo.TableName
    on serverA.Database1.dbo.TableName.BlahID = serverB.Database2.dbo.TableName.BlergID

如果是这样的话,那么这就是在冰上吮吸并且非常难以理解。所以你可以做的是添加别名来清理这个代码,这样你就有了一个类似的查询。

select
    A.ColumnExample,
    B.SecondExample
from serverA.Database1.dbo.TableName as A --By setting the Alias as A you can now
inner join serverB.Database2.dbo.TableName as B --reference that instead of 
    on A.BlahID = B.BlergID --qualifying the whole statement

这将使构建可读的动态SQL语句变得更加简单,该语句在许多服务器上调用许多数据库。然后,只需使用您正在使用的任何方法将动态SQL语句称为

N'select
    A.ColumnExample,
    B.SecondExample
from ' + @Server1 + @Database1 + '.dbo.TableName as A --By setting the Alias as A you can now
inner join ' + @Server2 + @Database2 + '.dbo.TableName as B --reference that instead of 
    on A.BlahID = B.BlergID --qualifying the whole statement'

我建议在服务器变量中添加数据库之前的.,这样如果它是本地服务器就可以将其关闭。

答案 2 :(得分:0)

如果它是同一个只需要在不同上下文中执行的查询,您可以尝试通过调用相应的sp_executesql实例来指定上下文来执行动态查询:

linkedserver.remotedatabase.sys.sp_executesql N'
SELECT
  ...
FROM dbo.Table1 AS a
INNER JOIN dbo.Table2 AS b ON ...
';

那样 linkedserver.remotedatabase 将是当前数据库,并且确实是 linkedserver 指定查询的当前服务器。

但是,由于您正在从表中读取名称,因此该方法可能需要更高级别的动态性。对于下面这个查询构建部件在这种情况下的外观,我假设服务器和数据库的名称存储在变量中(例如,就像你在游标迭代中填充了变量一样) ):

DECLARE @sql nvarchar(max), @metasql nvarchar(max);
SET @sql = N'your dynamic query (without USE)';
SET @metasql = QUOTENAME(@servername) + N'.' + QUOTENAME(@databasename) + N'.sys.sp_execute @sql';
EXECUTE sp_execute @metasql, N'@sql nvarchar(max)', @sql;

这种双嵌套可能不是很适合你在一篇评论中偶尔进行的调试。但是,您可以将@sql内容的合并转换为@metasql而不是参数化:

DECLARE @sql nvarchar(max), @metasql nvarchar(max);
SET @sql = N'your dynamic query (without USE)';
SET @metasql = QUOTENAME(@servername) + N'.' + QUOTENAME(@databasename) + N'.sys.sp_execute N' + QUOTENAME(@sql, '''');
EXECUTE sp_execute @metasql;