Group String Concatenation: which approach, if any, is any more guaranteed?
Itzik Ben-Gan explains in his book 'Inside Microsoft® SQL Server® 2008: T-SQL' how Appoach A works, because of the undocumented behavior of SQL Server in which it performs assignment for each result record from the SELECT
.
A well respected collegue and DB guru has suggested that Approach B is guaranteed to work. His argument is based on the recursive nature of COALESCE
versus the 'values expansion' method of CAST
.
Actually, I have no idea what 'values expansion' refers to (except for the fact that it is casting one value to another) or how it applies to this problem? Perhaps he misunderstood? Yes COALESCE
is recursive in a sense, but as far as I can see it is irrelevant and the desired result is produced because of the undocumented behavior of multiple assignment.
Is he correct? Please, no "Use FOR XML PATH
instead" answers!
Approach A
DECLARE @output VARCHAR(100);
SET @output = '';
SELECT @output = @output + CAST(COL_VCHAR AS VARCHAR(10)) + ';'
FROM someTable;
Approach B
DECLARE @output VARCHAR(100);
SELECT @output = COALESCE(@output + ', ', '') + COL_VCHAR
from someTable;
sql sql-server-2008 tsql
add a comment |
Itzik Ben-Gan explains in his book 'Inside Microsoft® SQL Server® 2008: T-SQL' how Appoach A works, because of the undocumented behavior of SQL Server in which it performs assignment for each result record from the SELECT
.
A well respected collegue and DB guru has suggested that Approach B is guaranteed to work. His argument is based on the recursive nature of COALESCE
versus the 'values expansion' method of CAST
.
Actually, I have no idea what 'values expansion' refers to (except for the fact that it is casting one value to another) or how it applies to this problem? Perhaps he misunderstood? Yes COALESCE
is recursive in a sense, but as far as I can see it is irrelevant and the desired result is produced because of the undocumented behavior of multiple assignment.
Is he correct? Please, no "Use FOR XML PATH
instead" answers!
Approach A
DECLARE @output VARCHAR(100);
SET @output = '';
SELECT @output = @output + CAST(COL_VCHAR AS VARCHAR(10)) + ';'
FROM someTable;
Approach B
DECLARE @output VARCHAR(100);
SELECT @output = COALESCE(@output + ', ', '') + COL_VCHAR
from someTable;
sql sql-server-2008 tsql
Have you tried it?
– Adrian Carneiro
Feb 16 '12 at 18:49
@Adrian They both work. Question is not if they work, but if I am correct in saying that they both work because of the same undocumented behavior?
– J Cooper
Feb 16 '12 at 18:57
add a comment |
Itzik Ben-Gan explains in his book 'Inside Microsoft® SQL Server® 2008: T-SQL' how Appoach A works, because of the undocumented behavior of SQL Server in which it performs assignment for each result record from the SELECT
.
A well respected collegue and DB guru has suggested that Approach B is guaranteed to work. His argument is based on the recursive nature of COALESCE
versus the 'values expansion' method of CAST
.
Actually, I have no idea what 'values expansion' refers to (except for the fact that it is casting one value to another) or how it applies to this problem? Perhaps he misunderstood? Yes COALESCE
is recursive in a sense, but as far as I can see it is irrelevant and the desired result is produced because of the undocumented behavior of multiple assignment.
Is he correct? Please, no "Use FOR XML PATH
instead" answers!
Approach A
DECLARE @output VARCHAR(100);
SET @output = '';
SELECT @output = @output + CAST(COL_VCHAR AS VARCHAR(10)) + ';'
FROM someTable;
Approach B
DECLARE @output VARCHAR(100);
SELECT @output = COALESCE(@output + ', ', '') + COL_VCHAR
from someTable;
sql sql-server-2008 tsql
Itzik Ben-Gan explains in his book 'Inside Microsoft® SQL Server® 2008: T-SQL' how Appoach A works, because of the undocumented behavior of SQL Server in which it performs assignment for each result record from the SELECT
.
A well respected collegue and DB guru has suggested that Approach B is guaranteed to work. His argument is based on the recursive nature of COALESCE
versus the 'values expansion' method of CAST
.
Actually, I have no idea what 'values expansion' refers to (except for the fact that it is casting one value to another) or how it applies to this problem? Perhaps he misunderstood? Yes COALESCE
is recursive in a sense, but as far as I can see it is irrelevant and the desired result is produced because of the undocumented behavior of multiple assignment.
Is he correct? Please, no "Use FOR XML PATH
instead" answers!
Approach A
DECLARE @output VARCHAR(100);
SET @output = '';
SELECT @output = @output + CAST(COL_VCHAR AS VARCHAR(10)) + ';'
FROM someTable;
Approach B
DECLARE @output VARCHAR(100);
SELECT @output = COALESCE(@output + ', ', '') + COL_VCHAR
from someTable;
sql sql-server-2008 tsql
sql sql-server-2008 tsql
edited Feb 16 '12 at 19:16
Aaron Bertrand
207k27361404
207k27361404
asked Feb 16 '12 at 18:44
J Cooper
3,44022739
3,44022739
Have you tried it?
– Adrian Carneiro
Feb 16 '12 at 18:49
@Adrian They both work. Question is not if they work, but if I am correct in saying that they both work because of the same undocumented behavior?
– J Cooper
Feb 16 '12 at 18:57
add a comment |
Have you tried it?
– Adrian Carneiro
Feb 16 '12 at 18:49
@Adrian They both work. Question is not if they work, but if I am correct in saying that they both work because of the same undocumented behavior?
– J Cooper
Feb 16 '12 at 18:57
Have you tried it?
– Adrian Carneiro
Feb 16 '12 at 18:49
Have you tried it?
– Adrian Carneiro
Feb 16 '12 at 18:49
@Adrian They both work. Question is not if they work, but if I am correct in saying that they both work because of the same undocumented behavior?
– J Cooper
Feb 16 '12 at 18:57
@Adrian They both work. Question is not if they work, but if I am correct in saying that they both work because of the same undocumented behavior?
– J Cooper
Feb 16 '12 at 18:57
add a comment |
4 Answers
4
active
oldest
votes
Since a conforming SQL implementation could evaluate all of the output rows simultaneously, in parallel, neither is guaranteed to work. That they happen to work, today, is an artifact of the current SQL Server implementation.
Your colleague is incorrect to assert that COALESCE
somehow changes the processing model.
I.e. a conforming implementation could effectively hand each potential row in the result set (having evaluated FROM
and WHERE
) to a separate thread, that then performs whatever processing is required in the SELECT
clause (before presumably recombining results in order to assess GROUP BY
, HAVING
and ORDER BY
).
There are no standard requirements governing access to variables during such processing, so each thread could "see" the same initial value of @output
(NULL
or ''
, depending on which form you're using), perform it's own update calculation, and assign that result value to @output
- the final value of @output
might then any of the individual row results - or anything else for that matter.
add a comment |
I believe they both work because of the same underlying (and undocumented) behavior. I am fairly confident that if you take a case where Itzik has demonstrated that Approach A fails, that Approach B will also fail in the same way and for the same reasons, in spite of your colleague's claims. I don't see how
DECLARE @output VARCHAR(100);
SELECT @output = COALESCE(@output + ', ', '') + COL_VCHAR
Is any different from:
DECLARE @output VARCHAR(100) = '';
SELECT @output = @output + ', ' + COL_VCHAR
-- or SELECT @output += ',' + COL_VCHAR
So what exactly does COALESCE
magically introduce? SQL Server isn't going to change its plan because of something you're doing to the output, AFAIK.
I use them all the time for dynamic SQL generation and don't recall ever seeing them fail, and I realize that's not your question. Unfortunately there isn't really a way to prove it unless you know of a case that fails for either approach.
I wrote a blog post about string concatenation a few months ago. It's not completely relevant to your problem but Rob Farley made a comment that may be considered another downside to the COALESCE
approach:
https://sqlblog.org/2011/03/08/t-sql-tuesday-16-this-is-not-the-aggregate-youre-looking-for
Thanks for your input. The concern is relying on an undocumented behavior/feature in a massive production system. Some hotfix down the road, microsoft decides to do things different behind the scenes and this no longer works and breaks things.
– J Cooper
Feb 16 '12 at 19:07
Both can fail if if you want a specific order of the concatenated values. Not the case here but if you do,for xml
is the way to go.
– Mikael Eriksson
Feb 16 '12 at 19:09
If your concern is forward compatibility then I would say both approaches introduce the same level of risk. With that in mindFOR XML
is, as @Mikael suggests for other reasons, probably the most future-proof method. I realize that's not what you want to hear, but better safe than sorry. It's quite easy to encapsulate this kind of thing - how many different queries are you doing this concatenation for? If it is a lot then perhaps the data model should be a more important concern.
– Aaron Bertrand
Feb 16 '12 at 19:12
I read your article - you sure would be the right guy to answer this question! Yes, I thoughtFOR XML
would be the safe, supported way to go. Actually, Ben-Gan suggests this method in his book. As far as the data model, the data is pulled this way for presentational purposes a good bit - but not my call
– J Cooper
Feb 17 '12 at 0:54
@J Cooper one other comment. If guaranteeing future compatibility (or order) is paramount to strict performance, use a cursor. Anything else is an undocumented trick.
– Aaron Bertrand
Feb 17 '12 at 12:40
|
show 3 more comments
In your example, there is a way to get different results, and that is if NULL values are introduced into the data set. e.g.:
set nocount on
declare @test table (value int)
insert into @test values (10)
insert into @test values (20)
insert into @test values (null)
insert into @test values (40)
insert into @test values (50)
DECLARE @output VARCHAR(max);
-- Approach A
SET @output = '';
SELECT @output = @output + CAST(value AS VARCHAR(10)) + ';'
FROM @test
print 'Result from A:'
print isnull(@output, '{null}')
-- Approach B
set @output = ''
SELECT @output = COALESCE(@output + ', ', '') + cast(value as varchar(10))
from @test
print 'Result from B:'
print isnull(@output, '{null}')
set nocount off
Approach A will return null, whereas Approach B will return 40, 50
add a comment |
They work differently, the first example adds an additional character to the end of the output variable, and yes they work because of the same behaviour.
The first example will work if your column had been a numeric or date also. It would however only take the first 10 characters of any value in the column. The second example would not cut off the column.
There is absolutely no recursive nature of COALESCE.
COALESCE is a way of replacing null values with replacement values.
EDIT:
I should add that i also prefer the second version, because you don't get that extra semicolon, in the end of output implying that more values will follow.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function () {
StackExchange.using("externalEditor", function () {
StackExchange.using("snippets", function () {
StackExchange.snippets.init();
});
});
}, "code-snippets");
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "1"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f9317170%2fgroup-string-concatenation-which-approach-if-any-is-any-more-guaranteed%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
Since a conforming SQL implementation could evaluate all of the output rows simultaneously, in parallel, neither is guaranteed to work. That they happen to work, today, is an artifact of the current SQL Server implementation.
Your colleague is incorrect to assert that COALESCE
somehow changes the processing model.
I.e. a conforming implementation could effectively hand each potential row in the result set (having evaluated FROM
and WHERE
) to a separate thread, that then performs whatever processing is required in the SELECT
clause (before presumably recombining results in order to assess GROUP BY
, HAVING
and ORDER BY
).
There are no standard requirements governing access to variables during such processing, so each thread could "see" the same initial value of @output
(NULL
or ''
, depending on which form you're using), perform it's own update calculation, and assign that result value to @output
- the final value of @output
might then any of the individual row results - or anything else for that matter.
add a comment |
Since a conforming SQL implementation could evaluate all of the output rows simultaneously, in parallel, neither is guaranteed to work. That they happen to work, today, is an artifact of the current SQL Server implementation.
Your colleague is incorrect to assert that COALESCE
somehow changes the processing model.
I.e. a conforming implementation could effectively hand each potential row in the result set (having evaluated FROM
and WHERE
) to a separate thread, that then performs whatever processing is required in the SELECT
clause (before presumably recombining results in order to assess GROUP BY
, HAVING
and ORDER BY
).
There are no standard requirements governing access to variables during such processing, so each thread could "see" the same initial value of @output
(NULL
or ''
, depending on which form you're using), perform it's own update calculation, and assign that result value to @output
- the final value of @output
might then any of the individual row results - or anything else for that matter.
add a comment |
Since a conforming SQL implementation could evaluate all of the output rows simultaneously, in parallel, neither is guaranteed to work. That they happen to work, today, is an artifact of the current SQL Server implementation.
Your colleague is incorrect to assert that COALESCE
somehow changes the processing model.
I.e. a conforming implementation could effectively hand each potential row in the result set (having evaluated FROM
and WHERE
) to a separate thread, that then performs whatever processing is required in the SELECT
clause (before presumably recombining results in order to assess GROUP BY
, HAVING
and ORDER BY
).
There are no standard requirements governing access to variables during such processing, so each thread could "see" the same initial value of @output
(NULL
or ''
, depending on which form you're using), perform it's own update calculation, and assign that result value to @output
- the final value of @output
might then any of the individual row results - or anything else for that matter.
Since a conforming SQL implementation could evaluate all of the output rows simultaneously, in parallel, neither is guaranteed to work. That they happen to work, today, is an artifact of the current SQL Server implementation.
Your colleague is incorrect to assert that COALESCE
somehow changes the processing model.
I.e. a conforming implementation could effectively hand each potential row in the result set (having evaluated FROM
and WHERE
) to a separate thread, that then performs whatever processing is required in the SELECT
clause (before presumably recombining results in order to assess GROUP BY
, HAVING
and ORDER BY
).
There are no standard requirements governing access to variables during such processing, so each thread could "see" the same initial value of @output
(NULL
or ''
, depending on which form you're using), perform it's own update calculation, and assign that result value to @output
- the final value of @output
might then any of the individual row results - or anything else for that matter.
edited Sep 8 '14 at 22:20
Riley Major
1,1481432
1,1481432
answered Feb 17 '12 at 10:54
Damien_The_Unbeliever
192k17245331
192k17245331
add a comment |
add a comment |
I believe they both work because of the same underlying (and undocumented) behavior. I am fairly confident that if you take a case where Itzik has demonstrated that Approach A fails, that Approach B will also fail in the same way and for the same reasons, in spite of your colleague's claims. I don't see how
DECLARE @output VARCHAR(100);
SELECT @output = COALESCE(@output + ', ', '') + COL_VCHAR
Is any different from:
DECLARE @output VARCHAR(100) = '';
SELECT @output = @output + ', ' + COL_VCHAR
-- or SELECT @output += ',' + COL_VCHAR
So what exactly does COALESCE
magically introduce? SQL Server isn't going to change its plan because of something you're doing to the output, AFAIK.
I use them all the time for dynamic SQL generation and don't recall ever seeing them fail, and I realize that's not your question. Unfortunately there isn't really a way to prove it unless you know of a case that fails for either approach.
I wrote a blog post about string concatenation a few months ago. It's not completely relevant to your problem but Rob Farley made a comment that may be considered another downside to the COALESCE
approach:
https://sqlblog.org/2011/03/08/t-sql-tuesday-16-this-is-not-the-aggregate-youre-looking-for
Thanks for your input. The concern is relying on an undocumented behavior/feature in a massive production system. Some hotfix down the road, microsoft decides to do things different behind the scenes and this no longer works and breaks things.
– J Cooper
Feb 16 '12 at 19:07
Both can fail if if you want a specific order of the concatenated values. Not the case here but if you do,for xml
is the way to go.
– Mikael Eriksson
Feb 16 '12 at 19:09
If your concern is forward compatibility then I would say both approaches introduce the same level of risk. With that in mindFOR XML
is, as @Mikael suggests for other reasons, probably the most future-proof method. I realize that's not what you want to hear, but better safe than sorry. It's quite easy to encapsulate this kind of thing - how many different queries are you doing this concatenation for? If it is a lot then perhaps the data model should be a more important concern.
– Aaron Bertrand
Feb 16 '12 at 19:12
I read your article - you sure would be the right guy to answer this question! Yes, I thoughtFOR XML
would be the safe, supported way to go. Actually, Ben-Gan suggests this method in his book. As far as the data model, the data is pulled this way for presentational purposes a good bit - but not my call
– J Cooper
Feb 17 '12 at 0:54
@J Cooper one other comment. If guaranteeing future compatibility (or order) is paramount to strict performance, use a cursor. Anything else is an undocumented trick.
– Aaron Bertrand
Feb 17 '12 at 12:40
|
show 3 more comments
I believe they both work because of the same underlying (and undocumented) behavior. I am fairly confident that if you take a case where Itzik has demonstrated that Approach A fails, that Approach B will also fail in the same way and for the same reasons, in spite of your colleague's claims. I don't see how
DECLARE @output VARCHAR(100);
SELECT @output = COALESCE(@output + ', ', '') + COL_VCHAR
Is any different from:
DECLARE @output VARCHAR(100) = '';
SELECT @output = @output + ', ' + COL_VCHAR
-- or SELECT @output += ',' + COL_VCHAR
So what exactly does COALESCE
magically introduce? SQL Server isn't going to change its plan because of something you're doing to the output, AFAIK.
I use them all the time for dynamic SQL generation and don't recall ever seeing them fail, and I realize that's not your question. Unfortunately there isn't really a way to prove it unless you know of a case that fails for either approach.
I wrote a blog post about string concatenation a few months ago. It's not completely relevant to your problem but Rob Farley made a comment that may be considered another downside to the COALESCE
approach:
https://sqlblog.org/2011/03/08/t-sql-tuesday-16-this-is-not-the-aggregate-youre-looking-for
Thanks for your input. The concern is relying on an undocumented behavior/feature in a massive production system. Some hotfix down the road, microsoft decides to do things different behind the scenes and this no longer works and breaks things.
– J Cooper
Feb 16 '12 at 19:07
Both can fail if if you want a specific order of the concatenated values. Not the case here but if you do,for xml
is the way to go.
– Mikael Eriksson
Feb 16 '12 at 19:09
If your concern is forward compatibility then I would say both approaches introduce the same level of risk. With that in mindFOR XML
is, as @Mikael suggests for other reasons, probably the most future-proof method. I realize that's not what you want to hear, but better safe than sorry. It's quite easy to encapsulate this kind of thing - how many different queries are you doing this concatenation for? If it is a lot then perhaps the data model should be a more important concern.
– Aaron Bertrand
Feb 16 '12 at 19:12
I read your article - you sure would be the right guy to answer this question! Yes, I thoughtFOR XML
would be the safe, supported way to go. Actually, Ben-Gan suggests this method in his book. As far as the data model, the data is pulled this way for presentational purposes a good bit - but not my call
– J Cooper
Feb 17 '12 at 0:54
@J Cooper one other comment. If guaranteeing future compatibility (or order) is paramount to strict performance, use a cursor. Anything else is an undocumented trick.
– Aaron Bertrand
Feb 17 '12 at 12:40
|
show 3 more comments
I believe they both work because of the same underlying (and undocumented) behavior. I am fairly confident that if you take a case where Itzik has demonstrated that Approach A fails, that Approach B will also fail in the same way and for the same reasons, in spite of your colleague's claims. I don't see how
DECLARE @output VARCHAR(100);
SELECT @output = COALESCE(@output + ', ', '') + COL_VCHAR
Is any different from:
DECLARE @output VARCHAR(100) = '';
SELECT @output = @output + ', ' + COL_VCHAR
-- or SELECT @output += ',' + COL_VCHAR
So what exactly does COALESCE
magically introduce? SQL Server isn't going to change its plan because of something you're doing to the output, AFAIK.
I use them all the time for dynamic SQL generation and don't recall ever seeing them fail, and I realize that's not your question. Unfortunately there isn't really a way to prove it unless you know of a case that fails for either approach.
I wrote a blog post about string concatenation a few months ago. It's not completely relevant to your problem but Rob Farley made a comment that may be considered another downside to the COALESCE
approach:
https://sqlblog.org/2011/03/08/t-sql-tuesday-16-this-is-not-the-aggregate-youre-looking-for
I believe they both work because of the same underlying (and undocumented) behavior. I am fairly confident that if you take a case where Itzik has demonstrated that Approach A fails, that Approach B will also fail in the same way and for the same reasons, in spite of your colleague's claims. I don't see how
DECLARE @output VARCHAR(100);
SELECT @output = COALESCE(@output + ', ', '') + COL_VCHAR
Is any different from:
DECLARE @output VARCHAR(100) = '';
SELECT @output = @output + ', ' + COL_VCHAR
-- or SELECT @output += ',' + COL_VCHAR
So what exactly does COALESCE
magically introduce? SQL Server isn't going to change its plan because of something you're doing to the output, AFAIK.
I use them all the time for dynamic SQL generation and don't recall ever seeing them fail, and I realize that's not your question. Unfortunately there isn't really a way to prove it unless you know of a case that fails for either approach.
I wrote a blog post about string concatenation a few months ago. It's not completely relevant to your problem but Rob Farley made a comment that may be considered another downside to the COALESCE
approach:
https://sqlblog.org/2011/03/08/t-sql-tuesday-16-this-is-not-the-aggregate-youre-looking-for
edited Nov 11 at 14:21
answered Feb 16 '12 at 19:02
Aaron Bertrand
207k27361404
207k27361404
Thanks for your input. The concern is relying on an undocumented behavior/feature in a massive production system. Some hotfix down the road, microsoft decides to do things different behind the scenes and this no longer works and breaks things.
– J Cooper
Feb 16 '12 at 19:07
Both can fail if if you want a specific order of the concatenated values. Not the case here but if you do,for xml
is the way to go.
– Mikael Eriksson
Feb 16 '12 at 19:09
If your concern is forward compatibility then I would say both approaches introduce the same level of risk. With that in mindFOR XML
is, as @Mikael suggests for other reasons, probably the most future-proof method. I realize that's not what you want to hear, but better safe than sorry. It's quite easy to encapsulate this kind of thing - how many different queries are you doing this concatenation for? If it is a lot then perhaps the data model should be a more important concern.
– Aaron Bertrand
Feb 16 '12 at 19:12
I read your article - you sure would be the right guy to answer this question! Yes, I thoughtFOR XML
would be the safe, supported way to go. Actually, Ben-Gan suggests this method in his book. As far as the data model, the data is pulled this way for presentational purposes a good bit - but not my call
– J Cooper
Feb 17 '12 at 0:54
@J Cooper one other comment. If guaranteeing future compatibility (or order) is paramount to strict performance, use a cursor. Anything else is an undocumented trick.
– Aaron Bertrand
Feb 17 '12 at 12:40
|
show 3 more comments
Thanks for your input. The concern is relying on an undocumented behavior/feature in a massive production system. Some hotfix down the road, microsoft decides to do things different behind the scenes and this no longer works and breaks things.
– J Cooper
Feb 16 '12 at 19:07
Both can fail if if you want a specific order of the concatenated values. Not the case here but if you do,for xml
is the way to go.
– Mikael Eriksson
Feb 16 '12 at 19:09
If your concern is forward compatibility then I would say both approaches introduce the same level of risk. With that in mindFOR XML
is, as @Mikael suggests for other reasons, probably the most future-proof method. I realize that's not what you want to hear, but better safe than sorry. It's quite easy to encapsulate this kind of thing - how many different queries are you doing this concatenation for? If it is a lot then perhaps the data model should be a more important concern.
– Aaron Bertrand
Feb 16 '12 at 19:12
I read your article - you sure would be the right guy to answer this question! Yes, I thoughtFOR XML
would be the safe, supported way to go. Actually, Ben-Gan suggests this method in his book. As far as the data model, the data is pulled this way for presentational purposes a good bit - but not my call
– J Cooper
Feb 17 '12 at 0:54
@J Cooper one other comment. If guaranteeing future compatibility (or order) is paramount to strict performance, use a cursor. Anything else is an undocumented trick.
– Aaron Bertrand
Feb 17 '12 at 12:40
Thanks for your input. The concern is relying on an undocumented behavior/feature in a massive production system. Some hotfix down the road, microsoft decides to do things different behind the scenes and this no longer works and breaks things.
– J Cooper
Feb 16 '12 at 19:07
Thanks for your input. The concern is relying on an undocumented behavior/feature in a massive production system. Some hotfix down the road, microsoft decides to do things different behind the scenes and this no longer works and breaks things.
– J Cooper
Feb 16 '12 at 19:07
Both can fail if if you want a specific order of the concatenated values. Not the case here but if you do,
for xml
is the way to go.– Mikael Eriksson
Feb 16 '12 at 19:09
Both can fail if if you want a specific order of the concatenated values. Not the case here but if you do,
for xml
is the way to go.– Mikael Eriksson
Feb 16 '12 at 19:09
If your concern is forward compatibility then I would say both approaches introduce the same level of risk. With that in mind
FOR XML
is, as @Mikael suggests for other reasons, probably the most future-proof method. I realize that's not what you want to hear, but better safe than sorry. It's quite easy to encapsulate this kind of thing - how many different queries are you doing this concatenation for? If it is a lot then perhaps the data model should be a more important concern.– Aaron Bertrand
Feb 16 '12 at 19:12
If your concern is forward compatibility then I would say both approaches introduce the same level of risk. With that in mind
FOR XML
is, as @Mikael suggests for other reasons, probably the most future-proof method. I realize that's not what you want to hear, but better safe than sorry. It's quite easy to encapsulate this kind of thing - how many different queries are you doing this concatenation for? If it is a lot then perhaps the data model should be a more important concern.– Aaron Bertrand
Feb 16 '12 at 19:12
I read your article - you sure would be the right guy to answer this question! Yes, I thought
FOR XML
would be the safe, supported way to go. Actually, Ben-Gan suggests this method in his book. As far as the data model, the data is pulled this way for presentational purposes a good bit - but not my call– J Cooper
Feb 17 '12 at 0:54
I read your article - you sure would be the right guy to answer this question! Yes, I thought
FOR XML
would be the safe, supported way to go. Actually, Ben-Gan suggests this method in his book. As far as the data model, the data is pulled this way for presentational purposes a good bit - but not my call– J Cooper
Feb 17 '12 at 0:54
@J Cooper one other comment. If guaranteeing future compatibility (or order) is paramount to strict performance, use a cursor. Anything else is an undocumented trick.
– Aaron Bertrand
Feb 17 '12 at 12:40
@J Cooper one other comment. If guaranteeing future compatibility (or order) is paramount to strict performance, use a cursor. Anything else is an undocumented trick.
– Aaron Bertrand
Feb 17 '12 at 12:40
|
show 3 more comments
In your example, there is a way to get different results, and that is if NULL values are introduced into the data set. e.g.:
set nocount on
declare @test table (value int)
insert into @test values (10)
insert into @test values (20)
insert into @test values (null)
insert into @test values (40)
insert into @test values (50)
DECLARE @output VARCHAR(max);
-- Approach A
SET @output = '';
SELECT @output = @output + CAST(value AS VARCHAR(10)) + ';'
FROM @test
print 'Result from A:'
print isnull(@output, '{null}')
-- Approach B
set @output = ''
SELECT @output = COALESCE(@output + ', ', '') + cast(value as varchar(10))
from @test
print 'Result from B:'
print isnull(@output, '{null}')
set nocount off
Approach A will return null, whereas Approach B will return 40, 50
add a comment |
In your example, there is a way to get different results, and that is if NULL values are introduced into the data set. e.g.:
set nocount on
declare @test table (value int)
insert into @test values (10)
insert into @test values (20)
insert into @test values (null)
insert into @test values (40)
insert into @test values (50)
DECLARE @output VARCHAR(max);
-- Approach A
SET @output = '';
SELECT @output = @output + CAST(value AS VARCHAR(10)) + ';'
FROM @test
print 'Result from A:'
print isnull(@output, '{null}')
-- Approach B
set @output = ''
SELECT @output = COALESCE(@output + ', ', '') + cast(value as varchar(10))
from @test
print 'Result from B:'
print isnull(@output, '{null}')
set nocount off
Approach A will return null, whereas Approach B will return 40, 50
add a comment |
In your example, there is a way to get different results, and that is if NULL values are introduced into the data set. e.g.:
set nocount on
declare @test table (value int)
insert into @test values (10)
insert into @test values (20)
insert into @test values (null)
insert into @test values (40)
insert into @test values (50)
DECLARE @output VARCHAR(max);
-- Approach A
SET @output = '';
SELECT @output = @output + CAST(value AS VARCHAR(10)) + ';'
FROM @test
print 'Result from A:'
print isnull(@output, '{null}')
-- Approach B
set @output = ''
SELECT @output = COALESCE(@output + ', ', '') + cast(value as varchar(10))
from @test
print 'Result from B:'
print isnull(@output, '{null}')
set nocount off
Approach A will return null, whereas Approach B will return 40, 50
In your example, there is a way to get different results, and that is if NULL values are introduced into the data set. e.g.:
set nocount on
declare @test table (value int)
insert into @test values (10)
insert into @test values (20)
insert into @test values (null)
insert into @test values (40)
insert into @test values (50)
DECLARE @output VARCHAR(max);
-- Approach A
SET @output = '';
SELECT @output = @output + CAST(value AS VARCHAR(10)) + ';'
FROM @test
print 'Result from A:'
print isnull(@output, '{null}')
-- Approach B
set @output = ''
SELECT @output = COALESCE(@output + ', ', '') + cast(value as varchar(10))
from @test
print 'Result from B:'
print isnull(@output, '{null}')
set nocount off
Approach A will return null, whereas Approach B will return 40, 50
answered Feb 16 '12 at 20:29
CD Jorgensen
1,20087
1,20087
add a comment |
add a comment |
They work differently, the first example adds an additional character to the end of the output variable, and yes they work because of the same behaviour.
The first example will work if your column had been a numeric or date also. It would however only take the first 10 characters of any value in the column. The second example would not cut off the column.
There is absolutely no recursive nature of COALESCE.
COALESCE is a way of replacing null values with replacement values.
EDIT:
I should add that i also prefer the second version, because you don't get that extra semicolon, in the end of output implying that more values will follow.
add a comment |
They work differently, the first example adds an additional character to the end of the output variable, and yes they work because of the same behaviour.
The first example will work if your column had been a numeric or date also. It would however only take the first 10 characters of any value in the column. The second example would not cut off the column.
There is absolutely no recursive nature of COALESCE.
COALESCE is a way of replacing null values with replacement values.
EDIT:
I should add that i also prefer the second version, because you don't get that extra semicolon, in the end of output implying that more values will follow.
add a comment |
They work differently, the first example adds an additional character to the end of the output variable, and yes they work because of the same behaviour.
The first example will work if your column had been a numeric or date also. It would however only take the first 10 characters of any value in the column. The second example would not cut off the column.
There is absolutely no recursive nature of COALESCE.
COALESCE is a way of replacing null values with replacement values.
EDIT:
I should add that i also prefer the second version, because you don't get that extra semicolon, in the end of output implying that more values will follow.
They work differently, the first example adds an additional character to the end of the output variable, and yes they work because of the same behaviour.
The first example will work if your column had been a numeric or date also. It would however only take the first 10 characters of any value in the column. The second example would not cut off the column.
There is absolutely no recursive nature of COALESCE.
COALESCE is a way of replacing null values with replacement values.
EDIT:
I should add that i also prefer the second version, because you don't get that extra semicolon, in the end of output implying that more values will follow.
edited Feb 17 '12 at 10:30
answered Feb 17 '12 at 9:54
t-clausen.dk
35.7k104380
35.7k104380
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f9317170%2fgroup-string-concatenation-which-approach-if-any-is-any-more-guaranteed%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Have you tried it?
– Adrian Carneiro
Feb 16 '12 at 18:49
@Adrian They both work. Question is not if they work, but if I am correct in saying that they both work because of the same undocumented behavior?
– J Cooper
Feb 16 '12 at 18:57