INSERT INTO 테이블 [(열1, 열2, …)] VALUES (값1, 값2, …);INSERT INTO 테이블 [(열1, 열2, …)] SELECT …;
CREATE TABLE T_DEPT AS SELECT * FROM DEPT;INSERT INTO T_DEPT (DEPTNO, DNAME, LOC) VALUES (50, 'EDUCATION', 'SEOUL');INSERT INTO T_DEPT VALUES (60, 'IT', NULL);INSERT INTO T_DEPT (DEPTNO, DNAME) VALUES (70, 'HR');SELECT * FROM T_DEPT ORDER BY DEPTNO;DROP TABLE T_DEPT PURGE;
Table created.1 row created.1 row created.1 row created. DEPTNO DNAME LOC---------- -------------- ------------- 10 ACCOUNTING NEW YORK 20 RESEARCH DALLAS 30 SALES CHICAGO 40 OPERATIONS BOSTON 50 EDUCATION SEOUL 60 IT 70 HR7 rows selected.Table dropped.
쓰는 법
규칙
열 목록을 쓴다 (50)
적은 열의 순서대로 값을 준다. 테이블 정의 순서와 달라도 된다
열 목록을 생략한다 (60)
모든 열에 정의 순서대로 값을 준다. 비울 열은 NULL 을 직접 적는다
일부 열만 적는다 (70)
빠진 LOC 에는 DEFAULT 값, 없으면 NULL 이 들어간다
문자와 날짜 값은 작은따옴표로 감싼다. 숫자는 감싸지 않는다.
빠진 열에 NOT NULL 제약이 있고 DEFAULT 가 없으면 ORA-01400(cannot insert NULL) 오류가 난다.
CREATE TABLE T_DEPT (DEPTNO NUMBER(2), DNAME VARCHAR2(14), LOC VARCHAR2(13) DEFAULT 'SEOUL');INSERT INTO T_DEPT (DEPTNO, DNAME) VALUES (50, 'EDUCATION');INSERT INTO T_DEPT VALUES (60, 'IT', DEFAULT);INSERT INTO T_DEPT VALUES (70, 'HR', NULL);INSERT INTO T_DEPT VALUES (80, 'SUPPORT');INSERT INTO T_DEPT (DEPTNO, DNAME) VALUES (90, 'SALES', 'BUSAN');SELECT * FROM T_DEPT ORDER BY DEPTNO;DROP TABLE T_DEPT PURGE;
Table created.1 row created.1 row created.1 row created.INSERT INTO T_DEPT VALUES (80, 'SUPPORT') *ERROR at line 1:ORA-00947: not enough valuesINSERT INTO T_DEPT (DEPTNO, DNAME) VALUES (90, 'SALES', 'BUSAN') *ERROR at line 1:ORA-00913: too many values DEPTNO DNAME LOC---------- -------------- ------------- 50 EDUCATION SEOUL 60 IT SEOUL 70 HR3 rows selected.Table dropped.
50 은 LOC 를 빼서, 60 은 DEFAULT 키워드로 기본값 SEOUL 을 받았다.
70 은 NULL 을 직접 넣었다. 값을 명시하면 DEFAULT 는 쓰이지 않는다.
80 은 열 목록 없이 값 둘만 줘서 ORA-00947(not enough values), 90 은 열 둘에 값 셋을 줘서 ORA-00913(too many values)이다. 오류 난 행은 들어가지 않았다.
VALUES 대신 SELECT 를 쓰면 조회 결과 전체가 한 번에 들어간다. VALUES 와 괄호를 쓰지 않는다.
CREATE TABLE EMP_T AS SELECT EMPNO, ENAME, SAL FROM EMP WHERE 1 = 2;INSERT INTO EMP_T SELECT EMPNO, ENAME, SAL FROM EMP WHERE DEPTNO = 10;INSERT INTO EMP_T (EMPNO, ENAME) SELECT EMPNO, ENAME FROM EMP WHERE JOB = 'ANALYST';SELECT * FROM EMP_T ORDER BY EMPNO;DROP TABLE EMP_T PURGE;
Table created.3 rows created.2 rows created. EMPNO ENAME SAL---------- ---------- ---------- 7782 CLARK 2450 7788 SCOTT 7839 KING 5000 7902 FORD 7934 MILLER 13005 rows selected.Table dropped.
WHERE 1 = 2 는 항상 거짓이라 구조만 복사하고 행은 0개인 빈 테이블을 만든다.
한 문장으로 10번 부서 3행이 들어갔다. 피드백도 3 rows created. 다.
SELECT 의 열 수와 순서는 INSERT 대상 열과 맞아야 한다. 두 번째 INSERT 는 SAL 을 빼서 SCOTT·FORD 의 SAL 이 NULL 이다.
CREATE TABLE EMP_T AS SELECT * FROM EMP;UPDATE EMP_T SET SAL = SAL * 1.1, COMM = 100 WHERE DEPTNO = 10;UPDATE EMP_T SET SAL = (SELECT MAX(SAL) FROM EMP WHERE DEPTNO = 20) WHERE ENAME = 'SMITH';UPDATE EMP_T SET (JOB, SAL) = (SELECT JOB, SAL FROM EMP WHERE ENAME = 'SCOTT') WHERE ENAME = 'ADAMS';UPDATE EMP_T SET COMM = 0 WHERE ENAME = 'NOBODY';SELECT ENAME, JOB, SAL, COMM FROM EMP_T WHERE DEPTNO IN (10, 20) ORDER BY DEPTNO, ENAME;UPDATE EMP_T SET COMM = NULL;DROP TABLE EMP_T PURGE;
DELETE FROM 테이블 [WHERE 조건]; 은 조건에 맞는 행을 지운다. Oracle 에서는 FROM 을 생략해도 된다.
CREATE TABLE EMP_T AS SELECT * FROM EMP;DELETE FROM EMP_T WHERE DEPTNO = 30;SELECT COUNT(*) FROM EMP_T;ROLLBACK;SELECT COUNT(*) FROM EMP_T;DELETE EMP_T;TRUNCATE TABLE EMP_T;ROLLBACK;SELECT COUNT(*) FROM EMP_T;DROP TABLE EMP_T PURGE;SELECT COUNT(*) FROM EMP_T;
Table created.6 rows deleted. COUNT(*)---------- 81 row selected.Rollback complete. COUNT(*)---------- 141 row selected.14 rows deleted.Table truncated.Rollback complete. COUNT(*)---------- 01 row selected.Table dropped.SELECT COUNT(*) FROM EMP_T *ERROR at line 1:ORA-00942: table or view "SCOTT"."EMP_T" does not exist
DELETE 로 지운 6행은 ROLLBACK 으로 돌아왔다. 아직 COMMIT 하지 않은 변경이기 때문이다.
TRUNCATE 는 DDL 이다. 실행하는 순간 앞의 DELETE EMP_T 까지 함께 확정되어 ROLLBACK 해도 0행이다.
DROP 뒤에는 테이블 자체가 없어 ORA-00942 다. 오류 문구의 "SCOTT"."EMP_T" 표기는 23ai 형식이고, 이전 버전은 table or view does not exist 만 보여 준다.
구분
DELETE
TRUNCATE
DROP
종류
DML
DDL
DDL
지우는 것
조건에 맞는 행 (WHERE 가능)
모든 행 (WHERE 불가)
행 + 테이블 구조
ROLLBACK
가능 (COMMIT 전)
불가 (자동 커밋)
불가 (자동 커밋)
테이블 구조
남는다
남는다
없어진다
저장 공간
그대로 둔다
처음 크기로 돌려준다
돌려준다
속도
행마다 기록을 남겨 느리다
빠르다
빠르다
SQL Server 에서는 BEGIN TRAN 안에서 실행한 TRUNCATE 를 ROLLBACK 으로 되돌릴 수 있다. 위 표의 "불가"는 Oracle 기준이다.
⚠️ 함정: "모든 행을 지우되 되돌릴 수 있어야 한다"면 TRUNCATE 가 아니라 WHERE 없는 DELETE 다. "구조는 남기고 빠르게 비운다"면 TRUNCATE, "테이블이 필요 없다"면 DROP 이다.
원본 데이터를 대상 테이블에 반영할 때, 이미 있는 행은 UPDATE, 없는 행은 INSERT 해야 할 때가 있다. 두 문장을 나눠 쓰는 대신 MERGE 한 문장으로 처리한다.
MERGE INTO 대상 테이블 별칭USING 원본(테이블·뷰·서브쿼리) 별칭ON (대상과 원본을 잇는 조건)WHEN MATCHED THEN UPDATE SET 열 = 값 [, …]WHEN NOT MATCHED THEN INSERT (열, …) VALUES (값, …);
T_BONUS 에는 10번 부서 CLARK·KING·MILLER 가 보너스 0 으로 있다. MANAGER·PRESIDENT 4명(JONES·BLAKE·CLARK·KING)을 원본으로 MERGE 한다.
CREATE TABLE T_BONUS AS SELECT EMPNO, ENAME, SAL AS BONUS FROM EMP WHERE DEPTNO = 10;UPDATE T_BONUS SET BONUS = 0;MERGE INTO T_BONUS B USING (SELECT EMPNO, ENAME, SAL FROM EMP WHERE JOB IN ('MANAGER', 'PRESIDENT')) E ON (B.EMPNO = E.EMPNO) WHEN MATCHED THEN UPDATE SET B.BONUS = E.SAL * 0.1 WHEN NOT MATCHED THEN INSERT (EMPNO, ENAME, BONUS) VALUES (E.EMPNO, E.ENAME, E.SAL * 0.05);SELECT * FROM T_BONUS ORDER BY EMPNO;DROP TABLE T_BONUS PURGE;
Table created.3 rows updated.4 rows merged. EMPNO ENAME BONUS---------- ---------- ---------- 7566 JONES 148.75 7698 BLAKE 142.5 7782 CLARK 245 7839 KING 500 7934 MILLER 05 rows selected.Table dropped.
원본 행
ON 결과
처리
보너스
CLARK, KING
대상에 있다 (MATCHED)
UPDATE
급여의 10%
JONES, BLAKE
대상에 없다 (NOT MATCHED)
INSERT
급여의 5%
(원본에 없는 MILLER)
원본에 없다
손대지 않는다
0 그대로
피드백 4 rows merged. 는 UPDATE 2행과 INSERT 2행을 합친 수다.
MERGE 는 원본 기준으로 돈다. 대상에만 있는 MILLER 는 지워지지도 바뀌지도 않는다.
UPDATE·INSERT 문장 안에는 테이블 이름을 다시 쓰지 않는다. UPDATE SET …, INSERT (…) VALUES (…) 로 바로 이어진다.
CREATE TABLE T_BONUS AS SELECT EMPNO, ENAME, SAL AS BONUS FROM EMP WHERE DEPTNO = 10;MERGE INTO T_BONUS B USING (SELECT EMPNO, SAL FROM EMP WHERE DEPTNO = 10) E ON (B.EMPNO = E.EMPNO) WHEN MATCHED THEN UPDATE SET B.EMPNO = E.EMPNO;MERGE INTO T_BONUS B USING (SELECT EMPNO, ENAME FROM EMP WHERE DEPTNO = 20) E ON (B.EMPNO = E.EMPNO) WHEN NOT MATCHED THEN INSERT (EMPNO, ENAME, BONUS) VALUES (E.EMPNO, E.ENAME, 0);SELECT COUNT(*) FROM T_BONUS;DROP TABLE T_BONUS PURGE;
Table created.MERGE INTO T_BONUS B USING (SELECT EMPNO, SAL FROM EMP WHERE DEPTNO = 10) E ON (B.EMPNO = E.EMPNO) WHEN MATCHED THEN UPDATE SET B.EMPNO = E.EMPNO *ERROR at line 1:ORA-38104: Columns referenced in the ON Clause cannot be updated: "B"."EMPNO"5 rows merged. COUNT(*)---------- 81 row selected.Table dropped.
ON 절에 쓴 열은 UPDATE SET 에서 바꿀 수 없다(ORA-38104). 연결 기준이 바뀌면 매칭이 흔들리기 때문이다.
WHEN MATCHED 와 WHEN NOT MATCHED 중 하나만 써도 된다. 두 번째 MERGE 는 INSERT 절만 써서 20번 부서 5명을 넣었다. Oracle 9i 에서는 둘 다 필요했고 10g 부터 하나만 쓸 수 있다.
그래서 COUNT 는 기존 3행에 5행을 더한 8 이다.
10g 부터 UPDATE SET … WHERE 조건, DELETE WHERE 조건 을 MATCHED 절에 덧붙일 수 있다.
원본 두 행이 대상 한 행과 맞으면 같은 행을 두 번 고치게 되어 ORA-30926 이 난다. 원본은 ON 열 기준으로 한 행씩이어야 한다.
내일은 DML 의 변경을 확정하거나 되돌리는 TCL(COMMIT·ROLLBACK·SAVEPOINT)과 트랜잭션을 다룬다.
DML : 행의 내용을 바꾸는 문장. INSERT·UPDATE·DELETE·MERGE 가 있다.
열 목록 : INSERT 에서 테이블 이름 뒤 괄호에 적는 열 이름들. 값을 넣을 열과 순서를 정한다.
DEFAULT : 값을 주지 않은 열에 대신 들어갈 기본값. VALUES 안에 키워드로 직접 쓸 수도 있다.
INSERT … SELECT : 조회 결과의 모든 행을 한 문장으로 넣는 INSERT. VALUES 를 쓰지 않는다.
TRUNCATE : 테이블의 모든 행을 지우고 공간을 돌려주는 DDL. 구조는 남고 ROLLBACK 은 안 된다.
MERGE : 원본과 대상을 ON 조건으로 비교해 맞으면 UPDATE, 없으면 INSERT 하는 문장.
ORA-00947 / ORA-00913 : INSERT 의 값이 열보다 모자랄 때 / 남을 때의 오류.
📝 연습 문제
선택지를 클릭하면 정답·해설이 펼쳐집니다.
문제 1
CREATE TABLE T_DEPT (DEPTNO NUMBER(2), DNAME VARCHAR2(14), LOC VARCHAR2(13) DEFAULT 'SEOUL'); 로 만든 테이블에 INSERT INTO T_DEPT (DEPTNO, DNAME) VALUES (50, 'EDUCATION'); 를 실행했다. 이 행의 LOC 값은?
문제 2
DEPT 를 복사한 T_DEPT(DEPTNO, DNAME, LOC)에 INSERT INTO T_DEPT VALUES (80, 'SUPPORT'); 를 실행한 결과는?
문제 3
Oracle 의 DELETE·TRUNCATE·DROP 에 대한 설명으로 옳은 것은?
문제 4
T_BONUS 에 CLARK·KING·MILLER 3행이 있다. 원본 JONES·BLAKE·CLARK·KING 4행으로 MERGE INTO T_BONUS B USING (…) E ON (B.EMPNO = E.EMPNO) WHEN MATCHED THEN UPDATE SET … WHEN NOT MATCHED THEN INSERT … 를 실행한 뒤 T_BONUS 의 행 수는?
문제 5
EMP 를 복사한 EMP_T 에 UPDATE EMP_T SET COMM = 0 WHERE ENAME = 'NOBODY'; 를 실행했다. 이름이 NOBODY 인 사원은 없다. SQL*Plus 의 결과는?