我有一个主数据库 ( MAIN
) 和几个客户端数据库 ( CLIENTDB
)。我需要开始查询MAIN
并从中获取数据CLIENTDB
。客户端数据库也可以在链接服务器上找到。我的问题是我需要在一个函数中执行此操作EXEC
,所以我可以得到SELECT * FROM SRV.CLIENTDB
,但是 SQL Server 不允许这样做。还有另一种方法吗?
我需要在函数内部有代码:
DECLARE @sSRV AS VARCHAR(128) = 'SRV';
DECLARE @sDB AS VARCHAR(128) = 'CLIENTDB1';
EXEC('SELECT * FROM ' + sSRV + '.' + @sDB + '.MyTable');
我需要一个函数,因为我需要在我的引擎中与它进行连接。
不可能通过 动态执行此操作
EXEC
,因为 IIRC 您无法在函数中执行此操作。您不能通过OPENROWSET
(https://msdn.microsoft.com/en-us/library/ms187569.aspx)使用临时分布式查询,因为OPENROWSET
明确要求其输入(包括查询文本)是字符串文字而不是更通用字符串值(因此您不能使用表达式或变量)。我能想到的唯一方法是为每个远程数据库设置一个函数或
CASE/IF
玛丽安评论中的建议。您可以通过在基于视图和其他 DMV 的视图中游标来实用地创建这样的函数,以sys.servers
通过字符串连接将函数组合在一起,然后使用对EXEC
. 每次链接服务器列表更改时,您仍然需要运行生成过程,但至少它只是一个过程调用(或脚本/语句运行),而不是更手动的代码更改。不过,这听起来很老套。如果你有这样的能力,这种“代码味道”表明重新设计是有必要的!
我认为这篇文章很好地回答了这个问题。使用
https://www.mssqltips.com/sqlservertip/1757/dynamic-sql-execution-on-remote-sql-server-using-exec-at/
这是帖子的一部分:
谢谢,
鉴于此要求:
我会说,考虑到既定目标(数据需要与本地表和/或视图连接),需求本身(它需要是一个函数)是错误的。问题在于 TVF(无论是 T-SQL 还是 SQLCLR)的行为方式不利于被连接。他们:
由于这两个原因,通常最好将结果转储到本地临时表,然后加入该表。因此,您可以通过执行以下操作轻松完成此操作:
'SELECT * FROM ' + sSRV + '.' + @sDB + '.MyTable'
(当然,包括表名之前的模式名称 ;-)INSERT INTO #LocalTempTable (column_list) EXEC dbo.NewStoredProcedure;
这将以比初始请求更好的方式获得您想要的结果,同时还允许服务器和数据库列表随时间波动。