4

我被困在这个非常简单的脚本上。它不像我期望的那样工作。

declare
 st VARCHAR(1024);
begin
  for x in (SELECT sequence_name FROM USER_SEQUENCES) loop
      st := 'ALTER SEQUENCE ' || x.sequence_name ||  ' INCREMENT BY 1000';
      execute immediate st;
      st := 'select ' || x.sequence_name ||  '.nextval from dual';
      execute immediate st;
      st := 'ALTER SEQUENCE ' || x.sequence_name ||  ' INCREMENT BY 1';
      execute immediate st;
  end loop;
end;
/

当我运行它时,它似乎根本不起作用——我的所有序列都保持原样,并且它们没有被动态语句增加一千。如果我nextval在匿名块之前和之后检查,差异只有1,而不是1001。

如果我手动替换execute immediatedbms_output.put_line执行生成的命令,则序列会根据需要进行更改。

我错过了什么?

4

2 回答 2

15

两种alter sequence说法都有效,只是两者之间的增量没有发生。循环中的nextval调用没有被评估,因为 select 语句没有将其输出发送到任何地方。从文档中,恰好是指您正在做的事情的注释:

注意:
如果dynamic_sql_statement是一个SELECT语句,并且您同时省略了into_clausebulk_collect_into_clause,那么execute_immediate_statement永远不会执行。
例如,此语句从不增加序列:

EXECUTE IMMEDIATE 'SELECT S.NEXTVAL FROM DUAL'

因此,您需要将该值选择为:

declare
 st VARCHAR(1024);
 val number;
begin
  for x in (SELECT sequence_name FROM USER_SEQUENCES) loop
      st := 'ALTER SEQUENCE ' || x.sequence_name ||  ' INCREMENT BY 1000';
      execute immediate st;
      st := 'select ' || x.sequence_name ||  '.nextval from dual';
      execute immediate st into val;
      st := 'ALTER SEQUENCE ' || x.sequence_name ||  ' INCREMENT BY 1';
      execute immediate st;
  end loop;
end;
/

我在第二个立即执行时添加了一个val变量和一个子句。into val

为了证明它现在可以工作:

create sequence s42;

Sequence s42 created.

declare
 st VARCHAR(1024);
 n number;
begin
  for x in (SELECT sequence_name FROM USER_SEQUENCES) loop
      st := 'ALTER SEQUENCE ' || x.sequence_name ||  ' INCREMENT BY 1000';
      execute immediate st;
      st := 'select ' || x.sequence_name ||  '.nextval from dual';
      execute immediate st into n;
      st := 'ALTER SEQUENCE ' || x.sequence_name ||  ' INCREMENT BY 1';
      execute immediate st;
  end loop;
end;
/

anonymous block completed

select s42.nextval from dual;

   NEXTVAL
----------
      1001 

如果没有该into子句,则返回 1 而不是 1001,这就是您所看到的。

于 2015-02-24T17:34:47.810 回答
3

12c中的restart start with语法可以简化步骤:

create sequence test_sequence;

declare
 st VARCHAR(1024);
begin
  for x in (SELECT sequence_name, last_number FROM USER_SEQUENCES) loop
      st := 'ALTER SEQUENCE ' || x.sequence_name
          || ' RESTART START WITH ' || to_char(x.last_number+1000);
      execute immediate st;
  end loop;
end;
/

select test_sequence.nextval from dual;

NEXTVAL
-------
   1001
于 2015-02-25T08:06:40.947 回答