我想每天将我的Oracle Sequence重置为0,如下所示:
create or replace procedure reset_seq(p_seq_name in varchar2) is
l_val number;
begin
execute immediate 'select ' || p_seq_name || '.nextval from dual'
INTO l_val; --1
execute immediate 'alter sequence ' || p_seq_name || ' increment by -' ||
l_val || ' minvalue 0'; --2
execute immediate 'select ' || p_seq_name || '.nextval from dual'
INTO l_val; --3
execute immediate 'alter sequence ' || p_seq_name ||
' increment by 1 minvalue 0'; --4
end;
但是运行约2年后,突然出现错误,增量是一个负整数,如-16,起始值也为-16。所以任何人都可以帮助我解释这个问题。
我认为是那样。
但是我不确定,任何人都可以向我解释。谢谢。
答案 0 :(得分:0)
问题在于您提交的过程和您的外部程序都可能在步骤2和步骤4之间都调用nextval
。可以按任何顺序调用;并可能使外部程序可以进行多次调用。
您可以尝试通过更改过程和外部调用来减轻这种情况。
如果第3步出错,此过程将终止,并且永远不会到达第4步,因此以后对nextval
的所有调用将继续出错。因此,您可以捕获并忽略ORA-08004错误,因为您将仅获得以下信息:如果在步骤2和3之间进行了外部调用,则该调用将序列加回到零,因此3在这种情况下实际上是多余的:
create or replace procedure reset_seq(p_seq_name in varchar2) is
l_val number;
e_8004 exception;
pragma exception_init(e_8004, -8004);
begin
execute immediate 'select ' || p_seq_name || '.nextval from dual'
INTO l_val; --1
execute immediate 'alter sequence ' || p_seq_name || ' increment by -' ||
l_val || ' minvalue 0'; --2
begin
execute immediate 'select ' || p_seq_name || '.nextval from dual'
INTO l_val; --3
exception
when e_8004 then
-- nextval has already been called by someone else
null;
end;
execute immediate 'alter sequence ' || p_seq_name ||
' increment by 1 minvalue 0'; --4
end;
现在,如果外部程序在第2步和第3步之间调用nextval
,那么您将在第3步得到错误,但忽略它,第4步仍然会发生。
如果外部程序在第2步和第3步之间进行调用,则其nextval
值将为零;如果在第3步和第4步之间进行了调用,或者在第2步和第4步之间在窗口中进行了多次调用,则将获得ORA-08004。因此,假设您不希望零为有效结果(这看起来很合理)您通常不会得到),您可以重复拨打电话,直到得到非零答案且没有错误为止。用伪代码类似:
loop
val = seq.nextval;
if error == -8004 then continue;
if val == 0 then continue;
break;
end loop
您可以考虑将该逻辑放入PL / SQL函数中,并让您的程序调用该函数而不是直接访问该序列,这既可以隐藏该复杂性,又可以避免在可能影响多个程序的情况下重复执行该操作