ORACLE数据库:如何修正测试环境在插入数据时,出现唯一性错误

栏目:云星空知识作者:金蝶来源:金蝶云社区发布:2024-09-23浏览:1

ORACLE数据库:如何修正测试环境在插入数据时,出现唯一性错误

--A

背景:撰写此文档,是为了处理这类错误,

 


--B 

分析问题的产生原因:

 

1、 问题发生在客户使用Expdp/Impdp的方法,新建的数据库账号上。

 

2、 Expdp 时,先导出了序列对象,然后再导出使用这些序列的表。

 

3、 由于是在业务期间的操作,某些序列的信息被导出到DMP后,应用系统此时还在持续读取该序列值,作为对应表的主键值,插入到表中。之后,该表才被导出到DMP文件里。

 

4、 显然,此时表里的主键值,比保存在DMP文件里该序列的当前值,要大;故,当将此DMP文件的数据导入库后,使用序列的下一个值,将出现表的主键值重复的情况,就会报上述错误。

 

--C

显然,要消除此语句,只要让序列的输出值,大于表中主键字段的最大值即可。这一点实现起来并不难,关键是,如何确保表和序列的一一匹配?为此,需要设计表来保存两者的关系,如下结构:

create table t_bas_tabandseqs

(table_name      varchar2(30) not null,

 seq_name        varchar2(30) not null,

 column_name     varchar2(30));

/

 

table_name   :表名,必填项。

seq_name    :该表主键对应的序列名,必填项。

column_name :表主键字段,辅助,主键只能一个字段。

 

alter table t_bas_tabandseqs add constraint pk_bas_tabandseqs primary key(table_name);

create unique index idx_ bas_tabandseqs on t_ bas_tabandseqs (seq_name);


 

--D 编写了个存储过程来修正序列的当前值,使得序列当前值大于表的主键最大值。

入参为:发生唯一性错误的索引;如上面的 PK_BD_SUPPLIER_L,

 

   存储过程根据入参,找到所属的表,当此索引是由一个索引字段组成时,在辅助表:

t_bas_tabandseqs里搜索此表对应的序列,

 

然后对比表的主键最大值,及序列的下一个值,若序列值比主键最大值小,则更改序列步伐

属性(下个值跨过主键最大值),然后取序列的下一个值,此时,序列的当前值将大于主键最

大值,然后,再把序列的步伐改回1。

 

create or replace procedure p_bas_alterseqstartval(v_accid_idx in varchar2) as

  v_maxval        number;

  v_nextval       number;

  v2_nextval      number;

begin

  for i in (select table_name, column_name, col_position from (select table_name, column_name, column_position col_position,

                   row_number() over(partition by table_name, index_name order by column_position desc) seq

            from user_ind_columns where index_name=upper(v_accid_idx)) where seq=1 ) loop

    if (i.col_position = 1) then

        for j in (select seq_name from t_bas_tabandseqs where table_name=i.table_name) loop

          begin execute immediate 'select '||j.seq_name||'.nextval from dual' into v_nextval;

                execute immediate 'select max('||i.column_name||') from '||i.table_name into v_maxval;

                if (v_maxval > v_nextval) then

                    execute immediate 'alter sequence '||j.seq_name||' increment by '||(v_maxval - v_nextval + 1);                   

                    execute immediate 'select '||j.seq_name||'.nextval from dual' into v2_nextval;

                    execute immediate 'alter sequence '||j.seq_name||' increment by 1';

                elsif v_maxval = v_nextval then null;

                elsif (v_maxval < v_nextval) then

                  raise_application_error(-20010,'序列值和主键值并无冲突,或者序列:'||j.seq_name||',并非给该主键使用.');

                end if;

          end;

        end loop;

    else raise_application_error(-20001,'该索引由多字段组成,得人工处理.'); end if;

  end loop;

end;

/


ORACLE数据库:如何修正测试环境在插入数据时,出现唯一性错误

--A背景:撰写此文档,是为了处理这类错误, --B 分析问题的产生原因: 1、 问题发生在客户使用Expdp/Impdp的方法,新建的数据库账号上。 ...
点击下载文档
确认删除?
回到顶部
客服QQ
  • 客服QQ点击这里给我发消息