備忘録的プログラミングリファレンス

UPDATE クエリ

 UPDATE クエリは、すでに記録されたデータを更新するためのコマンドです。SQLの基本となるコマンドのひとつです。

 基本的には WHERE 句を使って特定の行データを更新するようにします。WHERE 句で行を指定しないとすべてのデータを更新してしまうので十分に注意してください。

UPDATE クエリ
UPDATE table_name SET name='example', kana='example' WHERE id='001';

 この例は、table_name というテーブルに記録されている id='001' に該当する行を更新します。
 更新する内容はカラム名 = 値で SET の後に続いて指定します。複数ある場合はカンマ,で区切ります。

 重要なデータを間違ってすべて更新しないように十分にテストを行いましょう。試用する前にバックアップデータを取っておくことも重要です。

 クエリとは、問い合わせを意味し、データベースではデータの検索( SELECT )、入力( INSERT )、更新( UPDATE )、削除( DELETE )といった命令をサーバーに送る行為を指します。
 クエリには、作成( CREATE )、変更( ALTER )、削除( DROP )も含みます。

構文(Syntax)

 UPDATE 文はデータベースに記録されたデータを更新する SQL 文です。
 通常は WHERE によって特定のデータを更新します。

UPDATE 文の簡単な例
	UPDATE table_name
		SET column_name_a = value_a, column_name_b = value_b
		WHERE id = 1;

 データベースによってその仕様は異なります。

MySQL

 MySQL での UPDATE 文は以下のような仕様になっています。

UPDATE [LOW_PRIORITY] [IGNORE] table_reference
    SET assignment_list
    [WHERE where_condition]
    [ORDER BY ...]
    [LIMIT row_count]

value:
    {expr | DEFAULT}

assignment:
    col_name = value

assignment_list:
    assignment [, assignment] ...
	

PostgreSQL

 PostgreSQL では以下のうような仕様になっています。

UPDATE [ ONLY ] table SET column = { expression | DEFAULT } [, ...]
    [ FROM fromlist ]
    [ WHERE condition ]
	

句について

 UPDATE 文はいくつかの句で構成されています。例えば以下のような句があります。

 はデータベースによって文節とも呼ばれます。Oracle では、MySQLやPostgreSQL ではと呼ばれることが多いようです。
 このサイトではと呼ぶようにしています。

UPDATE 句

 簡単な UPDATE 文は、以下のようなテーブル、カラムとその値を指定した SQL 文です。
 ただし、WHERE 句がないと全てのデータを更新してしまいますので十分に注意してください。

UPDATE table_name
		SET column_a = value_a, column_b = value_b, ...

 既にデータがある場合は十分注意してください。すべてのデータを更新してしまいます。データが戻せるように、ロールバックポイントを作成しておいた方がよいでしょう。

 例えば、以下のような sales_slip テーブルの 指定した id の date_time を現在の日時に変更するには以下のようにします。

MySQL UPDATE クエリ
UPDATE sales_slip
	SET date_time = now()
	WHERE id = 1;

Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

 上記は MySQL による結果です。PostgreSQL では以下のように表示されます。

PostgreSQL UPDATE クエリ
UPDATE 1

 UPDATE されているかを確かめるには SELECT クエリを実行します。

UPDATE の確認
SELECT * FROM sales_slip WHERE id = 1;

+----+---------------------+----------+------------+--------+
| id | date_time           | goods_id | unit_price | amount |
+----+---------------------+----------+------------+--------+
|  1 | 2023-10-02 08:00:15 |        1 |          3 |    100 |
+----+---------------------+----------+------------+--------+

 ここの例で主に使用しているデータはテーブルページの外部キー制約( FOREIGN KEY )の作成例です。

 以下のようなデータを使用しています。

SELECT * FROM goods;
+----+----------------+------------+
| id | name           | unit_price |
+----+----------------+------------+
|  1 | candy          |          3 |
|  2 | snack          |          5 |
|  3 | chocolate      |          8 |
|  4 | ice            |          8 |
|  5 | lollipop candy |         15 |
+----+----------------+------------+
...

select * from sales_slip;
+----+---------------------+----------+------------+--------+
| id | date_time           | goods_id | unit_price | amount |
+----+---------------------+----------+------------+--------+
|  1 | 2023-09-26 22:29:57 |        1 |          3 |    100 |
|  2 | 2023-09-26 22:29:58 |        2 |          8 |     50 |
|  3 | 2023-09-28 22:42:10 |        2 |          5 |     30 |
|  4 | 2023-09-28 22:42:10 |        1 |          5 |     80 |
|  5 | 2023-09-28 22:42:53 |        3 |         10 |     10 |
+----+---------------------+----------+------------+--------+
...

