Reputation: 48
I have really strange problem (or misunderstanding) of the string concatenation on Azure Sql. I used to build T-SQL code for EXEC like this:
DECLARE @tsql nvarchar(max)
SELECT @tsql = CONCAT(@tsql, Prop1, Prop2) FROM Table
PRINT @tsql
This works fine in SQL from 2012 to 2016. But in Azure SQL I have really strange behavior: only LAST row is in @tsql
Here is live T-SQL to clean up some tables:
DECLARE @deleteTsql nvarchar(max)
SET @deleteTsql = ''
-- just show all table
SELECT O.[name] FROM [sys].[objects] O
LEFT JOIN sys.schemas SCH on O.schema_id = SCH.schema_id
WHERE (SCH.[name] = 'dbo' AND [type] = 'U') or (SCH.[name] = 'data' and O.[name] = 'Objects')
ORDER BY O.create_date desc
-- build T-SQL to cleanup
SELECT @deleteTsql = CONCAT(@deleteTsql, 'PRINT ''Deleting data from ', O.[name], '''', CHAR(10), CHAR(13), 'DELETE FROM [', SCH.[name], '].', '[', O.[name],']', CHAR(10), CHAR(13)) FROM [sys].[objects] O
LEFT JOIN [sys].[schemas] SCH on O.[schema_id] = SCH.[schema_id]
WHERE (SCH.[name] = 'dbo' AND [type] = 'U') or (SCH.[name] = 'data' and O.[name] = 'Objects')
ORDER BY O.create_date desc
PRINT @deleteTsql
This works fine in SQL 2016. For instance I have tables data.Objects, dbo.Table1 and dbo.Table2. Then following will be printed:
(3 rows affected)
PRINT 'Deleting data from Objects'
DELETE FROM [data].[Objects]
PRINT 'Deleting data from Table1'
DELETE FROM [dbo].[Table1]
PRINT 'Deleting data from Table2'
DELETE FROM [dbo].[Table2]
But if I do the same on Azure SQL (v12) database with same tables then I got this:
(3 rows affected)
PRINT 'Deleting data from Table2'
DELETE FROM [dbo].[Table2]
So only last record is in @deleteTsql. Why?????
Upvotes: 0
Views: 189
Reputation: 5694
The result for aggregate concatenation (with the SELECT @x=@x+...
syntax) is undefined. See KB 287515 and this answer. Using CONCAT
does not change that. As Panagiotis Kanavos suggested, you should use STRING_AGG
or GROUP_CONCAT
.
And one more thing: in my databases, I get the results from a single row using your query, even in SQL Server 2016 or SQL Server 2017. So it's not an Azure thing, it's just depending on the execution plan (if it is using a nested loops join, you get all the rows; if it is using a merge join, you get a single row). That may be dependant on the number of rows in the system tables, the CPU count, the updated statistics, etc.
Upvotes: 1