programing

Oracle 10g에서 왼쪽 조인으로 삭제

cafebook 2023. 7. 17. 21:25
반응형

Oracle 10g에서 왼쪽 조인으로 삭제

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

기본적으로 다음에서 찾을 수 있는 모든 항목을 삭제합니다.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

A IN여러 개의 키가 없으면 절이 작동하지만 데이터로 어떻게 사용할 수 있는지 알 수 없습니다.그렇다면, 대안은 무엇일까요?

Shannon의 솔루션은 NOT IN(또는 NOT EXES) 연산자를 사용하는 방법입니다.

그러나 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

또한 Oracle은 문에서 액세스할 기본 행에 대한 모호성이 없는 경우에만 조인을 업데이트할 수 있습니다.특히 Oracle은 조인에 행이 두 번 나타날 가능성이 있는 경우 업데이트 또는 삭제 위험을 감수하지 않습니다(문은 실패함).이 경우 삭제는 다음에 고유한 제약 조건이 있는 경우에만 작동합니다.my_data(id1, id2, id3, id4).

표 및 데이터:

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.

사용.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

사용.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> 

삭제되는 내용에 모호함이 없도록 하려면 빈센트의 솔루션을 다음과 같이 변경할 수 있습니다.

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
    )

Vincent의 답변 https://stackoverflow.com/a/3675205 이 전혀 작동하지 않거나 Oracle 12c에서 작동하지 않습니다.이러한 답변은 가장 낮은 버전 또는 가장 높은 버전의 Oracle을 지정하여 개선해야 합니다.증거:

SELECT * FROM v$version where banner like 'Oracle%';
/*
Oracle Database 12c Standard Edition Release 12.2.0.1.0 - 64bit Production
*/
create table a (id int);
create table b (id int);
insert into a select 1 from dual union select 2 from dual;
insert into b select 1 from dual union select 2 from dual union select 3 from dual;
select * from a right join b on b.id = a.id;
/*
1   1
2   2
null    3
*/
delete from (
  select b.*
  from b
  inner join a on a.id = b.id
)    
/*
Error at Command Line : 7 Column : 13
Error report -
SQL Error: ORA-01752: cannot delete from view without exactly one key-preserved table
01752. 00000 -  "cannot delete from view without exactly one key-preserved table"
*Cause:    The deleted table had
           - no key-preserved tables,
           - more than one key-preserved table, or
           - the key-preserved table was an unmerged view.
*Action:   Redefine the view or delete it from the underlying base tables.
*/

delete from b
where rowid in (
  select b.rowid
  from b
  inner join a on a.id = b.id
)
/*
2 rows deleted.
*/
select * from a right join b on b.id = a.id
/*
null  3
*/

drop table a;
drop table b;

요컨대, 사용하는 것입니다.WHERE ROWID IN ()적어도 12c에서.

50회가 필요해서 코멘트를 추가할 수 없어서 여기에 답변을 추가합니다.

빈센트가 쿼리에서 삭제한 것을 테스트했는데, 구문으로는 원하는 것을 삭제할 수 없습니다. 적어도 모든 삭제 가입 사례에서 일반적으로 사용되는 것은 아닙니다.

처음에는 Oracle 기본 사용자 scott을 사용하여 테이블을 만듭니다.

create table emp1 as select * from emp where sal<2000;

emp1의 empno가 있는 empno에서 레코드를 삭제하고 싶어서 쿼리에서 이 삭제를 사용했습니다.

delete from (select a.* from emp a join emp1 b on a.empno=b.empno);

테이블이나 조인 순서가 무엇이든, 왼쪽 조인이든, 내부 조인이든, 내가 사용하는 절이 무엇이든, sql은 emp1의 해당 레코드를 삭제합니다.

따라서 쿼리에서 삭제하면 지정된 테이블에서 삭제할 수 없습니다.이러한 경우에는 커서를 루프로 전환하는 것이 좋습니다.

언급URL : https://stackoverflow.com/questions/3672285/delete-with-left-join-in-oracle-10g

반응형