存储过程错误“必须声明标量变量”

use*_*765 3 sql-server stored-procedures dynamic-sql t-sql

我正在尝试创建一个包含动态 SQL 的存储过程。proc 接收 5 个变量,其中 3 个是列和字段的名称,另外 2 个用于 OFFSET 和 FETCH NEXT 部分。我在最后两个变量上不断收到此错误:

消息 137,级别 15,状态 2,第 34 行 必须声明标量变量“@numOfOffset”。消息 137,级别 15,状态 2,第 34 行 必须声明标量变量“@numOfRows”。

我会感谢一些帮助,请

IF (SELECT 1 FROM sys.procedures WHERE [name] = 'sp_targil1') = 1
    DROP PROCEDURE sp_targil1;
GO

CREATE PROCEDURE sp_targil1 (@tableName varchar(30), @fieldNameAggBy varchar(30), @fieldNameToAggOn varchar(30)
    ,  @numOfOffset int, @numOfRows int
    )
AS
BEGIN
    DECLARE @query1 varchar(500)
    DECLARE @qaeryMain varchar(500)
    DECLARE @maxNumberOfRows int

    SET @qaeryMain = 
    '
    SELECT ' + @fieldNameAggBy + ', SUM(' + @fieldNameToAggOn + ') AS ' + @fieldNameToAggOn + '_Sum_By_' + @fieldNameAggBy +
    ' FROM ' + @tableName +
    ' GROUP BY ' + @fieldNameAggBy + 
    ' ORDER BY SUM(' + @fieldNameToAggOn + ') DESC OFFSET @numOfOffset - 1 ROWS FETCH NEXT @numOfRows ROWS ONLY'
    PRINT @qaeryMain
    EXECUTE (@qaeryMain)
END

Run Code Online (Sandbox Code Playgroud)

Joh*_*ner 7

您没有在动态 SQL 语句的上下文中声明@numOfOffset@numOfRows变量。如果您复制PRINT @qaeryMain语句的输出,您会注意到明显缺少任何DECLARE语句,这就是您收到错误的原因。

如果您只是将代码更改为以下内容,它应该可以解决您的问题,因为它将在您的 DSQL 语句中指定文字而不是未定义的变量。

IF (SELECT 1 FROM sys.procedures WHERE [name] = 'sp_targil1') = 1
    DROP PROCEDURE sp_targil1;
GO

CREATE PROCEDURE sp_targil1 (@tableName varchar(30), @fieldNameAggBy varchar(30), @fieldNameToAggOn varchar(30)
    ,  @numOfOffset int, @numOfRows int
    )
AS
BEGIN
    DECLARE @query1 varchar(500)
    DECLARE @qaeryMain varchar(500)
    DECLARE @maxNumberOfRows int

    SET @qaeryMain = 
    '
    SELECT ' + @fieldNameAggBy + ', SUM(' + @fieldNameToAggOn + ') AS ' + @fieldNameToAggOn + '_Sum_By_' + @fieldNameAggBy +
    ' FROM ' + @tableName +
    ' GROUP BY ' + @fieldNameAggBy + 
    ' ORDER BY SUM(' + @fieldNameToAggOn + ') DESC OFFSET ' + CAST(@numOfOffset AS VARHCAR(50)) + ' - 1 ROWS FETCH NEXT ' + CAST(@numOfRowsAS VARHCAR(50)) + ' ROWS ONLY'
    PRINT @qaeryMain
    EXECUTE (@qaeryMain)
END
Run Code Online (Sandbox Code Playgroud)