1. 程式人生 > 其它 >django2.2和oracle11g版本衝突問題

django2.2和oracle11g版本衝突問題

上次用django2.2和oracle11g,在migrate的時候發生了版本衝突,最終 [ 將Oracle升級到了12c才解決問題

](https://www.jb51.net/article/189974.htm)

那麼到底能不能用別的方法來解決這個衝突呢?想了個解決思路,實踐一下:

用django2.2連Oracle12c環境下做migrate,建立基礎表

將基礎表匯出,再匯入到Oracle11g資料庫中

用django2.2連Oracle11g

實施步驟

1、用django2.2連Oracle12c環境下做migrate,建立基礎表

在前文中已經完成,連線到資料庫,可以看到有10張基礎表

看一張表,比如AUTH_GROUP表,發現有個ID欄位是用了12c特有的generated語法,除了DJANGO_SESSION外,其他每張表都有一個自增序列的id欄位作為主鍵。

    -- Create table
    create table AUTH_GROUP
    (
     id NUMBER(11) generated by default on null as identity,
     name NVARCHAR2(150)
    )
    tablespace DJANGO;
    -- Create/Recreate primary, unique and foreign key constraints 
    alter table AUTH_GROUP
     add primary key (ID)
     using index 
     tablespace DJANGO;
    alter table AUTH_GROUP
     add unique (NAME)
     using index 
     tablespace DJANGO;

2. 將基礎表匯出,再匯入到Oracle11g資料庫中

匯出django使用者資料庫,注意使用11g版本

接著匯入到11g資料庫中,非常順利

再看AUTH_GROUP表,發現表結構是一樣的,但是id上面自增序列的預設值沒有了。

    -- Create table
    create table AUTH_GROUP
    (
     id NUMBER(11) not null,
     name NVARCHAR2(150)
    )
    tablespace DJANGO;
    -- Create/Recreate primary, unique and foreign key constraints 
    alter table AUTH_GROUP
     add primary key (ID)
     using index 
     tablespace DJANGO;
    alter table AUTH_GROUP
     add unique (NAME)
     using index 
     tablespace DJANGO;

3、用django2.2連Oracle11g

修改settings檔案,連Oracle11g,然後啟動django服務,果然成功啟動

但是,但是,建立admin使用者密碼的時候就報錯了,ORA-01400: cannot insert NULL into
(“DJANGO”.“AUTH_USER”.“ID”)

    PS D:\parttime\python\django\guanxiangzhiji> python manage.py createsuperuser
    使用者名稱 (leave blank to use 'administrator'):
    電子郵件地址:
    Password:
    Password (again):
    密碼長度太短。密碼必須包含至少 8 個字元。
    這個密碼太常見了。
    Bypass password validation and create user anyway? [y/N]: y
    Traceback (most recent call last):
     File "D:\app\anaconda\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
     return self.cursor.execute(sql, params)
     File "D:\app\anaconda\lib\site-packages\django\db\backends\oracle\base.py", line 510, in execute
     return self.cursor.execute(query, self._param_generator(params))
    cx_Oracle.IntegrityError: ORA-01400: cannot insert NULL into ("DJANGO"."AUTH_USER"."ID")
    
    The above exception was the direct cause of the following exception:
    
    Traceback (most recent call last):
     File "manage.py", line 21, in <module>
     main()
     File "manage.py", line 17, in main
     execute_from_command_line(sys.argv)
     File "D:\app\anaconda\lib\site-packages\django\core\management\__init__.py", line 381, in execute_from_command_line
     utility.execute()
     File "D:\app\anaconda\lib\site-packages\django\core\management\__init__.py", line 375, in execute
     self.fetch_command(subcommand).run_from_argv(self.argv)
     File "D:\app\anaconda\lib\site-packages\django\core\management\base.py", line 323, in run_from_argv
     self.execute(*args, **cmd_options)
     File "D:\app\anaconda\lib\site-packages\django\contrib\auth\management\commands\createsuperuser.py", line 61, in execute
     return super().execute(*args, **options)
     File "D:\app\anaconda\lib\site-packages\django\core\management\base.py", line 364, in execute
     output = self.handle(*args, **options)
     File "D:\app\anaconda\lib\site-packages\django\contrib\auth\management\commands\createsuperuser.py", line 156, in handle
     self.UserModel._default_manager.db_manager(database).create_superuser(**user_data)
     File "D:\app\anaconda\lib\site-packages\django\contrib\auth\models.py", line 162, in create_superuser
     return self._create_user(username, email, password, **extra_fields)
     File "D:\app\anaconda\lib\site-packages\django\contrib\auth\models.py", line 145, in _create_user
     user.save(using=self._db)
     File "D:\app\anaconda\lib\site-packages\django\contrib\auth\base_user.py", line 66, in save
     super().save(*args, **kwargs)
     File "D:\app\anaconda\lib\site-packages\django\db\models\base.py", line 741, in save
     force_update=force_update, update_fields=update_fields)
     File "D:\app\anaconda\lib\site-packages\django\db\models\base.py", line 779, in save_base
     force_update, using, update_fields,
     File "D:\app\anaconda\lib\site-packages\django\db\models\base.py", line 870, in _save_table
     result = self._do_insert(cls._base_manager, using, fields, update_pk, raw)
     File "D:\app\anaconda\lib\site-packages\django\db\models\base.py", line 908, in _do_insert
     using=using, raw=raw)
     File "D:\app\anaconda\lib\site-packages\django\db\models\manager.py", line 82, in manager_method
     return getattr(self.get_queryset(), name)(*args, **kwargs)
     File "D:\app\anaconda\lib\site-packages\django\db\models\query.py", line 1186, in _insert
     return query.get_compiler(using=using).execute_sql(return_id)
     File "D:\app\anaconda\lib\site-packages\django\db\models\sql\compiler.py", line 1335, in execute_sql
     cursor.execute(sql, params)
     File "D:\app\anaconda\lib\site-packages\django\db\backends\utils.py", line 99, in execute
     return super().execute(sql, params)
     File "D:\app\anaconda\lib\site-packages\django\db\backends\utils.py", line 67, in execute
     return self._execute_with_wrappers(sql, params, many=False, executor=self._execute)
     File "D:\app\anaconda\lib\site-packages\django\db\backends\utils.py", line 76, in _execute_with_wrappers
     return executor(sql, params, many, context)
     File "D:\app\anaconda\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
     return self.cursor.execute(sql, params)
     File "D:\app\anaconda\lib\site-packages\django\db\utils.py", line 89, in __exit__
     raise dj_exc_value.with_traceback(traceback) from exc_value
     File "D:\app\anaconda\lib\site-packages\django\db\backends\utils.py", line 84, in _execute
     return self.cursor.execute(sql, params)
     File "D:\app\anaconda\lib\site-packages\django\db\backends\oracle\base.py", line 510, in execute
     return self.cursor.execute(query, self._param_generator(params))
    django.db.utils.IntegrityError: ORA-01400: cannot insert NULL into ("DJANGO"."AUTH_USER"."ID")
    

