获得序列的最小值

时间:2016-06-16 11:49:33

标签: sql oracle oracle11g sequence

我在数据库中定义了大约100个序列,在执行测试后设置为某个数字。

例如: 有一个序列:suppier_seq。 那将从1开始,现在它的currval是101。

我需要根据最小值重置所有存在的序列。

如果我提取序列的DDL,它会带有当前值作为开头:

CREATE SEQUENCE  "RMS14"."SUPPLIER_SEQUENCE"  MINVALUE 0 MAXVALUE 99999999999 INCREMENT BY 1 START WITH 101 CACHE 100 NOORDER  NOCYCLE ;

我需要以最小值重新启动序列。

如何通过SQL捕获序列的最小值?

1 个答案:

答案 0 :(得分:4)

您无法说明序列的原始START WITH值是什么。您只能将其基于MINVALUE,或者使用它(即使它为零),或者添加一个,或者仅在它为非零时执行此操作。

您可以从user_sequences视图获取自己序列的当前值,并使用PL / SQL块循环它们,在路上生成drop和create语句:

set serveroutput on
begin
  for r in (
    select 'DROP SEQUENCE "' || sequence_name || '"' as drop_stmt,
      'CREATE SEQUENCE "' || sequence_name || '"'
        || ' MINVALUE ' || min_value
        || ' MAXVALUE ' || max_value
        || ' INCREMENT BY ' || increment_by
        || ' START WITH ' || min_value
        || case when cache_size = 0 then ' NOCACHE' else ' CACHE ' || cache_size end
        || case when order_flag = 'Y' then ' ORDER' else ' NOORDER' end
        || case when cycle_flag = 'Y' then ' CYCLE' else ' NOCYCLE' end
        as create_stmt
    from user_sequences
  )
  loop
    dbms_output.put_line(r.drop_stmt);
--    execute immediate r.drop_stmt;
    dbms_output.put_line(r.create_stmt);
--    execute immediate r.create_stmt;
  end loop;
end;
/

我已经将execute immediate声明留下来,试图避免因没有任何检查而被复制和粘贴的事故;最初它只会显示它将运行的命令,例如

PL/SQL procedure successfully completed.

DROP SEQUENCE "SUPPLIER_SEQUENCE"
CREATE SEQUENCE "SUPPLIER_SEQUENCE" MINVALUE 0 MAXVALUE 99999999999 INCREMENT BY 1 START WITH 0 CACHE 100 NOORDER NOCYCLE
...

如果您正在使用其他架构并拥有正确的权限,则可以查询 而是all_sequencesdba_sequences,并指定所有者:

    select 'DROP SEQUENCE "' || sequence_owner || '"."' || sequence_name ||'"' as drop_stmt,
      'CREATE SEQUENCE "' || sequence_owner || '"."' || sequence_name || '"'
        || ' MINVALUE ' || min_value
...

另一种方法是更改​​序列以将INCREMENT BY设置为减去当前最高值(或最高值减去MINVALUE),调用{{1} },然后重置增量。这动态有点混乱,尤其是因为你需要动态语句的第二级才能获得当前序列值,直接在这样的循环中完成,但基本上是相同的想法:

nextval

你也可以在循环中生成动态语句,这可能对这种方法来说有点简洁:

declare
  l_nextval number;
begin
  for r in (
    select 'BEGIN EXECUTE IMMEDIATE ''ALTER SEQUENCE "' || sequence_name || '"'
        || ' INCREMENT BY -''|| ("' || sequence_name || '".nextval - ' || min_value ||'); END;'
        as alter_stmt_1,
      'SELECT "' || sequence_name || '".nextval from dual' as adjust_stmt,
      'ALTER SEQUENCE "' || sequence_name || '"'
        || ' INCREMENT BY ' || increment_by
        as alter_stmt_2
    from user_sequences
  )
  loop
    dbms_output.put_line(r.alter_stmt_1);
--    execute immediate r.alter_stmt_1;
    dbms_output.put_line(r.adjust_stmt);
--    execute immediate r.adjust_stmt into l_nextval;
    dbms_output.put_line(r.alter_stmt_2);
--    execute immediate r.alter_stmt_2;
  end loop;
end;
/

PL/SQL procedure successfully completed.

BEGIN EXECUTE IMMEDIATE 'ALTER SEQUENCE "SUPPLIER_SEQUENCE" INCREMENT BY -'|| ("SUPPLIER_SEQUENCE".nextval - 0); END;
SELECT "SUPPLIER_SEQUENCE".nextval from dual
ALTER SEQUENCE "SUPPLIER_SEQUENCE" INCREMENT BY 1

问题特别是关于11g,但是this is even simpler in 12c