如何在 Oracle 中重置序列?

How do I reset a sequence in Oracle?

提问人:Mauli 提问时间:9/9/2008 最后编辑:StevoisiakMauli 更新时间:8/13/2023 访问量:721508

问:

PostgreSQL中,我可以做这样的事情:

ALTER SEQUENCE serial RESTART WITH 0;

有没有 Oracle 等价物?

SQL 数据库 Oracle 序列

评论

3赞 4/13/2011
警告:以下所有代码仅对最初使用“递增 1”创建的序列有效。如果原始序列是以增量创建的,则 != 1;应用上述任何过程后,增量将更改为 1!可以从user_sequences视图中获取要使用的正确增量值。
1赞 gerikson 9/9/2008
请在此处查看“序列重置”。
2赞 Viswanath Lekshmanan 7/27/2016
删除并重新创建序列

答:

122赞 Mo. 9/9/2008 #1

AFAIK不可能真正重新启动。(如果我错了,请纠正我!

但是,如果要将其设置为 0,则可以将其删除并重新创建。

如果要将其设置为特定值,可以将 INCREMENT 设置为负值并获取下一个值。

也就是说,如果您的序列为 500,您可以通过以下方式将其设置为 100

ALTER SEQUENCE serial INCREMENT BY -400;
SELECT serial.NEXTVAL FROM dual;
ALTER SEQUENCE serial INCREMENT BY 1;

评论

4赞 user830914 3/7/2014
只是给PLSQL人员的注意事项。请务必将 “limit 1;” 或 “rownum =1” 添加到 select 语句中,否则您最终可能会运行 nextVal 几次并增加 -400 多次。
1赞 zloctb 8/18/2015
错误序列 。NEXTVAL 低于 MINVALUE,当 INCREMENT BY -<<big_number>> 时无法实例化
2赞 Neil Kodner 9/15/2008 #2

更改序列的 INCREMENT 值,递增它,然后将其改回是非常轻松的,而且您还有一个额外的好处,即不必像删除/重新创建序列那样重新建立所有授权。

163赞 Doug Porter 9/18/2008 #3

这是将 Oracle 大师 Tom Kyte 的任何序列重置为 0 的好过程。在下面的链接中也对利弊进行了很好的讨论。

[email protected]> 
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;

    execute immediate
    'alter sequence ' || p_seq_name || ' increment by -' || l_val || 
                                                          ' minvalue 0';

    execute immediate
    'select ' || p_seq_name || '.nextval from dual' INTO l_val;

    execute immediate
    'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
end;
/

从此页面: 动态 SQL 重置序列值
另一个很好的讨论也在这里: 如何重置序列?

评论

0赞 Thiyagu ATR 2/23/2013
@Dougman:嗨,我是初学者......在上面的答案中,为什么你在最后一个提到 into 子句,而是立即执行 'select ' ||p_seq_name ||'.nextval INTO l_val from dual' ;
0赞 Doug Porter 2/27/2013
@Thiyagu:在 PL/SQL 中,这是用于捕获最多返回 1 行的选择的输出时的语法。以下是有关立即执行的文档: docs.oracle.com/cd/B28359_01/appdev.111/b28370/...execute immediate
0赞 Liz Av 9/19/2014
@matra 我没有看到需要重置序列并与同一序列的其他用户处于并发环境中的场景。
1赞 Goku 12/15/2018
为什么需要选择序列,为什么不只做最后一行'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
6赞 Boris Stul 7/30/2009 #4

存储过程将重新启动我的序列:

Create or Replace Procedure Reset_Sequence  
  is
  SeqNbr Number;
begin
   /*  Reset Sequence 'seqXRef_RowID' to 0    */
   Execute Immediate 'Select seqXRef.nextval from dual ' Into SeqNbr;
   Execute Immediate 'Alter sequence  seqXRef increment by - ' || TO_CHAR(SeqNbr) ;
   Execute Immediate 'Select seqXRef.nextval from dual ' Into SeqNbr;
   Execute Immediate 'Alter sequence  seqXRef increment by 1';
END;

/

评论

0赞 DCookie 2/6/2013
+1 - 您还可以将其参数化以传入序列名称。
5赞 Vipin Vij 12/11/2009 #5

1) 假设您创建了一个如下所示的 SEQUENCE:

