在Oracle 10g中使用Left Join删除

Sim*_* T. 15 oracle oracle10g

我有以下代码在MS SQL Server中正常工作:

delete grp
from grp
left join my_data
on grp.id1 = my_data.id1
and grp.id2 = my_data.id2
and grp.id3 = my_data.id3
and grp.id4 = my_data.id4
where my_data.id1 is NULL
Run Code Online (Sandbox Code Playgroud)

基本上,我想删除所有可以找到grp并且没有任何等价的事件in my_data.遗憾的是,它在Oracle 10g中不起作用.我尝试使用左连接(+)的旧语法,但它也不起作用.像这样:

delete grp
from grp,
my_data
where grp.id1 = my_data.id1 (+)
and grp.id2 = my_data.id2 (+)
and grp.id3 = my_data.id3 (+)
and grp.id4 = my_data.id4 (+)
and my_data.id1 is NULL
Run Code Online (Sandbox Code Playgroud)

IN如果我没有多个键但是我不知道如何将它用于我的数据,那么一个子句就可以工作.那么,替代方案是什么?

Sha*_*nce 16

表格和数据:

SQL> create table grp (id1 number null, id2 number null, id3 number null, id4 number null);    
Table created.

SQL> create table my_data (id1 number null, id2 number null, id3 number null, id4 number null);

Table created.

SQL> insert into grp values (1, 2, 3, 4);

1 row created.

SQL> insert into grp values (10, 20, 30, 40);

1 row created.

SQL> insert into grp values (1, 2, 30, 40);

1 row created.

SQL> insert into my_data values (1, 2, 3, 4);

1 row created.

SQL> commit;

Commit complete.
Run Code Online (Sandbox Code Playgroud)

in.注意如果子查询中的ID可以,不要使用null.Not innull永远返回true.

SQL> delete grp where (id1, id2, id3, id4) not in (select id1, id2, id3, id4 from my_data);

2 rows deleted.

SQL> select * from grp;

       ID1        ID2        ID3        ID4
---------- ---------- ---------- ----------
         1          2          3          4
Run Code Online (Sandbox Code Playgroud)

运用 exists

SQL> rollback;

Rollback complete.

SQL> delete grp where not exists (select * from my_data where grp.id1 = my_data.id1 and grp.id2 = my_data.id2 and grp.id3 = my_data.id3 and grp.id4 = my_data.id4);

2 rows deleted.

SQL> select * from grp;

       ID1        ID2        ID3        ID4
---------- ---------- ---------- ----------
         1          2          3          4

SQL> 
Run Code Online (Sandbox Code Playgroud)


Vin*_*rat 16

香农的解决方案是要走的路:使用运算符NOT IN(或不是EXISTS).

但是,您可以删除或更新Oracle中的连接,但是synthax与MS SQL Server不同:

SQL> DELETE FROM (SELECT grp.*
  2                  FROM grp
  3                  LEFT JOIN my_data ON grp.id1 = my_data.id1
  4                                   AND grp.id2 = my_data.id2
  5                                   AND grp.id3 = my_data.id3
  6                                   AND grp.id4 = my_data.id4
  7                 WHERE my_data.id1 IS NULL);

2 rows deleted
Run Code Online (Sandbox Code Playgroud)

此外,如果没有关于语句将访问哪个基本行的歧义,Oracle将只允许您更新连接.特别是,如果某行可能在连接中出现两次,Oracle将不会冒更新或删除(该语句将失败)的风险.在这种情况下,只有在存在UNIQUE约束时,删除才有效my_data(id1, id2, id3, id4).


Nic*_*int 16

如果您想确保删除的内容没有歧义,您可以将Vincent的解决方案更改为:

delete from grp where rowid in
    (
    select
         grp.rowid
    from
         grp left outer join my_data on
            grp.id1 = my_data.id1
        and grp.id2 = my_data.id2
        and grp.id3 = my_data.id3
        and grp.id4 = my_data.id4
    where
        my_data.id1 is NULL
    )
Run Code Online (Sandbox Code Playgroud)