使用数据类型varchar转换日期时间失败

时间:2016-05-01 11:04:55

标签: sql sql-server

我的数据库表名=" SearchTask"看起来像这样 列的数据类型

Task = varchar
AssignedDate = varchar

  **Task | AssignedDate**
    A    | 01/02/2016
    A    | 02/03/2016
    A    | 05/04/2016
    A    | '
    A    | '

PS:第3行和第4行是char(39),当用户不想要任何指定日期时添加它们,并且无法更改此规则。客户必须这样。

现在我写一个查询

select task, AssignedDate
from SearchTask
where AssignedDate not like char(39)
      and convert(varchar(10), convert(date,assigneddate, 105),112) >= 20160301
      and convert(varchar(10), convert(date,assigneddate, 105),112) <= 20160331

它给了我错误信息

从字符串

转换日期和/或时间时,

转换失败

有人可以帮忙吗?

但我真正的问题是 如何在

时编写应该打印输出的查询
  1. 当其中一个AssignedDate为null时,它应该打印 除char之外的所有值(39)
    1. 当两个both子句中的AssignedDate都为null时,它应该打印所有值,包括char(39)
  2. 根据要求我正在添加更多样本数据和预期输出:

     **Task | AssignedDate**
       A    | 01/02/2016
       A    | 02/03/2016
       A    | 05/04/2016
       A    | '
       A    | '
    

    如果我的情况说:

    场景#1

    where AssignedDate not like char(39)
        and convert(varchar(10), convert(date,assigneddate, 105),112) >= 20160301
        and convert(varchar(10), convert(date,assigneddate, 105),112) <= 20160331
    It should print me:
    A    | 02/03/2016
    

    场景#2

    where AssignedDate not like char(39)
        and convert(varchar(10), convert(date,assigneddate, 105),112) >= 20160201
        and convert(varchar(10), convert(date,assigneddate, 105),112) <= null
    
    它应该打印我:

           A    | 01/02/2016
           A    | 02/03/2016
           A    | 05/04/2016
    

    场景#3

    where AssignedDate not like char(39)
        and convert(varchar(10), convert(date,assigneddate, 105),112) >= null
        and convert(varchar(10), convert(date,assigneddate, 105),112) <= 20160301
    
    它应该打印我:

     A    | 01/02/2016
     A    | 02/03/2016
    

2 个答案:

答案 0 :(得分:1)

最重要的经验教训:从不让您的客户设计您的数据库 您应该使用可为空的datedatetime列来保留日期而不是您现在使用的varchar,并且只要此列包含,表示层就会显示char(39) null

如果您无法更改数据库,则应更改您的sql:

SELECT task, assigneddate
FROM SearchTask
WHERE CASE WHEN assigneddate <> '''' THEN convert(date,assigneddate, 105) ELSE '1900-01-01' END >= '2016-03-01'
AND CASE WHEN assigneddate <> '''' THEN convert(date,assigneddate, 105) ELSE '9999-12-31' END  <= '2016-03-31'

使用case语句可阻止数据库尝试将char(39)转换为datetime值。在原始查询中不是这种情况,因为Sql server不保证短路条件。

请注意,如果您可以更改数据库结构,那么这是最好的行动方案 在这里阅读更多相关信息:Aaron Bertrand的Bad habits to kick : choosing the wrong data type

答案 1 :(得分:0)

很抱歉回复很晚: 我能够通过使用您提供的上述帮助来解决上述问题。我做的第一件事是使用日期选择器获取日期的用户输入并使用以下变量@AssignedDateFrom和@AssignedDateTo然后最后我使用了以下查询:

where 
  (@AssignedDateFrom is null or 
        (len(assigneddate)<>1 and
         convert(date,substring(assigneddate,1,10),103)>=@AssignedDateFrom
        )
  )
 and 
  (@AssignedDateTo is null or 
       (len(assigneddate)<>1 and
        convert(date,substring(assigneddate,1,10),103)<=@AssignedDateTo
       )
  )