我们在日常维护数据库过程中,经常会通过exp、expdp,imp、impdp等导入导出数据。但通过这种方式进行的数据迁移,如果使用到序列,由于序列缓存(cache)的问题,如果使用序列做主键,经常会发生保存不了(违反唯一约束的问题),处理起来也比较麻烦。
方法1:
针对此类问题的处理,我总结了一下。最好的方法是在导入前,将序列的信息提取出来,生产sql脚本。导入完成后,删除导入的序列,通过sql脚本重建序列即可。
sql脚本如下:
--导出用户下执行,执行结果存成sql文件
select 'create sequence '||sequence_name||
' minvalue '||min_value||
' maxvalue '||max_value||
' start with '||last_number||
' increment by '||increment_by||
(case when cycle_flag='N' then '' else ' cycle ' end) ||
(case when order_flag='N' then '' else ' order ' end) ||
(case when cache_size=0 then ' nocache' else ' cache '||cache_size
end) ||';'
from USER_sequences;
--导入用户下执行,执行结果存成sql文件,然后立即执行此文件,执行成功后即删除了所有序列,然后再执行上面生成的sql文件来重建序列,完成之后就OK了。
select 'drop sequence '||sequence_name||' ;' from
user_sequences;
也可尝试(select dbms_metadata.get_ddl('SEQUENCE',u.object_name) from
user_objects u where object_type='SEQUENCE')
方法2:
批量添加序列下一跳为当前值+1000
SELECT 'Alter Sequence '||sequence_owner||'.'|| SEQUENCE_NAME ||
' Increment By ' || to_char(last_number +
1000)||';' from DBA_SEQUENCES
WHERE SEQUENCE_OWNER in
(select b.username from dba_users b
where b.account_status = 'OPEN' and b.username not in('SYS',
'SYSTEM', 'SYSMAN', 'MGMT_VIEW', 'DBSNMP',
'SAMPLE_DBA'))
执行生成下一跳
select 'Select '||sequence_owner||'.'||SEQUENCE_NAME||'.NextVal
From Dual;' from DBA_SEQUENCES WHERE
SEQUENCE_OWNER in (select b.username
from dba_users b
where b.account_status = 'OPEN'
and b.username not in ('SYS',
'SYSTEM','SYSMAN','MGMT_VIEW','DBSNMP','SAMPLE_DBA'))
修改回序列下一跳为1 SELECT 'Alter Sequence '||sequence_owner||'.'|| SEQUENCE_NAME || '
Increment By 1;'
from DBA_SEQUENCES
WHERE SEQUENCE_OWNER in
(select b.username
from dba_users b
where b.account_status = 'OPEN'
and b.username not in ('SYS', 'SYSTEM', 'SYSMAN',
'MGMT_VIEW',
'DBSNMP', 'SAMPLE_DBA'))