도서/불친절한 SQL 프로그래밍

불친절한 SQL 프로그래밍 - 4부 관리 구문 - 18장 DML 문

귀찮은 개발자 2025. 2. 18. 02:40

DML 문

UPDATE / DELETE 실수 방지 습관

  1. 쿼리를 실행하기 전 트렌젝션으로 묶는다.
  2. 쿼리를 작성할 때 SELECT 절을 사용하여 삭제할 데이터를 확인한다.
    SELECT a.*, (SELECt sum(x.comm) FROM emp x WHERE x.deptno = b.deptno) FROM t1 a WHERE t1 a WHERE EXISTS (SELECT 1 FROM emp x WHERE x.deptno. a.deptno);
  3. 이후 쿼리를 UPDATE / DELETE 쿼리로 변경한다.
    UPDATE t1 a SET a.sal = (SELECt sum(x.comm) FROM emp x WHERE x.deptno = b.deptno) WHERE EXISTS (SELECT 1 FROM emp x WHERE x.deptno. a.deptno);
  4. 변경된 결과를 확인한 후 COMMIT / ROLLBACK 을 진행한다.

Merge 문

Merge 문을 사용하면 테이블에 신규 행을 추가하거나, 갱신 또는 삭제를 할 수 있다.

다른 DB 에서는 UPSERT 또는 CONFRIT 문이 있는 것 같다. 한번 찾아봐야겠다.
언어의 차이인지, 다른 기능인지.

Merge 문 문법

  • INTO TABLE_NAME : 갱신 또는 삽입할 타겟 테이블
  • USING TABLE_NAME : 갱신 또는 삽입에 사용할 소스 테이블
  • ON : 조건
  • MATCHED THEN : 조건이 만족할 경우 업데이트
  • NOT MATCHED THEN : 조건이 만족하지 않을 경우 추가
    MERGE
      INTO TABLE_NAME
      USING TABLE_NAME
      ON (Condition)
    WHEN MATCHED THEN 
      UPDATE_QUERY
    WHEN NOT MATCHED THEN 
      INSERT_QUERY

Merge 절은 10.1 버전 미만의 경우 UPDATE/INSERT 을 동시에 사용해야한다.
하지만 10.1 버전 이상은 독립적인 사용이 가능하다.

INTO / USING 절에는 INLINE VIEW 절을 사용할 수 있다.
WHEN MATCHED THEN 절에는 WHERE 절 사용이 가능하며(Update), WHEN NOT MATCHED THEN 절에는 INSERT 이기 때문에 WHERE 절을 사용할 수 없다.

INSERT 절에는 WHERE 절을 사용할 경우 USING TABLE_NAME 을 인용해야 한다.
솔직히 이 부분이 소리인지 잘 모르겠다. 484Page 참고

옵티마이저 동작 원리에 따라서 MERGE UPDATE/INSERT 절의 WHERE 절보다 인라인 뷰에 일반 조건을 기술하는 편이 성능 측면에서 유리하다.

MERGE
    INTO t1 t
    USING (SELECT * FROM t2 WHERE job = 'CLERK') s
    ON (t.empno = s.empno)
WHEN NOT MATCHED THEN
    INSERT (t.empno, t.ename, t.job)
    VALUES (s.empno, s.ename, s.job);

또한 10.1 버전 이후부터 MATCHED THEN(UPDATE) 에서는 DELETE 을 사용할 수 있다.
이 경우 갱신된 데이터 중 조건에 충족하는 경우에 데이터를 업데이트 한 후 삭제한다.
't1, t2 테이블에 모두 존재하는 행 중 job이 CLERK 인 행의 sal가 갱신되고, 갱신된 sal가 3000보다 작은 행이 삭제된다. MERGE INSERT 절에 의해 t2 테이블에만 존재하는 행 중 job이 CLERK 인 행이 삽입된다.'

MERGE
     INTO t1 t
     USING t2 s
     ON (t.empno = s.empno)
WHEN MATCHED THEN
    UPDATE SET t.sal = s.sal - 500 WHERE t.job = 'CLERK'
    DELETE WHERE t.sal < 3000
WHEN NOT MATCHED THEN
    INSERT (t.empno, t.ename, t.job)
    VALUES (s.empno, s.enama, s.job)
    WHERE s.job = 'CLERK';

MERGE 고급 - 차수 조인

MERGE 문도 UPDATE 문처럼 조인 차수에 따라 에러가 발생할 수 있다.
t1 테이블에서 empno 는 1개의 값(PK)만 있지만, t4 테이블에는 empno 가 N개가 있을 수 있다.
이 경우 WHEN MATCH TEHN 에서 WHERE 을 사용할 때 SET t.sal = s.sal - 500; s.sal 가 N개 이기 때문이다.
이럴 때에는 ROW_NUMBER 등을 사용하여 N개가 아닌 1개가 선택될 수 있도록 해야한다.

MERGE 고급 - 조인 조건

ON 절에 기술된 열은 무한 루프에 걸릴 수 있기 때문에 갱신할 수 없다.

MERGE 고급 - 일반 조건 - PASS

MERGE 고급 - 아우터 조인 - PASS

DML 에러 로깅

DML 문에서 에러가 밸상한다면 해당 DML 문에 의한 변경 사항이 모두 롤백된다. 99행까지 변경한 후 마지막 1행에서 에러가 밸생한다면 99행이 모두 롤백된다는 것이다. 이런 상황을 하기 위해 DML 에러 로깅 기능을 사용할 수 있다. DML 에러 로깅 기능은 10.2 버전부터 사용할 수 있다.

DML 에러 로깅 기능은 DML 수행 시 에러가 밸상하면 에러를 로그 테이블에 기록한 후, 다음 행에 대한 DML을 계속 진행한다.

  • INTO : 에러 로깅 테이블을 지정
  • simple_expression : 에러 태그로 사용할 값을 지정
  • REJECT LIMIT : interger로 에러의 한계 값을 지정(기본값은 0 또는 UNLIMITED)