使用不带 WHERE 或 IN 的子选择删除 (Key-Preserved-Table)

Delete with subselect without WHERE or IN (Key-Preserved-Table)

这是一个删除子句,它对我来说非常有用,但我想知道 oracle 如何知道要删除哪个 table 数据?

delete from (select * from t1 join t2  
on t1.field1 = t2.field1) 

确定将删除哪些 table 的机制是什么?

在我的例子中,数据从 t1 中删除,t1 和 t2 之间的关系是 n -> 1。

如果我更改子选择的顺序 return,结果将是相同的:

delete from (select * from t2 join t1  
on t1.field1 = t2.field1) 

Oracle 只会从所谓的 key preserved table 中删除。即 table,其键保存在生成​​的连接中。也就是说,key preserved table 的行在结果 join. 中只能出现 一次.

在这里,由于外键约束,您在 t1 和 t2 之间有一个 n -> 1 映射。因此,Oracle 必然会选择 t1 作为保留 table 的键,因为在连接结果中,t2 的相同行可能有好几倍。


table 的密钥保留 属性 不依赖于 table 中的实际数据。它是其架构的 属性。根据下面评论中的 OP 请求,这里有一个示例:

create table a (n int primary key);
create table b (n int);

insert into a values(1);
insert into b values(1);
insert into b values(1);

以下语句将从 b 中删除行:

delete from (select * from a join b on a.n = b.n);

为什么行来自 b ?因为,Oracle可以确保tableb中的行与结果集中的行之间存在一对一的映射关系。因此,b 保留的密钥 table。参见:

select a.*, a.rowid, b.*, b.rowid from a join b on a.n = b.n;

  a.n | a.ROWID            | b.n| b.ROWID
  ----+--------------------+----+-------------------
    1 | AAAKUKAAEAAAAv8AAA |  1 | AAAKUMAAEAAAAwMAAA 
    1 | AAAKUKAAEAAAAv8AAA |  1 | AAAKUMAAEAAAAwMAAB