CREATE SEQUENCE TESTSEQ
INCREMENT BY 1
MINVALUE 1
MAXVALUE 500
NOCACHE
NOCYCLE
NOORDER

2)现在你从SEQUENCE中获取值。假设我已经取了四次,如下所示。

SELECT TESTSEQ.NEXTVAL FROM dual
SELECT TESTSEQ.NEXTVAL FROM dual
SELECT TESTSEQ.NEXTVAL FROM dual
SELECT TESTSEQ.NEXTVAL FROM dual

3) 执行以上四个命令后,SEQUENCE 的值将为 4。现在假设我再次将 SEQUENCE 的值重置为 1。请按照以下步骤操作。按照如下所示的相同顺序执行所有步骤:

  1. ALTER SEQUENCE TESTSEQ INCREMENT BY -3;
  2. SELECT TESTSEQ.NEXTVAL FROM dual
  3. ALTER SEQUENCE TESTSEQ INCREMENT BY 1;
  4. SELECT TESTSEQ.NEXTVAL FROM dual
51赞 Gina 5/19/2010 #6

这是我的方法:

  1. 删除序列
  2. 重新创建它

例:

--Drop sequence

DROP SEQUENCE MY_SEQ;

-- Create sequence 

create sequence MY_SEQ
minvalue 1
maxvalue 999999999999999999999
start with 1
increment by 1
cache 20;

评论

34赞 Doug Porter 12/24/2011
请注意,删除将使依赖于该序列的任何对象无效,并且必须重新编译它们。
26赞 GreenGiant 1/8/2013
您还必须重新授予从序列中进行选择的任何赠款。
10赞 Navin 11/5/2010 #7

以下脚本将序列设置为所需值:

给定一个名为 PCS_PROJ_KEY_SEQ 的新创建序列和表 PCS_PROJ:

BEGIN
   DECLARE
      PROJ_KEY_MAX       NUMBER := 0;
      PROJ_KEY_CURRVAL   NUMBER := 0;
   BEGIN

    SELECT MAX (PROJ_KEY) INTO PROJ_KEY_MAX FROM PCS_PROJ;
    EXECUTE IMMEDIATE 'ALTER SEQUENCE PCS_PROJ_KEY_SEQ INCREMENT BY ' || PROJ_KEY_MAX;
    SELECT PCS_PROJ_KEY_SEQ.NEXTVAL INTO PROJ_KEY_CURRVAL FROM DUAL;
    EXECUTE IMMEDIATE 'ALTER SEQUENCE PCS_PROJ_KEY_SEQ INCREMENT BY 1';

END;
END;
/

评论

4赞 Priidu Neemre 12/15/2016
您忘记了第一个 DDL 语句中的减号(此外,还有一个额外的关键字)。END
34赞 Allbite 5/20/2011 #8

我的方法是对道格曼的例子的微不足道的延伸。

扩展是...

将种子值作为参数传入。为什么?我喜欢将序列重置为某些表中使用的最大 ID 的东西。我最终从另一个脚本调用这个程序,该脚本对一大堆序列执行多个调用,将 nextval 重置回某个级别,该级别足够高,不会导致主键冲突,因为我使用序列的值作为唯一标识符。

它还遵循以前的最小值。实际上,如果所需的p_val现有最小值高于当前或计算的下一个值,它可能会将下一个值推得更高

最重要的是,可以调用它以重置为指定值,然后等到最后看到包装器“修复我的所有序列”过程。

create or replace
procedure Reset_Sequence( p_seq_name in varchar2, p_val in number default 0)
is
  l_current number := 0;
  l_difference number := 0;
  l_minvalue user_sequences.min_value%type := 0;

