Cx_oracle 在某些特定情况下在日期字段中削减年份

Cx_oracle is cutting year in a date field in some specific cases

在使用 python & cx_Oracle 处理日期时,我遇到了下一个问题。

这个很好用:

In [29]: cursor.execute("SELECT TO_DATE('23.09.2015','DD.MM.YYYY') FROM dual")
Out[29]: <cx_Oracle.Cursor on <cx_Oracle.Connection to web@hdb:1521/db11>>

In [30]: cursor.fetchone()
Out[30]: (datetime.datetime(2015, 9, 23, 0, 0),)

这也很好用:

In [33]: cursor.execute("SELECT sysdate FROM dual")
Out[33]: <cx_Oracle.Cursor on <cx_Oracle.Connection to web@hdb:1521/db11>>

In [34]: cursor.fetchone()
Out[34]: (datetime.datetime(2015, 9, 23, 21, 25, 16),)

但是当我使用带有日期字段的 oracle to_date 函数时 cx_Oracle 将年份值削减为 2 位数字,因此我得到的不是 2015,而是 15。此处示例:

In [31]: cursor.execute("SELECT TO_DATE(TO_DATE('23.09.2015','DD.MM.YYYY'),'DD.MM.YYYY') FROM dual")
Out[31]: <cx_Oracle.Cursor on <cx_Oracle.Connection to web@hdb:1521/db11>>

In [32]: cursor.fetchone()
Out[32]: (datetime.datetime(15, 9, 23, 0, 0),)

这里:

In [36]: cursor.execute("SELECT TO_DATE(sysdate,'DD.MM.YYYY') FROM dual")
Out[36]: <cx_Oracle.Cursor on <cx_Oracle.Connection to web@hdb:1521/db11>>

In [37]: cursor.fetchone()
Out[37]: (datetime.datetime(15, 9, 23, 0, 0),)

oracle 中还有一个 trunc 函数可以用于日期舍入并且不会触发问题:

In [39]: cursor.execute("SELECT TRUNC(sysdate) FROM dual")
Out[39]: <cx_Oracle.Cursor on <cx_Oracle.Connection to web@hdb:1521/db11>>

In [40]: cursor.fetchone()
Out[40]: (datetime.datetime(2015, 9, 23, 0, 0),)

但我想我的工具可以在没有任何特定限制的情况下处理用户定义的数据库对象(包括视图)。不幸的是,这个问题不允许我正确处理日期,目前我找不到任何合适的解决方案。

编辑。 Rajesh 回答后的工作示例:

In [104]: cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT='DD.MM.YYYY'")

In [105]: cursor.execute("SELECT TO_DATE(sysdate,'DD.MM.YYYY') FROM dual")
Out[105]: <cx_Oracle.Cursor on <cx_Oracle.Connection to web@hdb:1521/db11>>

In [106]: cursor.fetchone()
Out[106]: (datetime.datetime(2015, 9, 23, 0, 0),)

这个问题的简单答案是不再对日期函数使用 to_date。

你的转换函数应该是

a) to_date(string_column,'string_representation') 如果您尝试将某些内容转换为日期

b) to_char(date_column,'string_representation') 如果您尝试将某些内容从日期转换为字符串,通常用于报告、假脱机处理或打印。

如果您想了解奇怪的行为,可以查看会话的 NLS 设置。当您说 TO_DATE(sysdate,...) 时,to_date 需要一个字符串,因此我认为 Oracle 会尝试将 sysdate 隐式转换为 strng。这发生在您当前会话中使用 NLS_DATE_FORMAT。