我正在寻找一个很好的SQL方法(Oracle数据库(来满足下一个要求:
- 从表A 表A 表>表B。 中删除行
- 两个表都有相同的结构
- 某些字段是无效
- 列和行的数量很大(比较100k行和20-30列(
- 每个行的每个字段都需要从表A 与表B。 进行比较
- 这样的要求是由于每天必须运行的过程,因为更改将来自表B 。
换句话说:表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 子句中的正常减去,因为不将无效字段的nulls置于考虑(oracle的未知结果(上,因此没有匹配,那么(。
我也尝试过成功,但是我必须使用nvl函数用虚拟值替换nulls,我不想要它,因为我不能保证在NVL中替换的值不是字段中的有效值。
有人知道一种完成此类事情的方法吗?请记住性能和无效的字段为"必须"。
谢谢
decode
找到相同性(即使两个值为null(:
decode( field1, field2, 1, 0 ) = 1
删除表2中未找到的表1中的行:
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 ...
使用左外连接并在您的Where子句中测试null
删除a 来自 左外连接b在a.x = b.x上其中b.x为null
您是否考虑过Oralce SQL MERGE
语句?
使用大量记录使用大量操作。明智的性能将更快。
并使用两个表之间的联接以获取要删除的行。可以将无效的列与某些默认值进行比较。
另外,如果您希望表A与表B相似,为什么不截断表A,然后从表B
假设您在每个表上可用相同的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重置为与表格相同的话,为什么不作为另一个答案截断tablea,然后从tableb中选择全部。
100k不是很大。我可以在不到1秒的时间内进行〜100K截断,然后在笔记本电脑实例上插入。
> DELETE FROM purchase WHERE clientcode NOT IN (
> SELECT clientcode FROM client );
这将删除其客户端代码不在客户端表中的购买表中的行。购买表的客户端代码引用客户端表的客户端代码。
DELETE FROM TABLE1 WHERE FIELD1 NOT IN (SELECT CLIENT1 FROM TABLE2);