Django使用oracle常见问题

1. Django2.0+和Oracle11

Traceback (most recent call last):
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/migrations/recorder.py", line 55, in ensure_schema
    editor.create_model(self.Migration)
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/backends/base/schema.py", line 298, in create_model
    self.execute(sql, params or None)
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/backends/base/schema.py", line 117, in execute
    cursor.execute(sql, params)
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/backends/utils.py", line 100, in execute
    return super().execute(sql, params)
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/backends/utils.py", line 68, in execute
    return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/backends/utils.py", line 77, in _execute_with_wrappers
    return executor(sql, params, many, context)
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/backends/utils.py", line 85, in _execute
    return self.cursor.execute(sql, params)
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/utils.py", line 89, in __exit__
    raise dj_exc_value.with_traceback(traceback) from exc_value
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/backends/utils.py", line 83, in _execute
    return self.cursor.execute(sql)
  File "/Users/user/anaconda3/lib/python3.6/site-packages/django/db/backends/oracle/base.py", line 500, in execute
    return self.cursor.execute(query, self._param_generator(params))
django.db.utils.DatabaseError: ORA-02000: missing ALWAYS keyword

原因:
Django2.0+只支持Oracle 12.1+以后的版本, Django2.0创建Oracle表时使用'GENERATED BY DEFAULT ON NULL' ,这个是Oracle 12c的新特性。官方ReleaseNotes
解决方案:

  1. 升级Oracle到12.1+.
  2. 降级Django到1.11-.
  3. 如果既不能控制Oracle版本(比如对接其它系统,对方提供的是Oracle视图时),也不想降级Django,可以通过避免使用manage去管理Oracle数据库中的表,即在表定义中设置Meta属性
    managed=False

2. Django1.11和Oracle 11、cx_Oracle 7

File "django/db/backends/oracle/operations.py", line 229, in fetch_returned_insert_id
   return int(cursor._insert_id_var.getvalue())
TypeError: int() argument must be a string, a bytes-like object or a number, not 'list'

参考链接1
参考链接2
解决方式:
需要降级cx_Oracle 7到cx_Oracle 6

3. Django1.11和Oracle 11、cx_Oracle 6.0

"AttributeError: 'cx_Oracle.Cursor' object has no attribute 'numbersAsStrings'"

解决方案:
注释代码:

lib\site-packages\django\db\backends\oracle\base.py 
def __init__(self, connection):
     self.cursor = connection.cursor()
     # Necessary to retrieve decimal values without rounding error.
     self.cursor.numbersAsStrings = True
     self.cursor.outputtypehandler = self._output_type_handler
     # Default arraysize of 1 is highly sub-optimal.
     self.cursor.arraysize = 100
     # https://github.com/django/django/commit/d52577b62b3138674807ac74251fab7faed48331

将上述代码中 self.cursor.numbersAsStrings = True注释即可

4. Django1.11和Oracle 11、cx_Oracle 6.0

TypeError: argument of type 'int' is not iterable
def _rowfactory(row, cursor):
# Cast numeric values as the appropriate Python type based upon the
# cursor description, and convert strings to unicode.
casted = []
for value, desc in zip(row, cursor.description):
    if value is not None and desc[1] is Database.NUMBER:
        precision = desc[4] or 0
        scale = desc[5] or 0
        if scale == -127:
            if precision == 0:
                # NUMBER column: decimal-precision floating point
                # This will normally be an integer from a sequence,
                # but it could be a decimal value.
                if '.' in value:
                    value = decimal.Decimal(value)
                else:
                    value = int(value)
            else:
                # FLOAT column: binary-precision floating point.
                # This comes from FloatField columns.
                value = float(value)
        elif precision > 0:
            # NUMBER(p,s) column: decimal-precision fixed point.
            # This comes from IntField and DecimalField columns.
            if scale == 0:
                value = int(value)
            else:
                value = decimal.Decimal(value)
        elif '.' in value:
            # No type information. This normally comes from a
            # mathematical expression in the SELECT list. Guess int
            # or Decimal based on whether it has a decimal point.
            value = decimal.Decimal(value)
        else:
            value = int(value)
    elif desc[1] in (Database.STRING, Database.FIXED_CHAR,
                     Database.LONG_STRING):
        value = to_unicode(value)
    casted.append(value)
return tuple(casted)

问题发生在:
当value=0时

if '.' in value: 

解决方案:
升级Django到1.11.15 解决问题(pip install Django==1.11.15)

你可能感兴趣的:(Django使用oracle常见问题)