立即执行更改序列不起作用
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
我被这个非常简单的脚本卡住了。它没有像我预期的那样工作。
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 aSELECT
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