행을 넣고 고치고 지우기
INSERT · UPDATE · DELETE 와 OUTPUT 절입니다. WHERE 를 빠뜨리면 어떤 일이 벌어지는지 직접 봅니다.
자료를 바꾸는 세 문장
지금까지는 읽기만 했습니다. 자료를 바꾸는 문장은 셋입니다.
| 문장 | 하는 일 |
|---|---|
| INSERT | 행을 넣습니다 |
| UPDATE | 이미 있는 행의 값을 고칩니다 |
| DELETE | 행을 지웁니다 |
셋 다 되돌리는 단추가 없습니다. 잘못 실행하면 그대로 반영됩니다. 그래서 이 단원은 실습 데이터를 건드리지 않고 dbo.NOTE 라는 연습 테이블을 따로 만들어 사용하고, 마지막에 지웁니다.
USE MssqlLab; CREATE TABLE dbo.NOTE ( num INT IDENTITY(1, 1) NOT NULL, title NVARCHAR(100) NOT NULL, writer NVARCHAR(30) NOT NULL, hit_count INT NOT NULL DEFAULT 0, reg_date DATETIME2(0) NOT NULL, CONSTRAINT PK_NOTE PRIMARY KEY (num) );
행 넣기 — INSERT
열 이름을 적고 그 차례대로 값을 넣습니다. 적지 않은 열은 기본값이 들어갑니다 —
hit_count 는 DEFAULT 0 이라
0 이 되고, num 은 IDENTITY 라
자동으로 매겨집니다.
INSERT INTO dbo.NOTE (title, writer, reg_date) VALUES (N'첫 글', N'홍길동', '2026-01-01 09:00:00'); SELECT num, title, writer, hit_count FROM dbo.NOTE ORDER BY num;
| num | title | writer | hit_count |
|---|---|---|---|
| 1 | 첫 글 | 홍길동 | 0 |
열 이름을 생략하지 마십시오.
INSERT INTO dbo.NOTE VALUES (…) 처럼 적으면 테이블의 열
차례에 기대게 되어, 나중에 열이 늘거나 자리가 바뀌면 엉뚱한 값이 들어갑니다.
여러 행을 한 번에
괄호를 쉼표로 이으면 한 문장으로 여러 행이 들어갑니다.
INSERT INTO dbo.NOTE (title, writer, hit_count, reg_date) VALUES (N'둘째 글', N'김철수', 10, '2026-01-02 09:00:00'), (N'셋째 글', N'이영희', 20, '2026-01-03 09:00:00');
| num | title | writer | hit_count |
|---|---|---|---|
| 1 | 첫 글 | 홍길동 | 0 |
| 2 | 둘째 글 | 김철수 | 10 |
| 3 | 셋째 글 | 이영희 | 20 |
행마다 INSERT 를 부르는 것보다 빠릅니다. 한 번의 왕복으로
끝나기 때문입니다.
조회 결과를 그대로 넣기
VALUES 자리에 SELECT 를 두면
조회한 것이 그대로 들어갑니다. 자료를 옮기거나 복사할 때 사용합니다.
INSERT INTO dbo.NOTE (title, writer, hit_count, reg_date) SELECT TOP 3 title, N'옮겨옴', hit_count, reg_date FROM Board.POSTS WHERE board_num = 1 ORDER BY num;
| num | title | writer | hit_count |
|---|---|---|---|
| 1 | 첫 글 | 홍길동 | 0 |
| 2 | 둘째 글 | 김철수 | 10 |
| 3 | 셋째 글 | 이영희 | 20 |
| 4 | 제약 조건 질문드립니다 | 옮겨옴 | 70 |
| 5 | 인덱스 정리해 봤습니다 | 옮겨옴 | 140 |
| 6 | 제약 조건 정리해 봤습니다 | 옮겨옴 | 210 |
SELECT 에 적은 차례와 INSERT INTO 의
열 차례가 서로 맞아야 합니다. 이름이 아니라 자리로 맞춥니다.
값 고치기 — UPDATE
SET 에 고칠 열과 값을 적고,
WHERE 로 어느 행인지 좁힙니다. 지금 값을 바탕으로 셈할
수도 있습니다.
OUTPUT 을 붙이면 무엇이 어떻게 바뀌었는지
돌려받습니다. 고치기 전 값은 deleted, 고친 뒤 값은
inserted 로 부릅니다.
UPDATE dbo.NOTE SET hit_count = hit_count + 100 OUTPUT deleted.num, deleted.hit_count AS 이전, inserted.hit_count AS 이후 WHERE num <= 2;
| num | 이전 | 이후 |
|---|---|---|
| 1 | 0 | 100 |
| 2 | 10 | 110 |
조회수를 올리거나 상태를 바꾸는 일이 실제로 몇 건에 걸렸는지 확인할 때 유용합니다. 기록을 남겨야 하는 자리에서도 사용합니다 — 바뀐 값을 이력 테이블에 그대로 넣을 수 있습니다.
행 지우기 — DELETE
DELETE 도 OUTPUT 을 받습니다.
무엇이 사라졌는지 확인할 수 있습니다.
DELETE FROM dbo.NOTE OUTPUT deleted.num, deleted.title WHERE hit_count < 50;
| num | title |
|---|---|
| 3 | 셋째 글 |
앞에서 1·2번의 조회수를 100 이상으로 올렸으므로 20 이었던 3번만 지워졌습니다.
WHERE 를 빠뜨리면 전부 바뀝니다
이것이 이 단원에서 가장 중요한 이야기입니다.
UPDATE 와 DELETE 는
WHERE 가 없어도 오류를 내지 않습니다.
테이블에 있는 모든 행에 적용될 뿐입니다.
-- WHERE 가 없습니다. 연습 테이블이라 벌여 보는 것입니다. UPDATE dbo.NOTE SET writer = N'누구세요'; SELECT num, title, writer FROM dbo.NOTE ORDER BY num;
| num | title | writer |
|---|---|---|
| 1 | 첫 글 | 누구세요 |
| 2 | 둘째 글 | 누구세요 |
| 4 | 제약 조건 질문드립니다 | 누구세요 |
| 5 | 인덱스 정리해 봤습니다 | 누구세요 |
| 6 | 제약 조건 정리해 봤습니다 | 누구세요 |
다섯 행의 글쓴이가 모두 바뀌었습니다. 원래 누가 작성했는지는 이제 알 수 없습니다. 운영 중인 테이블에서 이 일이 벌어지면 백업으로 되돌리는 것 말고는 방법이 없습니다.
그래서 이렇게 합니다
-
먼저
SELECT로 확인합니다. 고칠 조건을 그대로 넣어 조회해 보고, 나온 행이 뜻한 것과 같은지 본 뒤에SELECT …를UPDATE …로 바꿉니다. - 키로 좁힙니다. 되도록 기본 키를 조건에 넣으십시오. 조건이 틀려도 번호 하나만 잘못 바뀝니다.
- 트랜잭션으로 감쌉니다. 확인하고 되돌릴 수 있습니다. 4.6 에서 다룹니다.
-- 1) 먼저 이렇게 보고 SELECT * FROM dbo.NOTE WHERE num <= 2; -- 2) 나온 행이 맞으면 앞부분만 바꿉니다 UPDATE dbo.NOTE SET writer = N'홍길동' WHERE num <= 2;
비우는 방법 둘 — DELETE 와 TRUNCATE
테이블을 통째로 비울 때는 TRUNCATE TABLE 이 훨씬 빠릅니다.
그런데 번호를 매기는 방식이 다릅니다.
-- DELETE 로 지운 뒤 새 행을 넣으면 DELETE FROM dbo.NOTE WHERE num >= 4; INSERT INTO dbo.NOTE (title, writer, reg_date) VALUES (N'DELETE 뒤에 넣은 글', N'박민수', '2026-01-04 09:00:00'); SELECT num, title FROM dbo.NOTE ORDER BY num;
| num | title |
|---|---|
| 1 | 첫 글 |
| 2 | 둘째 글 |
| 3 | 셋째 글 |
| 7 | DELETE 뒤에 넣은 글 |
4 가 아니라 7 입니다. IDENTITY 는 한 번
사용한 번호를 되돌려 주지 않습니다. 지워진 자리를 다시 채우지 않으므로 번호에 구멍이
생기는 것은 정상입니다.
-- TRUNCATE 로 비운 뒤 넣으면 TRUNCATE TABLE dbo.NOTE; INSERT INTO dbo.NOTE (title, writer, reg_date) VALUES (N'TRUNCATE 뒤에 넣은 글', N'최지우', '2026-01-05 09:00:00'); SELECT num, title FROM dbo.NOTE ORDER BY num;
| num | title |
|---|---|
| 1 | TRUNCATE 뒤에 넣은 글 |
번호가 1 로 돌아갔습니다. 둘의 차이를 정리하면 이렇습니다.
| 항목 | DELETE | TRUNCATE |
|---|---|---|
| 조건 | WHERE 로 고를 수 있습니다 | 없습니다. 전부 비웁니다 |
| IDENTITY | 이어서 매깁니다 | 1 부터 다시 |
| 속도 | 행마다 기록을 남깁니다 | 훨씬 빠릅니다 |
| OUTPUT | 받을 수 있습니다 | 받을 수 없습니다 |
| 외래 키 | 가리키는 행이 없으면 지워집니다 | 가리키는 테이블이 있으면 막힙니다 |
연습이 끝났으니 지웁니다 — DROP TABLE dbo.NOTE;
직접 해보기
연습 테이블을 하나 만들어 두 행을 넣고, 그중 하나의 값을 고친 뒤, 다른 하나를 지워 보세요. 고칠 때와 지울 때 OUTPUT 으로 무엇이 바뀌었는지 확인하십시오.
"질문답변 게시판에서 조회수가 400 이상인 글의 조회수를 0 으로 되돌린다" 를 실행하기 전에, 몇 건이 걸리는지 먼저 확인하는 문장을 적어 보세요. 실행은 하지 마십시오.
INSERT는 열 이름을 반드시 적습니다. 자리에 기대면 열이 바뀔 때 어긋납니다.VALUES자리에SELECT를 두면 조회 결과가 그대로 들어갑니다.OUTPUT으로 바뀌기 전(deleted)과 뒤(inserted) 를 돌려받습니다.WHERE가 없으면 테이블 전체에 적용됩니다. 오류가 나지 않습니다.- 고치기 전에 같은 조건으로
SELECT해 보십시오. 조건은 그대로 두고 앞부분만 바꿉니다. TRUNCATE는 빠르지만 조건을 줄 수 없고 IDENTITY 가 1 로 돌아갑니다.