【问题标题】: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,我该如何在这个版本上做到这一点?

标签: oracle plsql sequence execute-immediate


【解决方案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
    

    【讨论】:

      猜你喜欢
      • 2021-10-25
      • 2013-04-02
      • 1970-01-01
      • 1970-01-01
      • 2020-10-18
      • 1970-01-01
      • 2018-04-28
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多