Sql 从约束相关的两个表中删除行

Sql 从约束相关的两个表中删除行,sql,oracle,plsql,Sql,Oracle,Plsql,我们有两张桌子: HUSBANDS --------------- id name surname age WIFES --------------- id name surname age husbandId --(with constrain -> HUSBANDS.ID) 假设我们需要写一个程序,把60岁以上的妻子和他们的丈夫一起带走;) 使用典型的SQL语句可以很好地做到这一点,但在Oracle中,不可能在一个delete语句中删除两个

我们有两张桌子:

HUSBANDS
---------------
id
name
surname
age

WIFES
---------------
id
name
surname
age
husbandId                      --(with constrain -> HUSBANDS.ID)
假设我们需要写一个程序,把60岁以上的妻子和他们的丈夫一起带走;)

使用典型的SQL语句可以很好地做到这一点,但在Oracle中,不可能在一个delete语句中删除两个表中的行,对吗?所以

我们不能这样做:

PROCEDURE remove_old_wifes() IS
BEGIN
    DELETE FROM husbands WHERE id IN (SELECT husbandId FROM wifes WHERE age >= 60); 
    DELETE FROM wifes WHERE age >= 60; 
END;
因为约束

另一方面,下面提到的解决方案也是错误的:

PROCEDURE remove_old_wifes() IS
BEGIN
    DELETE FROM wifes WHERE age >= 60; 
    DELETE FROM husbands WHERE id IN (SELECT husbandId FROM wifes WHERE age >= 60); 
END;
因为当我们先解除妻子的职务时,没有一个丈夫会被解除职务

这个案例的典型解决方案是什么

重要提示:我无法设置级联。

如果表中不允许“未婚丈夫”,您可以先删除妻子,然后删除所有不再有妻子的丈夫。如果临时不一致是一个问题,您可能希望将删除内容包装在事务中

PROCEDURE remove_old_wifes() IS
BEGIN
    DELETE FROM wifes WHERE age >= 60; 
    DELETE FROM husbands WHERE id NOT IN (SELECT husbandId FROM wifes); 
END;

您可以首先使用丈夫没有妻子的指示器更新丈夫。对于您的数据,让我们使用
age=-1
。然后从妻子处删除[sic],然后从丈夫处删除

update husbands
    set age = -1
    where id in (select husbandId from wifes where age >= 60);

delete from wifes where age >= 60;

delete from husbands where age = -1;

在Oracle中有许多外键子句。 例如,您可以在外键中包含“on delete cascade”子句:

alter table WIFES 
add foreign key (husbandId ) 
   references HUSBANDS(id)
on delete cascade;
有了这个子句,您可以只使用一个delete来删除两个表中的行。 因此,您的程序将是:

PROCEDURE remove_old_wifes() IS
BEGIN
    DELETE FROM husbands WHERE id IN (SELECT husbandId FROM wifes WHERE age >= 60); 
END;
如果无法设置on delete cascade子句,则应使用全局临时表,例如:

create table gtt_id( id number) on commit delete rows;


PROCEDURE remove_old_wifes() IS
BEGIN
    insert into gtt_id SELECT husbandId FROM wifes WHERE age >= 60;
    delete FROM wifes WHERE age >= 60
    DELETE FROM husbands WHERE id IN (SELECT id FROM gtt_id); 
END;

你为什么不能设置cascade?@GordonLinoff,因为我不是schema的自动生成者,我对此有禁令;)在婚姻关系(丈夫和妻子)的情况下,这可能是有效的,但我需要解决丈夫ID可以为空的问题(可选)。@LuisSuarez你能在你的问题中添加一些样本数据来说明你的意思吗?