2013-03-20 29 views
5

tôi có mô hình sau đây trong Django:Django - Oracle backend lỗi

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

Tôi đang sử dụng Oracle 10g Database với Django 1.5 và cx_oracle 5.1.2. Vấn đề ở đây là khi tôi cố gắng tạo ra một đối tượng mới trong giao diện admin (chọn ngày từ lịch), các lỗi sau được nâng lên:

ORA-01843: not a valid month 

syncdb đã tạo ra một lĩnh vực DATE trong oracle cho start_dateend_date. Điều này có giống như một lỗi phụ trợ hay tôi đang làm điều gì sai?

Tôi có các mô hình khác với DateTimeField() và chúng hoạt động tốt khi tôi vẫn tồn tại đối tượng mới, vấn đề có vẻ liên quan đến DateField.

UPDATE: Tôi đã kiểm tra việc thực hiện phụ trợ, và trong backends/oracle/base.py dòng 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 '')) 

Thực thi tuyên bố này cho phép một tuyên bố chèn để có giá trị văn chương cho DATE lĩnh vực. Tôi đã kiểm tra truy vấn được tạo bởi chương trình phụ trợ và nó đang chèn '2013-03-20' vào start_dateend_date. Ngày phù hợp với NLS_DATE_FORMAT, vì vậy điều này trong lý thuyết nên hoạt động!

CẬP NHẬT: Tôi tin rằng trường hợp của tôi là related to cx_oracle.

CẬP NHẬT: Kể từ khi tôi vẫn chưa có một câu trả lời rõ ràng (mặc dù tôi gần như chắc chắn đó là cx_oracle đó là gây ra vấn đề này), tôi đã thay đổi DateField của tôi vào một DateTimeField mà dịch thành oracle của TIMESTAMP và làm việc hoàn toàn tốt đẹp.

+0

vì vậy, chỉ để được rõ ràng, bạn đang kiểm tra các bảng Oracle SYS cho SQL được chạy và nhìn thấy một cái gì đó như 'TO_DATE ('2013- 03-20 ',' YYYY-MM-DD ') 'trong phần chèn của bạn?Từ câu hỏi của bạn, có vẻ như 'NLS_DATE_FORMAT = 'YYYY-MM-DD HH24: MI: SS'', khác với chèn thực tế, mặc dù tôi không biết tác dụng này sẽ có gì trong ngữ cảnh này. – woemler

+0

Không, vì cài đặt câu lệnh phiên thay đổi 'NLS_DATE_FORMAT', bạn có thể chèn ngày dưới dạng chữ mà không có to_date, đây là trường hợp khi tôi kiểm tra SQL đang được thực thi. – abstractpaper

+0

Bạn có thể đăng SQL có liên quan đang được chạy trên máy chủ dẫn đến lỗi 'ORA-01843' không? – woemler

Trả lời

-2

Nguyên nhân gây ra lỗi là bạn đã nhập ngày, nhưng phần tháng của ngày không phải là tháng hợp lệ. Oracle đưa ra các giải pháp cho vấn đề này.

- Nhập lại giá trị ngày bằng cách sử dụng mặt nạ định dạng MONTH hoặc MON. Các giá trị hợp lệ cho tháng là:

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

HOẶC

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

- nếu độ phân giải trên là thất bại, sử dụng to_date function để thay thế.

to_date(string1, [ format_mask ], [ nls_language ]) 
1

Dựa trên jtiai vấn đề description, tôi đã thực hiện cách giải quyết sau - trước khi gọi bất kỳ sql-s có vấn đề (ví dụ như oracle 10.5.0.2 và 11.2.0.1, cx_oracle 5.1.2), thiết lập lại NLS_DATE_FORMAT/NLS_TIMESTAMP_FORMAT một lần nữa - thực hiện trong django/db/backends/oracle/base.py trong phương pháp 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])