This question already has an answer here:
I have a sql function that includes this code:
DECLARE @CodeNameString varchar(100)
SELECT CodeName FROM AccountCodes ORDER BY Sort
I need to concatenate all results from the select query into CodeNameString.
Obviously a FOREACH loop in C# code would do this, but how do I do it in SQL?
If you're on SQL Server 2005 or up, you can use this
FOR XML PATH & STUFF
trick:The
FOR XML PATH('')
basically concatenates your strings together into one, long XML result (something like,code1,code2,code3
etc.) and theSTUFF
puts a "nothing" character at the first character, e.g. wipes out the "superfluous" first comma, to give you the result you're probably looking for.UPDATE: OK - I understand the comments - if your text in the database table already contains characters like
<
,>
or&
, then my current solution will in fact encode those into<
,>
, and&
.If you have a problem with that XML encoding - then yes, you must look at the solution proposed by @KM which works for those characters, too. One word of warning from me: this approach is a lot more resource and processing intensive - just so you know.
@AlexanderMP's answer is correct, but you can also consider handling nulls with
coalesce
:Here is another real life example that works fine at least with 2008 release (and later).
This is the original query which uses simple
max()
to get at least one of the values:Improved version, where the main improvement is that we show all values comma separated:
Note that we have solved all possible
NULL
case issues that I can think of and also we fixed an error that we got for numeric values (field Sorting).For SQL Server 2005 and above use Coalesce for
nulls
and I am using Cast or Convert if there arenumeric values
-from msdn Do not use a variable in a SELECT statement to concatenate values (that is, to compute aggregate values). Unexpected query results may occur. This is because all expressions in the SELECT list (including assignments) are not guaranteed to be executed exactly once for each output row
The above seems to say that concatenation as done above is not valid as the assignment might be done more times than there are rows returned by the select