转换SQL日期格式的结果不相同

转换SQL日期格式的结果不相同,sql,tsql,sql-server-2008-r2,Sql,Tsql,Sql Server 2008 R2,我试图从我的日期值中删除时间戳,因此我最终得到了mm/dd/yy或mm/dd/yyyy之类的值。我引用了许多technet、stackoverflow和w3schools的文章,但仍然无法正确显示日期。表中我的所有列都定义为datetime,它们来自同一个表 我使用的convert语句如下:convert(VARCHAR(10),E.PD_DT,101)作为“支付日期” 我使用了10和11来代替101,但数据仍然存在相同的问题(见下文)。发生的情况是,当日期值(不包括时间)为8个字符时,我从时间

我试图从我的日期值中删除时间戳,因此我最终得到了mm/dd/yy或mm/dd/yyyy之类的值。我引用了许多technet、stackoverflow和w3schools的文章,但仍然无法正确显示日期。表中我的所有列都定义为datetime,它们来自同一个表

我使用的convert语句如下:convert(VARCHAR(10),E.PD_DT,101)作为“支付日期”

我使用了10和11来代替101,但数据仍然存在相同的问题(见下文)。发生的情况是,当日期值(不包括时间)为8个字符时,我从时间中获得一个额外字符,如索赔调整日期-10和索赔调整日期-11列所示。以下是我的数据:

Claim Paid Date-101     Claim Paid Date     Claim Adjustment Date-10    Claim Adjustment Date-11    Claim Adjustment Date
10/23/2012              10/23/12 12:00 AM   9/4/2012 1                  9/4/2012 1                      9/4/12 12:00 AM
10/23/2012              10/23/12 12:00 AM   9/4/2012 1                  9/4/2012 1                      9/4/12 12:00 AM
10/23/2012              10/23/12 12:00 AM   9/4/2012 1                  9/4/2012 1                      9/4/12 12:00 AM
09/06/2011              09/06/11 12:00 AM   9/4/2012 1                  9/4/2012 1                      9/4/12 12:00 AM
10/23/2012              10/23/12 12:00 AM   8/21/2012                   8/21/2012                       8/21/12 12:00 AM
09/06/2011              09/06/11 12:00 AM   8/21/2012                   8/21/2012                       8/21/12 12:00 AM

奇怪的是,“索赔支付日期”列中的所有日期都有一个零作为填充,如果月份或日期小于10。这使得转换结果很好,但如果月份或日期小于10且没有零,我就有问题了。

您有一个字符串源,而不是
DATETIME

日期时间会发生什么情况:

SELECT GETDATE() -- DATETIME
      ,CAST(GETDATE() AS DATE) --DATE
      ,CONVERT(VARCHAR(10),GETDATE(),101) --101 format
DECLARE @fake_date VARCHAR(25) = '10/23/12 12:00 AM'
SELECT CAST(@fake_date AS DATETIME) --DATETIME
      ,CAST(@fake_date AS DATE) --DATE
      ,CONVERT(VARCHAR(10),@fake_date,101) --101 format
结果:

DateTime                Date       101 Format
----------------------- ---------- ----------
2013-09-24 13:58:48.880 2013-09-24 09/24/2013
DateTime                Date       101 Format
----------------------- ---------- ----------
2012-10-23 00:00:00.000 2012-10-23 10/23/12 1
如果字符串显示为
DATETIME
,会发生什么情况:

SELECT GETDATE() -- DATETIME
      ,CAST(GETDATE() AS DATE) --DATE
      ,CONVERT(VARCHAR(10),GETDATE(),101) --101 format
DECLARE @fake_date VARCHAR(25) = '10/23/12 12:00 AM'
SELECT CAST(@fake_date AS DATETIME) --DATETIME
      ,CAST(@fake_date AS DATE) --DATE
      ,CONVERT(VARCHAR(10),@fake_date,101) --101 format
结果:

DateTime                Date       101 Format
----------------------- ---------- ----------
2013-09-24 13:58:48.880 2013-09-24 09/24/2013
DateTime                Date       101 Format
----------------------- ---------- ----------
2012-10-23 00:00:00.000 2012-10-23 10/23/12 1
所以,也许你想要:

CONVERT(VARCHAR(10),CAST(@fake_date AS DATE),101) 

您有一个字符串源,而不是
DATETIME

日期时间会发生什么情况:

SELECT GETDATE() -- DATETIME
      ,CAST(GETDATE() AS DATE) --DATE
      ,CONVERT(VARCHAR(10),GETDATE(),101) --101 format
DECLARE @fake_date VARCHAR(25) = '10/23/12 12:00 AM'
SELECT CAST(@fake_date AS DATETIME) --DATETIME
      ,CAST(@fake_date AS DATE) --DATE
      ,CONVERT(VARCHAR(10),@fake_date,101) --101 format
结果:

DateTime                Date       101 Format
----------------------- ---------- ----------
2013-09-24 13:58:48.880 2013-09-24 09/24/2013
DateTime                Date       101 Format
----------------------- ---------- ----------
2012-10-23 00:00:00.000 2012-10-23 10/23/12 1
如果字符串显示为
DATETIME
,会发生什么情况:

