> ## 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 の UPDATE

> MySQL の UPDATE 文がテーブルに既にある行を変更する仕組み、Rows matched と Changed がそれぞれ数えるもの、および WHERE を省いたときに起きること。

> [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 →

`UPDATE` は既にある行を変更します。どの行かは `WHERE` が決め、1 行とテーブル
全体を隔てているのは `WHERE` だけです。

これらの例は、[INSERT](https://villagesql.com/docs/ja/tutorial/insert.md) の `sakila_practice` データベースを
使います。始める前にそこにあるセットアップのブロックをもう一度実行し、次に
`mysql -u root -p sakila_practice` でクライアントを開いてください。

## UPDATE の仕組み

```sql theme={null}
UPDATE TABLE_NAME
SET COLUMN_NAME = NEW_VALUE
WHERE CONDITION;
```

`TABLE_NAME` をテーブルに、`COLUMN_NAME` を変更する列に、`NEW_VALUE` をそこに
入れる値に、`CONDITION` を行を選ぶテストに置き換えます。

`WHERE` は `SELECT` の場合とまったく同じように動作し、それが `UPDATE` を書く
最も安全な方法です。まず `SELECT` として実行し、行を確認し、それから
`SELECT ...` を `UPDATE ... SET ...` に変え、`WHERE` はそのままにします。

## 例

### 1 行を変更する

```sql theme={null}
UPDATE member SET active = 0 WHERE member_id = 2;
```

```text theme={null}
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
```

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

```text theme={null}
+-----------+------------+-----------+--------+
| member_id | first_name | last_name | active |
+-----------+------------+-----------+--------+
|         1 | Mary       | Smith     |      1 |
|         2 | Patricia   | Johnson   |      0 |
|         3 | Linda      | Williams  |      0 |
+-----------+------------+-----------+--------+
3 rows in set (0.00 sec)
```

### Matched と Changed は別のものを数える

同じ文をもう一度実行します。

```sql theme={null}
UPDATE member SET active = 0 WHERE member_id = 2;
```

```text theme={null}
Query OK, 0 rows affected (0.00 sec)
Rows matched: 1  Changed: 0  Warnings: 0
```

`WHERE` は依然としてその行を見つけたため、`Rows matched` は 1 です。行は既に
0 を保持していたため、何も書き込まれず、`Changed` は 0 です。2 つの数を
一緒に読んでください。`matched 0` は `WHERE` が何も見つけなかったという意味で、
`changed 0` とは別の問題です。`changed 0` は、行が既に持っている値を指定した
という意味です。

### 複数の列を一度に変更する

代入は `AND` ではなくカンマで区切ります。

```sql theme={null}
UPDATE member
SET last_name = 'Smith-Davis', email = 'mary.smith-davis@example.com'
WHERE member_id = 1;
```

```text theme={null}
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0
```

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

```text theme={null}
+-----------+------------+-------------+------------------------------+
| member_id | first_name | last_name   | email                        |
+-----------+------------+-------------+------------------------------+
|         1 | Mary       | Smith-Davis | mary.smith-davis@example.com |
+-----------+------------+-------------+------------------------------+
1 row in set (0.00 sec)
```

## UPDATE は INSERT と同じ制約を受ける

別の行が保持している値を `UNIQUE` 列に移すと、同じように失敗し、行は元の値を
保持します。

```sql theme={null}
UPDATE member SET email = 'patricia.johnson@example.com' WHERE member_id = 3;
```

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

## WHERE がないとすべての行が変わる

確認のステップはありません。文は実行され、テーブル内のすべての行が新しい値を
取ります。

セッションの設定でこの形を拒否させることができます。セーフアップデートモードは、
`WHERE` でキー列をテストせず、`LIMIT` も付けていない `UPDATE` または `DELETE` を
拒否します。このモードは、要求しない限りオフです。

```sql theme={null}
SET SESSION sql_safe_updates = 1;
UPDATE member SET active = 1;
```

```text theme={null}
Query OK, 0 rows affected (0.00 sec)

ERROR 1175 (HY000): You are using safe update mode and you tried to update a table without a WHERE that uses a KEY column.
```

最初の文からこの保護を得るには、`mysql -u root -p --safe-updates sakila_practice`
でクライアントを起動します。このフラグはこの 1 つの変数を設定する以上のことを
します。`sql_select_limit` によって `SELECT` を 1,000 行に制限し、`max_join_size`
によって結合を制限するため、大きなテーブルに対する読み取りは、何も言わずに
途中で打ち切られて返ってきます。`ERROR 1175` は、保護があなたを止めたという意味です。

文が本当にすべての行に触れることを意図しているときは、もう一度オフにします。

```sql theme={null}
SET SESSION sql_safe_updates = 0;
```

```text theme={null}
Query OK, 0 rows affected (0.00 sec)
```

保護をオフにすると、文は実行されます。

```sql theme={null}
UPDATE member SET active = 1;
```

```text theme={null}
Query OK, 2 rows affected (0.00 sec)
Rows matched: 3  Changed: 2  Warnings: 0
```

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

```text theme={null}
+-----------+------------+--------+
| member_id | first_name | active |
+-----------+------------+--------+
|         1 | Mary       |      1 |
|         2 | Patricia   |      1 |
|         3 | Linda      |      1 |
+-----------+------------+--------+
3 rows in set (0.00 sec)
```

`Rows matched: 3  Changed: 2` となるのは、1 人のメンバーが既にアクティブだった
ためです。

テーブル全体の更新がまさに正しいこともあります。すべての残高を 5% 上げるのは
1 つの文で、新しい値は古い値から計算されます。

```sql theme={null}
UPDATE account SET balance = balance * 1.05;
```

```text theme={null}
Query OK, 2 rows affected (0.00 sec)
Rows matched: 2  Changed: 2  Warnings: 0
```

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

```text theme={null}
+------------+------------------+---------+
| account_id | owner            | balance |
+------------+------------------+---------+
|          1 | Mary Smith       |  525.00 |
|          2 | Patricia Johnson |  262.50 |
+------------+------------------+---------+
2 rows in set (0.00 sec)
```

`balance = balance * 1.05` は各行の現在の値を読むため、すべての行がそれぞれ
自分の答えを得ます。

## まとめ

* 既存の行を変更するには `UPDATE table SET column = value WHERE condition` と書きます。
* まず `WHERE` を `SELECT` として実行し、それから文の先頭だけを変えます。
* `Rows matched` と `Changed` は 2 つの別々の事実として読みます。
* 複数の代入はカンマで区切ります。
* `UPDATE` は `INSERT` と同じ `UNIQUE` と `NOT NULL` の規則に当たると考えてください。
* セーフアップデートモードをオンにし、`ERROR 1175` は保護が仕事をしているものとして読みます。

## 関連項目

* [WHERE](https://villagesql.com/docs/ja/tutorial/where.md) — どの行が変わるかを決める句
* [DELETE](https://villagesql.com/docs/ja/tutorial/delete.md) — 行を変更するのではなく削除する
* [アップサート](https://villagesql.com/docs/ja/tutorial/upsert.md) — 既存の行を更新するか、なければ挿入する
* [トランザクション](https://villagesql.com/docs/ja/tutorial/transactions.md) — 誤った UPDATE の取り消し


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