TO_CHAR 和 TO_DATE 给出不同的结果。如何使用 TO_DATE 实现 TO_CHAR 功能?

Posted

技术标签:

【中文标题】TO_CHAR 和 TO_DATE 给出不同的结果。如何使用 TO_DATE 实现 TO_CHAR 功能?【英文标题】:TO_CHAR and TO_DATE giving different results.How to achieve the TO_CHAR functionality using TO_DATE? 【发布时间】:2016-02-10 08:03:16 【问题描述】:
SELECT TO_CHAR((select logical_date -1 from logical_date 
where logical_date_type='B'),'DD/MM/YYYY HH24:MI:SS') FROM DUAL;

此查询返回23/04/2016 00:00:00

o/p of select logical_date -1 from logical_date where logical_date_type='B' :4/23/2016

SELECT TO_DATE((select logical_date -1 from logical_date 
where logical_date_type='B'),'DD/MM/YYYY HH24:MI:SS') FROM DUAL;

此查询返回4/23/0016

如何使用 TO_DATE 获得 TO_CHAR 给出的格式??

【问题讨论】:

【参考方案1】:

日期没有任何内在格式。 Oracle 有一个内部表示,它看起来不像您认为是日期的任何东西。客户端或应用程序决定如何显示日期(例如,使用 NLS_DATE_FORMAT),或者您可以使用 TO_CHAR 将日期转换为您指定格式的字符串,就像您在第一个示例中所做的那样。

在您的第二个示例中,您正在使用您的 NLS 设置将您的实际日期隐式转换为字符串 - 在此过程中丢失了世纪,因此大概有 YY 而不是 YYYY - 然后将其转换回日期。我很惊讶当您交换月份和日期位置时没有出错。

不要那样做。转换为字符串并返回日期是没有意义的,即使您的设置不会在途中丢失信息。

如果您希望它作为客户或其他进程使用的日期,请执行以下操作:

select logical_date -1
from logical_date 
where logical_date_type='B'

如果您想与另一个日期进行比较,则仍将其保留为日期:

select other_columns
from logical_date 
where logical_date_type='B'
and logical_date -1 < sysdate

如果要指定显示格式,请使用:

select to_char(logical_date -1, 'DD/MM/YYYY')
from logical_date 
where logical_date_type='B'

【讨论】:

其实存储的字节还是可读的:ixora.com.au/notes/date_representation.htm. 我想在 where 子句中将它与 sysdate ('DD/MM/YYYY HH24:MI:SS') 进行比较,那么如何使用 TO_DATE() 而不是 TO_CHAR() 来实现它 @Husqvik - 我没有说它不可读,只是 OP 不会将其识别为日期。我不认为更详细地介绍如何通过转储查看它或如何解释这将有助于此时的 OP *8-) @Rishi - 它们都是日期,所以将它们作为日期进行比较。 您的客户以该格式显示 SYSDATE。不要将它们中的任何一个转换为字符串。 @Husqvik 格式掩码的全部意义在于使字节数据可读,因为非oracle的人不会理解内部格式:-)【参考方案2】:

问题与您在 oracle 客户端设置中配置的会话的默认日期格式有关 检查会话的 NLS_DATE_FORMAT 设置

SELECT value
FROM   nls_session_parameters
WHERE  parameter = 'NLS_DATE_FORMAT'

您可以通过以下方式为您的会话更改此设置以达到预期结果:

alter session set nls_date_format='DD/MM/YYYY HH24:MI:SS';

【讨论】:

这假设 OP 将始终能够控制查询运行的环境;最好不要真正依赖 NLS 设置。它还让他们在第二个示例中执行不必要的字符串转换。 嗨@AlexPoole,我同意...假设您正在编写应用程序代码,您应该避免依赖 NLS_DATE_FORMAT 设置并使用 TO_CHAR。【参考方案3】:

如何使用 TO_DATE 获得 TO_CHAR 给出的格式?

首先,DATE 没有任何格式。 Oracle 不会以您看到的格式存储日期。它在内部将其存储在 7 个字节 中,每个字节存储 datetime 值的不同组成部分。

Byte    Description
----    -------------------------------------------------
1       Century value but before storing it add 100 to it
2       Year and 100 is added to it before storing
3       Month
4       Day of the month
5       Hours but add 1 before storing it
6       Minutes but add 1 before storing it
7       Seconds but add 1 before storing it

格式仅用于显示目的。 TO_DATE 用于将文字转换为日期,与格式无关。要以所需格式显示日期,请使用 TO_CHAR 和正确的 FORMAT MODEL

另外,请记住,格式化有一个优先顺序

让我们看看优先级的时间顺序,即从高到低:

单个 SQL 语句

中使用 TO_CHARTO_DATE

ALTER SESSION SET NLS_DATE_FORMAT=’whatever format model you want’;

将其设置为客户端计算机上的操作系统环境变量

NLS_DATE_FORMAT 的设置在数据库初始化参数

例如,

单独的 SQL 语句:

SQL> SELECT HIREDATE, TO_CHAR(hiredate, 'YYYY-MM-DD') FROM emp;

HIREDATE            TO_CHAR(HI
------------------- ----------
17/12/1980 00:00:00 1980-12-17
20/02/1981 00:00:00 1981-02-20
22/02/1981 00:00:00 1981-02-22
02/04/1981 00:00:00 1981-04-02
28/09/1981 00:00:00 1981-09-28
01/05/1981 00:00:00 1981-05-01
09/06/1981 00:00:00 1981-06-09
09/12/1982 00:00:00 1982-12-09
17/11/1981 00:00:00 1981-11-17
08/09/1981 00:00:00 1981-09-08
12/01/1983 00:00:00 1983-01-12
03/12/1981 00:00:00 1981-12-03
03/12/1981 00:00:00 1981-12-03
23/01/1982 00:00:00 1982-01-23

14 rows selected.

会话级别:

SQL> alter session set nls_date_format='YYYY-MM-DD';

Session altered.

SQL> SELECT hiredate FROM emp;

HIREDATE
----------
1980-12-17
1981-02-20
1981-02-22
1981-04-02
1981-09-28
1981-05-01
1981-06-09
1982-12-09
1981-11-17
1981-09-08
1983-01-12
1981-12-03
1981-12-03
1982-01-23

14 rows selected.

SQL>

TO_DATE((选择逻辑日期

这是错误的。

切勿将 TO_DATE 应用于 DATE 列。它迫使甲骨文:

先转成字符串 然后将其转换回日期

基于特定于区域设置的 NLS 设置。您需要 TO_DATE 将文字转换为日期。对于 date-arithmetic,保留日期不变。

【讨论】:

以上是关于TO_CHAR 和 TO_DATE 给出不同的结果。如何使用 TO_DATE 实现 TO_CHAR 功能?的主要内容,如果未能解决你的问题,请参考以下文章

Oracle数据库to_date()和to_char()的相关

Oracle中的日期处理函数TO_DATE 和 TO_CHAR

Orcale日期函数to_date(),to_char()

Oracle中的TO_DATE和TO_CHAR函数以及日期处理

to_date & to_char

sysdate 的 to_date 函数问题