> ## 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 여러 행 삽입

> MySQL INSERT 문 1개가 여러 행을 어떻게 추가하는지, Records와 Duplicates 줄이 무엇을 보고하는지, 그리고 잘못된 행 1개가 왜 문 전체를 버리게 하는지 설명합니다.

> [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` 하나에 원하는 만큼 많은 행을 실을 수 있습니다. 각 행의 괄호를 쉼표로 구분하세요. 행마다 문 1개를 쓰는 것보다 타이핑이 적고, 서버를 여러 번이 아니라 1번만 오갑니다.

이 예제들은 [INSERT](https://villagesql.com/docs/ko/tutorial/insert.md)의 `sakila_practice` 데이터베이스를 사용합니다. 시작하기 전에 거기 있는 설정 블록을 다시 실행한 다음, `mysql -u root -p sakila_practice`로 클라이언트를 여세요.

## 여러 행 INSERT의 동작 방식

```sql theme={null}
INSERT INTO TABLE_NAME (COLUMN_LIST) VALUES
  (FIRST_ROW_VALUES),
  (SECOND_ROW_VALUES);
```

`TABLE_NAME`을 테이블로, `COLUMN_LIST`를 값을 제공할 열로, `FIRST_ROW_VALUES`와 `SECOND_ROW_VALUES` 각각을 그 열마다 1개씩의 값으로 바꾸세요.

열 목록은 한 번만 쓰고 모든 행을 지배합니다. 각 괄호 묶음은 그 순서대로 값을 제공합니다.

## 예제

### 문 1개에 행 3개

```sql theme={null}
INSERT INTO member (first_name, last_name, email, joined) VALUES
  ('Jennifer', 'Davis',  'jennifer.davis@example.com',  '2026-03-18'),
  ('Barbara',  'Jones',  'barbara.jones@example.com',   '2026-03-19'),
  ('Elizabeth','Brown',  'elizabeth.brown@example.com', '2026-03-21');
```

```text theme={null}
Query OK, 3 rows affected (0.00 sec)
Records: 3  Duplicates: 0  Warnings: 0
```

두 번째 줄은 문이 1개보다 많은 행을 쓸 수 있을 때마다 나타나는데, 여러 행 `VALUES` 목록과 모든 [INSERT SELECT](https://villagesql.com/docs/ko/tutorial/insert-select.md)가 여기에 해당합니다. `Records`는 보낸 행을, `Duplicates`는 이미 저장된 행과 충돌한 행을, `Warnings`는 서버가 조정해야 했던 것을 셉니다. 3개의 숫자가 모두 보낸 것과 일치하면 조용히 바뀐 것이 없다는 표시입니다.

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

```text theme={null}
+-----------+------------+-----------+
| member_id | first_name | last_name |
+-----------+------------+-----------+
|         1 | Mary       | Smith     |
|         2 | Patricia   | Johnson   |
|         3 | Linda      | Williams  |
|         4 | Jennifer   | Davis     |
|         5 | Barbara    | Jones     |
|         6 | Elizabeth  | Brown     |
+-----------+------------+-----------+
6 rows in set (0.00 sec)
```

id는 행을 쓴 순서대로 이어집니다.

## 잘못된 행 하나가 문 전체를 버립니다

아래 문은 3개의 행을 싣고 있습니다. 가운데 행은 Mary Smith의 주소를 다시 쓰는데, `email`의 `UNIQUE` 인덱스가 그것을 거부합니다.

```sql theme={null}
INSERT INTO member (first_name, last_name, email, joined) VALUES
  ('Maria',  'Miller', 'maria.miller@example.com', '2026-04-02'),
  ('Susan',  'Wilson', 'mary.smith@example.com',   '2026-04-03'),
  ('Margaret','Moore', 'margaret.moore@example.com','2026-04-04');
```

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

나머지 2개의 행도 들어가지 않았습니다.

```sql theme={null}
SELECT COUNT(*) AS members FROM member;
```

```text theme={null}
+---------+
| members |
+---------+
|       6 |
+---------+
1 row in set (0.00 sec)
```

문 하나는 전부 아니면 전무이므로, 잘못된 값 1개가 있는 10,000개 행의 배치는 아무것도 쓰지 않습니다. 전부 아니면 전무라는 것은 큰 배치는 보내기 전에 데이터를 검사해야 한다는 뜻이기도 한데, 서버는 문제가 되는 행 1개를 지목하고 멈추기 때문입니다.

## INSERT IGNORE는 오류를 경고로 바꿉니다

`INSERT IGNORE`는 넣을 수 있는 행은 넣고 나머지는 건너뜁니다.

```sql theme={null}
INSERT IGNORE INTO member (first_name, last_name, email, joined) VALUES
  ('Maria',  'Miller', 'maria.miller@example.com', '2026-04-02'),
  ('Susan',  'Wilson', 'mary.smith@example.com',   '2026-04-03');
SHOW WARNINGS;
```

```text theme={null}
Query OK, 1 row affected, 1 warning (0.00 sec)
Records: 2  Duplicates: 1  Warnings: 1

+---------+------+---------------------------------------------------------------------------+
| Level   | Code | Message                                                                   |
+---------+------+---------------------------------------------------------------------------+
| Warning | 1062 | Duplicate entry 'mary.smith@example.com' for key 'member.uq_member_email' |
+---------+------+---------------------------------------------------------------------------+
1 row in set (0.00 sec)
```

`Records: 2  Duplicates: 1`은 일어난 일을 정확히 보고합니다: 2개의 행을 제시했고, 1개가 거부되었습니다. 그다음 `SHOW WARNINGS`가 그것을 지목하고, 같은 `ERROR 1062` 텍스트가 실패가 아니라 경고로 도착합니다.

```sql theme={null}
SELECT COUNT(*) AS members FROM member;
```

```text theme={null}
+---------+
| members |
+---------+
|       7 |
+---------+
1 row in set (0.00 sec)
```

중복이 정말로 "이미 가지고 있다"는 뜻일 때 `IGNORE`를 사용하세요. 그 밖의 경우에는 무딘 도구인데, 열에 비해 너무 긴 값과 필수 열에 값이 없는 행을 포함해 다른 오류도 함께 격하시키기 때문입니다. 모든 `INSERT IGNORE` 뒤에 `SHOW WARNINGS`를 실행하세요. 그렇지 않으면 무엇을 버렸는지 알 수 없습니다. 올바른 답이 이미 저장된 행을 갱신하는 것이라면 대신 [upsert](https://villagesql.com/docs/ko/tutorial/upsert.md)를 사용하세요.

## 요약

* 각 행의 괄호를 쉼표로 구분하고, 열 목록은 한 번만 쓰세요.
* `Records`, `Duplicates`, `Warnings`를 읽어 조정된 것이 없음을 확인하세요.
* 거부된 행 1개가 문장 전체를 중단시켜 아무것도 쓰이지 않습니다.
* 좋은 행을 남기려면 `INSERT IGNORE`를 사용하고, 그 뒤에 `SHOW WARNINGS`를 읽으세요.
* 단일 행 문 여러 개보다 여러 행 문 1개를 쓰세요.

## 함께 보기

* [INSERT](https://villagesql.com/docs/ko/tutorial/insert.md) — 단일 행 형태와 그것이 내는 오류
* [INSERT SELECT](https://villagesql.com/docs/ko/tutorial/insert-select.md) — 쿼리에서 가져온 행
* [Upsert](https://villagesql.com/docs/ko/tutorial/upsert.md) — 건너뛰는 대신 기존 행 갱신
* [MySQL의 대량 삽입](https://villagesql.com/docs/ko/guides/bulk-inserts.md) — 배치 크기, LOAD DATA, 그리고 중요한 설정


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