执行立即更改序列不工作

时间:2015-02-24 16:57:52

标签: oracle plsql sequence execute-immediate

我坚持这个非常简单的脚本。它不像我期望的那样工作。

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 immediate替换dbms_output.put_line并手动执行生成的命令,则会根据需要更改序列。

我错过了什么?

2 个答案:

答案 0 :(得分:12)

两个alter sequence语句都有效,它是不发生之间的增量。您的循环中的nextval调用未被评估,因为select语句不会将其输出发送到任何位置。从the documentation开始,这个注释恰好指的是你在做什么:

  

注意:
  如果 dynamic_sql_statement SELECT语句,并且您省略 into_clause bulk_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,这就是您所看到的。

答案 1 :(得分: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