From 656dfe1a98a1fd5f5c8cbfd359082753e51d9a94 Mon Sep 17 00:00:00 2001 From: Mass-min <18160222+mass-min@users.noreply.github.com> Date: Sun, 5 Sep 2021 12:18:05 +0800 Subject: [PATCH 1/2] =?UTF-8?q?Update=20Post=20=E2=80=9C2021-09-05--mysql-?= =?UTF-8?q?update-with-sub-query/index=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../index.md | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/content/posts/2021-09-05--mysql-update-with-sub-query/index.md b/content/posts/2021-09-05--mysql-update-with-sub-query/index.md index 5a90518..c287615 100644 --- a/content/posts/2021-09-05--mysql-update-with-sub-query/index.md +++ b/content/posts/2021-09-05--mysql-update-with-sub-query/index.md @@ -8,16 +8,20 @@ cover: Screen_Shot_2021-09-05.png author: hideyoshi --- # 【MySQL】サブクエリを使ったUPDATEを実行する + こんにちは。 [GAOGAO](https://gaogao.asia/) にてスタートアップスタジオのエンジニアをしております [@mass-min](https://twitter.com/masumi_sugae) と申します。 GAOGAO では秀吉と呼ばれています。どうぞよろしくお願いいたします。 +![【MySQL】サブクエリを使ったUPDATEを実行する](Screen_Shot_2021-09-05.png "【MySQL】サブクエリを使ったUPDATEを実行する") + ## 結論 + サブクエリで扱うテーブルは、 UPDATE 対象のテーブルとは別物扱いにする必要があります。 更新対象テーブルと同一のテーブルに対してサブクエリを書きたい場合は、サブクエリでの取得結果に対してエイリアスを貼るようにしましょう。 -前提 ---- +## 前提 + 下記のようなテーブル構成になっているものとします。 ![ER_image](er.png) @@ -46,8 +50,8 @@ mysql> SELECT * FROM posts; 3 rows in set (0.00 sec) ``` -サブクエリを用いた UPDATE の失敗 ---- +## サブクエリを用いた UPDATE の失敗 + `users` テーブルは `status` の default 値が `registered` で、1つでも記事を公開する(`published_at` が null でない `posts` を1つ以上持つ)と以降 `status` は `posted` になる運用をしています。 この UPDATE 処理を日次バッヂ処理で回すことを考えます。 @@ -108,8 +112,8 @@ mysql> UPDATE users ERROR 1093 (HY000): You can't specify target table 'users' for update in FROM clause ``` -エラー原因・解決方法 ---- +## エラー原因・解決方法 + 結論から言うと、以下のようにサブクエリ部分を書き換えることで解決できます。 ```sql @@ -131,7 +135,7 @@ WHERE MySQL では、同一テーブルの条件をサブクエリに入れることは出来ません。ドキュメントでも以下のように記述があります。 ->You cannot update a table and select directly from the same table in a subquery. You can work around this by using a multi-table update in which one of the tables is derived from the table that you actually wish to update, and referring to the derived table using an alias. +> You cannot update a table and select directly from the same table in a subquery. You can work around this by using a multi-table update in which one of the tables is derived from the table that you actually wish to update, and referring to the derived table using an alias. https://dev.mysql.com/doc/refman/5.6/en/update.html @@ -144,6 +148,7 @@ https://dev.mysql.com/doc/refman/5.6/en/update.html 各ステップの取得結果を確認してみましょう。 ### id 取得用 SQL + 以下では取得対象のレコードの組み合わせを INNER JOIN でそのまま全て取得していますが、このステップの時点で DISTINCT の宣言をしても良いです。 ```sql @@ -190,11 +195,11 @@ mysql> SELECT * FROM users; これでアップデートができるようになりました。 ## まとめ + サブクエリで扱うテーブルは、 UPDATE 対象のテーブルとは別物扱いにする必要があります。 更新対象テーブルと同一のテーブルに対してサブクエリを書きたい場合は、サブクエリでの取得結果に対してエイリアスを貼るようにしましょう。 - ## 最後に 弊社 GAOGAO は現在副業含めて40名以上のエンジニアの方が参画し、グローバル(シンガポール、バンコク、US、日本など)で20社以上お客様の開発のお手伝いをさせていただいております。 @@ -204,6 +209,6 @@ mysql> SELECT * FROM users; 世界中で「モノつくり」の連鎖を起こすことができる世界を実現するための仕組みを是非一緒に作っていきましょう! -参考URL ---- -https://qiita.com/Kohei-Sato-1221/items/d1cbdc1d3affcd9c3a9e +## 参考URL + +https://qiita.com/Kohei-Sato-1221/items/d1cbdc1d3affcd9c3a9e \ No newline at end of file From bae3e5ab53f7b28408ff72894f851649e1d4836f Mon Sep 17 00:00:00 2001 From: Mass-min <18160222+mass-min@users.noreply.github.com> Date: Sun, 5 Sep 2021 13:02:33 +0800 Subject: [PATCH 2/2] =?UTF-8?q?Update=20Post=20=E2=80=9C2021-09-05--mysql-?= =?UTF-8?q?update-with-sub-query/index=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- content/posts/2021-09-05--mysql-update-with-sub-query/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/content/posts/2021-09-05--mysql-update-with-sub-query/index.md b/content/posts/2021-09-05--mysql-update-with-sub-query/index.md index c287615..c646405 100644 --- a/content/posts/2021-09-05--mysql-update-with-sub-query/index.md +++ b/content/posts/2021-09-05--mysql-update-with-sub-query/index.md @@ -176,7 +176,7 @@ mysql> SELECT DISTINCT id FROM (SELECT users.id FROM users INNER JOIN posts ON u ### さらにサブクエリ化して UPDATE 文を実行 -``` +```sql mysql> UPDATE users SET status = 'posted' WHERE id IN (SELECT DISTINCT id FROM (SELECT users.id FROM users INNER JOIN posts ON users.id = posts.user_id WHERE posts.published_at IS NOT NULL) AS tmp_table); Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0