问题描述
DELETE FROM reminder
WHERE EXISTS (SELECT r.ROWID,r.id,r.name,r.remark,u.user_id,u.deadline,u.audt_creation_date,d.next_test_date_internal,t.test_internal_external
FROM reminder r,reminder_users u,device d,device_test t
WHERE r.id = u.reminder_id
AND u.receipt = 0
AND ( Regexp_replace(r.origin_values,'[^0-9]','') ) = d.id
AND d.next_test_int_id = t.id
AND t.test_internal_external = 0
AND r.name LIKE '%Interne%'
AND r.name NOT LIKE '%Externe%'
AND u.deadline <> d.next_test_date_internal
AND u.deadline > SYSDATE
AND reminder.id = r.id
GROUP BY r.ROWID,t.test_internal_external);
第二个查询是这样的:
DELETE FROM reminder_users
WHERE EXISTS (SELECT u.reminder_id,'') ) = d.id
AND d.next_test_int_id = t.id
AND t.test_internal_external = 0
AND r.name LIKE '%Interne%'
AND r.name NOT LIKE '%Externe%'
AND u.deadline <> d.next_test_date_internal
AND u.deadline > SYSDATE
AND reminder_users.reminder_id = u.reminder_id
GROUP BY u.reminder_id,t.test_internal_external);
表 REMINDER 是父表,表 REMINDER_USERS 包含子记录。我无法使用级联删除选项创建外键,因为只能删除某些子记录和父记录。
当我尝试运行第一个查询时,我收到 ora 02292-Error(ora-02292 完整性约束违反 - 找到子记录)。所以理论上我必须先运行第二个查询,以便之后删除父表中的相应行。但是当我先运行第二个查询时,第一个查询中的select显然返回0值,因为我之前删除了子记录。
提前致谢!
解决方法
使用逻辑删除,在父表中创建一个列,你可以让它不可见,我猜你有一个外键来确保父子引用完整性。
因此,此列将根据您的条件(无论您必须删除行的任何条件)判断该行是否已被逻辑删除。 创建一个触发器,如果逻辑删除设置为 1,该触发器将被触发,该触发器将删除子表中的行,并创建第二个触发器,该触发器将跟随您的第一个触发器删除父表中的行。
,最简单的选择就是在循环中进行删除。当然,您将进行逐行操作,这通常不是最有效的。但对于大多数事情来说,它已经足够快了
for rows_to_delete in (**your select statement**)
loop
delete from child
where parent_id = rows_to_delete.parent_id;
delete from parent
where parent_id = rows_to_delete.parent_id;
end loop;
为了提高效率,您可以执行 delete
with a returning into
。
create table parent (
parent_id integer primary key,parent_val varchar2(10)
);
create table child (
child_id integer primary key,parent_id integer references parent( parent_id),child_val varchar2(10)
);
create type parent_tbl is table of integer;
declare
l_parent_keys_to_remove parent_tbl;
begin
delete from child
where child_val in ('aaa','ccc')
returning parent_id
bulk collect into l_parent_keys_to_remove;
delete from parent
where parent_id member of l_parent_keys_to_remove;
end;
/
或者你可以select
the rows to delete into the collection first and then use the collection for both deletes
declare
l_parent_keys_to_remove parent_tbl;
begin
select parent_id
bulk collect into l_parent_keys_to_remove
from parent
where parent_val in ('a','c');
delete from child
where parent_id member of l_parent_keys_to_remove;
delete from parent
where parent_id member of l_parent_keys_to_remove;
end;
/
请注意,如果您要删除的父行可能没有关联的子行,则您需要执行 select
方法。如果您只是先针对子表发出 delete
,则 returning into
将不会为没有子表的父表提供值。