pl/sql触发改变序列
pl/sql trigger alter sequence
我真的是 pl/sql 的新手。我正在尝试做一个像这样的触发器(删除行后的 adr =),但似乎我不能使用 ALTER SEQUENCE。这是删除行后递减的正确方法还是我应该使用过程?
CREATE OR REPLACE TRIGGER adr_trg
AFTER DELETE ON table
FOR EACH ROW
BEGIN
ALTER SEQUENCE table_seq INCREMENT BY -1;
END;
编辑:
我正在使用的序列:
CREATE SEQUENCE table_seq INCREMENT BY 1 START WITH 1;
我正在使用的触发器:
CREATE OR REPLACE TRIGGER bir_trg
BEFORE INSERT ON table
FOR EACH ROW
BEGIN
IF :new.id IS NULL
THEN
:new.id := table_seq.nextval;
END IF;
END bir_trg;
您不能在触发器内使用 Alter 语句。根据定义,触发器不能直接使用提交或回滚,并且 "Alter" 语句具有自动提交。如果你想在触发器中使用提交或回滚,你可以为此目的使用 "Autonomous transaction" 块。
另外,你不需要使用触发器将序列 nextval 插入到列中,你可以直接在插入语句中使用 seq_name.next_val。减小序列的值会导致数据不一致,例如您在 table 中插入了 10 行,而序列的当前值为 11。假设现在删除了 id= 2 的行,并且您将序列值减小为 10.On new insert 如果 id 列是 PK 它将抛出错误,否则创建两行 id = 10.
首先,创建这个函数:
SQL> create or replace function fn_inc_by_minus_one( i_sch_name varchar2, i_seq_name varchar2 ) return number is
v_seq_no number;
begin
execute immediate 'select '||i_sch_name||'.'||i_seq_name||'.nextval from dual' INTO v_seq_no;
execute immediate 'alter sequence '||i_sch_name||'.'||i_seq_name||' increment by -2 minvalue 0';
execute immediate 'select '||i_sch_name||'.'||i_seq_name||'.nextval from dual' INTO v_seq_no;
execute immediate 'alter sequence '||i_sch_name||'.'||i_seq_name||' increment by 1 minvalue 0';
return v_seq_no;
end;
/
每当您需要将序列递增 -1
时,只需 运行 这条语句(不会破坏序列的原始递增机制
select jsao_super_cities_seq.nextval from dual;
一如既往地递增 +1
) :
SQL> var n number;
SQL> exec :n:=fn_inc_by_minus_one('myschema','jsao_super_cities_seq');
/
我可能是 "reading between the lines",但我怀疑你的目的是如果你在 table 中有 5 个条目由 sequence.nextval 填充,例如
ID
---
1
2
3
4
5
然后有人删除了第 5 行,您想将序列恢复为值 4。
这有两点不对:
如果有人删除“3”怎么办?你不能将序列回滚 2,因为当你使用 seq=3 并移动到 seq=4 时,你会得到一个冲突
您不能保证序列没有间隙。只需要有人获取一个序列值,然后发出回滚(或者在交易中遇到任何其他类型的错误,序列值就永远消失了)
这让我想到了最重要的问题:
你为什么还要担心差距?
我真的是 pl/sql 的新手。我正在尝试做一个像这样的触发器(删除行后的 adr =),但似乎我不能使用 ALTER SEQUENCE。这是删除行后递减的正确方法还是我应该使用过程?
CREATE OR REPLACE TRIGGER adr_trg
AFTER DELETE ON table
FOR EACH ROW
BEGIN
ALTER SEQUENCE table_seq INCREMENT BY -1;
END;
编辑:
我正在使用的序列:
CREATE SEQUENCE table_seq INCREMENT BY 1 START WITH 1;
我正在使用的触发器:
CREATE OR REPLACE TRIGGER bir_trg
BEFORE INSERT ON table
FOR EACH ROW
BEGIN
IF :new.id IS NULL
THEN
:new.id := table_seq.nextval;
END IF;
END bir_trg;
您不能在触发器内使用 Alter 语句。根据定义,触发器不能直接使用提交或回滚,并且 "Alter" 语句具有自动提交。如果你想在触发器中使用提交或回滚,你可以为此目的使用 "Autonomous transaction" 块。
另外,你不需要使用触发器将序列 nextval 插入到列中,你可以直接在插入语句中使用 seq_name.next_val。减小序列的值会导致数据不一致,例如您在 table 中插入了 10 行,而序列的当前值为 11。假设现在删除了 id= 2 的行,并且您将序列值减小为 10.On new insert 如果 id 列是 PK 它将抛出错误,否则创建两行 id = 10.
首先,创建这个函数:
SQL> create or replace function fn_inc_by_minus_one( i_sch_name varchar2, i_seq_name varchar2 ) return number is
v_seq_no number;
begin
execute immediate 'select '||i_sch_name||'.'||i_seq_name||'.nextval from dual' INTO v_seq_no;
execute immediate 'alter sequence '||i_sch_name||'.'||i_seq_name||' increment by -2 minvalue 0';
execute immediate 'select '||i_sch_name||'.'||i_seq_name||'.nextval from dual' INTO v_seq_no;
execute immediate 'alter sequence '||i_sch_name||'.'||i_seq_name||' increment by 1 minvalue 0';
return v_seq_no;
end;
/
每当您需要将序列递增 -1
时,只需 运行 这条语句(不会破坏序列的原始递增机制
select jsao_super_cities_seq.nextval from dual;
一如既往地递增 +1
) :
SQL> var n number;
SQL> exec :n:=fn_inc_by_minus_one('myschema','jsao_super_cities_seq');
/
我可能是 "reading between the lines",但我怀疑你的目的是如果你在 table 中有 5 个条目由 sequence.nextval 填充,例如
ID
---
1
2
3
4
5
然后有人删除了第 5 行,您想将序列恢复为值 4。
这有两点不对:
如果有人删除“3”怎么办?你不能将序列回滚 2,因为当你使用 seq=3 并移动到 seq=4 时,你会得到一个冲突
您不能保证序列没有间隙。只需要有人获取一个序列值,然后发出回滚(或者在交易中遇到任何其他类型的错误,序列值就永远消失了)
这让我想到了最重要的问题:
你为什么还要担心差距?