begin

  select min_value
  into l_minvalue
  from user_sequences
  where sequence_name = p_seq_name;

  execute immediate
  'select ' || p_seq_name || '.nextval from dual' INTO l_current;

  if p_Val < l_minvalue then
    l_difference := l_minvalue - l_current;
  else
    l_difference := p_Val - l_current;
  end if;

  if l_difference = 0 then
    return;
  end if;

  execute immediate
    'alter sequence ' || p_seq_name || ' increment by ' || l_difference || 
       ' minvalue ' || l_minvalue;

  execute immediate
    'select ' || p_seq_name || '.nextval from dual' INTO l_difference;

  execute immediate
    'alter sequence ' || p_seq_name || ' increment by 1 minvalue ' || l_minvalue;
end Reset_Sequence;

该过程本身很有用,但现在让我们添加另一个调用它并使用序列命名约定以编程方式指定所有内容的过程,并查找现有表/字段中使用的最大值......

create or replace
procedure Reset_Sequence_to_Data(
  p_TableName varchar2,
  p_FieldName varchar2
)
is
  l_MaxUsed NUMBER;
BEGIN

  execute immediate
    'select coalesce(max(' || p_FieldName || '),0) from '|| p_TableName into l_MaxUsed;

  Reset_Sequence( p_TableName || '_' || p_Fieldname || '_SEQ', l_MaxUsed );

END Reset_Sequence_to_Data;

现在我们用煤气做饭!

上述过程将检查表中字段的最大值,从表/字段对构建序列名称,并使用该检测到的最大值调用“Reset_Sequence”。

接下来是这个拼图的最后一块,锦上添花......

create or replace
procedure Reset_All_Sequences
is
BEGIN

  Reset_Sequence_to_Data( 'ACTIVITYLOG', 'LOGID' );
  Reset_Sequence_to_Data( 'JOBSTATE', 'JOBID' );
  Reset_Sequence_to_Data( 'BATCH', 'BATCHID' );

END Reset_All_Sequences;

在我的实际数据库中,大约有一百个其他序列通过这种机制被重置,因此在上面的过程中还有 97 个对Reset_Sequence_to_Data的调用。

爱上它?讨厌它?冷漠?

评论

2赞 Harv 7/22/2011
我喜欢。我将添加一个变量来获取并保存user_sequences表中的增量值。(它可能不是 1)。注意:可能需要改用all_sequences表。在这种情况下,您可能还想传入sequence_owner。
1赞 Dominique Eav 11/28/2012
不能给你投足够的票。当您处理数据迁移时,这是一个非常常见的问题,如果您坚持序列,这是最好的方法 AFAIK。
1赞 Jeffrey Kemp 8/19/2014
点赞,因为这是一个很好的方法。唯一的缺点是,它可能导致 RAC 系统中不可预测的行为,其中可能是各种值之一,具体取决于运行脚本的节点;重新运行脚本可能会导致不同的结果。我发现,如果我多次运行它,它最终会落在一个特定的值上。l_current
6赞 Chris Saxon 2/11/2013 #9

在 Oracle 中还有另一种重置序列的方法:设置 和 属性。当 的 序列命中 时,如果设置了该属性,则它将从序列的 重新开始。maxvaluecyclenextvalmaxvaluecycleminvalue

与设置负数相比,此方法的优点是可以在重置过程运行时继续使用序列,从而减少了执行重置所需的某种形式的中断的机会。increment by

的值必须大于当前值,因此下面的过程包括一个可选参数,该参数允许缓冲区,以防在过程中选择 和设置属性之间再次访问序列。maxvaluenextvalnextvalcycle

create sequence s start with 1 increment by 1;

select s.nextval from dual
connect by level <= 20;

   NEXTVAL
----------
         1 
...
        20

create or replace procedure reset_sequence ( i_buffer in pls_integer default 0)
as
  maxval pls_integer;
