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

时间:2018-08-16 01:40:09

标签: sql sql-server stored-procedures

我已经编写了一个存储过程来从SQL Server中的表中提取数据:

SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO

ALTER PROCEDURE [dbo].[csp_OperatorVarianceMonthlyView]
-- =============================================
-- Procedure: csp_OperatorVarianceMonthlyView
--
-- Summary: Produce the result table that is needed for the Operator Variance Tracker report.
--
-- Params: @RetailStoreId - Store Id on which the results need to be filtered
--         @StartDate - The start business day date for which results are to be collected (NULL = Today)
--         @EndDate - The end business day date for which results are to be collected (NULL = Today)
--         @OperatorIDList - OperatorID comma seperated list

-- Returns:   A result set to populate a Operator Variance Report tab
--
-- Version: 2013-06-25 11:00
-- ==============================================
    @TenantID       t_ID,
    @RetailStoreID  t_ID,
    @StartDate      t_Timestamp = null,
    @EndDate        t_Timestamp = null,
    @OperatorIDList varchar(500)=null
AS
    IF 1 = 0 
    BEGIN
        SET FMTONLY OFF
    END
BEGIN
    declare @SQL                    nvarchar(2500)
    declare @StartBusinessDayDate   t_TimeStamp
    declare @EndBusinessDayDate     t_TimeStamp
    declare @StartDateOfYear        t_TimeStamp
    declare @StartDateOfMonth       t_TimeStamp
    declare @Sunday                 t_TimeStamp
    declare @FirstSundayOfMonth     t_TimeStamp

    SET NOCOUNT ON;

    if (@StartDate is null)
        select @StartDate = GETDATE()

    if (@EndDate is null)
        select @EndDate = GETDATE()

    -- Eliminate any time information that might be in the Start/End dates
    select @StartBusinessDayDate = convert(varchar(8), cast (@StartDate as datetime), 112)
    select @EndBusinessDayDate   = convert(varchar(8), cast (@EndDate   as datetime), 112)

    -- Compute StartDateOfYear and StartDateOfMonth to compute the YTD and MTD variances
    set @StartDateOfYear = DATEADD(year, DATEDIFF(year, 0, @EndBusinessDayDate),0)
    set @StartDateOfMonth = DATEADD(month, DATEDIFF(month, 0, @EndBusinessDayDate), 0)

    -- Select a Sunday 
    set @Sunday = '2017-01-01' 
    -- Get first Sunday of the month for getting week-wise data for the OVT report
    set @FirstSundayOfMonth = DATEADD(WEEK, DATEDIFF(WEEK, @Sunday, @StartBusinessDayDate), @Sunday)  

-- Create temporary tables to hold the monthly and yearly variance amounts for each operator
Create table #TempOperatorVarianceYTD ([OperatorID] int, [VarianceAmtYTD] decimal)
Create table #TempOperatorVarianceMTD ([OperatorID] int, [VarianceAmtMTD] decimal)

-- Insert Year To Date (YTD) variance amounts by operator to the tempoarary table
Insert into #TempOperatorVarianceYTD 
Select OperatorID, sum(NetOverShortAmount)
from TillBalanceExceptionPTDSummary
where BusinessDayDate between @StartDateOfYear and @EndBusinessDayDate
and RetailStoreID = @RetailStoreID
and PeriodTypeCode = 1
group by OperatorID

-- Insert Month To Date (MTD) variance amounts by operator to the tempoarary table
Insert into #TempOperatorVarianceMTD 
Select OperatorID, sum(NetOverShortAmount)
from TillBalanceExceptionPTDSummary
where BusinessDayDate between @StartDateOfMonth and @EndBusinessDayDate
and RetailStoreID = @RetailStoreID
and PeriodTypeCode = 1
group by OperatorID

