데이터 바꾸기: INSERT, UPDATE, DELETE

INSERT, UPDATE, DELETE는 데이터를 실제로 바꿉니다. 각 문장의 기본 형태와 함께, 실행 전에 영향 범위를 확인하고 필요하면 되돌리는 방법을 다룹니다.

이 레슨은 데이터를 바꿉니다. 바꾸는 것은 여러분의 사본입니다. 샘플 데이터베이스는 브라우저 안에 로드되어 밖으로 나가지 않으므로, 여기 있는 것은 전부 마음 놓고 실행해도 되고 마음 놓고 틀려도 됩니다. 처음으로 되돌리려면 환영 화면에서 샘플을 다시 불러오면 됩니다.

INSERT

INSERT할 컬럼을 나열하고 각 컬럼에 값을 지정합니다. 생략한 컬럼에는 기본값이 들어갑니다. 이 예제에서 added_at의 기본값은 현재 시각입니다.

1

INSERT INTO wishlists (customer_id, product_id)
VALUES (1, 288);
Planche에서 실행

1행 변경

브라우저의 새 탭에서 Planche가 열리고, 샘플 데이터베이스가 로드된 채로 이 쿼리가 들어갑니다. 이 페이지의 다른 예제도 같은 탭을 다시 씁니다. F9를 누르기 전까지는 아무것도 실행되지 않습니다.

한 행이 추가되었습니다. 컬럼 이름을 명시하면 테이블에 새 컬럼이 추가돼도 쿼리가 컬럼 순서에 영향을 받지 않습니다.

데이터베이스가 거부하는 것

똑같은 문장을 한 번 더 실행해 보세요.

2

-- The same statement a second time. (customer_id, product_id) is the
-- primary key of wishlists, so the database refuses the duplicate.
INSERT INTO wishlists (customer_id, product_id)
VALUES (1, 288);
Planche에서 실행

오류

UNIQUE constraint failed: wishlists.customer_id, wishlists.product_id

오류가 나고 데이터는 바뀌지 않습니다. wishlists의 기본 키가 (customer_id, product_id)이므로 같은 쌍을 두 번 저장할 수 없기 때문입니다. 이런 제약은 잘못된 데이터가 저장되는 것을 막습니다.

UPDATE, 그리고 가장 중요한 절

3

UPDATE customers
SET loyalty_points = loyalty_points + 100
WHERE id = 1;
Planche에서 실행

1행 변경

변경 전에는 같은 FROM과 WHERE를 사용한 SELECT로 대상 행을 먼저 확인하세요.

두 번째는 Planche가 대신 해줍니다. 설정 › 안전장치 › 영향 행 미리보기를 켜면 UPDATE나 DELETE가 대응하는 SELECT로 다시 쓰여 개수와 함께 먼저 보여집니다. 읽기 전용 연결과 운영 연결에 색을 지정하는 기능도 같은 자리에 있습니다.

4

SELECT id, first_name, last_name, loyalty_points
FROM customers
WHERE id = 1;
Planche에서 실행

결과 — 1행

idfirst_namelast_nameloyalty_points
1LiamFischer3619

DELETE

5

DELETE FROM wishlists
WHERE customer_id = 1
  AND product_id = 288;
Planche에서 실행

1행 변경

서브쿼리로 대상 행 고르기

UPDATE와 DELETE의 WHERE는 평범한 WHERE입니다. 그래서 서브쿼리 레슨에서 배운 내용을 그대로 쓸 수 있습니다. 다른 테이블의 내용을 기준으로 이 테이블의 행을 바꾸는 방법이 이것입니다.

6

-- Which rows to change is its own question, and a subquery can answer it.
UPDATE customers
SET loyalty_points = loyalty_points + 50
WHERE id IN (
  SELECT customer_id
  FROM orders
  WHERE status = 'refunded'
    AND total > 2000
);
Planche에서 실행

242행 변경

2,000이 넘는 환불 주문을 가진 고객이 242명이고, 그 242행이 바뀌었습니다. 앞에서 말한 습관이 그대로 적용됩니다. 먼저 SELECT id FROM customers WHERE id IN (...)으로 돌려서 행 수를 세어 보세요. 실수는 대부분 그 서브쿼리에서 나옵니다.

7

DELETE FROM wishlists
WHERE product_id IN (
  SELECT id FROM products WHERE stock_quantity = 0
);
Planche에서 실행

260행 변경

EXISTS와 NOT EXISTS도 여기서 쓸 수 있고, 부정형에서는 서브쿼리 레슨에서 설명한 이유로 그쪽이 더 안전합니다. 반면 UPDATE나 DELETE 안에서 바로 조인하는 문법은 이식되지 않습니다. 엔진마다 표기가 다르고, 아예 못 하는 엔진도 하나 있습니다. 방언 비교 페이지에서 다섯 가지를 모두 다룹니다.

트랜잭션

트랜잭션은 여러 변경을 하나로 묶습니다. 모두 반영하거나 모두 취소할 수 있고, 커밋 전에는 결과를 확인한 뒤 되돌릴 수 있습니다.

8

BEGIN;

UPDATE coupons
SET used_count = used_count + 1
WHERE code = 'WELCOME10';

SELECT code, used_count FROM coupons WHERE code = 'WELCOME10';

ROLLBACK;
Planche에서 실행

결과 — 1행

codeused_count
WELCOME1063

BEGIN으로 트랜잭션을 시작하고, SELECT로 증가한 쿠폰 사용 횟수를 확인한 뒤 ROLLBACK으로 되돌립니다. ROLLBACK을 COMMIT으로 바꾸면 변경이 영구히 반영됩니다.

9

SELECT code, used_count FROM coupons WHERE code = 'WELCOME10';
Planche에서 실행

결과 — 1행

codeused_count
WELCOME1062

실제 데이터베이스에서 위험한 변경을 할 때는 트랜잭션을 열고, 문장을 실행한 뒤 영향 행 수를 확인하고 커밋하세요. Planche에서는 연결 › 수동 트랜잭션을 켜면 트랜잭션이 열린 상태로 유지됩니다. 툴바의 커밋·롤백으로 확정하거나 되돌릴 수 있습니다.

여기까지로 할 수 있는 것

다음 레슨에서는 실행 계획을 읽어 쿼리가 느린 이유와 인덱스가 쓰이는 조건을 확인합니다.

직접 해보기

  1. 재고가 없는 상품을 전부 판매 중지 상태로 바꾸세요. 실행하기 전에 몇 행이 바뀔지 먼저 확인해 보세요.

    정답 보기

    정답 보기

    UPDATE products
    SET is_active = 0
    WHERE stock_quantity = 0;
    Planche에서 실행

    40행 변경

    40행입니다. SELECT COUNT(*) FROM products WHERE stock_quantity = 0을 먼저 돌려보세요. 문장을 실행하기 전에 숫자를 알고 있으면, 예상과 다른 개수가 나왔을 때 그것이 발견이 아니라 경고가 됩니다.

  2. 이미 읽었고 2025년보다 오래된 알림을 지우세요.

    정답 보기

    정답 보기

    DELETE FROM notifications
    WHERE is_read = 1
      AND created_at < '2025-01-01';
    Planche에서 실행

    1202행 변경

    1,202행입니다. 두 조건 다 중요합니다. is_read = 1을 빼면 읽지 않은 알림까지 지워지고, 이건 DELETE라서 트랜잭션을 먼저 열지 않았다면 되돌릴 방법이 없습니다.