为什么我从两个SQL查询中获得这些不同的结果?

时间:2012-10-22 20:49:23

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

这一整天都在杀我= D。请帮忙!

场景1:同一服务器(A,B)上有两个DB,A有三个表。查询从B执行。

场景2:两个DB的一个服务器链接到另一个服务器。 (B有链接A),A有三个表。查询从B执行。

在方案1(非链接服务器)中:

SET @val = ''
SELECT @val = @val + 'Hello, my name is ' + [name] + '!' + CHAR(10) + CHAR(13)
FROM A.sys.tables

返回: 您好,我的名字是Table1! 你好,我的名字是Table2! 您好,我的名字是Table3!

在方案2(链接服务器)中:

SET @val = ''
SELECT @val = @val + 'Hello, my name is ' + [name] + '!' + CHAR(10) + CHAR(13)
FROM LINKED.A.sys.tables

返回: 您好,我的名字是Table3!

为什么这些不同?如果我在链接服务器上使用openquery(),结果与方案1相同。我尽量避免使用openquery()。谢谢!

1 个答案:

答案 0 :(得分:4)

不幸的是,这是SQL Server中字符串连接的一种不可靠的方法。除了最微不足道的情况之外,我会避免它。此知识库中包含更多信息:Execution Plan and Results of Aggregate Concatenation Queries Depend Upon Expression Location

尽管如此,我能够复制您的问题并在我的环境中提供解决方法:

SET @val = ''
SELECT @val = @val + 'Hello, my name is ' + replace([name], '', '') + '!' + CHAR(10) + CHAR(13)
FROM LINKED.A.sys.tables

请注意,我在表达式中添加了一个空替换函数。虽然它不应对输出执行任何操作,但它会在查询计划中添加 local “compute scalar”步骤。这似乎从name列中取回所有数据,然后在本地处理,而不是让远程查询返回它认为需要的内容。

我不确定除了replace之外还有一个更好的函数可以使用空参数。也许是双reverse或其他东西。如果需要,请确保转换为最大数据类型,如文档所述。

<强>更新

简单地将@var声明为varchar(max)而不是nvarchar(max)可以解决问题,因为它会带回整个名称列(类型为sysname - 或nvarchar(128) - I相信)就像替换功能那样进行本地处理。我不能假装知道linked server settings和隐式转换的哪种组合会导致这种情况出现。希望在这方面有更多知识的人可以加入!