본문으로 건너뛰기

DML

SQLD 목차관리 구문레슨 32 / 35

목차

DML(Data Manipulation Language, 데이터 조작어)은 테이블의 행을 넣고(INSERT), 바꾸고(UPDATE), 지웁니다(DELETE). MERGE는 짝이 있는 행은 바꾸고 없는 행은 넣습니다. 테이블의 구조는 그대로 둡니다.

신입 사원이 들어오면 행을 넣고, 월급이 오르면 값을 바꾸고, 퇴사하면 행을 지웁니다. 행을 읽는 SELECT도 DML로 묶지만, 이 레슨은 행을 바꾸는 네 문장을 봅니다. 그림의 문장은 한 세션(session — 데이터베이스에 접속해 있는 연결 하나)에서 차례로 실행해, 단계마다 앞 단계의 결과에서 이어집니다.

7단계 중 1단계. DML은 테이블의 행을 넣고, 바꾸고, 지우는 문장입니다.

1INSERT로 행 넣기

열 목록과 VALUES의 값은 적은 순서대로 짝을 짓고, 목록의 순서는 테이블의 열 순서와 달라도 됩니다. 목록에서 뺀 열에는 NULL이 들어가는데, 기본값(DEFAULT)을 정해 둔 열이면 그 값이 들어갑니다. 기본값이 없는 NOT NULL 열을 빼면 ORA-01400 오류로 막힙니다. 열 목록을 아예 빼면 모든 열의 값을 테이블의 열 순서대로 줘야 하고, 값이 모자라면 ORA-00947 오류입니다. VALUES 대신 서브쿼리를 쓰면(INSERT INTO 테이블 SELECT …) 그 결과 행을 한 번에 넣습니다.

2UPDATE와 DELETE

UPDATE는 SET에 바꿀 열과 새 값을 쓰고, 새 값에는 SAL + 50처럼 지금 값을 쓴 식도 됩니다. DELETE는 행을 통째로 지워서 열 이름을 쓰지 않고, DELETE EMP WHERE …처럼 FROM을 빼도 됩니다(Oracle·SQL Server 모두). 두 문장 모두 WHERE로 행을 고르고, 조건은 SELECT의 WHERE와 같은 규칙으로 따집니다.

WHERE고르는 행
DEPTNO = 2020번 부서 3행
없음모든 행
DEPTNO = NULL0행(오류 없음)
DEPTNO IS NULL정하늘 1행

행을 모두 지우는 TRUNCATE, 테이블을 없애는 DROP과 DELETE의 차이는 DDL 레슨에서 봅니다.

3MERGE로 바꾸거나 넣기

MERGE INTO 뒤에 바꿀 대상을, USING 뒤에 원본을 쓰고, ON 조건으로 원본 행마다 대상에서 짝을 찾습니다. Oracle은 ON 조건을 괄호로 감싸야 합니다(빼면 ORA-00969).

절하는 일그림에서
WHEN MATCHED짝이 있으면 UPDATE1004 SAL 450 → 480
WHEN NOT MATCHED짝이 없으면 INSERT1008 새 행

두 절 가운데 하나만 써도 되고, 원본에 없는 대상의 행은 건드리지 않습니다. ON에 쓴 열은 짝을 찾는 기준이라 UPDATE SET에서 바꿀 수 없습니다(ORA-38104). 여기까지 바꾼 행은 아직 확정 전이라 ROLLBACK으로 되돌릴 수 있습니다(TCL 레슨에서 자세히).

예제

예제는 저마다 처음 데이터에서 시작하고, 끝의 SELECT로 바뀐 결과를 봅니다. 그림의 INSERT에서 목록에 없는 MGR도 NULL입니다.

INSERT INTO EMP
  (EMPNO, ENAME, SAL)
VALUES (1007, '윤서아', 360);
SELECT *
FROM EMP
WHERE EMPNO = 1007;
EMPNOENAMESALDEPTNOMGR
1007윤서아360NULLNULL

열 목록을 빼면 DEPT의 열 순서(DEPTNO, DNAME, LOC)대로 값을 씁니다.

INSERT INTO DEPT
VALUES (50, '총무', '대전');
SELECT *
FROM DEPT
WHERE DEPTNO = 50;
DEPTNODNAMELOC
50총무대전

그림의 UPDATE와 DELETE를 처음 데이터에 차례로 실행합니다.

UPDATE EMP
SET SAL = SAL + 50
WHERE DEPTNO = 20;
DELETE FROM EMP
WHERE SAL < 350;
SELECT EMPNO,
  ENAME,
  SAL
FROM EMP
ORDER BY EMPNO;
EMPNOENAMESAL
1001김민준520
1002이서연430
1003박지호460
1004최유나450
1006강도윤520

그림의 MERGE입니다. 원본 S는 두 SELECT를 UNION ALL로 이어 만든 두 행짜리 표입니다.

