- ベストアンサー
MySQL 複数テーブルのフィールドにUPDATE
- MySQLのJOINを使用して複数のテーブルのフィールドを一括でUPDATEする方法について調べています。
- PHP内で個別にテーブルを更新する方法も考えられますが、一度のSQLクエリでdel_flagの値を一括で更新する方法があるか知りたいです。
- 調査した結果、特定のテーブルだけでなく、全てのテーブルの該当するフィールドを更新するには、LEFT JOINを使用したUPDATE文を作成する必要があります。具体的なクエリが欲しいです。
- みんなの回答 (5)
- 専門家の回答
質問者が選んだベストアンサー
>left joinでつなげるよりスマートで効率的なのはわかりましたが、 >速度的にはどうなんでしょうね? left joinによるオーバーヘッドを考慮すれば おそらく個別でやった方が早いでしょう。 蛇足ですが、どうも今回の案件について疑問があります。 AテーブルについてはIDがプライマリになっていると思いますが Bテーブル(やCテーブル)についてはどういう仕様なのでしょう? BテーブルでもIDがプライマリなら、いっそのこと同じテーブルで管理すれば よい案件かもしれません。 通常子テーブルというのはIDでつながっても親IDに対して複数のデータを 持つような場合有効ですが、1対1ならあえて分けている意味があるか微妙です。 また、別解ですが、Bテーブルにdel_flg自体をつけること自体に意味があるのでしょか ? Aテーブルの正規化につかっているならAテーブルのdel_flgで処理すればよいし 場合によってBテーブルを単独で検索するとしてもAテーブルをジョインすれば 簡単にdel_flgレベルのことはできそうな気がしますが?
その他の回答 (4)
- yambejp
- ベストアンサー率51% (3827/7415)
>BやCのテーブルに >該当するID(AテーブルのプライマリID)が無いテーブル状況だと、処理はエラーとなりますよね? やってみればわかりますが、エラーは出ません また、もしも複数のSQLを投げるのに抵抗があれば、プロシージャを用意するとか・・・ DROP PROCEDURE IF EXISTS SET_FLG; DELIMITER // CREATE PROCEDURE SET_FLG(IN in_id INT,IN num INT) BEGIN SET AUTOCOMMIT=0; START TRANSACTION; UPDATE `table_a` SET `del_flg`=num WHERE `id`=in_id; UPDATE `table_b` SET `del_flg`=num WHERE `id`=in_id; UPDATE `table_c` SET `del_flg`=num WHERE `id`=in_id; COMMIT; END // DELIMITER ; としておき CALL SET_FLG(2,1);
お礼
この度は、いろいろと有難うございました。 プロシージャについても勉強になりました。 とにかく、今回の疑問が解決しましたので、ご報告いたいします。 お世話になりました。 また、よろしくお願いいたします。
- yambejp
- ベストアンサー率51% (3827/7415)
>でも、UPDATEしたいテーブルが計8つ程ありまして、 >ずらっと8つ連呼するべきでしょうか? 8個のSQLを投げる方が、8個つないで8箇所修正するより 効率的だと思いますよ
お礼
なるほど、わかりました。 8回foreachで連呼します。 left joinでつなげるよりスマートで効率的なのはわかりましたが、 速度的にはどうなんでしょうね?
- yambejp
- ベストアンサー率51% (3827/7415)
提示されたものを単純にかくとこうなります update table_a as a left join table_b as b on a.id=b.id left join table_c as c on a.id=c.id set a.del_flg=1,b.del_flg=1,c.del_flg=1 where a.id=2 でも、これって update table_a set del_flg=1 where id=2; update table_b set del_flg=1 where id=2; update table_c set del_flg=1 where id=2; と書く方がましなような気がしますが?
補足
確かに下の方がいいよな気もします・・・。 でも、UPDATEしたいテーブルが計8つ程ありまして、 ずらっと8つ連呼するべきでしょうか?
- o_chi_chi
- ベストアンサー率45% (131/287)
希望する回答ではありませんが、トリガー機能を使えばよいのでは。
お礼
トリガーについて勉強します! 有難うございました。
お礼
詳しく有難うございます! なるほど! 少し本質が見えてきました。 AのIDはプライマリです。 B,Cテーブルは、言葉たらすでしたが、 じつは複数の同一IDを格納していまして、1対1ではない現状です。 yambejp様のおっしゃる通りでございます。 やはり、オーバーヘッドを考慮すると、 個別の方が早いのですね。 まだまだジョインすることについて慣れておらず、恐る恐る勉強しております。 また、もし 以下のようにLEFT JOIN したとして、 ---------------------------------------- update A left join B on A.id=B.id left join C on A.id=C.id set A.del_flag=1, B.del_flag=1, C.del_flag=1 where A.id=2 ---------------------------------------- BやCのテーブルに 該当するID(AテーブルのプライマリID)が無いテーブル状況だと、処理はエラーとなりますよね? その場合、今の設計的に大変困ったことになります。 なぜなら、十分にBやCにIDが存在しないことがある設計だからです。 この辺り、また自分でも試して研究しようと思いますが、 よろしれば回答下さいませ。 次に、 >また、別解ですが、Bテーブルにdel_flg自体をつけること自体 >に意味があるのでしょか? についてです。 これは私に知識と経験のないことを証明する、根本的な解決策であると 、とてもありがたいご指摘です。 各BやCテーブルは、Aテーブルと正規化されています。 ですので、ご指摘のように、 今ふと考えると、del_flagのフィールドを各テーブルに設置しなくてもいいのだと気づきました。 ただ、いま作っているものが、上記のような正しいコントロールがされないまま開発してしまっているので、今から取り込むのはかなり厄介なことになりそうです。 でも、このような方法で、各ページで使用するデーターを取り込んでいたらと思うと、本当にバカな作りかたをしていたと後悔しています。