SQL要求声明声明的变量

时间:2016-01-08 13:56:59

标签: sql-server-2008 tsql

我正在尝试运行此SQL语法,但我一直收到错误:

  

Msg 137,Level 15,State 2,Line 1
  必须声明标量变量" @ startDate"。

但是,在我看来,变量已经在我的程序开始时声明了。为什么会抛出错误,我需要做些什么才能解决它?

我使用这种语法来调用我的存储过程:

exec [dbo].[DoThis] '01/01/2015','01/31/2015'

这是完整的程序,它会出现上面的编译错误。

ALTER Procedure [dbo].[DoThis]
(
  @startDate datetime,
  @endDate datetime
)
As 


Declare @storename varchar(500), @dblocation varchar(500), @sql varchar(max)

Select storename, dblocation
INTO #allstores
FROM tbl_allstores
where sales >= '1,000,000'

Declare c1 Cursor For

Select storename, dblocation
FROM #allstores

Open c1 

Fetch Next From c1 Into @storename, @dblocation

While @@FETCH_STATUS = 0
Begin
  Set @sql = 'Insert Into #storeinfo (storename, employeename, employeeaddress, employeephone) '
            +'Select '''+@storename+''' As ''storename'', '
            +'employeename, employeeaddress, employeephone '
            +'From '+@dblocation+' '
            +'where employeestatus = ''Active'' '
            +'and CAST(hiredate As Date) BETWEEN CAST(@startDate As Date) AND CAST(@endDate As Date) '
  Print(@sql)
  exec(@sql)

  Fetch Next From c1 Into @storename, @dblocation

End

Close c1
Deallocate c1


Select * from #storeinfo

Drop Table #allstores
Drop Table #storeinfo

2 个答案:

答案 0 :(得分:7)

当你exec(@sql)创建一个带有自己的局部变量的新上下文时,你还没有将@startDate值传递到该上下文中。

相反,请为您的SQL字符串声明参数:

exec sp_executesql @sql, '@startDate datetime, @endDate datetime', 
      @startDate, @endDate;

这些名称现在可供您的SQL使用,参数将传递给它们。

这种方法更好,因为它将变量视为参数更安全,因为它降低了SQL注入的风险。

作为附加提示,您还应该将@storeName作为参数传递。据我所知,你不能将@dbname作为参数传递,所以你应该确保它被正确引用。

所以完整的事情将是:

Set @sql = 'Insert Into #storeinfo (storename, employeename, employeeaddress, employeephone) '
        +' Select @storename As ''storename'', '
        +' employeename, employeeaddress, employeephone '
        +' From '+QUOTENAME(@dblocation)+' '
        +' where employeestatus = ''Active'' '
        +' and CAST(hiredate As Date) '
        +' BETWEEN CAST(@startDate As Date) AND CAST(@endDate As Date) '


Print(@sql)
exec sp_executesql @sql, 
    '@startDate datetime, @endDate datetime, @storeName nvarchar(100)', 
    @startDate, @endDate, @storeName;

答案 1 :(得分:3)

更改为:

+'and CAST(hiredate As Date) BETWEEN CAST(''' + @startDate + ''' As Date) AND CAST(''' + @endDate + ''' As Date) '

我认为会起作用,或者至少接近。您的问题是@startDate@endDate实际上并未在执行动态SQL的单独范围内声明。

基本上exec(@sql)是与存储过程范围的单独范围,实际上是声明@startDate@endDate