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

Posted

技术标签:

【中文标题】执行立即更改序列不起作用【英文标题】:execute immediate alter sequence not working 【发布时间】:2015-02-24 16:57:52 【问题描述】:

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

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

我错过了什么?

【问题讨论】:

我相信这对你有用。 asktom.oracle.com/pls/asktom/… 你得到了什么结果,你期望什么结果? 你用的是什么版本?在 12c 中,有一种稍微简单的方法可以做到这一点。 @JonHeller,我使用的是 12c,我该如何在这个版本上做到这一点? 【参考方案1】:

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

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

【讨论】:

【参考方案2】:

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

【讨论】:

以上是关于执行立即更改序列不起作用的主要内容,如果未能解决你的问题,请参考以下文章

jquery.when done 不起作用:它立即执行[关闭]

动态构建 DBMS_CLOUD.CREATE_EXTERNAL_TABLE,立即执行不起作用

AsyncTask中SplashScreen的动画序列不起作用

Objective-C:动画高度约束更改不起作用

鼠标按下时CSS光标更改不起作用

在匿名块中使用变量来更改 SQL SEQUENCE 不起作用