如何编写一个包含SQL服务器端模块(Stored Procedure)的动态SQL代码来创建文件?
How to write a SQL server-side module (Stored Procedure) containing the dynamic SQL code to create documents?
我写了一个包含动态的存储过程SQL来创建指定格式的文件。
文档是针对销售区域还是针对销售人员,将在 运行 时确定,因为它是动态的 SQL。
销售区域文件:
{"TerritoryID":1,"TotalYearlySales":[2620944,5325813,6759501,3355403]},
{"TerritoryID":2,"TotalYearlySales":[705672,3272240,2965567,876731]}
销售人员的文件:
{"SalesPersonID":274, "TotalYearlySales":[32568,516197,485881,201289]},
{"SalesPersonID":275, "TotalYearlySales":[986298,3806298,4490942,1191828]}
文档中的数据来自AdventureWorks
create procedure dbo.TotalYearlySales
@id nvarchar(30)
as
begin
set @id = cast (@id as varchar(30))
SELECT DISTINCT @id,
JSON_QUERY('[' +
STUFF(
(SELECT ',', rtrim(cast(SUM(TotalDue) as int))
FROM Sales.SalesOrderHeader SOH2
WHERE SOH1.@id = SOH2.@id
AND SOH2.@id is not null
GROUP BY YEAR(SOH2.OrderDate)
ORDER BY YEAR(SOH2.OrderDate)
FOR XML PATH(''))
, 1, 1, '')
+ ']') as TotalYearlySales
from Sales.SalesOrderHeader SOH1
GROUP BY cast (@id as varchar(30))
ORDER BY cast (@id as varchar(30))
FOR JSON AUTO;
end
declare @MyInput varchar(20);
set @MyInput= 'TerritoryID';
exec dbo.TotalYearlySales @MyInput;
此 SP 无法正常工作,因为我无法传递 @id,我收到一条错误消息 Incorrect syntax near '@id'。请告诉我如何使用动态 SQL 语句编写存储过程。
我正在使用 SQL Server 2019
如果我对问题的理解正确,您需要针对不同的分组标准(TerritoryID
和 SalesPersonID
)构建并执行动态语句。
基于问题中的尝试,一种可能的方法是以下存储过程。请注意,从 SQL Server 2017 开始,您可以使用 STRING_AGG()
(而不是 FOR XML PATH
)进行字符串聚合:
CREATE PROCEDURE dbo.TotalYearlySales
@id sysname
AS
BEGIN
DECLARE @stm nvarchar(max)
DECLARE @err int
-- Dynamic statement
SET @stm =
N'SELECT t.' + QUOTENAME(@id) + N', CONCAT(''['', STRING_AGG(t.TotalDue, '',''), '']'') AS TotalYearlySales ' +
N'FROM ( ' +
N'SELECT ' + QUOTENAME(@id) + N', CONVERT(int, SUM(TotalDue)) AS TotalDue ' +
N'FROM Sales.SalesOrderHeader ' +
N'WHERE ' + QUOTENAME(@id) + N' IS NOT NULL ' +
N'GROUP BY ' + QUOTENAME(@id) + N', YEAR(OrderDate) ' +
N') t ' +
N'GROUP BY t.' + QUOTENAME(@id) + N' ' +
N'FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER'
-- Statement execution
EXEC @err = sp_executesql @stm, N' @id sysname', @id
IF @err <> 0 BEGIN
PRINT 'Error'
END
END
执行:
DECLARE @MyInput sysname
SET @MyInput = N'TerritoryID';
EXEC dbo.TotalYearlySales @MyInput
我写了一个包含动态的存储过程SQL来创建指定格式的文件。 文档是针对销售区域还是针对销售人员,将在 运行 时确定,因为它是动态的 SQL。
销售区域文件:
{"TerritoryID":1,"TotalYearlySales":[2620944,5325813,6759501,3355403]},
{"TerritoryID":2,"TotalYearlySales":[705672,3272240,2965567,876731]}
销售人员的文件:
{"SalesPersonID":274, "TotalYearlySales":[32568,516197,485881,201289]},
{"SalesPersonID":275, "TotalYearlySales":[986298,3806298,4490942,1191828]}
文档中的数据来自AdventureWorks
create procedure dbo.TotalYearlySales
@id nvarchar(30)
as
begin
set @id = cast (@id as varchar(30))
SELECT DISTINCT @id,
JSON_QUERY('[' +
STUFF(
(SELECT ',', rtrim(cast(SUM(TotalDue) as int))
FROM Sales.SalesOrderHeader SOH2
WHERE SOH1.@id = SOH2.@id
AND SOH2.@id is not null
GROUP BY YEAR(SOH2.OrderDate)
ORDER BY YEAR(SOH2.OrderDate)
FOR XML PATH(''))
, 1, 1, '')
+ ']') as TotalYearlySales
from Sales.SalesOrderHeader SOH1
GROUP BY cast (@id as varchar(30))
ORDER BY cast (@id as varchar(30))
FOR JSON AUTO;
end
declare @MyInput varchar(20);
set @MyInput= 'TerritoryID';
exec dbo.TotalYearlySales @MyInput;
此 SP 无法正常工作,因为我无法传递 @id,我收到一条错误消息 Incorrect syntax near '@id'。请告诉我如何使用动态 SQL 语句编写存储过程。
我正在使用 SQL Server 2019
如果我对问题的理解正确,您需要针对不同的分组标准(TerritoryID
和 SalesPersonID
)构建并执行动态语句。
基于问题中的尝试,一种可能的方法是以下存储过程。请注意,从 SQL Server 2017 开始,您可以使用 STRING_AGG()
(而不是 FOR XML PATH
)进行字符串聚合:
CREATE PROCEDURE dbo.TotalYearlySales
@id sysname
AS
BEGIN
DECLARE @stm nvarchar(max)
DECLARE @err int
-- Dynamic statement
SET @stm =
N'SELECT t.' + QUOTENAME(@id) + N', CONCAT(''['', STRING_AGG(t.TotalDue, '',''), '']'') AS TotalYearlySales ' +
N'FROM ( ' +
N'SELECT ' + QUOTENAME(@id) + N', CONVERT(int, SUM(TotalDue)) AS TotalDue ' +
N'FROM Sales.SalesOrderHeader ' +
N'WHERE ' + QUOTENAME(@id) + N' IS NOT NULL ' +
N'GROUP BY ' + QUOTENAME(@id) + N', YEAR(OrderDate) ' +
N') t ' +
N'GROUP BY t.' + QUOTENAME(@id) + N' ' +
N'FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER'
-- Statement execution
EXEC @err = sp_executesql @stm, N' @id sysname', @id
IF @err <> 0 BEGIN
PRINT 'Error'
END
END
执行:
DECLARE @MyInput sysname
SET @MyInput = N'TerritoryID';
EXEC dbo.TotalYearlySales @MyInput