我有一个Django (1.5版)应用程序,它收到以下Oracle错误:
ORA-01461: can bind a LONG value only for insert into a LONG column在进行了一些数据库调试之后,问题似乎是由于使用SESSION_DATA (数据类型NCLOB)的较长(大约2.5k个字符) Unicode字符串值在DJANGO_SESSION表上执行INSERT而导致的。
我的一位同事告诉我,这个问题不会发生在更新上,而只发生在插入上,因为更新的Django数据库代码包含将数据库写入拆分成可管理的块的逻辑(我在这里解释),但由于某种原因,插入缺少该逻辑。
有了这些信息,我想我可以通过编写一小段自定义中间件来解决这个问题,该中间件使用SESSION_DATA的(可能)空值立即执行request.session.save(),然后在稍后设置会话数据时,这将导致更新而不是插入。
然而,事情似乎并没有那么简单。如果我在'django.contrib.sessions.middleware.SessionMiddleware',条目上方的settings.MIDDLEWARE_CLASSES中插入我的自定义中间件,request对象还没有session属性,并且我得到这个错误:
AttributeError: 'WSGIRequest' object has no attribute 'session'如果我在SessionMiddleware条目之后插入我的中间件,那么在这个过程中就太晚了,我会得到原始的ORA-01461错误。
那么,有没有办法使用中间件来解决ORA-01461错误呢?还是一点都不想?
发布于 2014-06-13 19:43:01
检查这个Django bug:https://code.djangoproject.com/ticket/11487
我也解决了这个问题(在Django1.6上),并通过将4000字符检查更改为1000 here https://github.com/django/django/blob/stable/1.6.x/django/db/backends/oracle/base.py#L699来验证它。不幸的是,因为它是Django核心代码,所以这很难在本地修复。
我还没有测试过,但AFAICT至少已经尝试在Django 1.7 - https://github.com/django/django/blob/stable/1.7.x/django/db/backends/oracle/base.py#L781中修复了这个问题
我猜如果你不能升级到1.7 (如果它确实解决了这个问题),你可以找到会话数据变得太大的地方,并通过将其存储在其他地方来解决-如果这是一个选择。
发布于 2015-08-27 05:24:09
对我起作用的变通方法是:
input_size设置为cx_Oracle.CLOBinput_size属性(请参阅https://github.com/django/django/blob/stable/1.6.x/django/db/backends/oracle/base.py#L796 -即研究模块中input_size属性的用法)这应该是可行的:
class clob_unicode(unicode):
def __new__(cls, *args, **kwargs):
ret = unicode.__new__(cls, *args, **kwargs)
import cx_Oracle
ret.input_size = cx_Oracle.CLOB # to set proper bind var type
return ret用法:
django_object.clob_variable = clob_unicode(u"some very long string")
django_object.save() # will use .input_size to set oracle bind var type另请参阅this answer,以查看有关如何正确子类化和初始化string/Unicode子类对象(在__new__方法中初始化,而不是在__init__中初始化)的讨论。
发布于 2016-11-29 20:30:41
对我来说起作用的是在会话数据变得非常大之前创建并保存一个会话对象:
from django.contrib.sessions.backends.db import SessionStore
def view(request):
s = SessionStore()
s.create()
request.session = s
s.save()
# rest of the code here后续查询由oracle作为更新命令而不是插入命令执行。
https://stackoverflow.com/questions/21197523
复制相似问题