SQL Server 链接服务器联接

3
我已经在我的SQL Server 2008中添加了一个链接服务器。我想从链接服务器上的一个表和一个表值函数中获取数据,并按照以下命名约定将这些数据与本地表联接。
<server>.<database>.<schema>.<table>

然而我的第一个问题是我需要从一个表中获取<server>部分。当我尝试执行以下操作时,会失败。

Select * FROM @ServerNameVariable.database.dbo.myTable

你知道如何使用用户定义变量来形成完全限定的链接服务器表名吗?

我的存储过程如下:

CREATE PROCEDURE TEST_SP    
AS
BEGIN
    DECLARE @NetworkDBName VARCHAR(255) 
    SET @NetworkDBName = '[MyLinkedServerName]'
    -- SET NOCOUNT ON added to prevent extra result sets from
    -- interfering with SELECT statements.
    SET NOCOUNT ON;

    -- Insert statements for procedure here 
    select * from @NetworkDBName + '.' + testDatabase.dbo.Invoice_tb
END
GO

3
不需要 @ - Gordon Linoff
2
SELECT name FROM sys.servers WHERE server_id > 0 - 您的链接服务器 - Devart
但是在用户定义变量之前必须使用“@”,否则SP将无法编译。 - ItsZeus
请提供您的 sp - Devart
给定的表单中的SP无法编译。 - ItsZeus
2个回答

6

您不能在数据库、模式或表名的位置使用变量。

相反,您可以使用sp_ExecuteSQL构建和执行动态SQL语句。

此示例不起作用,因为服务器名称被视为字符串而不是服务器对象。

失败的示例

/* Anti-pattern.
 * Does not work.
 */
DECLARE @Server    SYSNAME = 'Server001';

SELECT
    *
FROM
    @Server.Database1.dbo.Table1
;

这个例子展示了一种能够工作的方法。在这里,SQL语句被构建成字符串,然后执行。

/* Dynamic SQL statement.
 * Will work.
 */
DECLARE @Server    SYSNAME = 'Server001';
DECLARE @Statement    NVARCHAR(255);

SET @Statement = 'SELECT * FROM ' + QUOTENAME(@Server) + '.Database1.dbo.Table1;';

EXECUTE sp_ExecuteSQL @Statement;

请注意,在生成和执行动态SQL语句时要小心。您不希望自己成为 SQL注入攻击的目标。在执行之前,请查看OPENROWSET或检查传递的服务器名称是否与@Devart提供的代码匹配(SELECT name FROM sys.servers WHERE server_id > 0)。 编辑1:在有关SQL注入的段落中添加了更多细节。 编辑2:从第二个示例查询中删除方括号,并根据@TTs的评论替换为QUOTENAME。

2
不要手动使用方括号来封闭服务器名称(或数据库、表名等),而是使用QUOTENAME函数。如果名称包含方括号,此函数将正确转义。 - TT.
你的回答非常详细,我很感激。但是问题在于服务器名称保存在数据库中。其次,我需要使用结果集来连接本地表,以获取所需的数据。 - ItsZeus
重新加入:你仍然可以这样做。我越想越喜欢OPENROWSET方法。如果你跟随那个链接到MSDN,它包含一个带有INNER JOIN的示例。sp_ExecuteSQL可以实现相同的结果,你只需要添加连接和本地表名。重新命名保存在数据库中:我不确定我理解这一点。你能详细说明一下吗? - David Rushton

2
使用链接服务器的名称,它将成为一个由4部分构成的限定符,例如:
Select * From [Link Server Name ].[Database].[Schema].[Table]

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接