오라클은 다중 테이블을 조인하여 데이터를 갱신하는 기능을 지원합니다.
T1 테이블 A1, A2, A3 컬럼, T2 테이블 B1, B2, B3 컬럼에서 A2 와 B2 의 데이터가 같고 A1 의 데이터가 1 인경우 A3 을 B3 으로 업데이트 한다고 합니다.
CREATE TABLE A ( A1 INT, A2 INT, A3 INT ); CREATE TABLE B ( B1 INT, B2 INT, B3 INT ); INSERT INTO A VALUES (1, 3, 3); INSERT INTO B VALUES (1, 3, 5); COMMIT;
UPDATE 문은 다음과 같이 작성할 수 있습니다.
UPDATE A SET A3 = ( SELECT B3 FROM B WHERE A.A2 = B.B2 AND A.A1 = 1 );
이후 A 테이블의 데이터를 조회하면 A3 컬럼이 B3 의 데이터가 되는 것을 확인할 수 있습니다.
SQL> SELECT * FROM A; A1 A2 A3 ---------- ---------- ---------- 1 3 5
그런데 만약 일치하는 데이터가 없다고 하면 어떻게 될까요? 기존 데이터가 없기 때문에 NULL 값으로 업데이트 됩니다.
A.A1 을 2 로 설정하고 업데이트 한 경우
SQL> SELECT * FROM A; A1 A2 A3 ---------- ---------- ---------- 1 3
만약 NULL 인경우 업데이트를 원치 않는 경우에는 NVL 함수를 써야 합니다.
이 구문을 UPDATE JOIN 을 사용하여 업데이트를 해보겠습니다.
먼저, JOIN 대상이 되는 테이블의 부모/자식 관계를 오라클이 알고있어야 합니다. 이를 알지 못하는 경우 다음과 같은 에러가 발생합니다.
ORA-01779: cannot modify a column which maps to a non key-preserved table
위 테이블에서 부모와 자식관계를 알려주기 위해 B 테이블에 제약조건을 추가합니다.
SQL> ALTER TABLE B ADD CONSTRAINT B_PK PRIMARY KEY (B2);
이후 UPDATE JOIN 을 사용하여 데이터를 갱신합니다.
SQL> UPDATE ( SELECT A.A3 A_A3, B.B3 B_B3 FROM A, B WHERE A.A2 = B.B2 AND A.A1 = 1 ) SET A_A3 = B_B3; 1 row updated. SQL> SELECT * FROM A; A1 A2 A3 ---------- ---------- ---------- 1 3 5
오라클 11g 이전버전에는 /*+ BYPASS_UVJC */ 힌트를 사용하여 위의 에러를 무시했지만, 이는 적절치 못하는 방법이며 부모/자식의 관계를 오라클이 알도록 하는게 가장 좋은 방법입니다.
'Database > Oracle' 카테고리의 다른 글
[ORACLE] SPM ( SQL Plan Management ) 로 실행 계획 관리하기 (0) | 2018.08.27 |
---|---|
[ORACLE] 다량의 데이터를 FORALL 로 빠르게 넣기 (0) | 2018.08.23 |
[ORACLE] SQL 병렬 힌트를 부여하여 쿼리 성능 높이기 (0) | 2018.08.22 |
[ORACLE] INS-35075: The specified SID is already in use 해결하기 (0) | 2018.08.07 |
[ORACLE] ORA-65096: invalid common user or role name 해결하기 (0) | 2018.08.07 |