2015-11-01 35 views
0

考虑下表行级触发器:Insert语句计时问题

create table testtable 
(
id number(10), 
batch_id number(10), 
seq number(10) 
) 

的插入后,行级触发器对这个表,执行以下操作存在:

create or replace trigger tr_testtable after insert on testtable 
for each row 

pragma autonomous_transaction 

begin 

v_min_seq number(10); 
v_min_id number(10); 
v_batch_id number(10); 
v_count number(5); 

select count(*) into v_count,batch_id into v_batch_id 
from testtable 
where batch_id = :new.batch_id 
group by batch_id; 

if (v_count > 1) then 


with cte(min_seq,batch_id) as 
(
select min(seq),batch_id from testtable 
group by batch_id 
) 
select id into v_min_id from 
testtable tt 
inner join 
cte 
on cte.min_seq = tt.seq 
and cte.batch_id = tt.batch_id; 

delete from testtable 
where id <> v_min_id 
and batch_id = v_batch_id; 

commit; 

end if; 

end; 

下面的INSERT语句运行:

insert into testtable 
select 10, 100, 18 from dual; 
commit; 

insert into testtable 
select 11, 100, 32 from dual; 
commit; 

insert into testtable 
select 12, 100, 15 from dual; 
commit; 

因此,如果上面的Insert语句运行,预期的输出触发器被触发后:

Id Batch_Id Seq 
12 100  15 

现在,这些插入语句在同一时间发射。 我想知道是否有可能所有Insert语句同时执行,并且触发器触发时未满足条件if (v_count > 1)?如果是的话,输出将是下面的,这是不可取的:

Id Batch_Id Seq 

10 100  18 
11 100  32 
12 100  15 
+2

您的代码不会给你希望,因为触发一个自治事务中运行,不会看到该行作为输出插入,因此它只能处理表中以前的数据。它也可能会妨碍回滚。这听起来像一个[XY问题](http://meta.stackexchange.com/a/66378/150299)。你究竟在做什么*试图在这里实现? –

+0

我想要达到的是 - 在批处理(BatchId)中,保存包含最小序列(Seq)的记录并删除其他记录。 – youfree

+0

是否有可能收到两个不同ID的记录,但绑最小的SEQ?如果是这样,你想发生什么?你是否想保持最小SEQ的记录ID? – APC

回答

1

如果您需要管理重复的记录,让我们尝试另一种方式。 MERGE statement是你可以指定条件的方式来决定是否更新或插入到目标表

MERGE INTO testtable t1 
USING (select 10 as id, 100 as batch_id, 18 as seq from dual) t2 
ON (t1.batch_id = t2.batch_id) 
WHEN MATCHED THEN 
    UPDATE SET t1.seq = t2.seq 
    WHERE t1.seq > t2.seq 
WHEN NOT MATCHED THEN 
    INSERT (id, batch_id, seq) 
    VALUES (t2.id,t2.batch_id, t2.seq); 

MERGE INTO testtable t1 
USING (select 11 as id, 100 as batch_id, 32 as seq from dual) t2 
ON (t1.batch_id = t2.batch_id) 
WHEN MATCHED THEN 
    UPDATE SET t1.seq = t2.seq 
    WHERE t1.seq > t2.seq 
WHEN NOT MATCHED THEN 
    INSERT (id, batch_id, seq) 
    VALUES (t2.id,t2.batch_id, t2.seq); 

MERGE INTO testtable t1 
USING (select 12 as id, 100 as batch_id, 15 as seq from dual) t2 
ON (t1.batch_id = t2.batch_id) 
WHEN MATCHED THEN 
    UPDATE SET t1.seq = t2.seq 
    WHERE t1.seq > t2.seq 
WHEN NOT MATCHED THEN 
    INSERT (id, batch_id, seq) 
    VALUES (t2.id,t2.batch_id, t2.seq); 
+0

该解决方案为OP帖子中的ID生成不同的值。这可能也可能不重要,这取决于OP希望实施的具体业务规则。 – APC