【问题标题】:Dynamic Sp_Executesql failing on datetime conversion error动态 Sp_Executesql 因日期时间转换错误而失败
【发布时间】:2019-10-27 10:07:37
【问题描述】:

我有一个非常简单的动态 SQL 查询,特别需要使用带有参数的 sp_executesql 来调用它。此查询在常规动态 SQL 中运行良好,但在转换错误时使用 sp_executesql 时失败。

我尝试了许多动态 SQL 的组合,但似乎没有一个专门用于与 sp_executesql 相关的日期时间转换。

declare 
@sql_nvarchar nvarchar(max),
@datetime datetime = GETDATE(),
@sqlparams nvarchar(max),
@tablename nvarchar(max) = 'SomeTableName'

Set @sql_nvarchar =
N'
Select *
from ' + @tablename + '
where Date > ''' + convert(nvarchar(23), @datetime, 101) + ''' '

Set @sqlparams =
N'
@datetime datetime,
@tablename nvarchar(max)
'

EXEC(@sql_nvarchar)

EXEC [sp_executesql] @sql_nvarchar,@sqlparams, @datetime, @tablename

第一个 exec 正确返回所需的查询,第二个 EXEC 抛出错误:'Error convert data type nvarchar(max) to datetime.'

【问题讨论】:

  • 您的查询在我运行时有效。你确定SomeTableNameDate 列的类型是datetime
  • @DaleBurrell,如果我添加一个临时表 #SomeTableName,则两个 EXEC 都可以正确完成,但是当我将 #SomeTableName 替换为具有正确日期时间字段的生产表时,我仍然会看到错误消息引用的字段名称。
  • @DaleBurrell 如何获取要传入的参数?我不想使用静态查询进行测试,因为整个问题是我可以让它在常规和动态 sql 中工作,而不是 sp_executesql。
  • 为什么要将@datetime 转换为varchar 以将其与日期进行比较?它已经是一个日期,因此您无需将其转换为任何内容。也许这就是问题?删除转换。

标签: sql sql-server datetime dynamic-sql


【解决方案1】:

您不能参数化标识符,例如表名。因此,将其表述为:

Set @sql_nvarchar = N'
Select *
from ' + @tablename + '
where Date > @datetime
';

Set @sqlparams = N'@datetime datetime'
exec sp_executesql @sql_nvarchar, @sqlparams,
                   @datetime=@datetime

【讨论】:

  • @tablename 真的应该被引用,否则这只是一个等待发生的注入问题。特别是当 OP 使用nvarchar(MAX) 而不是sysname
  • 这解决了问题...我不完全确定最初的问题是什么(我认为它甚至可能与转换没有任何关系,并且可能是语法错误),但是把动态 SQL 查询中的参数并从参数中删除 @tablename 修复了问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
  • 1970-01-01
  • 1970-01-01
  • 2016-08-06
  • 1970-01-01
相关资源
最近更新 更多