begin

  maxval := s.nextval + greatest(i_buffer, 0); --ensure we don't go backwards!
  execute immediate 'alter sequence s cycle minvalue 0 maxvalue ' || maxval;
  maxval := s.nextval;
  execute immediate 'alter sequence s nocycle maxvalue 99999999999999';

end;
/
show errors

exec reset_sequence;

select s.nextval from dual;

   NEXTVAL
----------
         1 

该过程仍然允许另一个会话获取值 0 的可能性,这对您来说可能是也可能不是问题。如果是,您始终可以:

  • 设置在第一个更改中minvalue 1
  • 排除第二次提取nextval
  • 将语句移动到另一个过程中,以在以后运行(假设您要执行此操作)。nocycle
82赞 Jon Heller 10/30/2013 #10

对于常规序列:

alter sequence serial restart start with 1;

对于用于标识列的系统生成的序列:

alter table table_name modify id generated by default on null as identity(start with 1);

此功能在 18c 中正式添加,但自 12.1 起非正式可用。

可以说,在 12.1 中使用这个未记录的功能是安全的。尽管该语法包含在官方文档中,但它是由 Oracle 包DBMS_METADATA_DIFF生成的。我已经在生产系统上多次使用它。但是,我创建了一个 Oracle 服务请求,他们验证这不是文档错误,该功能确实不受支持。

在 18c 中,该功能不会出现在 SQL 语言语法中,但包含在《数据库管理员指南》中。

评论

1赞 Oliver 1/12/2017
我想这是为了支持“更改表your_table修改(默认情况下在 null 上生成的 id 作为标识以限制值开头);”。很高兴知道它也适用于标准序列!
1赞 conceptdeluxe 4/28/2019
如果序列的最小值大于 0,则考虑将... RESTART START WITH 0 MINVALUE 0
2赞 t0r0X 8/12/2020
信息:此功能也适用于 Oracle DB 12.2 (12c)。很好的答案,谢谢!
1赞 Jacky Supit 2/10/2021
这是最简单的解决方案,它有效。传统知识
1赞 tale852150 6/29/2022
似乎不适用于 19c 中的系统生成的序列。获取错误 ORA-32793:无法更改系统生成的序列。
2赞 justincohler 3/25/2014 #11

您可以使用 CYCLE 选项,如下所示:

CREATE SEQUENCE test_seq
MINVALUE 0
MAXVALUE 100
START WITH 0
INCREMENT BY 1
CYCLE;

在这种情况下,当序列达到 MAXVALUE (100) 时,它将回收到 MINVALUE (0)。

在递减序列的情况下,该序列将回收到 MAXVALUE。

评论

2赞 Jeromy French 7/4/2018
对于反对者(他们永远不会看到此评论):CYCLE 属性正是我用来完成序列重置的属性。复位是自动的这一事实并不意味着它没有实现目标——OP 没有指定复位必须针对预先存在的序列!
2赞 Wendel 6/5/2015 #12

我创建了一个块来重置我的所有序列:

DECLARE
    I_val number;
BEGIN
    FOR US IN
        (SELECT US.SEQUENCE_NAME FROM USER_SEQUENCES US)
    LOOP
        execute immediate 'select ' || US.SEQUENCE_NAME || '.nextval from dual' INTO l_val;
        execute immediate 'alter sequence ' || US.SEQUENCE_NAME || ' increment by -' || l_val || ' minvalue 0';
        execute immediate 'select ' || US.SEQUENCE_NAME || '.nextval from dual' INTO l_val;
        execute immediate 'alter sequence ' || US.SEQUENCE_NAME || ' increment by 1 minvalue 0';
    END LOOP;
END;
2赞 Sentinel 8/15/2015 #13

