cx_Oracle 'ORA-01843: not a valid month' with unicode parameter

生来就可爱ヽ(ⅴ<●) 提交于 2019-12-05 09:39:49

It's actually a bug in the Oracle 10.5.0.2 and 11.2.0.1.

Bug can be reproduced as following:

set NLS_TIMESTAMP_FORMAT in session.

Run any implicit or explicit TO_DATE conversion with unicode data.

Next implicit or explicit TO_TIMESTAMP with unicode data will trigger internal reset of timestamp format.

All consecutive TO_TIMESTAMP will fail and TO_CHAR of timestamp will produce invalid output.

Here is the code to test behaviour:

ALTER SESSION SET NLS_TERRITORY = 'AMERICA';
ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS' NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF';

REM --- WORKS:
SELECT TO_TIMESTAMP('2013-06-24 18:15:10.312') FROM DUAL;

REM --- WORKS:
SELECT TO_DATE('2013-06-24 18:15:10') FROM DUAL;

REM --- WORKS:
SELECT TO_TIMESTAMP('2013-06-24 18:15:10.312') FROM DUAL;

REM --- WORKS:
SELECT TO_TIMESTAMP(x) FROM (SELECT CAST('2013-06-24 18:15:10.312' AS NVARCHAR2(30)) AS X FROM DUAL);

REM --- WORKS:
SELECT TO_DATE(x) FROM (SELECT CAST('2013-06-24 18:15:10' AS NVARCHAR2(30)) AS X FROM DUAL);

REM --- WORKS:
SELECT TO_TIMESTAMP('2013-06-24 18:15:10.312') FROM DUAL;

REM !!! FAILS!
SELECT TO_TIMESTAMP(x) FROM (SELECT CAST('2013-06-24 18:15:10.312' AS NVARCHAR2(30)) AS X FROM DUAL);

REM !!! FAILS!
SELECT TO_TIMESTAMP('2013-06-24 18:15:10.312') FROM DUAL;

REM --- WORKS:
SELECT TO_DATE('2013-06-24 18:15:10') FROM DUAL;
Robert Lujo

Based on jtiai problem description, I made following workaround - before calling any problematic sql-s (e.g. oracle 10.5.0.2 and 11.2.0.1, cx_oracle 5.1.2), reset NLS_DATE_FORMAT/NLS_TIMESTAMP_FORMAT again:

cursor.execute(
     "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
     " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'")

# do execute ...
cursor.execute(query, params)

I was unable to recreate the error using RHEL 5,Cx_Oracle 5.1 python 2.4.3 Oracle 11.2.0.3.0 Did you try using format strings with the to_date and to_timestamp functions?

https://gist.github.com/fclrc/5435561

#! /bin/python
import cx_Oracle
import platform

print ("Python version: " + platform.python_version())
print ("cx_Oracle version: " + cx_Oracle.version)
print ("Oracle client: " + str(cx_Oracle.clientversion()).replace(', ','.'))

connection = cx_Oracle.connect('user/pass@tns')
cursor = connection.cursor()
#
# Option with format strings
#
cursor.execute("""select to_date(:arg1,'yyyy-mm-dd'), to_timestamp(:arg2,'yyyy-mm-dd hh24.mi.ss.ff') from dual""", arg1=u'2013-03-12', arg2=u'2013-03-12 08:22:31.332144')
#
# Option without format strings
#
#cursor.execute("ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS' NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'")
#cursor.execute("select to_date(:0), to_timestamp(:1) from dual", [u'2013-03-12', u'2013-03-12 08:22:31.332144'])

mydate = cursor.fetchall()
print mydate
cursor.close()
connection.close()
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!