2009-06-11 6 views
4

Betrachten Sie das folgende tsql ...tsql string concat mit select und order von funktioniert nicht mit funktion in by by clause?

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; 

Ich habe versucht, es auf MSSQL 2000 und 2005 und beide haben concat nicht die Zeichenfolge, wenn eine Funktion in der Reihenfolge verwenden. Im Jahr 2005 funktioniert der for xml-Pfad (''). Der Ausgang ist ...

bar 
blah 
foo 

barblahfoo 

foo --nothing concatenated? 

barblahfoo 

Ich kann nicht finden, wo dies dokumentiert ist. Kann jemand etwas darüber sagen, warum das nicht funktioniert?

EDIT:

Hier sind die tatsächlichen Ausführungspläne. Offensichtlich ist die Art und Rechen Skalar ist nicht in der gleichen Reihenfolge ...

alt text http://i41.tinypic.com/2d6pht3.jpg alt text http://i41.tinypic.com/w2og48.png

Antwort

4

Es scheint, dass dies ein known issue with Aggregate Concatenation Queries ist.

aus dem Link:

„Die ANSI SQL-92-Spezifikation erfordert, dass jede Spalte durch eine ORDER BY-Klausel referenziert die Ergebnismenge übereinstimmt, die durch die in der Auswahlliste Spalten definiert ist, wenn ein Ausdruck angewendet wird. Zu einem Member einer ORDER BY-Klausel wird diese resultierende Spalte in der SELECT-Liste nicht angezeigt, was zu einem nicht definierten Verhalten führt. "

+0

sehr schöne Entdeckung! – dotjoe

2

Ich weiß nicht, ob dies überhaupt hilfreich ist, aber wenn ich versuche, diesen:

set @s = '   '; 

select @s = @s + s from #test order by dbo.wtfunc(s); 
select @s AS myTest 

ich dieses (beachten Sie, gibt es Räume, die ‚foo‘ und keine Hintervoranstellen):

foo 

ich denke, das ist etwas unklar littl ein Fehler ?!

+0

ja, weiß nicht ich, was los mit ihm ist. Scheint nur die letzte Zeile zu verwenden. Denn wenn Sie es in "desc" ändern, erhalten Sie nur "bar". – dotjoe

3

Sie können dies tun, indem Sie eine berechnete Spalte, zum Beispiel unter Verwendung von:

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 
+0

total vergessen über berechnete Spalten. hmm, jetzt muss ich entscheiden, ob ich einen in meinen Tisch legen möchte ... aber ein guter Tipp! – dotjoe