如何编写包含动态SQL代码的SQL server端模块(存储过程)来创建文档?
我编写了一个包含动态SQL的存储过程来创建指定格式的文档。 文档是针对销售区域还是针对销售人员,将在运行时确定,因为它是动态SQL 销售区域的文件:如何编写包含动态SQL代码的SQL server端模块(存储过程)来创建文档?,sql,sql-server,stored-procedures,dynamic-sql,sql-server-2019,Sql,Sql Server,Stored Procedures,Dynamic Sql,Sql Server 2019,我编写了一个包含动态SQL的存储过程来创建指定格式的文档。 文档是针对销售区域还是针对销售人员,将在运行时确定,因为它是动态SQL 销售区域的文件: {"TerritoryID":1,"TotalYearlySales":[2620944,5325813,6759501,3355403]}, {"TerritoryID":2,"TotalYearlySales":[705672,3272240,2965567,8
{"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
创建过程dbo.TotalYearlySales
@id nvarchar30
像
开始
将@id=cast@id设置为varchar30
选择DISTINCT@id,
JSON_查询'['+
东西
选择“,”rtrimcastSUMTotalDue作为int
来自Sales.SalesOrderHeader SOH2
其中SOH1@id=SOH2@id
和SOH2。@id不为空
按年份分组2.OrderDate
按年份订购2.OrderDate
对于XML路径
, 1, 1,
+“]”作为全年销售总额
来自Sales.SalesOrderHeader SOH1
按cast@id作为varchar30分组
通过铸造@id作为varchar30订购
对于JSON AUTO;
终止
声明@MyInput varchar20;
设置@MyInput='TerritoryID';
exec dbo.TotalYearlySales@MyInput;
此SP无法工作,因为我无法传递@id,我在“@id”附近收到一个错误,语法不正确。请告诉我如何使用动态SQL语句编写存储过程
我正在使用SQL Server 2019如果我正确理解了这个问题,您需要为不同的分组标准TerritoryID和SalesorsOnId构建并执行动态语句 根据问题中的尝试,一种可能的方法是以下存储过程。请注意,从SQL Server 2017开始,您可以使用STRING_AGG代替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
如果我正确理解了这个问题,您需要为不同的分组标准TerritoryID和SalesorsOnId构建并执行动态语句 根据问题中的尝试,一种可能的方法是以下存储过程。请注意,从SQL Server 2017开始,您可以使用STRING_AGG代替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
您好@Zhorov我使用的是SQL Server 2019,这不是动态SQL。动态sql是使用代码构建包含要运行的静态sql的变量,然后使用sp_executesql执行它。我建议阅读有关动态sql online的文章,然后再回来找我们。如果销售区域或销售人员是唯一两个可能的选择,我建议完全避免使用动态sql。只需使用一个简单的if和两个版本的查询。顺便说一句,a=B和B不为null应该是a=B。null永远不等于null或=谓词中的任何内容。我猜具体的问题在于SOH1。@id-即使您有一个名为@id的列,在这种情况下,我强烈建议重命名它。您好@Zhorov,我使用的是SQL Server 2019,这不是动态sql。动态sql是使用代码构建包含要运行的静态sql的变量,然后使用sp_executesql执行它。我建议阅读有关动态sql online的文章,然后再回来找我们。如果销售区域或销售人员是唯一两个可能的选择,我建议完全避免使用动态sql。只需使用一个简单的if和两个版本的查询。顺便说一句,a=B和B不为null应该是a=B。null永远不等于null或=谓词中的任何内容。我猜具体的问题在于SOH1。@id-即使您有一个名为@id的列,在这种情况下,我强烈建议重命名它。