MERGE INTO EMP E
USING (
  SELECT 1004 AS EMPNO,
    '최유나' AS ENAME,
    480 AS SAL,
    30 AS DEPTNO
  FROM DUAL
  UNION ALL
  SELECT 1008,
    '임도현',
    390,
    30
  FROM DUAL
) S
ON (E.EMPNO = S.EMPNO)
WHEN MATCHED THEN
  UPDATE SET E.SAL = S.SAL
WHEN NOT MATCHED THEN
  INSERT (EMPNO, ENAME,
    SAL, DEPTNO)
  VALUES (S.EMPNO, S.ENAME,
    S.SAL, S.DEPTNO);
SELECT EMPNO,
  ENAME,
  SAL,
  DEPTNO
FROM EMP
WHERE DEPTNO = 30
ORDER BY EMPNO;
EMPNOENAMESALDEPTNO
1004최유나48030
1008임도현39030

시험 포인트

  • INSERT에서 열 목록을 빼면 모든 열의 값을 테이블의 열 순서대로 줘야 합니다. 모자라면 ORA-00947입니다.
  • 열 목록에서 뺀 열은 NULL이나 기본값(DEFAULT)이 되고, 기본값이 없는 NOT NULL 열을 빼면 ORA-01400입니다.
  • UPDATE·DELETE에 WHERE가 없으면 모든 행이 바뀌거나 지워집니다. WHERE 열 = NULL은 오류 없이 한 행도 고르지 않습니다.
  • DELETE는 FROM을 빼도 됩니다(Oracle·SQL Server 모두).
  • MERGE는 WHEN MATCHED·WHEN NOT MATCHED 가운데 하나만 써도 되고, ON에 쓴 열은 UPDATE SET에서 바꿀 수 없습니다.

확인 문제

1. DEPT에 다음 INSERT 셋을 차례로 실행합니다. DNAME은 NOT NULL입니다. 마지막 SELECT의 결과는 무엇이고, 막히는 문장은 왜 막힐까요?

INSERT INTO DEPT
  (DNAME, DEPTNO)
VALUES ('홍보', 60);
INSERT INTO DEPT
VALUES (70, '법무');
INSERT INTO DEPT
  (DEPTNO, LOC)
VALUES (80, '대구');
SELECT *
FROM DEPT
WHERE DEPTNO >= 50;
정답

60번 한 행입니다.

DEPTNODNAMELOC
60홍보NULL
  • 60번: 목록 순서대로 짝을 지어 들어가고, 목록에 없는 LOC는 비어 있습니다.
  • 70번: 목록이 없어 DEPT의 세 열을 다 채워야 하는데 값이 둘뿐이라 ORA-00947입니다.
  • 80번: 비울 수 없는 DNAME이 목록에 없어 ORA-01400입니다.

2. 다음 두 문장을 차례로 실행하면 EMP의 행 수와 SAL 합계는 얼마일까요? 처음 합계는 2530입니다.

UPDATE EMP
SET SAL = SAL + 50;
DELETE FROM EMP
WHERE DEPTNO = NULL;
SELECT COUNT(*) AS CNT,
  SUM(SAL) AS TOTAL
FROM EMP;
정답

6행, 합계 2830입니다.

CNTTOTAL
62830
  • UPDATE에 조건이 없어 여섯 사원이 모두 50씩 올라 합계가 300 늘어납니다.
  • 정하늘의 DEPTNO와 NULL을 =로 견주면 참이 아니라서 DELETE가 지우는 행은 없습니다. 정하늘을 지우려면 IS NULL로 씁니다.

3. WHEN NOT MATCHED를 쓰지 않은 다음 MERGE를 실행하면, EMP의 행 수와 SAL 합계는 얼마가 될까요? 1009는 왜 들어가지 않을까요?

MERGE INTO EMP E
USING (
  SELECT 1001 AS EMPNO,
    '김민준' AS ENAME,
    550 AS SAL,
    10 AS DEPTNO
  FROM DUAL
  UNION ALL
  SELECT 1009,
    '한유진',
    330,
    40
  FROM DUAL
) S
ON (E.EMPNO = S.EMPNO)
WHEN MATCHED THEN
  UPDATE SET E.SAL = S.SAL;
SELECT COUNT(*) AS CNT,
  SUM(SAL) AS TOTAL
FROM EMP;
정답

6행, 합계 2560입니다.

CNTTOTAL
62560
  • 1001은 EMP에 짝이 있어 SAL이 520에서 550으로 바뀌고 합계가 30 늘어납니다.
  • 1009는 짝이 없는데, 짝 없는 행을 넣는 절이 없어 MERGE가 아무것도 하지 않습니다.

끝까지 내려오면 저절로 표시됩니다. 이 기기에만 저장합니다.

SQLD 목차로