【问题标题】:Django Oracle integrity error when saving any instance to database将任何实例保存到数据库时出现 Django Oracle 完整性错误
【发布时间】:2011-06-22 16:43:48
【问题描述】:

我正在从 sqlite 迁移到 oracle 后端。 oracle 数据库已经存在并由其他人维护。它的版本是Oracle9i Enterprise Edition Release 9.2.0.1.0。

我有一个简单的模型:

class AliasType(models.Model):
    id = models.AutoField(primary_key=True, db_column="F_ALIAS_ID")
    name = models.CharField(u"Type name", max_length=255, unique=True, db_column="F_ALIAS_NAME")

    class Meta:
        db_table = "ALIAS"

./manage.py syncdb 不返回任何错误。但是当我尝试创建一个新实例并将其保存到数据库时,我收到以下错误:

>>> AliasType.objects.create(name="test")
Traceback (most recent call last):
  File "<console>", line 1, in <module>
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/manager.py", line 138, in create
    return self.get_query_set().create(**kwargs)
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/query.py", line 360, in create
    obj.save(force_insert=True, using=self.db)
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/base.py", line 460, in save
    self.save_base(using=using, force_insert=force_insert, force_update=force_update)
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/base.py", line 553, in save_base
    result = manager._insert(values, return_id=update_pk, using=using)
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/manager.py", line 195, in _insert
    return insert_query(self.model, values, **kwargs)
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/query.py", line 1435, in insert_query
    return query.get_compiler(using=using).execute_sql(return_id)
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/sql/compiler.py", line 791, in execute_sql
    cursor = super(SQLInsertCompiler, self).execute_sql(None)
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/models/sql/compiler.py", line 735, in execute_sql
    cursor.execute(sql, params)
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/backends/util.py", line 18, in execute
    return self.cursor.execute(sql, params)
  File "/mnt/Data/private/projects/envs/termary-oracle/src/django/django/db/backends/oracle/base.py", line 630, in execute
    return self.cursor.execute(query, self._param_generator(params))
IntegrityError: ORA-01400: cannot insert NULL into ("SINCE"."ALIAS"."F_ALIAS_ID")

如果我指定 id,例如AliasType.objects.create(id=5, name="test"),它有效。我认为 django 应该能够自动检索 id 值。我了解到 Oracle 不支持自动增量,我应该使用触发器和序列。有人告诉我,数据库中有一个现有序列返回所有新行的 id,我知道它的名称,比如SEQ_GET_NEW_ID

所以问题是如何以最优雅的方式实现它,即如何告诉 Django 到 get id values for all new objects from the sequence named SEQ_GET_NEW_ID 而不会过多地破解它(例如覆盖所有模型的 save() 方法)?

【问题讨论】:

    标签: sql django oracle django-models ora-01400


    【解决方案1】:

    有一个打开的票证 (#1946) 允许这样做,覆盖默认序列名称。但由于它还没有关闭,我认为没有办法不进行黑客攻击。

    我以前没有使用过 Oracle,但快速搜索表明可以为序列创建别名/同义词。 manage.py sqlall &lt;app&gt; 应该显示 Django 期望的序列名称。因此,您可能可以将其设为 SEQ_GET_NEW_ID 的别名。

    【讨论】:

    • 感谢您的回答。它帮助我找到了解决方法。我要求维护数据库的人为所有表创建触发器。触发器在从同一序列SEQ_GET_NEW_ID 插入之前获取下一个 id。所以这里不需要序列的别名。
    • 只是为了澄清有关 django 如何获取刚刚插入的行的 id 的事情。如果指定了选项use_returning_into,django 直接从INSERT 子句中获取id。在这种情况下,django 不需要序列。如果use_returning_into 为假,django 首先从名为APP_MODEL_SQ 的序列中获取一个新的id,然后插入具有该id 的行。在这种情况下,您需要为现有序列创建别名(它可以是整个数据库的相同序列),以便 django 能够使用它们。
    猜你喜欢
    • 2017-11-13
    • 1970-01-01
    • 2021-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多