WHERE 句

 条件を指定した行データの抽出をする場合は WHERE 句を加えます。この WHERE 句によってテーブルデータから条件にあった行のみが対象になります。

 UPDATE 句では WHERE 句による行データの抽出を行わないとすべてのデータが更新の対象になります。
 既に保存されたデータを更新する際には特に注意が必要になるでしょう。
 特にテストでは、更新が失敗してもデータを復元できるようにバックアップポイントを取っておいたほうがよいでしょう。

MySQL UPDATE クエリ
UPDATE sales_slip
	SET date_time = now()
	WHERE id = 1;

 上記の例は id が 1 であるデータのみを更新しています。

 詳しくはWHERE 句ページを参照してください。

主キーに関するエラー

 主キーであるカラムの値を変更する際にエラーが発生します。主キーは各行をユニークなデータとする大切なデータです。
 主キーのデータは変更ができるのですが、不都合が多く出ます。一度設定したら変更することは好ましくありません。

 また、主キーに指定してある値は更新することができるのですが、その値が重複するとエラーが起きます。

ORDER BY 句

 UPORDER BY 句は MySQL で機能します。

 UPDATE における ORDER BY 句は並べ替えは複数行の更新である場合で、返り値は並び替えられたレコード id になります。

 ORDER BY 句はデフォルトで昇順で並び替えが行われます。DESC を指定することで降順に指定することができます。

LIMIT 句

 LIMIT 句は MySQL で機能します。

 UPDATE における LIMIT 句は、指定された行数のみを更新します。
 ORDER BY 句と使用することで昇順の最初から、または降順の最初からの指定数という使い方ができます。

FROM 句

 UPDATE 文における FROM 句はテーブルを結合して更新する場合に使用します。
 UPDATE 文でのテーブル結合には FROM 句と WHERE 句を組み合わせます。この WHERE 句には結合条件を設定します。

 ただし、UPDATE における FROM 句は現行の MySQL では利用することができません。

FROM 句による結合
UPDATE table_name
	SET columm_name = join_table.column_name
	FROM join_table
		WHERE table_name.column = join_table.column;

 FROM 句に結合するためのテーブル名を指定します。 WHERE 句には結合するための条件を設定します。 SET 以降は結合するテーブルのカラムの値や式などを指定します。

 例えば、以下のような sales_slip テーブルの値を、 goods テーブルの結合条件に該当する unit_price の値に更新します。

 以下は PostgreSQL での例になります。

SELECT * FROM sales_slip;

id |         date_time          | goods_id | unit_price | amount
----+----------------------------+----------+------------+--------
 2 | 2023-10-02 08:03:05.43961  |        2 |          8 |     50
 3 | 2023-10-02 08:03:05.440602 |        2 |          5 |     30
 4 | 2023-10-02 08:03:05.441188 |        1 |          5 |     80
 5 | 2023-10-02 08:03:05.442138 |        3 |         10 |     10
 1 | 2023-10-02 08:03:11.271113 |        1 |          3 |    100

 更新するための UPDATE クエリは以下のようにします。

FROM 句による結合
UPDATE sales_slip AS s
	SET unit_price = g.unit_price
	FROM goods AS g
		WHERE s.goods_id = g.id;

 UPDATE クエリを実行すると以下のようになります。

SELECT * FROM sales_slip;

id |         date_time          | goods_id | unit_price | amount
----+----------------------------+----------+------------+--------
 2 | 2023-10-02 08:03:05.43961  |        2 |          5 |     50
 3 | 2023-10-02 08:03:05.440602 |        2 |          5 |     30
 4 | 2023-10-02 08:03:05.441188 |        1 |          3 |     80
 5 | 2023-10-02 08:03:05.442138 |        3 |          8 |     10
 1 | 2023-10-02 08:03:11.271113 |        1 |          3 |    100

 PostgreSQL では SET の値を設定する場合に UPDATE で指定したテーブル名を付ける必要はありません。

選択条件を加える CASE 句

 CASE 句といった選択条件によって更新する値を変更することができます。

UPDATE table_name
SET table_name.name_title =
CASE table_name.gender
	WHEN 'M' THEN 'Mr.'
	WHEN 'F' THEN 'Ms.'
END;

ROLLBACK や COMMIT について

 INSERT や UPDATE、DELETE クエリといったデータの変更処理において複数のテーブルをまたいだ複数回の処理を行う際には途中でエラーが発生する可能性があります。
 1回のトランザクション中で複数回のデータ変更が伴う処理を行う場合は、ROLLBACK といった対処方法をとる必要があるかもしれません。

 通常は自動でデータの変更は COMMIT(保存)されます。1回のトランザクションで1回のデータ変更を行う場合はエラーが発生しにくいのですが、ファンクションやスクリプトにおいてはエラーに対処する必要があるかもしれません。

 詳しくは ROLLBACKCOMMIT ページを参照してください。