我想限制插入表格的记录,我在创建触发器之前的插入位置。 我有一个场景
Table A
id number
id1 number
Table B
id number
Table c
id number
Table D
id number
id1 number
我的代码:
create or replace trigger trg_a --trigger name
before insert on a
for each row
declare
v_id b.id%type;
v_id1 c.id%type;
pragma autonomous_transaction;
begin
select id into v_id from b where id=:NEW.id;
select id into v_id1 from c where id=:NEW.id;
if(:NEW.id=v_id or :NEW.id=v_id1) then
insert into d
(id,id1,name)
values(:NEW.id,:NEW.id1,:NEW.name);
end if;
delete from a where id =v_id or id 1=v_id1 ; --matched id
commit;
end; --end statement
插入匹配记录与查找表,即b
,c
和并行y
也插入表a
。此记录插入需要限制,因此我保留了删除语句,但它不起作用。
答案 0 :(得分:0)
您正尝试在单独的交易中执行此操作。我没有看到原因,这也导致您的代码无法正常工作。
可能你没有在每次插入后提交,所以当在触发器体内启动新事务时,它没有看到表A中的任何记录被删除。
我遗漏了pragma autonomous_transaction和commit;现在它按照您的预期从表中删除记录。 (请注意,我对您的代码进行了一些更改,因为它不能编译,因为NAME列不存在且ID为1)
create or replace trigger trg_a --trigger name
before insert on a
for each row
declare
v_id b.id%type;
v_id1 c.id%type;
--pragma autonomous_transaction;
begin
select id into v_id from b where id=:NEW.id;
select id into v_id1 from c where id=:NEW.id;
if(:NEW.id=v_id or :NEW.id=v_id1) then
insert into d
(id,id1)
values(:NEW.id,:NEW.id1);
end if;
delete from a where id =v_id or id1=v_id1 ; --matched id
--commit;
end;
/
因此要么在每次插入后提交,要么省略自治事务。
更新: 现在你说清楚了,你根本不想插入表格a。由于INSTEAD OF触发器仅适用于视图,我担心只有这样才能实现此操作才会导致运行时异常,因此插入到A中将不会成功,但INSERT到表D中会成功。看看这个,当将varchar值分配给数字列时,它会导致插入PL / SQL数值或值错误
create or replace trigger trg_a --trigger name
before insert on a
for each row
declare
v_id b.id%type;
v_id1 c.id%type;
pragma autonomous_transaction;
begin
select id into v_id from b where id=:NEW.id;
select id into v_id1 from c where id=:NEW.id;
if(:NEW.id=v_id or :NEW.id=v_id1) then
insert into d
(id,id1)
values(:NEW.id,:NEW.id1);
end if;
delete from a where id =v_id or id1=v_id1 ; --matched id
commit;
:NEW.id:=null;
:NEW.id1:='a';
end;
/
答案 1 :(得分:0)
如果您有11g或更高版本,您可能需要查看使用复合触发器。
Create Or Replace Trigger Trg_A
For Insert On A
Compound Trigger
Type Id_T Is Table Of A.Id%type Index By Simple_Integer;
Id_List Id_T;
Id_ndx simple_integer := 0;
Id_Count Integer;
After Each Row Is Begin
-- If the same id is in Table B or Table C
Select Count(*) Into Id_Count From B Where Id = :New.ID;
If Id_Count = 0 Then
-- Only check C if nothing in B
Select Count(*) Into Id_Count From C Where Id = :New.ID;
End If;
If Id_Count > 0 Then
-- If already in B or C, log to D
Insert Into D( Id, Id1, Name )
Values( :New.ID, :New.ID, :New.Name);
-- Then save for later deletion from A
Id_ndx := Id_ndx + 1;
Id_List( Id_ndx ) := :New.Id;
End If;
End After Each Row;
After Statement Is Begin
Forall Idx In 1 .. Id_ndx
-- Delete saved IDs (if any)
Delete From A Where Id = Id_List( Idx );
Id_List.Delete();
Id_ndx := 0;
End After Statement;
End;
问题是在复合触发器中使用自治事务编译指示很棘手。它甚至可能是不可能的,我只是没有任何经验。
但是,有几个人在视图中提到“而不是”触发器。当我设计数据库时,几乎所有DML都通过视图,其中许多视图都存在,没有其他原因。很多时候,表将具有多个视图,因此无论数据如何被访问,都可以进行DML。我无法开始告诉你这解决了多少问题。因此,您可能需要认真考虑该选项。