プロが教えるわが家の防犯対策術!

よろしくお願いします。
PHP5、MySQL5、 PEAR DB、Smarty にて開発しております。

標題にもありますように、LEFT JOINを使ってUPDATEできる方法を探しております。

●Aテーブル(親)
id | del_flag
-----------------
1 | 0
2 | 0
3 | 0
4 | 0

●Bテーブル
id | del_flag
-----------------
1 | 0
3 | 0
4 | 0

●Cテーブル
id | del_flag
-----------------
1 | 0
2 | 0
3 | 0
4 | 0

上記のような3つ、またはもしくはそれ以上テーブルがあったとします。
そこで、
Aテーブルの id 2 のdel_flagを1 とアップデートしたときに、
同時に全てのB、Cのテーブルの id 2 のdel_flagも 1 としたく思います。

Bテーブルには、id 2 が存在しないため、結果的にはCテーブルだけが更新されますが、
A、B,Cともに同一のid値 がある場合も考慮して、
アップデートしたいと思います。

そこで、PHP内で、一つ一つのテーブルを地道にアップデートすることは可能だとおもいますが、

一度のSQLでdel_flagの値を1とできる方法はございませんでしょうか?
お手数ですが、
具体的なクエリを書いていただけると、大変助かります。
いろいろ調べましたが、なかなか上手くいかず・・・・。
よろしくお願いいいたします。

 

A 回答 (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レベルのことはできそうな気がしますが?
    • good
    • 0
この回答へのお礼

詳しく有難うございます!
なるほど! 少し本質が見えてきました。

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のフィールドを各テーブルに設置しなくてもいいのだと気づきました。

ただ、いま作っているものが、上記のような正しいコントロールがされないまま開発してしまっているので、今から取り込むのはかなり厄介なことになりそうです。
でも、このような方法で、各ページで使用するデーターを取り込んでいたらと思うと、本当にバカな作りかたをしていたと後悔しています。

お礼日時:2011/07/29 18:54

>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);
    • good
    • 0
この回答へのお礼

この度は、いろいろと有難うございました。
プロシージャについても勉強になりました。

とにかく、今回の疑問が解決しましたので、ご報告いたいします。
お世話になりました。
また、よろしくお願いいたします。

お礼日時:2011/08/01 11:20

>でも、UPDATEしたいテーブルが計8つ程ありまして、


>ずらっと8つ連呼するべきでしょうか?

8個のSQLを投げる方が、8個つないで8箇所修正するより
効率的だと思いますよ
    • good
    • 0
この回答へのお礼

なるほど、わかりました。
8回foreachで連呼します。

left joinでつなげるよりスマートで効率的なのはわかりましたが、
速度的にはどうなんでしょうね?

お礼日時:2011/07/29 17:21

提示されたものを単純にかくとこうなります



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つ連呼するべきでしょうか?

補足日時:2011/07/29 13:47
    • good
    • 0

希望する回答ではありませんが、トリガー機能を使えばよいのでは。

    • good
    • 0
この回答へのお礼

トリガーについて勉強します!
有難うございました。

お礼日時:2011/07/29 13:46

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!