Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

+= in SELECT clause; constant vs column [duplicate]

I observed some strange behavior in MS SQL Server 2017.

  • += in select acts as aggregator ('concatenate values from all rows') when on the right is a constant.
  • += in select acts as 'just set the value' when on the right is a column name. (also, this turns of aggregating behavior for other columns)

So my questions are:

  1. Why @c1 result contains value only last the row, even when += is used?
  2. Why is @c2 affected, by the change +=->= for @c1?

Version 1:

BEGIN
    DECLARE
        @c1 NVARCHAR(MAX) = N'',
        @c2 NVARCHAR(MAX) = N'';

    SELECT
        @c1 = constraint_name, -- version-1
        @c2 += '+'
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
    ORDER BY 1 DESC
    ;

    PRINT '@c1=' + @c1;
    PRINT '@c2=' + @c2;
END
;

Version 1 result:

@c1 = fk_abcde
@c2 = ++++++++++++++++++++++++++++++++++++++++++
(`@c2` result is aggregation of many rows; one plus for each row)

Version 2:

BEGIN
    DECLARE
        @c1 NVARCHAR(MAX) = N'',
        @c2 NVARCHAR(MAX) = N'';

    SELECT
        @c1 += constraint_name, -- version-2
        @c2 += '+'
    FROM INFORMATION_SCHEMA.REFERENTIAL_CONSTRAINTS
    ORDER BY 1 DESC
    ;

    PRINT '@c1=' + @c1;
    PRINT '@c2=' + @c2;
END
;

Version 2 Result:

@c1 = fk_abcde
@c2 = +
(`@c2` is just value assigned from last processed row)

This feels very strange - kind of like a bug. I fail to find any docs about this. The doc on '+= string' don't mention += usage in select query at all.

(at the moment my goal is to understand the behavior fully, so I would not accidentally step on it. Any hints to right documentation/keywords to search for would be helpful)

like image 736
IndustryUser1942 Avatar asked Feb 27 '19 06:02

IndustryUser1942


People also ask

Which order of clauses in a SELECT statement is correct?

Detailed Solution. The correct answer is Select, where, group by, having.

What are the two required clauses for a SELECT statement?

Each SQL query statement must contain both a SELECT and a FROM clause. The combination of these two clauses determine the table columns that are searched by the query. The WHERE clause and other advanced clauses further limit data retrieval to specific table rows.

Which clause is required in a SELECT statement?

The FROM clause is the only required clause in the SELECT statement. The FROM clause specifies the specific database tables to retrieve data from.

What items are there in column names can be included in the SELECT clause?

It can consist of these items individually or together: An asterisk, shorthand for all the columns in the table, displayed in CREATE TABLE order. One or more column names, in any order. One or more character constants (such as "Total") used as display headings or text embedded in the results.


1 Answers

It's in the wrong place in the documentation, so not surprising that you haven't found it:

Don't use a variable in a SELECT statement to concatenate values (that is, to compute aggregate values). Unexpected query results may occur. Because, all expressions in the SELECT list (including assignments) aren't necessarily run exactly once for each output row

It's better to look for different ways of doing string concatenation. If your version supports it, choose to use STRING_AGG. For earlier versions, Aaron Bertrand has provided a good set of options (hat tip to Panagiotis Kanavos for providing the link)

like image 182
Damien_The_Unbeliever Avatar answered Oct 07 '22 20:10

Damien_The_Unbeliever