[Django] #36687: Unexpected IntegrityError and unavailability during Django Oracle upgrades involving AutoField/BigAutoField and pre-Django 2.0 legacy triggers behavior

4 views
Skip to first unread message

Django

unread,
Oct 24, 2025, 12:24:30 PM10/24/25
to django-...@googlegroups.com
#36687: Unexpected IntegrityError and unavailability during Django Oracle upgrades
involving AutoField/BigAutoField and pre-Django 2.0 legacy triggers
behavior
-------------------------------------+-------------------------------------
Reporter: Fabio Caritas | Type:
Barrionuevo da Luz | Uncategorized
Status: new | Component: Database
| layer (models, ORM)
Version: 5.2 | Severity: Release
Keywords: oracle, oracle 11, | blocker
ora-00001, AutoField, | Triage Stage:
BigAutoField, IntegrityError | Unreviewed
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
I recently migrated a legacy project to Django 5.2 + Python 3.12 + Oracle
19c and encountered some unexpected issues.

The project started with Python 2.7 and Django 1.11 or earlier + Oracle 11
and was later migrated by someone to Django 3.0 + Oracle 12+.

== Context ==

Until Django 1.11, the Django Oracle backend created a `trigger` +
`sequence` for each `AutoField` and `BigAutoField` used in the project.
See
[https://github.com/django/django/blob/stable/1.11.x/django/db/backends/oracle/operations.py#L57-L78].

Django 2.0 introduced support for `identity` columns in `AutoField` and
`BigAutoField` on Oracle (see
[https://github.com/django/django/commit/924a89e135fe54bc7622aa6f03405211e75c06e9]),
but only for new tables/models. This means that a `trigger` + `sequence`
was no longer necessary because `identity` columns have an implicit
`sequence` created and managed automatically by Oracle. Note that support
for `identity` columns was added in Oracle 12+.

If the project started with versions prior to Django 2.0 (Django 1.11 or
lower) + Oracle 11 or lower and already has a created and populated
database, then existing tables/models will have been created with a
`trigger` + sequence for `AutoField`/`BigAutoField`.

After upgrading the codebase + database to run with Django 2.0+ and Oracle
12+, tables/models created after the upgrade will use `identity` columns,
but the old models will continue to use the `trigger` + `sequence`,
remaining fully functional and untouched.

In the future Django 6.0, the `BigAutoField` will be the default field
for primary keys.

The consequence of this is that in some situations, this results in the
creation of a new migration that will, at the database level (Oracle),
change the primary key column type from `NUMBER(11)` or `NUMBER(11)
GENERATED BY DEFAULT ON NULL AS IDENTITY` to `NUMBER(19) GENERATED BY
DEFAULT ON NULL AS IDENTITY`.

This does not cause problems for tables/models created after the project
is already using Django 2.0+ and Oracle 12+.

However, it can result in unique constraints errors, as there will now be
an `identity` column for the primary key with a `sequence` number that may
already exist in the primary key column of the table, plus a `trigger` +
`sequence` competing to generate the new value for the primary key,
randomly generating the error:

{{{
django.db.utils.IntegrityError: ORA-00001: unique constraint
(<DB_USER>.SYS_C<ID>) violated
Help: https://docs.oracle.com/error-help/db/ora-00001/
}}}

The point here is that, although the migration plan for `BigAutoField` to
be the default primary key type has been underway for some time, I could
not find any warning in the documentation about the existence of
`triggers` in Django 1.11 or lower, and I did not see or do not recall
seeing any Django warning that there would be a `trigger` and that it
could interfere with `identity` on Oracle 12+ and Django 2.0+.

Tools like `django-upgrade` and `django-codemod` also did not catch this.

== Suggestions ==

I think it would be prudent before the release of Django 6.0 to:

1. Document the behavior in the release notes for Django 2.0.
2. Document the behavior in the release notes for Django 6.0.
3. Perhaps create a migration guide to how to safe migrate from `trigger`
+ `sequence` to identity on Oracle and link it in the documentation for
`AutoField` and `BigAutoField` in all versions.
4. In the documentation for `AutoField` and `BigAutoField` in Django 2.0
and all subsequent versions, inform about the old behavior regarding the
`trigger`.
5. Perhaps improve the way migrations from `AutoField` to `BigAutoField`
are done and include the detection of the existence of the `trigger` +
sequence and inform how to resolve it.
6. Perhaps introduce some new functionality to be executed when running
`manage.py makemigrations` or `manage.py check` and thus issue a warning.


Note that Django's native application tables, such as auth, admin,
contenty_type, etc., do not generate any migrations or warnings, even with
DEFAULT_AUTO_FIELD = 'django.db.models.BigAutoField' set in the settings.
They continue to use the trigger + sequence combination if the project
born from a very old version of Django (Django 1.11 or lower + Oracle 11
or lower )

This may not be worth maintaining for the same reason that BigAutoField is
now the default primary key type on Django 6.0

A migration path/guide for these should probably be created for native
django app.
--
Ticket URL: <https://code.djangoproject.com/ticket/36687>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.

Django

unread,
Oct 24, 2025, 12:27:13 PM10/24/25
to django-...@googlegroups.com
#36687: Unexpected IntegrityError and unavailability during Django Oracle upgrades
involving AutoField/BigAutoField and pre-Django 2.0 legacy triggers
behavior
-------------------------------------+-------------------------------------
Reporter: Fabio Caritas | Owner: (none)
Barrionuevo da Luz |
Type: Uncategorized | Status: new
Component: Database layer | Version: 6.0
(models, ORM) |
Severity: Release blocker | Resolution:
Keywords: oracle, oracle 11, | Triage Stage:
ora-00001, AutoField, | Unreviewed
BigAutoField, IntegrityError |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Fabio Caritas Barrionuevo da Luz):

* version: 5.2 => 6.0

--
Ticket URL: <https://code.djangoproject.com/ticket/36687#comment:1>

Django

unread,
Oct 24, 2025, 1:18:51 PM10/24/25
to django-...@googlegroups.com
#36687: Unexpected IntegrityError and unavailability during Django Oracle upgrades
involving AutoField/BigAutoField and pre-Django 2.0 legacy triggers
behavior
-------------------------------------+-------------------------------------
Reporter: Fabio Caritas | Owner: (none)
Barrionuevo da Luz |
Type: Uncategorized | Status: new
Component: Database layer | Version: 6.0
(models, ORM) |
Severity: Normal | Resolution:
Keywords: oracle, oracle 11, | Triage Stage:
ora-00001, AutoField, | Unreviewed
BigAutoField, IntegrityError |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Mariusz Felisiak):

* severity: Release blocker => Normal

--
Ticket URL: <https://code.djangoproject.com/ticket/36687#comment:2>

Django

unread,
Oct 24, 2025, 4:41:16 PM10/24/25
to django-...@googlegroups.com
#36687: Unexpected IntegrityError and unavailability during Django Oracle upgrades
involving AutoField/BigAutoField and pre-Django 2.0 legacy triggers
behavior
-------------------------------------+-------------------------------------
Reporter: Fabio Caritas | Owner: (none)
Barrionuevo da Luz |
Type: Uncategorized | Status: closed
Component: Database layer | Version: 6.0
(models, ORM) |
Severity: Normal | Resolution: needsinfo
Keywords: oracle, oracle 11, | Triage Stage:
ora-00001, AutoField, | Unreviewed
BigAutoField, IntegrityError |
Has patch: 0 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Changes (by Jacob Walls):

* resolution: => needsinfo
* status: new => closed

Comment:

Hi, thanks for the report.

> The consequence of this is that in some situations, this results in the
creation of a new migration that will, at the database level (Oracle),
change the primary key column type from NUMBER(11) or NUMBER(11) GENERATED
BY DEFAULT ON NULL AS IDENTITY to NUMBER(19) GENERATED BY DEFAULT ON NULL
AS IDENTITY.

Can you share more information about why a migration was generated? My
understanding is that the system check we just removed has complained
since 3.2 with instructions about the
[https://docs.djangoproject.com/en/5.2/releases/3.2/#customizing-type-of-
auto-created-primary-keys three ways] to avoid a migration (per model, per
app, or per project).
--
Ticket URL: <https://code.djangoproject.com/ticket/36687#comment:3>
Reply all
Reply to author
Forward
0 new messages