正如标题所述,我正在寻找一种从TableA删除TableB中存在匹配行的所有行的方法。 表A和B中有大约30列,所以WHERE A.col1 = B.col1等会有点问题。理想情况下,我希望有这样的东西
DELETE FROM tableA WHERE IN TableB
(这种事情过度简化了)
答案 0 :(得分:1)
IN
子句可以比较select返回的所有列
DELETE FROM tableA WHERE ( col1,col2,col3,.. ) IN ( select col1,col2,col3... FROM TableB );
答案 1 :(得分:0)
确定每个表中的两个记录是否相同的暴力方式是只比较每列:
DELETE
FROM tableA a
WHERE EXISTS (SELECT 1 FROM tableB b WHERE a.col1 = b.col1 AND a.col2 = b.col2 AND ...
a.col30 = b.col30);
答案 2 :(得分:0)
您可以创建检查表结构的函数,如果它们相同,则创建包含要比较的正确条件的字符串。
例如,这里有两个表:
create table t1 (id, name, age) as (
select 1, 'Tom', 67 from dual union all
select 2, 'Tia', 42 from dual union all
select 3, 'Bob', 16 from dual );
create table t2 (id, name, age) as (
select 1, 'Tom', 51 from dual union all
select 3, 'Bob', 16 from dual );
现在使用功能:
select generate_condition('T1', 'T2') from dual;
结果:
T1.ID = T2.ID and T1.NAME = T2.NAME and T1.AGE = T2.AGE
复制此内容,粘贴并运行delete
查询:
delete from t1 where exists (select 1 from t2 where <<PASTE_HERE>>)
这是功能,如有需要,请对其进行调整。我使用了user_tab_columns
,因此如果表位于不同的架构上,则需要all_tab_columns
并比较所有者。如果您具有Oracle 11g,则可以将循环替换为listagg()
。第二个表必须包含第一个表的所有列,并且它们的类型和长度必须相同。
create or replace function generate_condition(i_t1 in varchar2, i_t2 in varchar2)
return varchar2 is
v varchar2(1000) := '';
begin
for rec in (select column_name, u2.column_id
from user_tab_cols u1
left join (select * from user_tab_cols where table_name = i_t2) u2
using (column_name, data_type, data_length)
where u1.table_name = i_t1 order by u1.column_id)
loop
if rec.column_id is null then
v := 'ERR: incompatible structures';
goto end_loop;
end if;
v := v||' and '||i_t1||'.'||rec.column_name
||' = '||i_t2||'.'||rec.column_name;
end loop;
<< end_loop >>
return(ltrim(v, ' and '));
end;
如果要避免手动运行进程,则需要动态PL / SQL。
答案 3 :(得分:0)
create table tableA (a NUMBER, b VARCHAR2(5), c INTEGER);
create table tableB (a NUMBER, b VARCHAR2(5), c INTEGER);
如您所说
A.col1 = B.col1等会有点问题
您可以将表相交并一次提及tableA中的所有列,如下所示:
delete tableA
where (a,b,c) in (select * from tableA
intersect
select * from tableB);