我使用的是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 。
谁能告诉我最简单,最好的方法呢?
表现不是问题。
提前谢谢。
答案 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)).