考虑以下tsql ...
create function dbo.wtfunc(@s varchar(50)) returns varchar(10) begin return left(@s, 2); end
GO
select t.* into #test from (
select 'blah' as s union
select 'foo' union
select 'bar'
) t
select * from #test;
declare @s varchar(100);
set @s = '';
select @s = @s + s from #test order by s;
select @s;
set @s = '';
select @s = @s + s from #test order by dbo.wtfunc(s);
select @s;
/* 2005 only*/
select cast((select s+'' from #test order by dbo.wtfunc(s) for xml path('')) as varchar(100))
drop function dbo.wtfunc;
drop table #test;
我在mssql 2000和2005上尝试过它,并且在按顺序使用函数时都不会连接字符串。在2005年,for xml路径('')确实有效。输出是......
bar
blah
foo
barblahfoo
foo --nothing concatenated?
barblahfoo
我无法找到记录的位置。有人可以解释为什么这不起作用吗?
编辑:
以下是实际的执行计划。显然,排序和计算标量的顺序不一样......
答案 0 :(得分:5)
这似乎是known issue with Aggregate Concatenation Queries。
从链接:
“ANSI SQL-92规范要求ORDER BY子句引用的任何列都匹配SELECT列表中存在的列定义的结果集。当表达式应用于ORDER BY的成员时子句,结果列未在SELECT列表中公开,导致未定义的行为。“
答案 1 :(得分:3)
您可以使用计算列来执行此操作,例如:
DROP TABLE dbo.temp;
CREATE TABLE dbo.temp
(
s varchar(20)
,t AS REVERSE(s)
);
INSERT INTO dbo.temp (s) VALUES ('foo');
INSERT INTO dbo.temp (s) VALUES ('bar');
INSERT INTO dbo.temp (s) VALUES ('baz');
INSERT INTO dbo.temp (s) VALUES ('blah');
GO
-- Using the function directly doesn't work:
DECLARE @s varchar(2000);
SELECT s, REVERSE(s) FROM dbo.temp ORDER BY REVERSE(s);
SET @s = '';
SELECT @s = @s + s FROM dbo.temp ORDER BY REVERSE(s);
SELECT @s;
GO
-- Hiding the function in a computed column works:
DECLARE @s varchar(2000);
SELECT s, t FROM dbo.temp ORDER BY t;
SET @s = '';
SELECT @s = @s + s FROM dbo.temp ORDER BY t;
SELECT @s;
GO
答案 2 :(得分:2)
我不知道这是否有用,但是当我尝试这个时:
set @s = ' ';
select @s = @s + s from #test order by dbo.wtfunc(s);
select @s AS myTest
我得到了这个(注意'foo'前面有空格而后面没有空格):
foo
我想这是一个不起眼的小虫子?!