我使用以下动态SQL查询来过滤数据范围的结果。如果我的“createdFrom
”和“createdTo
”日期不为null,我会在select语句中添加where子句。
我有两个问题:
你会怎么做呢?我的逻辑是否正确?
我在添加以下代码时收到错误消息,为什么我会收到此消息?:
将字符串转换为smalldatetime时转换失败 数据类型。
Declare @createdFromDate SMALLDATETIME = NULL ,
@createdToDate SMALLDATETIME = NULL
IF @createdFromDate IS NOT NULL
BEGIN
SELECT @sWhere = @sWhere + 'AND g.CreatedOn > '+@createdFromDate
END
IF @createdToDate IS NOT NULL
BEGIN
SELECT @sWhere = @sWhere + ' AND g.CreatedOn <'+@createdToDate
END
答案 0 :(得分:2)
对于你的问题
当我添加以下代码时,我当前收到错误消息,为什么我会收到此消息?
您收到此错误的原因是执行查询时您的条件变为
AND g.CreatedOn > 2015-05-07
哪个无效,而是你的需要
AND g.CreatedOn > '2015-05-07'
因此你的SQL应该是
SELECT @sWhere = @sWhere + 'AND g.CreatedOn > '''+@createdFromDate + ''''
对于你的问题
你会怎么做呢?我的逻辑是否正确?
您应该使用sp_executesql
并在动态SQL中传递变量。
IF @createdFromDate IS NOT NULL
BEGIN
SELECT @sWhere = @sWhere + 'AND g.CreatedOn > @createdFromDate'
END
IF @createdToDate IS NOT NULL
BEGIN
SELECT @sWhere = @sWhere + ' AND g.CreatedOn < @createdToDate'
END
而不是
EXEC(@SQL)
你会用
EXEC sp_executeSQL @SQL,N'@createdFromDate smalldatetime,@createdToDate smalldatetime',@createdFromDate,@createdToDate
从@SQL
@Where
的位置
注意:如果这是使用它的唯一原因,您就不需要动态SQL。
答案 1 :(得分:2)
您问题的直接答案是日期常量需要用单引号括起来。而不是:
SELECT @sWhere = @sWhere + 'AND g.CreatedOn > '+@createdFromDate
使用:
SELECT @sWhere = @sWhere + 'AND g.CreatedOn > ''' + @createdFromDate + ''''
您的问题的正确答案是您应该使用sp_executesql
来执行动态SQL。这允许您包含参数,因此您可以说:
exec sp_executesql @sql,
N'@createdFromDate date',
@createdFromDate = @createdFromDate;
其中@sql
是一个看起来像的字符串:
select . . .
. . .
where . . . and
g.CreatedOn = @createdFromDate;
答案 2 :(得分:2)
导致问题的原因是您尝试将smalldatetime
与VARCHAR
等字符串数据类型连接起来。您可以将日期转换为VARCHAR
来绕过它。 CONCAT()
会更好。在连接不同数据类型的值时,它是您最好的朋友。我强烈建议使用它,遗憾的是它只是SQL Server 2012及以上版本的支持,并且很少有人知道它甚至存在。
现在针对您的具体问题,我认为不需要动态SQL。您通常应该尽量避免使用动态SQL,因为以后很难调试和进行更改。像这样的东西对你来说会很好。
Declare @createdFromDate SMALLDATETIME = NULL,
@createdToDate SMALLDATETIME = NULL
SELECT *
FROM yourTable
WHERE (
date_column > @createdFromDate
OR @createdFromDate IS NULL
)
AND
(
date_column < @createdToDate
OR @createdToDate IS NULL
)