【问题标题】:Convert String to Date field for SQL Oracle将字符串转换为 SQL Oracle 的日期字段
【发布时间】:2017-02-28 18:10:13
【问题描述】:

我需要将字符串转换为日期字段。该字段存储 30 个字符。日期(如果存在)被格式化为“yyyymmdd”(20170202)。在所有情况下,日期后面都有 22 个空格。我需要将此字段格式化为这样的日期字段:dd-mm-yyyy。

我尝试了几个公式: TO_CHAR(PERSACTION.NEW_VALUE_02, 'dd-mm-yyyy'),TO_CHAR(PERSACTION.NEW_VALUE_02, 'yyyymmdd'),trim(TO_CHAR(PERSACTION.NEW_VALUE_02, 'yyyymmdd')) 错误信息:无效的数字格式模型。欢迎和赞赏您的专业知识。

【问题讨论】:

  • 不明白你说的字段是日期但包含30个字符。请包括表定义。
  • 您想将字符串转换为日期。从您的标题和您的帖子中准确引用。现在,Oracle 有函数TO_CHARTO_DATE。如果您想将转换为日期,您认为这两个函数中的哪一个(同样,它们的名字是TO_CHARTO_DATE)更可能是正确的?
  • 该表是一个字符串 (30)。我同意,我希望我们能够控制数据在表中的存储方式,但遗憾的是我们没有。
  • 另一方面,如果您想将转换为日期,则没有“格式”- 日期字段没有格式。这些格式仅适用于字符串,当您将字符串转换为日期时(当您以正确的数据类型(即 DATE)将数据存储在表中时)以及将日期转换回字符串时,仅用于报告目的。

标签: oracle


【解决方案1】:
to_char(to_date( rtrim(new_value_02), 'yyyymmdd'), 'dd-mm-yyyy')

应该做的伎俩。 rtrim 删除字符串右侧的空格。然后我使用指定的日期格式将其转换为日期,然后再次将其转换为所需格式的字符串。

【讨论】:

  • 如果 OP 想要转换为 date,为什么还需要 TO_CHAR
  • 这很好用,我也会保留它以备将来使用,非常感谢
  • @mathguy 好点。我添加了这个,因为他特别提到了日期格式作为结果。但是数据类型 Date 中的日期没有格式,它只是特定日期的表示。只需将 to_char 留在外面,您就会有一个约会。
【解决方案2】:

是否尝试转换为日期格式然后再次转换为字符?

TO_CHAR(TO_DATE(PERSACTION.NEW_VALUE_02,'yyyymmdd'),'dd-mm-yyyy')

【讨论】:

  • 如果 OP 想要转换为 date,为什么还需要 TO_CHAR
  • 因为它需要是char。该值存储在文本字段中,而不是 Tania 要求的日期字段中。
【解决方案3】:

请,请,不要存储 DATE 和 CHARACTER 数据类型。这只会导致使用 DATE 数据类型时可以避免的问题。

【讨论】:

    【解决方案4】:

    如果您想将 string 20170202 更改为另一个 string 而实际上不是日期(它没有固有的格式化文本表示),您可以选择使用常规表达式来转换它,而不是转换为日期并返回:

    select regexp_replace('20170202     ', '^(\d{4})(\d{2})(\d{2}) +$', '\3-\2-\1')
    from dual;
    
    REGEXP_REPLACE(
    ---------------
    02-02-2017     
    

    或者你可以使用substr而不是regexp_substr,即使你必须调用它3次,它的性能可能会更好;使用 CTE 只是为了避免重复值:

    with t(str) as (
      select '20170202     ' from dual
    )
    select substr(str, 7, 2) ||'-'|| substr(str, 5, 2) ||'-'|| substr(str, 1, 4)
    from t;
    
    SUBSTR(STR
    ----------
    02-02-2017
    

    如果您确实转换为日期并返回,您将发现任何无法转换的值,因为它们会导致抛出异常。这意味着您有错误的数据;当然,首先使用正确的数据类型可以避免这种情况。这些将转换任何旧垃圾,其结果取决于字符串偏离您期望的模式的距离 - 但包括表示无效日期的字符串,如“20170231”。并且 null 值或只有空格的字符串将在 substr 版本中转换为奇怪的东西,但您可以将它们过滤掉。

    您可以看到一些样本数据与您的期望不符:

    with t(str) as (
      select '20170202     ' from dual
      union all select '20170231     ' from dual
      union all select '2017020c     ' from dual
      union all select '2017020      ' from dual
      union all select '201702021    ' from dual
      union all select '             ' from dual
      union all select null from dual
    )
    select str,
      regexp_replace(str, '^(\d{4})(\d{2})(\d{2}) +$', '\3-\2-\1') as reg,
      substr(str, 7, 2) ||'-'|| substr(str, 5, 2) ||'-'|| substr(str, 1, 4) as sub
    from t;
    
    STR           REG           SUB          
    ------------- ------------- -------------
    20170202      02-02-2017    02-02-2017   
    20170231      31-02-2017    31-02-2017   
    2017020c      2017020c      0c-02-2017   
    2017020       2017020       0 -02-2017   
    201702021     201702021     02-02-2017   
                                  -  -       
                                --           
    

    使用锚点和空白预期,正则表达式不会修改任何不完全由 8 个数字字符组成的内容。但它仍然可以形成无效的“日期”。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-04-14
      • 1970-01-01
      • 1970-01-01
      • 2019-03-29
      • 1970-01-01
      • 2013-07-12
      • 2018-03-03
      相关资源
      最近更新 更多