将TSQL日期格式化为mm-dd-yyyy

时间:2019-02-14 21:43:57

标签: sql sql-server tsql date formatting

我有一个Datetime2格式的日期,它显示为yyyy-mm-dd。有没有办法重新格式化它,所以它是mm-dd-yyyy?

                CASE 
                WHEN CAST(ai.[Due Date] AS DATETIME2)  < GETDATE() THEN '[due]' + LEFT((ai.[Due Date]),10)
                WHEN CAST(ai.[Due Date] AS DATETIME2) IS NULL THEN ' '
                ELSE LEFT((ai.[Due Date]),10)
            END AS [TD]

2 个答案:

答案 0 :(得分:4)

传统方式是使用convert()

convert(varchar(10), ai.[Due Date], 110)

更通用的方法使用format()

select format(ai.[Due Date], 'dd-MM-yyyy')

答案 1 :(得分:3)

您误解了日期值如何在数据库中工作。 没有人类可读的格式。当您看到DateTimeDateTime2格式为yyyy-mm-dd的值时,您看到的是调试器或查询工具为方便起见显示的内容;数据库中使用的实际值是二进制的,而不是人类可读的,旨在有效地进行存储,索引和日期算术。

如果需要查看特定格式的值,则必须将其convert()format()设为varchar系列中的类型,作为查询的一部分。或者,甚至更好的是,让您的应用程序代码/报告工具为您完成此操作,然后只返回原始值。

我还看到这些日期可能最初存储在varcharnvarchar列中。如果是这样,这是架构设计中的一个主要缺陷。如果您可以开始使用以下方式存储这些值,那么您将获得显着的性能优势,并省去了很多麻烦。首先是DateTime系列的一种类型。

考虑到这一点,并且由于不清楚您是从什么开始的,所以让我们按喜好顺序看五个场景:

该列已使用DateTime系列中的类型,您可以让您的应用程序/报告工具处理该格式

在架构中使用真实的DateTime值对您有好处。这就是我们期望看到的。甚至更好的是,突然之间,您的SQL中的所有事情都变得真正变得简单了,问题中的整个代码片段都简化为:

 ai.[Due Date] AS [TD]

该列已使用DateTime系列的类型,但是客户端系统无法格式化

这还是相当不错的。模式仍然可以,在这种情况下,我们仍然可以对原始代码进行一些简化:

COALESCE(
    CASE WHEN ai.[Due Date] < GETDATE() THEN '[due] ' ELSE '' END 
    + FORMAT(ai.[Due Date], 'MM-dd-yyyy')
, ' ') AS [TD]

该列使用varchar系列中的a类型,但是您可以将其修复为使用DateTime2

我在这里说“修复”,因为现在该架构实际上是 broken 。但这没关系:您可以修复它。 这样做。然后使用上一个场景中的代码。

该列使用varchar系列的类型,您无法修复,但至少原始数据始终使用语义'yyyy-MM-dd`格式

笨蛋。您陷入了一个破碎的模式。但是我们至少可以利用格式良好的数据,通过对get_date()表达式使用强制转换/转换来匹配列,从而使事情 很多 更高效,而不是现在相反,就像这样:

WHEN ai.[Due Date] < CONVERT(varchar, GETDATE(), 120)

现在,我们正在进行字符串比较而不是日期比较,这通常比较慢,而且很容易出错。但是由于数据格式优美,我们可以避免这种情况,节省的余地是我们只需要强制转换一个get_date()值,而不是我们拥有的每一行。而且,以这种方式,列上的任何索引仍然有效。该问题的代码段将无法使用[Due Date]列上的任何索引。我知道这是一个SELECT子句,但这对于一般情况是值得记住的。

此方案的完整解决方案现在看起来像这样:

COALESCE(
    CASE WHEN ai.[Due Date] < CONVERT(varchar, GETDATE(), 120) THEN '[due] ' ELSE '' END
    + FORMAT(CAST(ai.[Due Date]) AS Date), 'MM-dd-yyyy')
, ' ') AS [TD]

同样,如果您无法将原始列数据转换为DateTime格式,请执行此操作。这就是您真正想要的。

该列使用varchar族中的一种类型,您无法修复,且格式不语义或不一致

哦,男孩。这是您真正不想要的地方。如果您无能为力,请至少 查看是否可以开始将一致的语义值添加到列中。在这一点上,我们不得不为几乎每一个查询对每行(可能不止一次)进行额外的工作。我们开始:

COALESCE(
    CASE WHEN CAST(ai.[Due Date] AS DATETIME2)  < GETDATE() THEN '[due] ' ELSE '' END 
    + FORMAT(CAST(ai.[Due Date] AS DATETIME2), 'MM-dd-yyyy')
, ' ') AS [TD]

代码看起来与其他选项没有太大不同,但是性能特征将完全不同……可能会恶化多个数量级。

请记住:由于国际化和时区问题,字符串和日期之间的转换出奇的缓慢和昂贵。避免在所有查询中都这样做。