【问题标题】:TSQL - See if date falls between dateTSQL - 查看日期是否在日期之间
【发布时间】:2015-05-07 12:58:19
【问题描述】:

我有以下动态 SQL 查询,用于过滤数据范围的结果。如果我的“createdFrom”和“createdTo”日期不为空,我会在我的选择语句中添加一个 where 子句。

我有两个问题:

  1. 你会怎么做呢?我的逻辑对吗?

  2. 当我添加以下代码时,我目前收到一条错误消息,我为什么会收到这个?:

    将字符串转换为 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

【问题讨论】:

  • 您使用的是什么版本的 SQL Server?
  • 应避免使用动态 SQL,因为它们容易受到 SQL 注入攻击。在不可能的情况下,请尝试将 smallDateTime 转换为 char 数据,然后再将它们连接到 @sWhere。
  • g.CreatedOn 是什么数据类型?

标签: sql tsql datetime


【解决方案1】:

导致您出现问题的原因是您试图将smalldatetimeVARCHAR 之类的字符串数据类型连接起来。您只需将日期设为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
        )

【讨论】:

    【解决方案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;
    

    【讨论】:

      【解决方案3】:

      关于你的问题

      当我添加以下代码时,我目前收到一条错误消息,为什么会收到此消息?

      您收到此错误的原因是执行查询时您的条件变为

      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。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-11
        • 2012-09-19
        • 1970-01-01
        相关资源
        最近更新 更多