【问题标题】:Formatting date in Oracle without knowing original format beforehand在事先不知道原始格式的情况下在 Oracle 中格式化日期
【发布时间】:2019-10-22 11:38:39
【问题描述】:

我有一个将日期存储在 VARCHAR 字段中的表。该字段中存储了几种格式:

DD-MMM-YY

MM/dd/yyyy hh:mm:ss

随着数据从不同来源进入表格,可能还会增加一些。

我有一个函数可以检索这些,我需要在从函数返回之前将它们重新格式化为相同的格式。在事先不知道日期的确切格式的情况下如何做到这一点?

【问题讨论】:

    标签: oracle


    【解决方案1】:

    我有一个在 VARCHAR 字段中存储日期的表

    将 VARCHAR2 更改为 DATE。

    然后,您可以存储任何有效的日期值,而不管您想要何种传入格式,并对它执行任何 DATE 操作。

    任何其他将 DATE 存储为 DATE 以外的任何其他解决方案只会导致更多问题。

    例外情况是您需要几分之一秒 (TIMESTAMP) 或您需要时区 (TIMESTAMP WITH TIMEZONE)

    【讨论】:

    • 这就是我想做的。不幸的是,这个决定不取决于我
    • 并不意味着这不是正确的答案,尤其是对于其他有类似情况的人来说:)
    • 顺便说一句,“将 VARCHAR2 更改为 DATE”正是这个问题的核心问题……
    • @jackohug 对,知道有多少日期格式模型实际存储在列中会很好,然后您需要构建一个 api 来填充表格以强制执行数据约会来了
    • @thatjeffsmith 并彻底追查最初造成问题的人并防止其再次发生!
    【解决方案2】:

    不容易。基本上,您必须了解所有使用的格式。如何?一步步。从最明显的开始(你已经提到的那些;注意分钟格式掩码是mi,而不是mm(几个月)。

    该查询将失败很多次 - 与您尚未捕获的“错误”一样多。

    REGEXP_LIKE 可能会有所帮助,因为您可以确定某些格式是否与您使用的掩码匹配,但是 - 在转换“有效”格式时,您无能为力,例如4 digits-two digits-two digits two digits:two digits:two digits 例如 2019-87-54 69:74:84 (yyyy-mm-dd hh:mi:ss) 到有效日期,因为显然没有第 87 个月、第 54 天和第 69 小时等。

    所以,慢慢来,循序渐进,经常测试。

    【讨论】:

      【解决方案3】:

      使用CASE 语句和REGEXP_LIKE 来匹配不同的模式:

      SELECT CASE
               WHEN REGEXP_LIKE( your_column, '^\d{1,2}[ \/-](JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)[ \/-]\d{4}$', 'i' )
               THEN TO_DATE( your_column, 'dd mon yyyy' )
               WHEN REGEXP_LIKE( your_column, '^\d{1,2}[ \/-](JAN|FEB|MAR|APR|MAY|JUN|JUL|AUG|SEP|OCT|NOV|DEC)[ \/-]\d{2}$', 'i' )
               THEN TO_DATE( your_column, 'dd mon yy' )
               WHEN REGEXP_LIKE( your_column, '^(0?[1-9]|[12]\d|3[01])[ \/-](0?[1-9]|1[0-2])[ \/-]\d{4}$' )
               THEN TO_DATE( your_column, 'dd mm yyyy' )
               WHEN REGEXP_LIKE( your_column, '^(0?[1-9]|1[0-2])[ \/-](0?[1-9]|[12]\d|3[01])[ \/-]\d{4}$' )
               THEN TO_DATE( your_column, 'mm dd yyyy' )
               WHEN REGEXP_LIKE( your_column, '^(0?[1-9]|[12]\d|3[01])[ \/-](0?[1-9]|1[0-2])[ \/-]\d{2}$' )
               THEN TO_DATE( your_column, 'dd mm rr' )
               WHEN REGEXP_LIKE( your_column, '^(0?[1-9]|1[0-2])[ \/-](0?[1-9]|[12]\d|3[01])[ \/-]\d{2}$' )
               THEN TO_DATE( your_column, 'mm dd rr' )
               ELSE NULL
             END AS your_column_date
      FROM   your_table
      

      如果您还需要包含时间,请扩展它以添加不同的模式。

      但最好的解决方案是停止使用字符串并使用DATE 数据类型来存储日期值,并强制用户在输入数据时使用一致的格式,否则您将遇到01-02-03 的问题,它可能是 2003 年 1 月 2 日、2003 年 2 月 1 日或 2001 年 2 月 3 日,因为您不知道格式是 MM-DD-YYDD-MM-YY 还是 YY-MM-DD

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2022-12-29
        • 1970-01-01
        • 2011-04-12
        • 1970-01-01
        • 1970-01-01
        • 2011-12-29
        • 2023-03-31
        • 2013-11-14
        相关资源
        最近更新 更多