exec sp_executesql错误'使用datetime参数时,语法接近1'

时间:2010-04-30 07:09:08

标签: sql-server datetime

我有一个SSRSreport,它将以下文本发送到数据库:

EXEC ( 'DECLARE @TeamIds as TeamIdTableType ' + @Teams +
       ' EXEC rpt.DWTypeOfSicknessByCategoryReport @TeamIds , ' + 
       @DateFrom + ', ' + @DateTo + ', ' + @InputRankGroups + ', ' + 
       @SubCategories )

当我在profiler中查看它时,它将其解释为:

exec sp_executesql N'EXEC ( ''DECLARE @TeamIds as TeamIdTableType '' + @Teams +
 '' EXEC rpt.DWTypeOfSicknessByCategoryAndEmployeeDetailsReport @TeamIds, '' + 
@DateFrom + '', '' + @DateTo + '', '' + @InputRankGroups + '', '' + 
@SubCategories )',
N'@Teams nvarchar(34),@DateFrom datetime,@DateTo datetime,
@InputRankGroups varchar(1),@SubCategories bit',
@Teams=N'INSERT INTO @TeamIds VALUES (5);',
@DateFrom='2010-02-01 00:00:00',@DateTo='2010-04-30 00:00:00',
@InputRankGroups=N'1',@SubCategories=1

当这个sql在日期运行时出现错误。

我尝试更改日期格式,但没有帮助。如果我删除日期,它可以正常工作。

2 个答案:

答案 0 :(得分:1)

我想我知道这里发生了什么。如果执行的SQL是

EXEC ( 'DECLARE @TeamIds as TeamIdTableType ' + @Teams
    + ' EXEC rpt.DWTypeOfSicknessByCategoryReport @TeamIds , '
    + @DateFrom + ', '
    + @DateTo + ', '
    + @InputRankGroups + ', '
    + @SubCategories )

... SQL Server将首先执行字符串连接,然后在连接字符串上调用EXEC。使用给定参数的值,这意味着连接的字符串将类似于以下内容(为了可读性而调整了空白):

DECLARE @TeamIds as TeamIdTableType
INSERT INTO @TeamIds VALUES (5);
EXEC rpt.DWTypeOfSicknessByCategoryReport @TeamIds ,
    2010-02-01 00:00:00, 2010-04-30 00:00:00, 1, 1

问题是EXEC不是参数化查询,因此它必须将datetime参数解释为原始字符串,但作为原始未加引号的字符串,它们不是正确的语法。您可以通过以下两种方式解决此问题。

首先,简单方法:引用日期时间字符串。

EXEC ( 'DECLARE @TeamIds as TeamIdTableType ' + @Teams
    + ' EXEC rpt.DWTypeOfSicknessByCategoryReport @TeamIds , '
    + '''' + @DateFrom + ''', '
    + '''' + @DateTo + ''', '
    + @InputRankGroups + ', '
    + @SubCategories )

这为您提供了有效语法:

DECLARE @TeamIds as TeamIdTableType
INSERT INTO @TeamIds VALUES (5);
EXEC rpt.DWTypeOfSicknessByCategoryReport @TeamIds ,
    '2010-02-01 00:00:00', '2010-04-30 00:00:00', 1, 1

其次,几乎是简单但更正确的方式:使用参数化查询。

DECLARE @sql varchar(max)
SET @sql = 'DECLARE @TeamIds AS TeamIdTableType ' + @Teams
    + ' EXEC rpt.DWTypeOfSicknessByCategoryReport @TeamIds , @DateFrom, @DateTo, @InputRankGroups, @SubCategories'
EXEC sp_executesql @sql, N'@DateFrom datetime,@DateTo datetime,@InputRankGroups varchar(1),@SubCategories bit',
    @DateFrom, @DateTo, @InputRankGroups, @SubCategories

这样您就不必担心如何转义特定的值类型,尽管它稍微冗长一些。请注意,由于将原始SQL作为@Teams中的参数传递,因此无法完全对其进行参数化。这可能不是你可以控制的东西 - 我对SSRS并不熟悉。

答案 1 :(得分:0)

感谢您分享您的解决方案。我试图实现第二个,但我收到一个错误调用存储过程。我不得不稍微调整语法,这对我有用:

DECLARE @vSQL nvarchar(max) = N'
DECLARE @customerIdList Report.IntegerListTableType; 
'+@customerIdInserts+';
EXEC rpt_CustomerTransactionSummary
@startDate=@startDate,
@endDate=@endDate,
@accountType=@accountType,
@customerIds = @customerIdList';
exec sp_executesql 
  @vSQL,
  N'@startDate datetime, @endDate datetime, @accountType int',
  @startDate,
  @endDate',
  @accountType;

此语法也允许NULL值(例如,@ accountType = NULL)