SQL Cook: 4. 12 테이블에서 모든 레코드 삭제하기 ~

0

SQL_COOK

목록 보기
32/35
post-thumbnail

제4. 12 장
테이블에서 모든 레코드 삭제하기

Q. 테이블의 모든 레코드를 삭제하려 한다

A. DELETE를 사용한다

delete from tb_name
  • WHERE절 없이 DELETE를 사용하면 지정된 테이블에서 모든 행을 삭제한다
  • TRUNCATE를 적용하면 WHERE절을 사용하지 않아도 되기에 더 빠르다
    단, Oracle에서는 TRUNCATE를 취소할 수 없다
    RDBMS마다 TRUNCATEDELETE간 성능 및 롤백 가능 여부에 차이가 있다
    -> 사용하는 벤더의 매뉴얼을 제대로 파악해야 한다

제4. 13 장
특정 레코드 삭제하기

Q. 테이블에서 특정 기준을 충족하는 레코드를 삭제하려한다

A. DELETE명령에 WHERE절을 사용하여 행을 제한한다

delete from emp where deptno = 10

제4. 14 장
단일 레코드 삭제하기

Q. 테이블에서 하나의 레코드를 삭제하려고 한다

A. 13장의 해법과 동일하나, 핵심은 선택 기준을 좁히는 것이다

delete from emp where empno = 7782
  • 단일 레코드를 삭제할 때는 일반적으로 기본 키(Primary Key) 또는 고유 키(Unique Key)를 기준으로 한다
  • 둘 모두 값의 중복을 허용하지 않기 때문이다

제4. 15 장
참조 무결성 위반 삭제하기

제목만 보면 이게 뭔 말인가 싶다.

Q. 레코드가 다른 테이블에 존재하지 않는 레코드를 참조할 때, 테이블에서 해당 레코드를 삭제하려고 한다

예를 들어,
일부 사원이, 현재 존재하지 않는 부서에 할당되었을 때, 해당 사원을 삭제하고자 한다.

A. WHERE절의 서브쿼리에 EXISTS를 사용한다

또는 NOT IN을 사용할 수도 있다.

/* 전후 비교를 위해 */
select * from emp;
>>
EMPNO	ENAME	JOB			MGR		HIREDATE	SAL		COMM	DEPTNO
7839	KING	PRESIDENT	 - 		17-NOV-81	5000	 - 		10
7698	BLAKE	MANAGER		7839	01-MAY-81	2850	 - 		30
7782	CLARK	MANAGER		7839	09-JUN-81	2450	 - 		10
7566	JONES	MANAGER		7839	02-APR-81	2975	 - 		20
7788	SCOTT	ANALYST		7566	19-APR-87	3000	 - 		20
7902	FORD	ANALYST		7566	03-DEC-81	3000	 - 		20
7369	SMITH	CLERK		7902	17-DEC-80	800	 	 -	 	20
7499	ALLEN	SALESMAN	7698	20-FEB-81	1600	300		30
7521	WARD	SALESMAN	7698	22-FEB-81	1250	500		30
7654	MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
7844	TURNER	SALESMAN	7698	08-SEP-81	1500	0		30
7876	ADAMS	CLERK		7788	23-MAY-87	1100	 - 		20
7900	JAMES	CLERK		7698	03-DEC-81	950	 	 - 		30
7934	MILLER	CLERK		7782	23-JAN-82	1300	 - 		10
14 rows selected.


delete from emp
where not exists(
	select * from dept
    where dept.deptno = emp.deptno
    );
>>
0 row(s) deleted.

'EMP' 테이블의 모든 부서값이 'DEPT' 테이블에 존재하므로 삭제되지 않은 것을 볼 수 있다.
임의의 레코드를 하나 집어 넣어서 확인해야겠다.

insert into emp values
(
9999, 'TESTER', 'TESTER', 9999, to_date('19-11-2020', 'dd-mm-yyyy'),
9999, 9999, 50
)
>>
ORA-00001: unique constraint (SQL_YIDSMRNAPUVJERHCFFLWNSQXS.PK_EMP) violated ORA-06512: at "SYS.DBMS_SQL", line 1721

오류가 난다. DEPTNO가 KEY로 설정되어 있기 때문인가 해서 KEY를 DROP했다.

ALTER TABLE emp DROP CONSTRAINT fk_deptno;
>>
Table altered.

