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 in
의null
절대 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
'programing' 카테고리의 다른 글
getApplication()을 컨텍스트로 사용하여 "창을 추가할 수 없음 - 응용 프로그램에 대한 토큰 null이 아닙니다"를 던지는 대화 상자 (0) | 2023.07.17 |
---|---|
하위 컬렉션을 통한 클라우드 Firestore 심층 분석 (0) | 2023.07.17 |
ClassNotFoundException: org.flywaydb.core.api.callback입니다.플라이웨이 콜백 (0) | 2023.07.17 |
사전 값을 여러 개 가져오는 방법? (0) | 2023.07.17 |
NSA 특성 문자열을 사용하여 문자열 색상을 변경하시겠습니까? (0) | 2023.07.17 |