在SQL Server 2008上,我试图将所有选定值的逗号分隔列表转换为变量。
SELECT field
FROM table
返回:
+-------+
| field |
+-------+
| foo |
+-------+
| bar |
+-------+
我想得到: “foo,bar,”
我试过了:
DECLARE @foo NVARCHAR(MAX)
SET @foo = ''
SELECT @foo = @foo + field + ','
FROM TABLE
PRINT @foo
什么都不返回。我做错了什么?
答案 0 :(得分:9)
您需要更改NULL
SELECT @foo = @foo + ISNULL(field + ',', '')
FROM TABLE
或删除它们
SELECT @foo = @foo + field + ','
FROM TABLE
WHERE field IS NOT NULL
答案 1 :(得分:3)
如果表中的某个SINGLE字段为NULL,则会发生这种情况。在SQL Server中,NULL + <any> = NULL
。省略它们
SELECT @foo = @foo + field + ','
FROM TABLE
WHERE field is not null
或解决他们的问题
SELECT @foo = @foo + isnull(field + ',', '')
FROM TABLE
你可以在没有更常见的前导SET语句的情况下编写整个事物。下面的查询返回“foo,bar”,没有逗号逗号
DECLARE @foo NVARCHAR(MAX)
SELECT @foo = isnull(@foo + ',', '') + field
FROM TABLE
WHERE field is not null
PRINT @foo
答案 2 :(得分:1)
请勿忘记在LTRIM
周围使用RTRIM
和@foo
(当数据类型为char
/ varchar
时)在串联其他地方不会在SQL 2008 R2中给出预期的结果。
答案 3 :(得分:1)
根据Lukasz Szozda对此处的答案之一所做的评论,您不应使用指示的方法在SQL Server中聚合字符串值,因为这不受支持。尽管在不使用任何order子句的情况下(尽管没有记录这种趋势的例外情况)这往往会起作用,但是Microsoft不能保证它会起作用,并且将来很有可能会停止工作。 SQL是一种声明性语言;您不能假定未明确定义为解释给定语句的正确行为的行为将继续起作用。
相反,请参见下面的示例,或者请参见本页以了解实现相同结果的有效方法及其各自的性能:Optimal way to concatenate/aggregate strings
以有效的方式进行操作(无论最终使用哪种方式)仍与此处其他答案中的注意事项相同。您需要从结果集中排除NULL值,或者明确说明如何将它们添加到结果字符串中。
此外,您可能应该使用某种显式排序,以便此代码具有确定性-如果像这样的代码在相同数据上运行时可能产生不同的结果,则可能会导致各种各样的问题。没有指定明确的顺序。
--Null values treated as empty strings
SET @Foo =
STUFF /*Stuff is used to remove the seperator from the start of the string*/
( (SELECT N','/*separator*/ + ISNULL(RTRIM(t.Field), '' /*Use an emptry string in the place of NULL values*/) /*Thing to List*/
FROM TABLE t
ORDER BY t.SomeUniqueColumn ASC /*Make the query deterministic*/
FOR XML PATH, TYPE).value(N'.[1]',N'varchar(max)')
,1
,1 /*Length of separator*/
,N'');
--Null values excluded from result
SET @Foo =
STUFF /*Stuff is used to remove the seperator from the start of the string*/
( (SELECT N','/*separator*/ + RTRIM(t.Field) /*Thing to List*/
FROM TABLE t
WHERE t.Field IS NOT NULL
ORDER BY t.SomeUniqueColumn ASC /*Make the query deterministic*/
FOR XML PATH, TYPE).value(N'.[1]',N'varchar(max)')
,1
,1 /*Length of separator*/
,N'');