ro如何存储rowids以便在删除相应的子记录后将其删除

How ro store rowids in order to delete them after corresponding child records are deleted

我想删除我收集的某些行 select:

DELETE from REMINDER 
where exists 
(
SELECT r.rowid
FROM reminder r
inner join reminder_users u on u.reminder_id = r.id
inner join device d on d.id = (regexp_replace(r.origin_values, '[^0-9]', '')) and d.NEXT_TEST_DATE_INTERNAL <> u.deadline
inner join device_test t on t.id = d.NEXT_TEST_INT_ID
where u.receipt = 0 and t.TEST_INTERNAL_EXTERNAL = 0 and r.NAME like '%Interne%' and r.NAME not like '%Externe%' and u.DEADLINE > sysdate
);

问题是,有一个 table 'reminder_users' 包含父 table 'Reminder' 的子记录。所以我必须先使用以下语句删除子记录:

DELETE from REMINDER_USERS
where exists
(
SELECT u.ROWID
from reminder_users u
inner join reminder r on r.id = u.reminder_id
inner join device d on d.id = (regexp_replace(r.origin_values, '[^0-9]', '')) and d.NEXT_TEST_DATE_INTERNAL <> u.deadline
inner join device_test t on t.id = d.NEXT_TEST_INT_ID
where u.receipt = 0 and t.TEST_INTERNAL_EXTERNAL = 0 and r.NAME like '%Interne%' and r.NAME not like '%Externe%' and u.DEADLINE > sysdate
);

当我执行第二个操作时,第一个语句return显然是零行,因为我删除了子记录。这就是为什么我正在寻找一种方法来存储第一个操作的 rowid,然后删除子记录,最后从 table 'REMINDER'.

中删除以前存储的数据

我必须在这里使用 CURSOR 吗? (注意:如果查询 return 行,总会有至少 2 行受到影响)。我试图声明一个存储行的变量,但随后出现 'ORA-01422: exact fetch returns more than requested number of rows' 错误...

提前致谢!

你绝对应该在 reminderreminder_users 之间有一个外键约束。如果 reminder_users 中有子记录,您不应该 能够 reminder 中删除。这只是基本的数据库参照完整性。

如果该外键定义为 on delete cascade,您就完成了。删除 reminder 将删除 reminder_users.

中的相关记录

假设您不能那样做,您可以做的一件事是先获取要删除的 ID,然后再删除它们。您需要创建架构级别 type:

create type id_tt as table of number;

declare
    l_reminder_ids id_tt;
begin
    select r.id 
      bulk collect into l_reminder_ids
      from reminder r
     inner join reminder_users u on u.reminder_id = r.id
     inner join device d 
             on d.id = (regexp_replace(r.origin_values, '[^0-9]', '')) 
            and d.NEXT_TEST_DATE_INTERNAL <> u.deadline
     inner join device_test t on t.id = d.NEXT_TEST_INT_ID
     where u.receipt = 0 
       and t.TEST_INTERNAL_EXTERNAL = 0 
       and r.NAME like '%Interne%' 
       and r.NAME not like '%Externe%' 
       and u.DEADLINE > sysdate
       for update;

    delete from reminder_users where reminder_id member of l_reminder_ids;

    delete from reminders where id member of l_reminder_ids;
end;

for update 子句用于防止其他会话进入并在您从 reminder_users 中删除时弄乱这些行。 (嗯,现在我考虑了一下,这里可能没有必要。)这假设您尝试删除的行数是“合理的”。如果您尝试删除 2000 万行,这可能不会有很好的性能。

如果@EJEgyed 建议的“on delete cascade”对您可用,那么这就是方法。但是许多 DBA(包括我自己)通常不允许这样做。副作用被认为太危险了。您可能不知道究竟删除了什么,Oracle 也不会告诉您,它只是删除了。如果是这种情况,您有几个选择。

  1. 只是重复子查询。那会成就你的 需要。
  2. 运行 在第一次删除中使用“返回...批量收集”的脚本, 第二个是“forall ... delete”。 (参见 demo)。
declare 
    type rem_list_t is table of reminder_users.rem_id%type;
    ren_list rem_list_t; 
begin 
    delete 
      from reminder_users 
     where rem_id in ( select rem_id 
                         from reminders 
                        where rem_id in  
                              (select to_char(floor(dbms_random.value(1,200)))
                                             from  dual connect by level <= 4           
                              )      
                          and message not like '%Event #6' )
     returning rem_id  
         bulk collect 
         into ren_list;
         
    dbms_output.put_line( 'Rows deleted from reminder_users:' || to_char(sql%rowcount));  
         
    forall ru in 1 .. ren_list.count
       delete 
         from reminders 
         where rem_id = ren_list(ru); 
    dbms_output.put_line( 'Rows deleted from reminders:' || to_char(sql%rowcount));          

end ;

一句警告。您当前的查询格式不正确。他们将删除 0 行,因为子选择没有满足 where 条件,或者它将删除 All ROWS,因为至少有 1 行满足 where 条件。如果 1 行或多行满足条件,则 EXIST 谓词的计算结果为真,但外部条件中的每一行都为真。演示,还包含一个示例。我没有您的 table 定义或示例数据,因此该演示基于简单的 table/query,但保持与您的 SQL.

相同的结构