下面是一个更可靠的过程,用于更改序列返回的下一个值,以及更多其他功能。

  • 首先,它可以防止SQL注入攻击,因为传入的任何字符串都不用于直接创建任何动态SQL语句,
  • 其次,它可以防止将下一个序列值设置在最小或最大序列值的边界之外。将是 != 和 之间。next_valuemin_valuemin_valuemax_value
  • 第三,在清理时,它会考虑当前(或建议的)设置以及所有其他序列设置。increment_by
  • 第四,除第一个参数外,所有参数都是可选的,除非指定,否则将当前序列设置作为默认值。如果未指定可选参数,则不执行任何操作。
  • 最后,如果您尝试更改不存在(或不属于当前用户)的序列,则会引发错误。ORA-01403: no data found

代码如下:

CREATE OR REPLACE PROCEDURE alter_sequence(
    seq_name      user_sequences.sequence_name%TYPE
  , next_value    user_sequences.last_number%TYPE := null
  , increment_by  user_sequences.increment_by%TYPE := null
  , min_value     user_sequences.min_value%TYPE := null
  , max_value     user_sequences.max_value%TYPE := null
  , cycle_flag    user_sequences.cycle_flag%TYPE := null
  , cache_size    user_sequences.cache_size%TYPE := null
  , order_flag    user_sequences.order_flag%TYPE := null)
  AUTHID CURRENT_USER
AS
  l_seq user_sequences%rowtype;
  l_old_cache user_sequences.cache_size%TYPE;
  l_next user_sequences.min_value%TYPE;
BEGIN
  -- Get current sequence settings as defaults
  SELECT * INTO l_seq FROM user_sequences WHERE sequence_name = seq_name;

  -- Update target settings
  l_old_cache := l_seq.cache_size;
  l_seq.increment_by := nvl(increment_by, l_seq.increment_by);
  l_seq.min_value    := nvl(min_value, l_seq.min_value);
  l_seq.max_value    := nvl(max_value, l_seq.max_value);
  l_seq.cycle_flag   := nvl(cycle_flag, l_seq.cycle_flag);
  l_seq.cache_size   := nvl(cache_size, l_seq.cache_size);
  l_seq.order_flag   := nvl(order_flag, l_seq.order_flag);

  IF next_value is NOT NULL THEN
    -- Determine next value without exceeding limits
    l_next := LEAST(GREATEST(next_value, l_seq.min_value+1),l_seq.max_value);

    -- Grab the actual latest seq number
    EXECUTE IMMEDIATE
        'ALTER SEQUENCE '||l_seq.sequence_name
            || ' INCREMENT BY 1'
            || ' MINVALUE '||least(l_seq.min_value,l_seq.last_number-l_old_cache)
            || ' MAXVALUE '||greatest(l_seq.max_value,l_seq.last_number)
            || ' NOCACHE'
            || ' ORDER';
    EXECUTE IMMEDIATE 
      'SELECT '||l_seq.sequence_name||'.NEXTVAL FROM DUAL'
    INTO l_seq.last_number;

    l_next := l_next-l_seq.last_number-1;

    -- Reset the sequence number
    IF l_next <> 0 THEN
      EXECUTE IMMEDIATE 
        'ALTER SEQUENCE '||l_seq.sequence_name
            || ' INCREMENT BY '||l_next
            || ' MINVALUE '||least(l_seq.min_value,l_seq.last_number)
            || ' MAXVALUE '||greatest(l_seq.max_value,l_seq.last_number)
            || ' NOCACHE'
            || ' ORDER';
      EXECUTE IMMEDIATE 
        'SELECT '||l_seq.sequence_name||'.NEXTVAL FROM DUAL'
      INTO l_next;
    END IF;
  END IF;

  -- Prepare Sequence for next use.
  IF COALESCE( cycle_flag
             , next_value
             , increment_by
             , min_value
             , max_value
             , cache_size
             , order_flag) IS NOT NULL
  THEN
    EXECUTE IMMEDIATE 
      'ALTER SEQUENCE '||l_seq.sequence_name
          || ' INCREMENT BY '||l_seq.increment_by
          || ' MINVALUE '||l_seq.min_value
          || ' MAXVALUE '||l_seq.max_value
          || CASE l_seq.cycle_flag
             WHEN 'Y' THEN ' CYCLE' ELSE ' NOCYCLE' END
          || CASE l_seq.cache_size
             WHEN 0 THEN ' NOCACHE'
             ELSE ' CACHE '||l_seq.cache_size END
          || CASE l_seq.order_flag
             WHEN 'Y' THEN ' ORDER' ELSE ' NOORDER' END;
  END IF;
