我正在使用选择查询和变量来连接查询中的一些字符串,如下所示:
DECLARE @sConcat nvarchar(max)
SET @sConcat = ''
SELECT @sConcat = @sConcat + '[' + SomeColumn + ']'
FROM SomeTable
ORDER BY SomeColumn
在我的特殊情况下,我将FROM
子句更改为派生表,它只是将整数列转换为 nvarchar,因此我不必每次在连接中出现时都将其转换。
进行此更改后,连接的结果只是表中的一个值。将 CAST 移动到外部查询或删除ORDER BY
子句时,结果符合预期。
这一切都可以用下面的 t-sql 来重现。
BEGIN TRAN
-- Create a dummy table and populate it with some values
CREATE TABLE TTest (
TTest_ID int IDENTITY(1,1) NOT NULL,
TTest_Text varchar(8) NOT NULL
CONSTRAINT PK_TTest PRIMARY KEY CLUSTERED (
TTest_Id ASC
)
) ON [PRIMARY]
INSERT INTO TTest (TTest_Text) VALUES ('A')
INSERT INTO TTest (TTest_Text) VALUES ('B')
INSERT INTO TTest (TTest_Text) VALUES ('C')
INSERT INTO TTest (TTest_Text) VALUES ('D')
INSERT INTO TTest (TTest_Text) VALUES ('E')
INSERT INTO TTest (TTest_Text) VALUES ('F')
INSERT INTO TTest (TTest_Text) VALUES ('G')
INSERT INTO TTest (TTest_Text) VALUES ('H')
-- Create a string with the ID values of each row in brackets
DECLARE @sConcat nvarchar(max)
-- First attempt, produces the result '[8]' which is not what I expected
SET @sConcat = ''
SELECT @sConcat = @sConcat + '[' + TTest_ID + ']'
FROM (SELECT CAST(TTest_ID AS nvarchar(100)) AS TTest_ID, TTest_Text
FROM TTest) TTestBis
ORDER BY TTestBis.TTest_ID ASC
PRINT @sConcat
-- Second attempt, with cast in the outer query,
-- produces the expected result '[1][2][3][4][5][6][7][8]'
SET @sConcat = ''
SELECT @sConcat = @sConcat + '[' + CAST(TTest_ID AS nvarchar(100)) + ']'
FROM (SELECT TTest_ID, TTest_Text
FROM TTest) TTestBis
ORDER BY TTestBis.TTest_ID ASC
PRINT @sConcat
-- Third attempt, same as first but without ORDER BY,
-- also produces the expected result '[1][2][3][4][5][6][7][8]'
SET @sConcat = ''
SELECT @sConcat = @sConcat + '[' + TTest_ID + ']'
FROM (SELECT CAST(TTest_ID AS nvarchar(100)) AS TTest_ID, TTest_Text
FROM TTest) TTestBis
PRINT @sConcat
ROLLBACK
为什么 SQL Server 会以这种方式运行?对我来说这没有意义。我在 SQL Server 2005、2008 和 2008R2 上重现了这一点。
编辑
这个问题确实是重复的。迄今为止给出的最佳答案似乎是 Martin Smith在这个问题中给出的答案。所以你可以投票关闭。