立即执行更改序列不起作用

execute immediate alter sequence not working

我被这个非常简单的脚本卡住了。它没有像我预期的那样工作。

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 并手动执行生成的命令,序列将根据需要进行更改。

我错过了什么?

两个 alter sequence 语句都有效,只是中间的增量没有发生。 nextval 循环中的调用未被评估,因为 select 语句未将其输出发送到任何地方。来自 the documentation,一条恰好指代你正在做的事情的注释:

Note:
If dynamic_sql_statement is a SELECT statement, and you omit both into_clause and bulk_collect_into_clause, then execute_immediate_statement never executes.
For example, this statement never increments the sequence:

EXECUTE IMMEDIATE 'SELECT S.NEXTVAL FROM DUAL'

所以你需要select那个值变成一些东西:

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,这就是您所看到的。

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