END;
2赞 Rakesh 9/29/2015 #14

在我的项目中,一旦有人在不使用序列的情况下手动输入记录,因此我必须手动重置序列值,为此我写了下面的sql代码片段:

declare
max_db_value number(10,0);
cur_seq_value number(10,0);
counter number(10,0);
difference number(10,0);
dummy_number number(10);

begin

-- enter table name here
select max(id) into max_db_value from persons;
-- enter sequence name here
select last_number into cur_seq_value from user_sequences where  sequence_name = 'SEQ_PERSONS';

difference  := max_db_value - cur_seq_value;

 for counter in 1..difference
 loop
    -- change sequence name here as well
    select SEQ_PERSONS.nextval into dummy_number from dual;
 end loop;
end;

请注意,如果序列滞后,上述代码将起作用。

1赞 Bruno Freitas 4/29/2016 #15

我做了一个替代方案,即用户不需要知道值,系统获取并使用变量进行更新。

--Atualizando sequence da tabela SIGA_TRANSACAO, pois está desatualizada
DECLARE
 actual_sequence_number INTEGER;
 max_number_from_table INTEGER;
 difference INTEGER;
BEGIN
 SELECT [nome_da_sequence].nextval INTO actual_sequence_number FROM DUAL;
 SELECT MAX([nome_da_coluna]) INTO max_number_from_table FROM [nome_da_tabela];
 SELECT (max_number_from_table-actual_sequence_number) INTO difference FROM DUAL;
IF difference > 0 then
 EXECUTE IMMEDIATE CONCAT('alter sequence [nome_da_sequence] increment by ', difference);
 --aqui ele puxa o próximo valor usando o incremento necessário
 SELECT [nome_da_sequence].nextval INTO actual_sequence_number from dual;
--aqui volta o incremento para 1, para que futuras inserções funcionem normalmente
 EXECUTE IMMEDIATE 'ALTER SEQUENCE [nome_da_sequence] INCREMENT by 1';
 DBMS_OUTPUT.put_line ('A sequence [nome_da_sequence] foi atualizada.');
ELSE
 DBMS_OUTPUT.put_line ('A sequence [nome_da_sequence] NÃO foi atualizada, já estava OK!');
END IF;
END;
1赞 user46748 1/8/2017 #16

