Oracle从tableA中删除,其中tableB中有重复的行

时间:2018-09-26 11:04:56

标签: oracle

正如标题所述,我正在寻找一种从TableA删除TableB中存在匹配行的所有行的方法。 表A和B中有大约30列,所以WHERE A.col1 = B.col1等会有点问题。理想情况下,我希望有这样的东西

DELETE FROM tableA WHERE IN TableB 

(这种事情过度简化了)

4 个答案:

答案 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);