Oracle删除而不禁用约束

时间:2015-04-02 20:13:14

标签: oracle constraints delete-row

我使用的是Oracle 11g。我是一名具有基本SQL知识的开发人员。 (:S)

我需要创建一个删除查询,但我的数据库用户没有禁用约束的权限。

我有以下结构。

TABLE CARD_HOLDER
CARD_HOLDER_ID
... (other fields)

/

TABLE CARD
Card_ID
... (other fields)

/

TABLE SERVICE
SERVICE_ID
SERVICE_DESCRIPTION (credit, debit, etc...)

/

TABLE CARD_HOLDER_SERVICES
CARD_HOLDER_ID
SERVICE_ID
... (other fields)

我需要删除CARD_HOLDERS的所有数据,这些数据的服务类型为" service = 10"。因此,为了简洁起见,我删除了卡,与持卡人相关的其他表格,我不会在这里显示,最后 CARD_HOLDER_SERVICES CARD_HOLDER itselt。

问题是,为了删除持卡人,我需要知道它是否有服务= 10 ,如果我删除 CARD_HOLDER_SERVICES ,我首先要不再拥有该信息来过滤我需要删除的持卡人。

我已在表 CARD_HOLDER_SERVICES 中检查了CARD_HOLDER_ID约束类型为 NOT DEFERRABLE

我唯一能想到的事情是,我不知道如何,无论它是否能够工作,都是创建一个包含我要删除的CARD_HOLDER_ID的临时表,然后删除 CARD_HOLDER_SERVICES 并上传 CARD_HOLDER

谁能告诉我最简单,最好的方法呢?

表现不是问题。

提前谢谢。

2 个答案:

答案 0 :(得分:2)

根据数据量和性能要求,我可能只是编写一些程序代码。如果我理解你的要求,比如

BEGIN
  FOR chs IN (SELECT *
                FROM card_holder_services
               WHERE service_id = 10)
  LOOP
    FOR ch IN (SELECT *
                 FROM card_holder
                WHERE card_holder_id = chs.card_holder_id)
    LOOP
      DELETE FROM card
       WHERE card_id = ch.card_id;
    END LOOP;

    DELETE FROM card_holder
     WHERE card_holder_id = chs.card_holder_id;

    DELETE FROM card_holder_services
     WHERE card_holder_id = chs.card_holder_id
       AND service_id     = 10;

  END LOOP;
END;
/

如果您对纯效率感兴趣,可以执行单独的DELETE语句,最终会复制相当多的代码

DELETE FROM card
 WHERE card_id IN (SELECT ch.card_id
                     FROM card_holder ch
                          JOIN card_holder_services chs
                            ON( ch.card_holder_id = chs.card_holder_id )
                    WHERE chs.service_id = 10);

DELETE FROM card_holder
 WHERE card_holder_id IN (SELECT card_holder_id
                            FROM card_holder_services chs
                           WHERE chs.service_id = 10);

DELETE FROM card_holder_services
 WHERE service_id = 10;

答案 1 :(得分:0)

我建议你使用收藏(最多让我们说50-80k的记录)。

首先将card_holder_id提取到集合中,在我的示例中为c_serv,然后根据此id创建delete语句。如果使用FORALL语句循环收集,它将比传统的FOR LOOP更快。

declare
   type t_c_serv is table of number;
   c_serv t_c_serv; 
begin
   select card_holder_id bulk collect into c_serv from card_holder_services where service_id=10;

  FORALL i IN c_serv.FIRST..c_serv.LAST
    DELETE FROM card where card_holder_id=c_serv(i);
  FORALL i IN c_serv.FIRST..c_serv.LAST
    DELETE FROM card_holder_services where card_holder_id=c_serv(i);
  FORALL i IN c_serv.FIRST..c_serv.LAST
    DELETE FROM card_holder where card_holder_id=c_serv(i);

end;

请注意,我认为卡表包含card_holder_id,您可以根据您的设计进行调整,例如:如果相反在card_holder中有card_id,则通过

替换卡中的删除
DELETE FROM card WHERE card_id in 
 (select card_id from card_holder where card_holder_id=c_serv(i)).