Sql server 动态查询和datepart SQL问题

Sql server 动态查询和datepart SQL问题,sql-server,dynamic-sql,Sql Server,Dynamic Sql,我发现了错误 为dateadd指定的参数1无效 当我尝试在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 = D

我发现了错误

为dateadd指定的参数1无效

当我尝试在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
等),而不是文字字符串,也不是变量。有些人遇到了同样的问题,他们认为他们可以参数化一些东西,比如表名。第一条语句失败,因为即使在静态sql中,这也是无效的:

declare @increment nvarchar(5) = 'day'

select dateadd(@increment, 1, getdate())
那相当于

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

第二条语句成功,因为您将要计算的字符串“day”连接到关键字

因此,考虑参数化动态sql的方法是,如果参数是静态sql,则只能在可以使用的地方使用参数
DATEADD
需要一个特殊的日期部分关键字(例如,
day、hour、year
等),而不是文字字符串,也不是变量。有些人遇到了同样的问题,他们认为他们可以参数化一些东西,比如表名。第一条语句失败,因为即使在静态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))
在第二个查询中,它变成:

SELECT @result=DATEADD('DAY', @Increment, CAST(@BaseDate AS DATE))
SELECT @result=DATEADD(DAY, @Increment, CAST(@BaseDate AS DATE))
第一个查询无效,因为DATEADD的第一个参数是字符串值,其中编译器需要语言关键字,而这些关键字在SQL中不相同

有关更多信息,请参见此处:

请注意datepart下的行,该行表示
用户定义的变量等效项无效
。换句话说,您不能在这些“值”周围加引号,它们不是字符串而是关键字,也不能放在变量中。

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

SELECT @result=DATEADD('DAY', @Increment, CAST(@BaseDate AS DATE))
SELECT @result=DATEADD(DAY, @Increment, CAST(@BaseDate AS DATE))
在第二个查询中,它变成:

SELECT @result=DATEADD('DAY', @Increment, CAST(@BaseDate AS DATE))
SELECT @result=DATEADD(DAY, @Increment, CAST(@BaseDate AS DATE))
第一个查询无效,因为DATEADD的第一个参数是字符串值,其中编译器需要语言关键字,而这些关键字在SQL中不相同

有关更多信息,请参见此处:

请注意datepart下的行,该行表示
用户定义的变量等效项无效
。换句话说,你不能在这些“值”周围加引号,它们不是字符串而是关键字,也不能放在变量中。

这是一个很好的答案,但要添加一些东西。。。请参阅其中关于datepart参数的说明“用户定义的变量等价物无效”。这是一个很好的答案,但要添加一些内容。。。请参阅其中关于datepart参数的说明“用户定义的变量等效项无效”