【问题标题】:Converting dates stored as VARCHAR2 to a date将存储为 VARCHAR2 的日期转换为日期
【发布时间】:2016-09-22 03:14:28
【问题描述】:

我看过与此类似的帖子,但我无法解决我的问题。

我正在尝试查询具有 VARCHAR2 数据类型的列(“VALUE”)的表。

此列中的行混合了数字值和日期值(我不知道为什么将日期存储为 VARCHAR2)。

我只需要日期,我已经用 LIKE 函数过滤掉了行。

SELECT
PARENTID,
NAME,
VALUE
FROM TIMINGEVENT
WHERE NAME like 'last%'
;

现在该列只有日期,我需要从 VARCHAR2 转换为日期。

PARENTID        ++  NAME            ++  VALUE 

1701480         ++  lastCycle1      ++  

1701480         ++  lastCycle2      ++  

1701480         ++  lastCycle3      ++  20150901092520 AM

1701480         ++  lastCycle4      ++  20150901092834 AM

1701480         ++  lastCycle5      ++  20150901085047 AM

我尝试使用 TO_DATE 导致以下错误:

ORA-01858:在需要数字的地方发现了一个非数字字符

我正在使用 Oracle 11g SQL Developer,并且日期格式的 NLS 首选项设置为 DD-MON-RR。

我在另一篇文章中找到了以下方法,但是当我使用它时会引发以下错误?

SELECT 
PARENTID,
NAME,
VALUE,
TO_CHAR(TO_DATE(VALUE, 'MM/DD/YYYY'), 'MM/DD/YYYY') AS "test"
FROM TIMINGEVENT
WHERE NAME like 'last%'
;


ORA-01843: not a valid month
01843. 00000 -  "not a valid month"

【问题讨论】:

  • 您尝试使用 to_date 的目的是什么?您是否提供了格式掩码,或依赖 NLS 设置?
  • 说实话,两者都是。我旋转了几个面具,也依赖于设置。我不断收到各种错误,包括:ORA-01861:文字与格式字符串不匹配。
  • 我用另一个例子更新了我上面的问题。请帮忙,谢谢。
  • 该格式掩码与您的 varchar2 字符串不匹配。你为什么不使用 Aleksej 的答案?

标签: sql date oracle11g to-date varchar2


【解决方案1】:

看来你只需要正确的格式:

with test(parentId, name, value) as (
select '1701480','lastCycle1','' from dual union all
select '1701480','lastCycle2','' from dual union all
select '1701480','lastCycle3','20150901092520 AM' from dual union all
select '1701480','lastCycle4','20150901092834 AM' from dual union all
select '1701480','lastCycle5','20150901085047 AM' from dual
)
select to_date(value, 'YYYYMMDDHHMISS AM')
from test

【讨论】:

    【解决方案2】:

    当您在 to_date() 中使用格式说明符时,它的作用是尝试将列中的值完全映射为格式说明符的格式,而不是更少,不是更多的东西。

    因此,当您使用 TO_DATE(VALUE, 'MM/DD/YYYY') 时,它会尝试将前 2 个字符(即 20)映射为 MM。因此,它给出的错误为not a valid month

    您需要一个适当的格式说明符来处理该列,如下所示 -

    从 TIMINGEVENT 中选择 TO_DATE(VALUE, 'yyyymmddhhhmiss am')

    它会给出类似的输出 -

    2015 年 9 月 1 日上午 9:25:20

    稍后您可以再次使用 to_char 并再次使用适当的格式说明符,根据您的要求再次格式化此输出。

    从 TIMINGEVENT 选择 to_char(TO_DATE(VALUE, 'yyyymmddhhmiss am'),'DD-MON-YYYY HH12:MI:SS AM')

    这将给出类似的输出 -

    01-SEP-2015 09:25:20 AM

    请注意,您的值中包含 am 或 pm 无关紧要,您可以同时使用 am 或 pm。我的意思是,具有讽刺意味的是,如果值中包含“am”,则不必使用“am”。即使值包含“am”,您也可以使用“pm”。并不是说以这种方式使用它有多大意义,仍然只是一个仅供参考。

    【讨论】:

      【解决方案3】:

      首先了解to_date和to_char函数的用法:

      TO_CHAR: 要将日期或数字等其他数据类型更改为字符串,如果要将日期更改为字符,则必须指定应转换为的日期格式。

      TO_DATE 要将字符串/字符更改为日期,第二个参数是您的字符串的日期格式,字符串“20150901092520 AM”的日期格式是“YYYYMMDDHHMISS AM”,因此您将其用作

      to_date('20150901092520 AM', 'YYYYMMDDHHMISS AM'),这会将其转换为日期对象,现在将所需格式打印为“09/01/2015”使用 to_char 并将格式指定为“MM/DD/ YYYY" 如下图

      to_char(to_date('20150901092520 AM', 'YYYYMMDDHHMISS AM'),'MM/DD/YYYY')

      【讨论】:

        【解决方案4】:

        您应该能够在转换之前使用 ISDATE 函数来测试字符串 https://docs.oracle.com/cd/B28359_01/olap.111/b28126/dml_functions_1106.htm

        一般... SELECT cust_last_name, CASE value WHEN isdate(value) = 'Yes' THEN convert(date,value) WHEN isdate(value) <> 'Yes' THEN '' END FROM TABLE;

        【讨论】:

        • 该语法在 Oracle SQL 中无效。
        • 这就是我偏离 MSSQL 的结果.. 哈哈。对不起:(
        猜你喜欢
        • 1970-01-01
        • 2022-01-23
        • 1970-01-01
        • 1970-01-01
        • 2015-10-19
        • 2015-08-10
        • 2018-07-11
        • 2019-10-05
        • 1970-01-01
        相关资源
        最近更新 更多