【问题标题】:Custom Date/Time formatting in SQL ServerSQL Server 中的自定义日期/时间格式
【发布时间】:2010-09-17 03:57:27
【问题描述】:

我正在尝试编写一个存储过程,它从表中选择列并将 2 个额外的列添加到 ResultSet。这 2 个额外的列是对表中的一个字段进行转换的结果,该字段是一个日期时间字段。

日期时间格式字段具有以下格式 'YYYY-MM-DD HH:MM:SS.S'

应采用以下格式的 2 个附加字段:

  1. DDMMM
  2. HHMMT,其中 T 是上午的“A”和下午的“P”

示例:如果字段中的数据为“2008-10-12 13:19:12.0”,则提取的字段应包含:

  1. 12OCT
  2. 0119P

我尝试过使用 CONVERT 字符串格式,但没有一种格式与我想要获得的输出相匹配。我正在考虑通过 CONVERT 提取字段数据,然后使用 REPLACE,但我在这里肯定需要一些帮助,因为我不确定。

任何精通存储过程的人都可以帮助我吗? 谢谢!

【问题讨论】:

  • 您正在寻找的这些输出结果让我想起了汤罐底部的日期。如果您要反复执行此操作,则只需要一个 sp。
  • 你说得对,我要反复这样做。
  • 请参考“SQL Server”,而不是“SQL”,因为不同的数据库有不同的日期格式。

标签: sql sql-server datetime stored-procedures sql-convert


【解决方案1】:

使用 DATENAME 并将逻辑包装在函数中,而不是存储过程中

declare @myTime as DateTime

set @myTime = GETDATE()

select @myTime

select DATENAME(day, @myTime) + SUBSTRING(UPPER(DATENAME(month, @myTime)), 0,4)

返回“14OCT”

在处理日期时尽量不要使用任何基于字符/字符串的操作。它们是数字(浮点数),性能会受到这些数据类型转换的影响。

挖掘我多年来编写的这些方便的转换...

/* Common date functions */
--//This contains common date functions for MSSQL server

/*Getting Parts of a DateTime*/
    --//gets the date only, 20x faster than using Convert/Cast to varchar
    --//this has been especially useful for JOINS
    SELECT (CAST(FLOOR(CAST(GETDATE() as FLOAT)) AS DateTime))

    --//gets the time only (date portion is '1900-01-01' and is considered the "0 time" of dates in MSSQL, even with the datatype min value of 01/01/1753. 
    SELECT (GETDATE() - (CAST(FLOOR(CAST(GETDATE() as FLOAT)) AS DateTime)))


/*Relative Dates*/
--//These are all functions that will calculate a date relative to the current date and time
    /*Current Day*/
    --//now
    SELECT (GETDATE())

    --//midnight of today
    SELECT (DATEADD(ms,-4,(DATEADD(dd,DATEDIFF(dd,0,GETDATE()) + 1,0))))

    --//Current Hour
    SELECT DATEADD(hh,DATEPART(hh,GETDATE()),CAST(FLOOR(CAST(GETDATE() AS FLOAT)) as DateTime))

    --//Current Half-Hour - if its 9:36, this will show 9:30
    SELECT DATEADD(mi,((DATEDIFF(mi,(CAST(FLOOR(CAST(GETDATE() as FLOAT)) as DateTime)), GETDATE())) / 30) * 30,(CAST(FLOOR(CAST(GETDATE() as FLOAT)) as DateTime)))

    /*Yearly*/
    --//first datetime of the current year
    SELECT (DATEADD(yy,DATEDIFF(yy,0,GETDATE()),0))

    --//last datetime of the current year
    SELECT (DATEADD(ms,-4,(DATEADD(yy,DATEDIFF(yy,0,GETDATE()) + 1,0))))

    /*Monthly*/
    --//first datetime of current month
    SELECT (DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))

    --//last datetime of the current month
    SELECT (DATEADD(ms,-4,DATEADD(mm,1,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0))))

    --//first datetime of the previous month
    SELECT (DATEADD(mm,DATEDIFF(mm,0,GETDATE()) -1,0))

    --//last datetime of the previous month
    SELECT (DATEADD(ms, -4,DATEADD(mm,DATEDIFF(mm,0,GETDATE()),0)))

    /*Weekly*/
    --//previous monday at 12AM
    SELECT (DATEADD(wk,DATEDIFF(wk,0,GETDATE()) -1 ,0))

    --//previous friday at 11:59:59 PM
    SELECT (DATEADD(ms,-4,DATEADD(dd,5,DATEADD(wk,DATEDIFF(wk,0,GETDATE()) -1 ,0))))

    /*Quarterly*/
    --//first datetime of current quarter
    SELECT (DATEADD(qq,DATEDIFF(qq,0,GETDATE()),0))

    --//last datetime of current quarter
    SELECT (DATEADD(ms,-4,DATEADD(qq,DATEDIFF(qq,0,GETDATE()) + 1,0)))

【讨论】:

  • 感谢您的指点和方便的函数参考。它应该派上用场!
【解决方案2】:

你可以在SQL server中使用以下命令来制作:

select FORMAT(getdate(), N'yyyy-MM-ddThh:mm:ss')

