Reputation: 4876
I am using SQL to concatenate strings together.
This statement works:
DECLARE @FirstNamesString nvarchar(256)
SELECT
@FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName
FROM
Person p
ORDER BY
p.SortOrder
And I get the list of first names like:
Name1, Name2, Name3
Now I want to add in a possibly null last name field for each of these persons. I tried the sql below but I only get the last item in the list (Name3
):
DECLARE @FirstNamesString nvarchar(256)
SELECT @FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName + ISNULL(' ' + p.LastName, '')
FROM
Person p
ORDER BY
p.SortOrder
BUT if I first insert all of these names into a temp table, then everything works as expected:
CREATE TABLE #Person2
(
FirstName nvarchar(128) NOT NULL
,LastName nvarchar(256) NULL
,SortOrder int NOT NULL
)
INSERT INTO #Person2 (FirstName, LastName, SortOrder) (
SELECT p.FirstName, p.LastName, p.SortOrder FROM Person p)
DECLARE @FirstNamesString nvarchar(256)
SELECT @FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName + ISNULL(' ' + p.LastName, '')
FROM
#Person2 p
ORDER BY
p.SortOrder
DROP TABLE #Person2
So what is the difference between the statement above against the original table and the one against the temp table? The temp table route works and I am going to use that but I am very curious... what am I missing here?
UPDATED WITH POSSIBLE SOLUTION
See @Martin's answer but the concatenation of strings isn't guaranteed to work. So a solution is to insert the last name into the temp table first prior to selecting the list of first names:
CREATE TABLE #Person2
(
FirstName nvarchar(256) NOT NULL
,SortOrder int NOT NULL
)
INSERT INTO #Person2 (FirstName, SortOrder) (
SELECT p.FirstName + ISNULL(' ' + p.LastName, ''), p.SortOrder
FROM Person p
)
DECLARE @FirstNamesString nvarchar(256)
SELECT
@FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName
FROM
#Person2 p
ORDER BY
p.SortOrder ASC
Upvotes: 1
Views: 613
Reputation: 453786
This approach to concatenate strings isn't guaranteed to work. Microsoft say "The correct behavior for an aggregate concatenation query is undefined.". It will fail if the compute scalar ends up in the wrong place in the plan. Can you show both plans?
You could/should of course just use XML PATH
to concatenate strings as you are on SQL Server 2008 and this is documented to work. reliable in current versions.
Example:
DECLARE @FirstNamesString nvarchar(256)
SELECT @FirstNamesString = (
SELECT CASE
WHEN ROW_NUMBER() OVER (ORDER BY (p.SortOrder)) = 1 THEN ''
ELSE ','
END + p.FirstName + ISNULL(' ' + p.LastName, '')
FROM Person p
ORDER BY p.SortOrder
FOR XML PATH(''), TYPE
).value('.[1]','nvarchar(256)')
PRINT @FirstNamesString
Upvotes: 3
Reputation: 11908
I tried this and it works fine. But the variable engine is indeed not guaranteed to work. (and it is undocumented)
create table Person(FirstName nvarchar(10), LastName nvarchar(20), SortOrder int)
insert into Person
VALUES ('Pers1', 'Last1', 1),
('Pers2', 'Last2', 2),
('Pers3', 'Last3', 3),
('Pers4', 'Last4', 4),
('Pers5', NULL, 5)
DECLARE @FirstNamesString nvarchar(256)
SELECT @FirstNamesString = COALESCE(@FirstNamesString + ', ', '') + p.FirstName + ISNULL(' ' + p.LastName, '')
FROM
Person p
ORDER BY
p.SortOrder
print @FirstNamesString
Upvotes: 0