SELECT GETDATE() -- DATETIME
      ,CAST(GETDATE() AS DATE) --DATE
      ,CONVERT(VARCHAR(10),GETDATE(),101) --101 format
DECLARE @fake_date VARCHAR(25) = '10/23/12 12:00 AM'
SELECT CAST(@fake_date AS DATETIME) --DATETIME
      ,CAST(@fake_date AS DATE) --DATE
      ,CONVERT(VARCHAR(10),@fake_date,101) --101 format
结果:

DateTime                Date       101 Format
----------------------- ---------- ----------
2013-09-24 13:58:48.880 2013-09-24 09/24/2013
DateTime                Date       101 Format
----------------------- ---------- ----------
2012-10-23 00:00:00.000 2012-10-23 10/23/12 1
所以,也许你想要:

CONVERT(VARCHAR(10),CAST(@fake_date AS DATE),101) 

正确的方法是首先将数据存储为
DATETIME
。目前,您正在将数据存储为字符串,出于各种原因,您不应该这样做:

  • 如果不先进行转换,您将无法进行排序(
    2012年9月1日
    将在2012年12月12日之后进行排序)。转换成本很高
  • 如果不先转换,您将无法执行有意义的范围查询(同样,
    9/1/2012
    12/12/2012
  • 您将失去所有内置验证手段-任何人都可以输入
    13/33/2999
    02/32/2099
    或简单地将
    foo
    作为“日期”
  • 如果不首先转换,您将无法对这些列执行与日期相关的功能,例如
    DATEADD
    DATEPART
    DATEDIFF
  • 您需要先转换为其他类型,然后才能执行转换,该转换将允许您执行修剪时间或以特定格式显示日期等操作
如果无法修复表设计,并且希望继续使用错误的数据类型存储日期,那么下一个最好的方法就是在客户机中格式化字符串。如果客户端知道这是一个日期/时间,那么使用
.Format()
.ToString()
应该允许您以您想要的任何格式显示没有时间的日期

你应该以明确的格式向用户展示日期,因为你永远不知道你的一些读者什么时候会看到2012年6月12日,也不知道那是6月12日还是12月6日(例如,加拿大人和美国人会有不同的看法)。因此,您可以使用以下示例:

DateVariable.Format('yyyy-MM-dd')
这将呈现一个明确的日期,如2012年6月12日,这只能在法国一些非常孤立的地区和年龄组中被误解(y-d-m似乎仍然盛行)

但是,如果您绝对希望呈现不明确的格式,您可以使用:

DateVariable.Format('MM/dd/yyyy')
…完全没有理由更改SQL查询。如果出于某种原因,您绝对希望或需要在查询级别执行此操作,则可以使用:

SELECT CONVERT(CHAR(10), CONVERT(DATE, col), 101) -- mm/dd/yyyy
SELECT CONVERT(CHAR(8),  CONVERT(DATE, col), 112) -- yyyymmdd
SELECT CONVERT(CHAR(10), CONVERT(DATE, col), 120) -- yyyy-mm-dd
如果您想使用不太模棱两可的表单,如
yyyymmdd
yyyy-mm-dd
,您可以使用:

SELECT CONVERT(CHAR(10), CONVERT(DATE, col), 101) -- mm/dd/yyyy
SELECT CONVERT(CHAR(8),  CONVERT(DATE, col), 112) -- yyyymmdd
SELECT CONVERT(CHAR(10), CONVERT(DATE, col), 120) -- yyyy-mm-dd
但同样,在数据库层的转换是昂贵的,而在客户端层的字符串格式(在最后一步中,您已经将这些东西作为字符串处理)是相对便宜的。您应该尽可能长时间地保留这些日期值,无论是在数据库中还是在数据库中。在SQLServer关注的任何地方,将它们作为字符串处理都没有好处

因此,总结如下:

  • 收拾桌子
  • 在客户机上执行转换(最好转换为明确的格式)
  • 如果无法在客户端上执行转换,请使用双嵌套的
    CONVERT
    (同样,最好使用明确的格式)

  • 正确的方法是首先将数据存储为
    DATETIME
    。目前,您正在将数据存储为字符串,出于各种原因,您不应该这样做:

    • 如果不先进行转换,您将无法进行排序(
      2012年9月1日
      将在2012年12月12日之后进行排序)。转换成本很高
    • 如果不先转换,您将无法执行有意义的范围查询(同样,
      9/1/2012
      12/12/2012
    • 您将失去所有内置验证手段-任何人都可以输入
      13/33/2999
      02/32/2099
      或简单地将
      foo
      作为“日期”
    • 如果不首先转换,您将无法对这些列执行与日期相关的功能,例如
      DATEADD
      DATEPART
      DATEDIFF
    • 您需要先转换为其他类型,然后才能执行转换,该转换将允许您执行修剪时间或以特定格式显示日期等操作
    如果无法修复表设计,并且希望继续使用错误的数据类型存储日期,那么下一个最好的方法就是在客户机中格式化字符串。如果客户端知道这是一个日期/时间,那么使用
    .Format()
    .ToString()
    应该允许您以您想要的任何格式显示没有时间的日期

    您应该以明确的格式向用户显示日期,因为您永远不知道什么时候会显示日期