原因分析

很明顯,插入到AUTH_USER表時,沒有指定ID的值,而ID是主鍵,非空。

因為在12c的環境下,這個ID是自增序列,insert語句中不需要指定這個值。

解決方案

解決方案也應運而出了,只要為每個ID列建立一個11g的序列,建立觸發器,在插入資料時補上id值就行了。

(1)生成序列。

用sql語句

    select 'create sequence seq_'||table_name||' minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;'
     from user_tab_columns
     where column_name='ID';

生成建立序列的批量執行語句,並執行。

    create sequence seq_DJANGO_ADMIN_LOG minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;
    create sequence seq_AUTH_USER minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;
    create sequence seq_AUTH_USER_GROUPS minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;
    create sequence seq_DJANGO_CONTENT_TYPE minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;
    create sequence seq_AUTH_GROUP minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;
    create sequence seq_AUTH_GROUP_PERMISSIONS minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;
    create sequence seq_DJANGO_MIGRATIONS minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;
    create sequence seq_AUTH_PERMISSION minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;
    create sequence seq_AUTH_USER_USER_PERMISSIONS minvalue 1 maxvalue 999999999 start with 1 increment by 1 cache 20;
    

(2)建立觸發器

用SQL語句

    select 'create or replace trigger tri_'||table_name||'
     before insert
     on '||table_name||' 
     for each row
     declare
     begin
     :new.id:=seq_'||table_name||'.nextval;
     end tri_'||table_name||';
     /'
     from user_tab_columns
     where column_name='ID';
    

生成觸發器指令碼:

    create or replace trigger tri_DJANGO_MIGRATIONS
    	before insert
    	on DJANGO_MIGRATIONS
    	for each row
    declare
    begin
    	:new.id:=seq_DJANGO_MIGRATIONS.nextval;
    end tri_DJANGO_MIGRATIONS;
    /
    create or replace trigger tri_DJANGO_CONTENT_TYPE
    	before insert
    	on DJANGO_CONTENT_TYPE
    	for each row
    declare
    begin
    	:new.id:=seq_DJANGO_CONTENT_TYPE.nextval;
    end tri_DJANGO_CONTENT_TYPE;
    /
    create or replace trigger tri_AUTH_PERMISSION
    	before insert
    	on AUTH_PERMISSION
    	for each row
    declare
    begin
    	:new.id:=seq_AUTH_PERMISSION.nextval;
    end tri_AUTH_PERMISSION;
    /
    create or replace trigger tri_AUTH_GROUP
    	before insert
    	on AUTH_GROUP
    	for each row
    declare
    begin
    	:new.id:=seq_AUTH_GROUP.nextval;
    end tri_AUTH_GROUP;
    /
    create or replace trigger tri_AUTH_GROUP_PERMISSIONS
    	before insert
    	on AUTH_GROUP_PERMISSIONS
    	for each row
    declare
    begin
    	:new.id:=seq_AUTH_GROUP_PERMISSIONS.nextval;
    end tri_AUTH_GROUP_PERMISSIONS;
    /
    create or replace trigger tri_AUTH_USER
    	before insert
    	on AUTH_USER
    	for each row
    declare
    begin
    	:new.id:=seq_AUTH_USER.nextval;
    end tri_AUTH_USER;
    /
    create or replace trigger tri_AUTH_USER_GROUPS
    	before insert
    	on AUTH_USER_GROUPS
    	for each row
    declare
    begin
    	:new.id:=seq_AUTH_USER_GROUPS.nextval;
    end tri_AUTH_USER_GROUPS;
    /
    create or replace trigger tri_AUTH_USER_USER_PERMISSIONS
    	before insert
    	on AUTH_USER_USER_PERMISSIONS
    	for each row
    declare
    begin
    	:new.id:=seq_AUTH_USER_USER_PERMISSIONS.nextval;
    end tri_AUTH_USER_USER_PERMISSIONS;
    /
    create or replace trigger tri_DJANGO_ADMIN_LOG
    	before insert
    	on DJANGO_ADMIN_LOG
    	for each row
    declare
    begin
    	:new.id:=seq_DJANGO_ADMIN_LOG.nextval;
    end tri_DJANGO_ADMIN_LOG;
    /
    

(3)此時再建立admin使用者,就成功了

新增使用者lurenjia成功!

以上這篇基於django2.2連oracle11g解決版本衝突的問題就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支援指令碼之家。