执行立即更改序列不起作用
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_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,这就是您所看到的。
【讨论】:
【参考方案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,立即执行不起作用