Oracle中的日期格式问题

Posted

技术标签:

【中文标题】Oracle中的日期格式问题【英文标题】:Date format issue in Oracle 【发布时间】:2021-10-08 04:19:04 【问题描述】:

在我们的package 中,我们有where 子句,如下所示。

 pp.start_date >= nvl(TO_DATE('01-JAN-2018', 'RRRR/MM/DD HH24:MI:SS'), pp.start_date)

它在客户环境中运行良好。但由于格式是'RRRR/MM/DD HH24:MI:SS',所以我们更改了日期,如下所示。

pp.start_date >= nvl(TO_DATE('2018/01/01', 'RRRR/MM/DD HH24:MI:SS'), pp.start_date)

理想情况下它应该可以工作,因为我们已经给出了正确的格式。在第一种情况下,它返回 679 行,但在第二种情况下,它返回 0 行。我们有 679 个正确的行数。

第二个 NVL 命令有什么问题?

【问题讨论】:

技术上我不认为RRRR 是一个有效的修饰符。 RR 旨在将 2 位数的年份向上或向下舍入以获得正确的世纪。如果您已有 4 位数年份,请使用 YYYY 我也检查了 YYYY RR 但只有当我使用 DD-MON-YYYY 格式的日期时才会输出。 请提供可重现的示例。您所说的在技术上或逻辑上都不正确。如果RRRR 给了你一些东西,它并不能保证它是正确的 我看不出TO_DATE('01-JAN-2018','RRRR/MM/DD HH24:MI:SS') 怎么可能“完美运行”。这给了我20-JAN-2001 18:00:00。另外,既然可以使用标准的date literal,为什么还要硬编码任何TO_DATE 表达式? 【参考方案1】:

在我看来,两者都是错误的。

如果日期值是2018/01/01,那么它的格式是(我认为)yyyy/mm/dd(也可以是yyyy/dd/mm,不能仅仅通过查看来判断)。 hh24:mi:ss 格式从何而来?你从来没用过。

因此,我会使用日期文字(始终为 date 'yyyy-mm-dd')(因为您对时间组件不感兴趣):

where pp.start_date >= date '2018-01-01'

没有NVL 功能。为什么?因为日期文字不能是NULL


使用NVL,如果它是关于其他列的,例如

where pp.start_date >= nvl(a.some_date, date '2018-01-01')

这意味着:如果a.some_date 列是NULL,请改用date '2018-01-01'


[EDIT] 如果有时间分量,毕竟使用TO_DATE函数和适当的格式掩码,例如

where pp.start_date >= to_date('2018-01-01 23:09', 'yyyy-mm-dd hh24:mi')

【讨论】:

谢谢@Littlefoot。实际上日期和时间来自 UI。无论客户设置什么日期,我们的查询都会从该日期加载数据。因此日期/时间会自动到来。如果我们想保持时间,我们应该怎么做? 不客气。如果同时涉及日期和时间,请使用 TO_DATE(请参阅编辑后的答案)。 第二个条件失败而不是第一个条件失败的逻辑原因是什么?我的意思是第二个不返回任何行。问是因为,我必须向客户说明理由。 PP.START_DATE 的数据类型是什么? 如果它是 DATE,那么您必须将它与另一个 DATE 进行比较(它是 DATE 数据类型列、DATE 文字、SYSDATE 函数、TO_DATE 函数返回的值)。当您使用 TO_DATE 时,您问题的唯一“答案”是您必须使用适当的格式掩码以及您为函数提供的值。如果是例如2018-01-23,则格式掩码必须是 YYYY-MM-DD,不能是 MM.DD.YYYY 也不能是 RRRR-DD-MM 也不能是 DD.MM.YYYY HH24:MI:SS 也不能是除格式 完全匹配的值。【参考方案2】:

如果你这样做:

SELECT TO_DATE('01-JAN-2018', 'RRRR/MM/DD HH24:MI:SS')
FROM   DUAL;

那么,来自string-to-date conversion rules:

RRRR 也匹配 RR 匹配 01,所以年份是 2001 年。 MM 也匹配 MON 匹配 JANDD 匹配 20HH24 匹配 18。 所以生成的日期是2001-01-20 18:00:00

如果你使用:

SELECT TO_DATE('2018/01/01', 'RRRR/MM/DD HH24:MI:SS')
FROM   DUAL;

然后:

RRRR 匹配 2018MM 匹配 01DD 匹配 01。 所以生成的日期是2018-01-01 00:00:00

sqlfiddle here

您正在生成两个完全不同的日期,相隔近 17 年。

在第一种情况下,它返回 679 行,但在第二种情况下,它返回 0 行。我们有 679 个正确的行数。

在第一种情况下,您将获得 2001-01-20T18:00:00 之后的 679 行。

在第二种情况下,您将获得 0 行在 2018-01-01T00:00:00 之后。

鉴于使用的日期分别是 01-JAN-20182018-01-01,我认为第二个是正确的,您应该得到 0 行而不是 679 行。

【讨论】:

以上是关于Oracle中的日期格式问题的主要内容,如果未能解决你的问题,请参考以下文章

oracle日期转换问题

为啥 APEX 和 Oracle SQL Developer 中的日期格式不同?

如何更改 Oracle BI Publisher 中的日期格式?

Oracle中的日期时间格式

Oracle 数据库 触发器 日期保存格式问题!

oracle日期转换问题