以下是使所有自动递增序列与实际数据匹配的方法:

  1. 创建一个过程来强制执行下一个值,如以下线程中所述:

    CREATE OR REPLACE PROCEDURE Reset_Sequence(
        P_Seq_Name IN VARCHAR2,
        P_Val      IN NUMBER DEFAULT 0)
    IS
      L_Current    NUMBER                      := 0;
      L_Difference NUMBER                      := 0;
      L_Minvalue User_Sequences.Min_Value%Type := 0;
    BEGIN
      SELECT Min_Value
      INTO L_Minvalue
      FROM User_Sequences
      WHERE Sequence_Name = P_Seq_Name;
      EXECUTE Immediate 'select ' || P_Seq_Name || '.nextval from dual' INTO L_Current;
      IF P_Val        < L_Minvalue THEN
        L_Difference := L_Minvalue - L_Current;
      ELSE
        L_Difference := P_Val - L_Current;
      END IF;
      IF L_Difference = 0 THEN
        RETURN;
      END IF;
      EXECUTE Immediate 'alter sequence ' || P_Seq_Name || ' increment by ' || L_Difference || ' minvalue ' || L_Minvalue;
      EXECUTE Immediate 'select ' || P_Seq_Name || '.nextval from dual' INTO L_Difference;
      EXECUTE Immediate 'alter sequence ' || P_Seq_Name || ' increment by 1 minvalue ' || L_Minvalue;
    END Reset_Sequence;
    
  2. 创建另一个过程以将所有序列与实际内容进行协调:

    CREATE OR REPLACE PROCEDURE RESET_USER_SEQUENCES_TO_DATA
    IS
      STMT CLOB;
    BEGIN
      SELECT 'select ''BEGIN'' || chr(10) || x || chr(10) || ''END;'' FROM (select listagg(x, chr(10)) within group (order by null) x FROM ('
        || X
        || '))'
      INTO STMT
      FROM
        (SELECT LISTAGG(X, ' union ') WITHIN GROUP (
        ORDER BY NULL) X
        FROM
          (SELECT CHR(10)
            || 'select ''Reset_Sequence('''''
            || SEQ_NAME
            || ''''','' || coalesce(max('
            || COL_NAME
            || '), 0) || '');'' x from '
            || TABLE_NAME X
          FROM
            (SELECT TABLE_NAME,
              REGEXP_SUBSTR(WTEXT, 'NEW\.(\S*) IS NULL',1,1,'i',1) COL_NAME,
              REGEXP_SUBSTR(BTEXT, '(\.|\s)([a-z_]*)\.nextval',1,1,'i',2) SEQ_NAME
            FROM USER_TRIGGERS
            LEFT JOIN
              (SELECT NAME BNAME,
                TEXT BTEXT
              FROM USER_SOURCE
              WHERE TYPE = 'TRIGGER'
              AND UPPER(TEXT) LIKE '%NEXTVAL%'
              )
            ON BNAME = TRIGGER_NAME
            LEFT JOIN
              (SELECT NAME WNAME,
                TEXT WTEXT
              FROM USER_SOURCE
              WHERE TYPE = 'TRIGGER'
              AND UPPER(TEXT) LIKE '%IS NULL%'
              )
            ON WNAME             = TRIGGER_NAME
            WHERE TRIGGER_TYPE   = 'BEFORE EACH ROW'
            AND TRIGGERING_EVENT = 'INSERT'
            )
          )
        ) ;
      EXECUTE IMMEDIATE STMT INTO STMT;
      --dbms_output.put_line(stmt);
      EXECUTE IMMEDIATE STMT;
    END RESET_USER_SEQUENCES_TO_DATA;
    

笔记:

  1. 过程从触发器代码中提取名称,并且不依赖于命名约定
  2. 若要在执行前检查生成的代码,请切换最后两行的注释
3赞 Lawrence 4/25/2017 #17

Jezus,所有这些编程只是为了重新启动索引...... 也许我是个白痴,但是对于预言机之前的 12(具有重启功能),简单化有什么问题:

drop sequence blah;
create sequence blah 

?

评论

2赞 Jon Heller 4/26/2017
删除序列的主要问题是它会失去授予它的权限。
1赞 Lawrence 6/23/2017
好的,乔恩。大多数情况下,恢复这些将花费比所有编程更少的时间。好的DBA通常有脚本,所以这应该不是问题:-)
-1赞 Jorge Santos Neill 11/19/2019 #18

对我有用的存储过程

create or replace
procedure reset_sequence( p_seq_name in varchar2, tablename in varchar2 )
is
    l_val number;
    maxvalueid number;
begin
    execute immediate 'select ' || p_seq_name || '.nextval from dual' INTO l_val;
    execute immediate 'select max(id) from ' || tablename INTO maxvalueid;
    execute immediate 'alter sequence ' || p_seq_name || ' increment by -' || l_val || ' minvalue 0';
    execute immediate 'select ' || p_seq_name || '.nextval from dual' INTO l_val;
    execute immediate 'alter sequence ' || p_seq_name || ' increment by '|| maxvalueid ||' minvalue 0';  
    execute immediate 'select ' || p_seq_name || '.nextval from dual' INTO l_val;
    execute immediate 'alter sequence ' || p_seq_name || ' increment by 1 minvalue 0';
end;

如何使用存储过程:

execute reset_sequence('company_sequence','company');