select * from emp;
>>
EMPNO	ENAME	JOB			MGR		HIREDATE	SAL		COMM	DEPTNO
7839	KING	PRESIDENT	 - 		17-NOV-81	5000	 - 		10
7698	BLAKE	MANAGER		7839	01-MAY-81	2850	 - 		30
7782	CLARK	MANAGER		7839	09-JUN-81	2450	 - 		10
7566	JONES	MANAGER		7839	02-APR-81	2975	 - 		20
7788	SCOTT	ANALYST		7566	19-APR-87	3000	 - 		20
7902	FORD	ANALYST		7566	03-DEC-81	3000	 - 		20
7369	SMITH	CLERK		7902	17-DEC-80	800	 	 -	 	20
7499	ALLEN	SALESMAN	7698	20-FEB-81	1600	300		30
7521	WARD	SALESMAN	7698	22-FEB-81	1250	500		30
7654	MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
7844	TURNER	SALESMAN	7698	08-SEP-81	1500	0		30
7876	ADAMS	CLERK		7788	23-MAY-87	1100	 - 		20
7900	JAMES	CLERK		7698	03-DEC-81	950	 	 -	 	30
7934	MILLER	CLERK		7782	23-JAN-82	1300	 - 		10
9999	TESTER	TESTER		9999	19-NOV-20	9999	9999	50
15 rows selected.

마지막 행에 값이 정상적으로 잘 들어갔다.
'EMP' 테이블의 'DEPTNO'칼럼에, 'DEPT' 테이블의 'DEPTNO'를 참조하는 방식의 외부키를 걸어뒀었다.
'DEPT' 테이블에서 'DEPTNO'는 고유하므로, 'DEPT' 테이블에는 존재하지 않는 'DEPTNO' 값을 넣으려다보니 오류가 났던 것이다.

이 상태에서 부서가 존재하지 않는 사원의 삭제를 다시 시도해보겠다.

/* 그 전에, 혹시나해서 'EMP' 테이블의 'DEPTNO'에 FK 제약조건을 걸어보려 했다 */
alter table emp add constraint fk_deptno foreign key (deptno) references dept (deptno)
>>
ORA-02298: cannot validate (SQL_QXNARBILYUMUWIVEGKISYZYFE.FK_DEPTNO) - parent keys not found 
/* 없는 값이 있는 상태에서 FK를 넣으려다 보니 역시나 오류가 발생한다 */

delete from emp
where not exists(
	select * from dept
    where dept.deptno = emp.deptno
    );
>>
1 row(s) deleted.

select * from emp;
>>
EMPNO	ENAME	JOB			MGR		HIREDATE	SAL		COMM	DEPTNO
7839	KING	PRESIDENT	 - 		17-NOV-81	5000	 - 		10
7698	BLAKE	MANAGER		7839	01-MAY-81	2850	 - 		30
7782	CLARK	MANAGER		7839	09-JUN-81	2450	 - 		10
7566	JONES	MANAGER		7839	02-APR-81	2975	 - 		20
7788	SCOTT	ANALYST		7566	19-APR-87	3000	 - 		20
7902	FORD	ANALYST		7566	03-DEC-81	3000	 - 		20
7369	SMITH	CLERK		7902	17-DEC-80	800	 	 -	 	20
7499	ALLEN	SALESMAN	7698	20-FEB-81	1600	300		30
7521	WARD	SALESMAN	7698	22-FEB-81	1250	500		30
7654	MARTIN	SALESMAN	7698	28-SEP-81	1250	1400	30
7844	TURNER	SALESMAN	7698	08-SEP-81	1500	0		30
7876	ADAMS	CLERK		7788	23-MAY-87	1100	 - 		20
7900	JAMES	CLERK		7698	03-DEC-81	950	 	 - 		30
7934	MILLER	CLERK		7782	23-JAN-82	1300	 - 		10
14 rows selected.

TESTER가 사라진 것을 볼 수 있다.
NOT IN을 사용하는 쿼리는 다음과 같다.

delete from emp
where deptno not in (select deptno from dept)

해설

삭제는 , 실제로는 '선택'에 관한 문제다.
삭제하려는 레코드를 올바르게 설명하기 위해 WHERE절 조건을 정교하게 작성하는 것이다.

  • NOT EXISTS 해법
    : 상관 서브쿼리를 사용하여 DEPTNO가 일치하는 레코드가 있는지 검증하고, 그 결과에 따라 삭제 여부도 결정되는 방식이다.

  • IN 해법
    : 서브쿼리를 이용하여 부서 번호 목록을 검색한 후, 이 결과셋과 'EMP' 테이블의 부서 번호 목록을 비교했다. 목록에 없는 DEPTNO를 사용하는 EMP 레코드를 발견했을 때 삭제하는 방식을 사용했다.


정리

다소 난도가 낮은 쿼리였지만, 고유한 값이 있고 FK로 연결되어 있을 때 INSERT 내지 UPDATE가 어떻게 작동하는지 알 수 있었다.

  • Primary Key와 Unique Key의 차이를 알 수 있었다 (NULL허용 여부)
  • 제약 조건은, 연결된 테이블에도 영향을 준다

0개의 댓글