【发布时间】:2021-06-27 17:51:46
【问题描述】:
我正在编写以下动态 SQL,并在 FROM 关键字周围出现错误。
关键字“FROM”附近的语法不正确。
' + @columnList + '
FROM [History]
我知道为什么,因为它前面不应该有逗号。但是,由于它前面的列 (@columnList) 是动态 SQL 的结果,我该如何解决这个问题?
基本上,我需要一种制作方法
SELECT @columnList =....
不要在最后选择的最后一列/帐户的末尾附加逗号。
在此部分末尾添加逗号:
quotename(AccTbl.Account), ',',
完整查询:
DECLARE @sqlCommand NVARCHAR(MAX) = '',
@columnList NVARCHAR(MAX) = '',
@pivotColumns NVARCHAR(MAX) = '';
SELECT @columnList =
(SELECT DISTINCT concat(CHAR(9), 'COALESCE(', quotename(AccTbl.Account), ', 0)', quotename(AccTbl.Account), ',', CHAR(10)) --CHAR(9) & CHAR(10) for indentation/formatting
FROM [Accounts] AccTbl
WHERE AccTbl.Account NOT IN ('WS')
FOR XML Path(''), TYPE).value('(./text())[1]', 'NVARCHAR(MAX)');
SELECT @pivotColumns = STUFF(
(SELECT DISTINCT concat(CHAR(9), ',', quotename(AccTbl.Account), CHAR(10))
FROM [Accounts] AccTbl
WHERE AccTbl.Account NOT IN ('WS')
FOR XML Path(''), TYPE).value('(./text())[1]', 'NVARCHAR(MAX)'), 1, 1, '');
/*
EXEC the sqlCommand as separate batches to prevent this error: 'CREATE VIEW' must be the first statement in a query batch.
https://stackoverflow.com/a/39135516/8397835
*/
SET @sqlCommand = '
USE [ABC_DB]
--GO
DROP VIEW IF EXISTS [dbo].[Piv];
--GO
SET ANSI_NULLS ON
--GO
SET QUOTED_IDENTIFIER ON
--GO
';
Execute sp_executesql @sqlCommand;
SET @sqlCommand = '
CREATE VIEW [dbo].[Piv]
AS
(SELECT
[Style Code],
' + @columnList + '
FROM [History]
PIVOT (SUM([Value]) FOR [Accounts] IN (
' + @pivotColumns + '
)
)
AS Piv);
';
PRINT @sqlCommand;
Execute sp_executesql @sqlCommand;
换句话说,现在发生的事情是这样的:
更新:
@columnList 使用前导逗号而不是尾随逗号修复,但前导逗号或尾随逗号将适用于 @pivotColumns,因为我们在查询的 PIVOT 部分中没有预先存在的列,就像我们在Style Code 的 SELECT 语句。
【问题讨论】:
-
您还附加了一个选项卡,因此您需要将
STUFF参数设置为, 1, 2, ''),如果可以的话,我强烈建议您使用STRING_AGG。此外,那些USE和SET命令需要在下一个查询中重复,它们仅适用于该范围。 -
@Charlieface 我考虑过使用
STRING AGG,但我有 sql server 2016 :( 另外,我什至需要那些 USE 和 SET 吗?我发现无论我手动创建视图,它们都会自动生成. 但是,我将它们放在单独的范围内的原因是因为我收到一个错误,即 CREATE VIEW 需要成为批处理中的第一个语句,并且一个 SO 答案建议将它们分成单独的批处理
标签: sql sql-server tsql dynamic-sql