【问题标题】:Why do I get these different results from two SQL queries?为什么我会从两个 SQL 查询中得到这些不同的结果?
【发布时间】:2012-10-12 17:54:50
【问题描述】:

这让我一整天都想死=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()。谢谢!

【问题讨论】:

  • 你能运行并告诉从这个查询返回多少行 EXEC ('SELECT name FROM [A].sys.tables') AT [LINKED]

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


【解决方案1】:

不幸的是,在 SQL Server 中,这是一种不可靠的字符串连接方法。除了最微不足道的情况外,我会避免它。此 KB 中有更多信息: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

请注意,我在表达式中添加了一个空的替换函数。虽然它不应对输出做任何事情,但它确实在查询计划中添加了一个本地“计算标量”步骤。这似乎是从 name 列拉回所有数据,然后在本地处理,而不是让远程查询返回它认为需要的内容。

我不确定除了带有空参数的replace 之外是否还有更好的函数可以使用。也许是双重reverse 或其他东西。如有必要,请务必按照文档所述强制转换为最大数据类型。

更新

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

【讨论】:

  • 我很好奇你的链接服务器有什么设置。我无法重现该问题。
  • @AaronBertrand,有趣的是,我想不出configuration of the linked server 并没有重现这个问题,尽管只是摆弄了几分钟。
  • @AaronBertrand,只需将@var 声明为varchar(max) 即可解决问题(我已使用nvarchar 进行了测试)。你用的是哪个?
  • 我对上述问题中的链接服务器查询所做的唯一修改是服务器名称和数据库名称。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多