这一整天都在杀我= 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()。谢谢!
答案 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和隐式转换的哪种组合会导致这种情况出现。希望在这方面有更多知识的人可以加入!