【问题标题】:exec sp_executesql error 'Incorrect syntax near 1' when using datetime parameter使用 datetime 参数时,exec sp_executesql 错误“接近 1 的语法不正确”
【发布时间】:2010-04-30 07:09:08
【问题描述】:

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

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

当我在分析器中查看时,它会将其解释为:

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 运行时,它会在日期上出错。

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

【问题讨论】:

    标签: sql-server datetime


    【解决方案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 不是参数化查询,因此它必须将日期时间参数解释为原始字符串,但作为未加引号的原始字符串,它们的语法不正确。您可以通过以下两种方法之一来解决此问题。

    第一,简单的方法:引用日期时间字符串。

    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
    

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

    【讨论】:

      【解决方案2】:

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

      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)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-12
        • 1970-01-01
        相关资源
        最近更新 更多