ORA-00001: unique constraint (BBASS.PK98) violated 主键约束问题

ORA-00001: unique constraint (BBASS.PK98) violated   主键约束问题

BBASS.PK98为当前要插入数据的表中的一个主键名。

出现这个错误的原因:主键存在重复的问题,在bbass平台中(包括以后很多时候),很多model在自动生成主键的时候,会采用sequence的方式,并且很多时候hibernate的配置文件中会将不同的model的sequence名称配置为相同的名称。

在网上查看了一些资料:

发现不少说这是一个9i的BUG,10g中已经fixed。这是我查到的原文:

ORA-00001 PERFSTAT.STATS$SQL_SUMMARY_PK2009-03-13 19:23又遇到了ORA-00001 PERFSTAT.STATS$SQL_SUMMARY_PK ,记得当时好像disable一下就可以了,今天有空metalink上查了一下,原来是9i的bug,10g中fixed.

 Database Bug.2784796 - ORA-00001 UNIQUE CONSTRAINT (PERFSTAT.STATS$SQL_SUMMARY_PK) VIOLATED.

 解决方法:

1.ALTER TABLE PERFSTAT.STATS$SQL_SUMMARY MODIFY CONSTRAINT STATS$SQL_SUMMARY_PK DISABLE NOVALIDATE;

2.1. Please run the following sql statements: (Please be sure the view STATS$V_$SQLXS created successfully in the sys schema) sqlplus " / as sysdba"

SQL> spool run_statspack.txt

SQL> create or replace view STATS$V_$SQLXS as select max(sql_text) sql_text , sum(sharable_mem) sharable_mem , sum(sorts) sorts , min(module) module , sum(loaded_versions) loaded_versions , sum(fetches) fetches , sum(executions) executions , sum(loads) loads , sum(invalidations) invalidations , sum(parse_calls) parse_calls , sum(disk_reads) disk_reads , sum(buffer_gets) buffer_gets , sum(rows_processed) rows_processed , max(command_type) command_type , address address , hash_value hash_value , count(1) version_count , sum(cpu_time) cpu_time , sum(elapsed_time) elapsed_time , max(outline_sid) outline_sid , max(outline_category) outline_category , max(is_obsolete) is_obsolete , max(child_latch) child_latch from v$sql where ( plan_hash_value > 0 or executions > 0 or parse_calls > 0 or disk_reads > 0 or buffer_gets > 0) group by hash_value, address;

SQL> select owner,object_name from dba_objects where status ='INVALID';

SQL> @?/rdbms/admin/utlrp

SQL> select owner,object_name from dba_objects where status ='INVALID';

SQL> conn perfstat/perfstat_password

SQL> execute statspack.snap(i_snap_level=>5);

SQL> spool off;

 
 
 

但是针对主键重复的问题是:save数据时,无法插入新的数据,

我们的解决方法重置sequence。在sqlplus中或者PS/SQL中手工重置一下sequence的值(前提是查出所有用同一sequence名称的表中最大的id)。

然后可以重置sequence中的start with的值,但是oracle是不允许直接这个语句(ALTER SEQUENCE SEQ_OTHERID start with 50000;)执行的。所以解决的方法是:

1、直接先drop再create,DROP SEQUENCE SEQ_OTHERID (SEQ_OTHERID 是sequence_name);

--SEQ_OTHERID 是sequence_name

SQL>DROP SEQUENCE SEQ_OTHERID;

 -- Create sequence

SQL>create sequence SEQ_OTHERID minvalue 1 maxvalue 999999999999999999999999999 start with 50000 increment by 1 cache 20;

 

 然后可以

SQL>select SEQ_OTHERID.nextval from dual;查看新的 start with的值,已经改变为50000了。 

注意:

在生产环境中:也就是说这些sequence正在被用到的时候,如果drop掉的话,就会出现错误。

所以可以采用下面的解决方法:

2、可以先修改increment by的值,这个是可以直接alter的

SQL>ALTER SEQUENCE SEQ_OTHERID INCREMENT BY 50000;

再执行下面的SQL语句

SQL>select SEQ_OTHERID.nextval from dual;

执行完后,start with的值就变为之前sequence中的start with+50000的值,

再将INCREMENT BY 修改回来

SQL>ALTER SEQUENCE SEQ_OTHERID INCREMENT BY 1;

 上述过程就相当于修改了start with的值。

再贴一个网上搜到的方法:

--create procedure pro_test for test

create or replace procedure pro_reset_seq(v_seqname varchar2) as n_temp number(10);

 s_tsql varchar2(100);

 begin execute immediate ' select ' || v_seqname || '.nextval from dual' into n_temp; if n_temp <> 1 then n_temp := -(n_temp-1); s_tsql := ' alter sequence ' || v_seqname || ' increment by ' || n_temp; execute immediate s_tsql; execute immediate ' select ' || v_seqname || '.nextval from dual' into n_temp; s_tsql := ' alter sequence ' || v_seqname || ' increment by 1 '; execute immediate s_tsql; end if; end;

/ 在SQL PLUS中调用 exec pro_reset_seq('seq_test'); 

/ 你所希望重置的序列就可以重新从1开始递增了。

猜你喜欢

转载自xm-koma.iteye.com/blog/2024870