5

我在 Django 中有以下模型:

class Event(models.Model):
    # some fields
    start_date = models.DateField()
    end_date = models.DateField()

我正在使用带有 Django 1.5 和 cx_oracle 5.1.2 的 Oracle 10g 数据库。这里的问题是当我尝试在管理界面中创建一个新对象(从日历中选择日期)时,会引发以下错误:

ORA-01843: not a valid month

syncdbDATE在 oracle 中为start_date和创建了一个字段end_date。这看起来像后端错误还是我做错了什么?

我确实有其他模型,DateTimeField()当我保留新对象时它们工作正常,问题看起来与DateField它本身有关。

更新:我检查了后端实现,并在backends/oracle/base.py第 513 到 516 行:

cursor.execute(
    "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
    " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'"
    + (" TIME_ZONE = 'UTC'" if settings.USE_TZ else ''))

执行此语句允许插入语句具有DATE字段的文字值。我检查了后端生成的查询,它正在'2013-03-20'插入start_dateand end_date。日期匹配NLS_DATE_FORMAT,所以理论上应该可以!

更新:我相信我的案例与 cx_oracle 有关

更新:由于我仍然没有明确的答案(尽管我几乎可以肯定是 cx_oracle 导致了这个问题),我把我的DateField变成了一个DateTimeField可以翻译成 oracle 的TIMESTAMP并且工作得很好。

4

2 回答 2

1

根据jtiai问题描述,我做了以下解决方法 - 在调用任何有问题的 sql-s(例如 oracle 10.5.0.2 和 11.2.0.1,cx_oracle 5.1.2)之前,再次重置 NLS_DATE_FORMAT/NLS_TIMESTAMP_FORMAT - 在 django/db/backends/oracle 中完成/base.py 在方法中def execute(...)

--- base.py 2013-10-31 12:19:24.000000000 +0100
+++ base_new.py 2013-10-31 12:20:32.000000000 +0100
@@ -707,6 +707,18 @@
         query = convert_unicode(query % tuple(args), self.charset)
         self._guess_input_sizes([params])
         try:
+            # BUG-WORKAROUND: ulr1-131031 
+            # https://stackoverflow.com/a/17269719/565525
+            # 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.
+            self.cursor.execute(
+                "ALTER SESSION SET NLS_DATE_FORMAT = 'YYYY-MM-DD HH24:MI:SS'"
+                " NLS_TIMESTAMP_FORMAT = 'YYYY-MM-DD HH24:MI:SS.FF'"
+                + (" TIME_ZONE = 'UTC'" if settings.USE_TZ else ''))
+
             return self.cursor.execute(query, self._param_generator(params))
         except Database.IntegrityError as e:
             six.reraise(utils.IntegrityError, utils.IntegrityError(*tuple(e.args)), sys.exc_info()[2])
于 2013-10-31T11:51:25.243 回答
-2

错误的原因是您输入了一个日期,但该日期的月份部分不是有效月份。Oracle 针对这个问题给出了解决方案。

1MONTH - 使用 a或MON格式掩码重新输入日期值。月份的有效值为:

January
February
March
.......
//and soon

或者

Jan
Feb
Mar
.......
//and soon

2 - 如果上述解决方案失败,请to_date function改用。

to_date( string1, [ format_mask ], [ nls_language ] )
于 2013-04-04T07:01:40.797 回答