动态查询和日期部分问题 SQL

Issue with dynamic query and datepart SQL

我遇到错误

Invalid parameter 1 specified for dateadd.

当我尝试在 SQL Server 2012 中执行以下动态参数化查询时:

DECLARE @Interval nvarchar(5) = 'DAY'  
DECLARE @Increment int = 10
DECLARE @BaseDate date = getdate()
DECLARE @ResultDate date
DECLARE @Query nvarchar(2000)

SET @Query = 'SELECT @result = DATEADD(@Interval, @Increment, CAST(@BaseDate AS DATE))'    

EXECUTE sp_executesql @Query,
           N'@result date OUTPUT, @Interval varchar(50), @Increment int, @BaseDate date',
           @Interval = @Interval, @Increment = @Increment, 
           @BaseDate = @BaseDate, @result = @ResultDate OUTPUT

SELECT @ResultDate

我已将 SET @Query 行更改为这一行。

SET @Query = 'SELECT @result = DATEADD(' + @Interval +', @Increment, CAST(@BaseDate AS DATE))'

虽然它工作正常,但我很好奇为什么第一条语句导致我的动态 SQL 查询出错?。 sp_executesql 生成的语句是否与串联查询生成的语句相同?

因此,考虑参数化动态 sql 的方法是,如果参数是静态的 SQL,您只能在可以使用的地方使用参数。 DATEADD 需要一个特殊的日期部分关键字(例如 day, hour, year 等),而不是文字字符串,也不是变量。一些人 运行 认为他们可以参数化 table 名称之类的东西也是同样的问题。第一条语句失败,因为即使在静态 sql 中,这也是无效的:

declare @increment nvarchar(5) = 'day'

select dateadd(@increment, 1, getdate())

这相当于

select dateadd('day', 1, getdate())

第二个语句成功,因为您将字符串 "day" 连接到 关键字

在第一种情况下,查询(@Interval 扩展为其值)变为:

SELECT @result=DATEADD('DAY', @Increment, CAST(@BaseDate AS DATE))

在第二个查询中变成这样:

SELECT @result=DATEADD(DAY, @Increment, CAST(@BaseDate AS DATE))

第一个查询无效,因为 DATEADD 的第一个参数是 字符串值 ,编译器需要 语言关键字 , SQL.

中的那些不一样

有关详细信息,请参阅此处:https://docs.microsoft.com/en-us/sql/t-sql/functions/dateadd-transact-sql
请注意 datepart 下的行 User-defined variable equivalents are not valid。换句话说,你不能在这些"values"两边加上引号,它们不是字符串而是关键字,它们不能放在变量中。