> ## Documentation Index
> Fetch the complete documentation index at: https://villagesql.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# MySQL INSERT

> MySQL INSERT 문이 행을 어떻게 추가하는지, 생략한 열에 서버가 무엇을 넣는지, 그리고 첫 INSERT가 가장 자주 만나는 2가지 오류를 설명합니다.

> [card] [VillageSQL is a drop-in replacement for MySQL with extensions.](https://villagesql.com/docs/en/8.4/stable/install-server.md)
>
> All examples on this page work on VillageSQL. Install Now →

지금까지의 모든 수업은 데이터를 읽었습니다. `INSERT`는 데이터를 씁니다. 여기서부터는 문이 테이블의 내용을 바꾸므로, 튜토리얼의 나머지는 샘플 데이터가 아니라 별도의 데이터베이스에서 작업합니다.

## 연습용 데이터베이스

Sakila는 모든 읽기 수업이 설명하는 기준이므로, 그대로 두세요. 대신 그 옆에 작은 데이터베이스를 만들고, 처음부터 다시 시작하고 싶을 때마다 이것을 다시 실행하세요.

```sql theme={null}
DROP DATABASE IF EXISTS sakila_practice;
CREATE DATABASE sakila_practice;
USE sakila_practice;

CREATE TABLE member (
  member_id  INT UNSIGNED NOT NULL AUTO_INCREMENT,
  first_name VARCHAR(45) NOT NULL,
  last_name  VARCHAR(45) NOT NULL,
  email      VARCHAR(100) DEFAULT NULL,
  joined     DATE NOT NULL,
  active     TINYINT NOT NULL DEFAULT 1,
  PRIMARY KEY (member_id),
  UNIQUE KEY uq_member_email (email)
);

INSERT INTO member (first_name, last_name, email, joined, active) VALUES
  ('Mary',     'Smith',    'mary.smith@example.com',       '2026-01-04', 1),
  ('Patricia', 'Johnson',  'patricia.johnson@example.com', '2026-02-11', 1),
  ('Linda',    'Williams', 'linda.williams@example.com',   '2026-03-02', 0);

CREATE TABLE rating_count (
  rating VARCHAR(10) NOT NULL,
  films  INT UNSIGNED NOT NULL,
  PRIMARY KEY (rating)
);

CREATE TABLE account (
  account_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
  owner      VARCHAR(45) NOT NULL,
  balance    DECIMAL(10,2) NOT NULL,
  PRIMARY KEY (account_id)
);

INSERT INTO account (owner, balance) VALUES
  ('Mary Smith',       500.00),
  ('Patricia Johnson', 250.00);
```

이 섹션의 모든 수업은 그 상태에서 시작합니다. 시작하기 전에 `mysql -u root -p sakila_practice`로 클라이언트를 열고, 수업 사이에 이 블록을 다시 실행하세요.

## INSERT의 동작 방식

```sql theme={null}
INSERT INTO TABLE_NAME (COLUMN_LIST)
VALUES (VALUE_LIST);
```

`TABLE_NAME`을 쓰기 대상 테이블로, `COLUMN_LIST`를 값을 제공할 열로, `VALUE_LIST`를 그 열마다 1개씩의 값으로 같은 순서로 바꾸세요.

서버는 행을 추가하고 몇 개를 썼는지 보고합니다. 행을 돌려주지는 않으므로, 그 뒤의 `SELECT`가 결과를 보는 방법입니다.

## 예제

### 행 추가

```sql theme={null}
INSERT INTO member (first_name, last_name, email, joined)
VALUES ('Jennifer', 'Davis', 'jennifer.davis@example.com', '2026-03-18');
```

```text theme={null}
Query OK, 1 row affected (0.00 sec)
```

`Query OK`와 `1 row affected`가 보고의 전부입니다. 무엇이 들어갔는지 보려면 테이블을 요청하세요.

```sql theme={null}
SELECT * FROM member;
```

```text theme={null}
+-----------+------------+-----------+------------------------------+------------+--------+
| member_id | first_name | last_name | email                        | joined     | active |
+-----------+------------+-----------+------------------------------+------------+--------+
|         1 | Mary       | Smith     | mary.smith@example.com       | 2026-01-04 |      1 |
|         2 | Patricia   | Johnson   | patricia.johnson@example.com | 2026-02-11 |      1 |
|         3 | Linda      | Williams  | linda.williams@example.com   | 2026-03-02 |      0 |
|         4 | Jennifer   | Davis     | jennifer.davis@example.com   | 2026-03-18 |      1 |
+-----------+------------+-----------+------------------------------+------------+--------+
4 rows in set (0.00 sec)
```

문은 4개의 열을 지정했고 행에는 6개가 있습니다. `member_id`는 열이 `AUTO_INCREMENT`라서 스스로 수를 올렸고, `active`는 테이블이 선언한 `DEFAULT 1`을 받았습니다.

### 서버가 고른 id 읽어 오기

`AUTO_INCREMENT` 값은 삽입 중에 결정되므로, 그 값을 아는 유일한 방법은 물어보는 것입니다. 삽입을 한 같은 세션에서 물어보세요.

```sql theme={null}
INSERT INTO member (first_name, last_name, email, joined)
VALUES ('Barbara', 'Jones', 'barbara.jones@example.com', '2026-03-20');
SELECT LAST_INSERT_ID() AS new_id;
```

```text theme={null}
Query OK, 1 row affected (0.00 sec)

+--------+
| new_id |
+--------+
|      5 |
+--------+
1 row in set (0.00 sec)
```

`LAST_INSERT_ID()`는 내 연결에 대해서만 답하므로, 바쁜 서버가 다른 세션의 id를 건네줄 수 없습니다. 새 연결은 줄 답이 없어서 0을 반환합니다.

## ERROR 1062는 행이 이미 있다는 뜻입니다

`UNIQUE` 열은 이미 가진 값을 실은 두 번째 행을 거부합니다. 여기서는 `email`이 유일하고, Mary Smith의 주소는 이미 사용 중입니다.

```sql theme={null}
INSERT INTO member (first_name, last_name, email, joined)
VALUES ('Mary', 'Smith', 'mary.smith@example.com', '2026-05-01');
```

```text theme={null}
ERROR 1062 (23000): Duplicate entry 'mary.smith@example.com' for key 'member.uq_member_email'
```

메시지는 값과 그것을 거부한 인덱스를 지목하는데, 보통 그것으로 진짜 중복인지, 유일하게 만들려다 그러지 못한 열인지 구분하기에 충분합니다. [Upsert](https://villagesql.com/docs/ko/tutorial/upsert.md)는 이 상황을 예상하고 대신 기존 행을 갱신하는 문입니다.

## ERROR 1364는 필수 열이 빠졌다는 뜻입니다

`NOT NULL`이고 기본값이 없는 열을 생략하면, 서버는 쓸 것이 없습니다.

```sql theme={null}
INSERT INTO member (first_name) VALUES ('Sam');
```

```text theme={null}
ERROR 1364 (HY000): Field 'last_name' doesn't have a default value
```

한 번에 열 1개를 지목하므로, 3개가 빠진 문은 3번 시도해야 합니다. `DESCRIBE member;`로 테이블을 읽고, `Null` 아래 `NO`로 표시되고 기본값이 없는 것을 모두 제공하세요.

NULL을 허용하는 열은 다른 경우입니다. 생략하면 행에 NULL이 들어갑니다.

```sql theme={null}
INSERT INTO member (first_name, last_name, joined)
VALUES ('George', 'Miller', '2026-04-01');
```

```text theme={null}
Query OK, 1 row affected (0.00 sec)
```

## 중복 키도 id를 하나 소비합니다

지금 id를 요청하면 6이 빠져 있습니다.

```sql theme={null}
SELECT member_id, first_name, last_name, email, active FROM member;
```

```text theme={null}
+-----------+------------+-----------+------------------------------+--------+
| member_id | first_name | last_name | email                        | active |
+-----------+------------+-----------+------------------------------+--------+
|         1 | Mary       | Smith     | mary.smith@example.com       |      1 |
|         2 | Patricia   | Johnson   | patricia.johnson@example.com |      1 |
|         3 | Linda      | Williams  | linda.williams@example.com   |      0 |
|         4 | Jennifer   | Davis     | jennifer.davis@example.com   |      1 |
|         5 | Barbara    | Jones     | barbara.jones@example.com    |      1 |
|         7 | George     | Miller    | NULL                         |      1 |
+-----------+------------+-----------+------------------------------+--------+
6 rows in set (0.00 sec)
```

중복 키 시도는 실패하기 전에 6을 가져갔고, InnoDB는 번호를 돌려주지 않습니다. `ERROR 1364` 시도는 테이블에 닿기 전에 거부되었으므로 아무것도 가져가지 않았습니다. 이런 빈틈은 정상이고 아무것도 잃지 않았다는 뜻입니다. 이 열은 식별자로 다루고, 행의 개수로도, 번호가 끊김 없이 이어진다는 약속으로도 결코 다루지 마세요.

## 요약

* 행을 추가하려면 `INSERT INTO table (columns) VALUES (values)`를 쓰세요.
* 행 자체가 아니라 쓴 행의 수가 돌아옵니다.
* 기본값이나 `AUTO_INCREMENT`가 있는 열은 생략하고 서버가 채우게 하세요.
* `ERROR 1062`는 `UNIQUE` 열이 이미 가진 값이라는 뜻으로 읽으세요.
* `ERROR 1364`는 제공하지 않은 필수 열이라는 뜻으로 읽으세요.
* 중복 키 실패는 번호를 그대로 소비하므로, `AUTO_INCREMENT` 열에는 빈틈이 생깁니다.

## 함께 보기

* [여러 행 삽입](https://villagesql.com/docs/ko/tutorial/insert-multiple-rows.md) — 문 1개, 여러 행
* [INSERT SELECT](https://villagesql.com/docs/ko/tutorial/insert-select.md) — 직접 입력하는 대신 쿼리에서 가져온 행
* [Upsert](https://villagesql.com/docs/ko/tutorial/upsert.md) — 삽입하거나, 길을 막는 행을 갱신하기
* [UPDATE](https://villagesql.com/docs/ko/tutorial/update.md) — 이미 있는 행 바꾸기


This documentation is built and hosted on [Mintlify](https://mintlify.com), a developer documentation platform.