-- Build the SQL statement to get the result table for the monthly view of the Operator Variance Tracker report. 
select @SQL = 'Select TBES.OperatorID as OperatorID, ' +
              'O.[Name] as OperatorName, ' +
              'YTD = YTD.VarianceAmtYTD, ' +
              'MTD = MTD.VarianceAmtMTD, ' +
              'Week1 = SUM(CASE WHEN TBES.PeriodTypeCode = 2 AND TBES.BusinessDayDate = @FirstSundayOfMonth THEN TBES.NetOverShortAmount ELSE 0 END), ' +
              'Week2 = SUM(CASE WHEN TBES.PeriodTypeCode = 2 AND TBES.BusinessDayDate = DATEADD(WEEK, 1, @FirstSundayOfMonth) THEN TBES.NetOverShortAmount ELSE 0 END), ' +
              'Week3 = SUM(CASE WHEN TBES.PeriodTypeCode = 2 AND TBES.BusinessDayDate = DATEADD(WEEK, 2, @FirstSundayOfMonth) THEN TBES.NetOverShortAmount ELSE 0 END), ' +
              'Week4 = SUM(CASE WHEN TBES.PeriodTypeCode = 2 AND TBES.BusinessDayDate = DATEADD(WEEK, 3, @FirstSundayOfMonth) THEN TBES.NetOverShortAmount ELSE 0 END), ' +
              'Week5 = SUM(CASE WHEN TBES.PeriodTypeCode = 2 AND TBES.BusinessDayDate = DATEADD(WEEK, 4, @FirstSundayOfMonth) THEN TBES.NetOverShortAmount ELSE 0 END) ' +
              'FROM [postrn001].[dbo].[TillBalanceExceptionPTDSummary] TBES ' +
              'join [posfdn001].[dbo].[Operator] O ' +
              'on TBES.OperatorID = O.OperatorID ' +
              'join #TempOperatorVarianceYTD YTD ' +
              'on O.OperatorID = YTD.OperatorID ' +
              'join #TempOperatorVarianceMTD MTD ' +
              'on O.OperatorID = MTD.OperatorID ' +
              'where TBES.RetailStoreID = @RetailStoreID '
-- Add the operator filter if necessary
if ( NOT (@OperatorIDList is null) )
    begin
        -- Avoid sql injection by cleaning the string
        set @OperatorIDList = REPLACE(@OperatorIDList, ';', '')
        set @OperatorIDList = REPLACE(@OperatorIDList, ')', '')
        set @OperatorIDList = REPLACE(@OperatorIDList, '-', '')
        select @SQL = @SQL + 'and TBES.OperatorID IN (' + @OperatorIDList + ') '
    end
--Add the group by clause
select @SQL = @SQL + 'group by TBES.OperatorID, O.[Name], YTD.VarianceAmtYTD, MTD.VarianceAmtMTD'

print @SQL
print @FirstSundayOfMonth

exec sp_executesql @SQL,
             N'@TenantID t_ID, @RetailStoreId t_ID, @StartBusinessDayDate t_TimeStamp, @EndBusinessDayDate t_TimeStamp, @OperatorIDList varchar(500)',
             @TenantID, @RetailStoreId, @StartBusinessDayDate, @EndBusinessDayDate, @OperatorIDList

return @@error

-- Drop the temporary tables. 
drop table #TempOperatorVarianceMTD, #TempOperatorVarianceYTD

END

执行此操作后,出现此错误:

  

必须声明标量变量“ @FirstSundayOfMonth”

您可以在代码中看到,我已经在存储过程中声明并初始化了@FirstSundayOfMonth的值。

我不确定在这里可能会缺少什么-我尝试将查询部分复制到单独的窗口中,并在将值分配给声明的变量之后执行它,然后执行并生成我期望的结果。

我猜想我遗漏了一些小东西,但是我无法弄清楚它是什么。

任何领先者都很棒!

1 个答案:

答案 0 :(得分:2)

在外部作用域中声明的变量对于动态SQL语句不可见。将@FirstSundayOfMonth作为另一个参数传递到sp_executesql