我正在寻找一个好的SQL方法(Oracle数据库)来满足下一个要求:
换句话说:表A减去表B =>从表A
中删除记录delete from Table A
where (field1, field2, field3) in
(select field1, field2, field3
from Table A
minus
select field1, field2, field3
from Table B);
非常重要的是要提到 DELETE 子句中的正常 MINUS 会失败,因为不考虑可空字段上的空值(oracle的未知结果) ,然后没有比赛)。
我也成功尝试了 EXISTS ,但是我必须使用NVL函数将空值替换为虚拟值,我不想要它,因为我不能保证将值替换为NVL不会成为该领域的有效值。
有人知道如何完成这样的事情吗?请记住性能和可空的字段为" a must"。
感谢
答案 0 :(得分:1)
在where子句中使用左外连接并测试null
删除一个 来自a 左外连接b在a.x = b.x上 其中b.x为空
答案 1 :(得分:1)
您是否考虑过ORALCE SQL MERGE
声明?
答案 2 :(得分:1)
decode
找到相同性(即使两个值都为null):
decode( field1, field2, 1, 0 ) = 1
删除table2中找不到的表:
delete table1 t
where t.rowid in (select t1.rowid
from table1 t1
left outer join table2 t2
on decode(t1.field1, t2.field1, 1, 0) = 1
and decode(t1.field2, t2.field2, 1, 0) = 1
and decode(t1.field3, t2.field3, 1, 0) = 1
/* ... */
where t2.rowid is null /* no matching row found */
)
使用现有索引
...
left outer join table2 t2
on (t1.index_field1=t2.index_field1 or
t1.index_field1 is null and t2.index_field1 is null)
and ...
答案 3 :(得分:0)
对大量记录使用批量操作。性能方面它会更快。
并使用两个表之间的连接来获取要删除的行。可以将可以为空的列与某个默认值进行比较。
另外,如果您希望表A与表B类似,为什么不截断表A然后从表b插入数据
答案 4 :(得分:0)
假设您在每个表上都有相同的PK字段......(拥有PK或其他一些唯一密钥对此至关重要。)
create table table_a (id number, name varchar2(25), dob date);
insert into table_a values (1, 'bob', to_date('01-01-1978','MM-DD-YYYY'));
insert into table_a values (2, 'steve', null);
insert into table_a values (3, 'joe', to_date('05-22-1989','MM-DD-YYYY'));
insert into table_a values (4, null, null);
insert into table_a values (5, 'susan', to_date('08-08-2005','MM-DD-YYYY'));
insert into table_a values (6, 'juan', to_date('11-17-2001', 'MM-DD-YYYY'));
create table table_b (id number, name varchar2(25), dob date);
insert into table_b values (1, 'bob', to_date('01-01-1978','MM-DD-YYYY'));
insert into table_b values (2, 'steve',to_date('10-14-1992','MM-DD-YYYY'));
insert into table_b values (3, null, to_date('05-22-1989','MM-DD-YYYY'));
insert into table_b values (4, 'mary', to_date('12-08-2012','MM-DD-YYYY'));
insert into table_b values (5, null, null);
commit;
-- confirm minus is working
select id, name, dob
from table_a
minus
select id, name, dob
from table_b;
-- from the minus, re-query to just get the key, then delete by key
delete table_a where id in (
select id from (
select id, name, dob
from table_a
minus
select id, name, dob
from table_b)
);
commit;
select * from table_a;
但是,如果在某个时间点,tableA将被重置为与tableB相同,为什么不,如另一个答案所示,截断tableA并从tableB中选择all。
100K并不大。我可以在不到1秒的时间内完成~100K截断并在我的笔记本电脑实例上插入。
答案 5 :(得分:0)
> DELETE FROM purchase WHERE clientcode NOT IN (
> SELECT clientcode FROM client );
这将从采购表中删除其客户代码不在客户表中的行。购买表的客户代码引用客户表的客户代码。
DELETE FROM TABLE1 WHERE FIELD1 NOT IN (SELECT CLIENT1 FROM TABLE2);