1

这让我一整天都死了=D。请帮忙!

场景 1:同一台服务器上的两个数据库(A,B)和 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()。谢谢!

4

1 回答 1

4

Unfortunately, this is an unreliable method of string concatenation in SQL Server. I would avoid it in all but the most trivial of cases. There is some more information in this KB: Execution Plan and Results of Aggregate Concatenation Queries Depend Upon Expression Location.

That said, I was able to both duplicate your problem and provide a workaround in my environment:

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

Notice that I've added an empty replace function to the expression. Though it should do nothing to the output, it does add a local "compute scalar" step to the query plan. This seems to pull back all of the data from the name column to then be processed locally rather than just letting the remote query return what it thinks is needed.

I'm not sure if there's a better function to use other than a replace with empty arguments. Perhaps a double reverse or something. Just be sure to cast to a max datatype if necessary as the documentation states.

UPDATE

Simply declaring @var as varchar(max) rather than nvarchar(max) clears up the problem, as it then brings back the entire name column (type sysname -- or nvarchar(128) -- I believe) for local processing just like the replace function did. I cannot pretend to know which combination of linked server settings and implicit casting causes this to come up. Hopefully someone with more knowledge in this area can chime-in!

于 2012-10-22T21:17:32.023 回答