带有select和order by的tsql字符串concat不适用于order by子句中的函数?
考虑以下tsql带有select和order by的tsql字符串concat不适用于order by子句中的函数?,sql,sql-server,tsql,Sql,Sql Server,Tsql,考虑以下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(10
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上尝试过了,当使用order by中的函数时,这两种方法都不会压缩字符串。在2005年,for xml路径(“”)起作用。输出是
bar
blah
foo
barblahfoo
foo --nothing concatenated?
barblahfoo
我找不到这是在哪里记录的。有人能解释一下为什么这不起作用吗
编辑:
以下是实际执行计划。显然,排序和计算标量的顺序不同
我不知道这是否有帮助,但当我尝试这一点时:
set @s = ' ';
select @s = @s + s from #test order by dbo.wtfunc(s);
select @s AS myTest
我明白了(注意在'foo'前面有空格,后面没有空格):
我猜这是个不起眼的小虫子 这似乎是一个错误 从链接:
ANSI SQL-92规范要求ORDER by子句引用的任何列都与SELECT列表中的列定义的结果集相匹配。当表达式应用于ORDER by子句的成员时,该结果列不会在SELECT列表中公开,从而导致未定义的行为您可以使用计算列来完成此操作,例如:
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
是的,我不知道是怎么回事。似乎只使用最后一行。因为如果你把它改成“desc”,你只会得到“bar”。完全忘记了计算列。嗯,现在我需要决定是否要在我的桌子上放一个……不过这是一个很好的提示!
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