【讨论】:

  • 此答案仅对 >=2014 版本有效
  • 该功能对SQL Server version 2012 SP4也有效
【解决方案3】:

如果 dt 是您的日期时间列,那么

对于 1:

SUBSTRING(CONVERT(varchar, dt, 13), 1, 2)
    + UPPER(SUBSTRING(CONVERT(varchar, dt, 13), 4, 3))

对于 2:

SUBSTRING(CONVERT(varchar, dt, 100), 13, 2)
    + SUBSTRING(CONVERT(varchar, dt, 100), 16, 3)

【讨论】:

  • 感谢您的回答。帮了我很多!我在第一部分使用了 106 格式,而不是 13。如果报告的时间类似于 924P,是否可以对格式 2(时间)进行左侧零填充。
  • 这绝对是可能的,但是如何在 SQL Server 中用零填充是一个不同的问题。这是一个例子:stackoverflow.com/questions/16760900/…
【解决方案4】:

没有具体回答您的问题,但这不应该由您的应用程序的表示层处理。按照您描述的方式执行此操作会在数据库端创建额外的处理并添加额外的网络流量(假设数据库存在于与应用程序不同的机器上),对于可以在应用程序端轻松计算的内容,具有更丰富的日期处理库,以及更多的语言不可知论,尤其是在您的第一个示例包含缩写月份名称的情况下。无论如何,如果您仍然决定走这条路,其他人给您的答案应该会为您指明正确的方向。

【讨论】:

  • 是的,你说的很对,我在这里附和你的观点,但是我上面有些人希望这件事能在 sp 中处理。否则,我可能不会问这个问题。 :)
  • 有时你想在你的数据库边界强制执行一个标准,有时你想将列组合成更短的输出列——让 SQL Server 在将它发送到网络之前这样做更有效.
  • 话虽如此,如果您必须这样做,请将格式化代码包装在它自己的函数中,以便在您需要使用它的任何查询/存储过程中轻松复制格式。跨度>
【解决方案5】:

日期时间格式字段具有以下格式 'YYYY-MM-DD HH:MM:SS.S'

那句话是错误的。这就是企业管理器或 SQL Server 选择显示日期的方式。在内部,它是一个 8 字节的二进制值,这就是为什么 Andrew 发布的一些函数会运行良好的原因。

Kibbee 也提出了一个有效的观点,在完美的世界中我会同意他的观点。但是,有时您希望将查询结果直接绑定到显示控件或小部件,而实际上没有机会进行任何格式化。有时表示层位于比数据库还要繁忙的 Web 服务器上。考虑到这些,知道如何在 SQL 中执行此操作不一定是坏事。

【讨论】:

    【解决方案6】:

    是的,Depart 是一个解决方案,但我认为这种方法是长途旅行!

    SQL 服务器:

    SELECT CAST(DATEPART(DD,GETDATE()) AS VARCHAR)+'/'
    +CAST(DATEPART(MM,GETDATE()) AS VARCHAR)
    +'/'+CAST(DATEPART(YYYY,GETDATE()) AS VARCHAR)
    +' '+CAST(DATEPART(HH,GETDATE()) AS VARCHAR)
    +':'+CAST(DATEPART(MI,GETDATE()) AS VARCHAR)
    

    甲骨文:

    Select to_char(sysdate,'DD/MM/YYYY HH24:MI') from dual
    

    你可以编写自己的函数,这样你就可以摆脱这个烂摊子了;

    http://sql.dzone.com/news/custom-date-formatting-sql-ser

    select myshortfun(getdate(),myformat)
    GO
    

    【讨论】:

    • 如果你走的是 datepart 路,你可能还需要在当天使用前导零:RIGHT('00' + CONVERT(NVARCHAR(2), DATEPART(DAY, GETDATE())) , 2),
    • Shame SQL Server 没有这个相同的功能。看看那愚蠢的语法!
    【解决方案7】:

    您需要在这里使用 DATEPART。您可以将 DATEPART 调用的结果连接在一起。

    要获取月份缩写,您可以使用 DATENAME;如果这对您不起作用,您可以在 DATEPART 上使用 CASE 语句。

    DATEPART 也适用于时间字段。

    我可以想到几种获取 AM/PM 指标的方法,包括比较通过 DATEPART 构建的新日期或计算一天中经过的总秒数并将其与已知的 AM/PM 阈值进行比较。

    【讨论】:

      【解决方案8】:

      在 MS SQL Server 中,您可以这样做:

      设置日期格式 ymd

      年, 月, 天,

      【讨论】:

        【解决方案9】:

        如果您需要像 DateKey (yyyymmdd) 这样更具体的维度模型,我建议不要进行任何转换/转换:

        DECLARE @DateKeyToday int = (SELECT 10000 * DATEPART(yy,GETDATE()) + 100 * DATEPART(mm,GETDATE()) + DATEPART(dd,GETDATE()));
        PRINT @DateKeyToday
        

        【讨论】:

          【解决方案10】:

          我将这个答案(为我自己)添加为与自定义格式相关。

          对于下划线 yyyy_MM_dd

          REPLACE(SUBSTRING(CONVERT(VARCHAR, @dt, 120), 1, 10),'-','_')
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2012-06-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2016-05-11
            相关资源
            最近更新 更多