0

mySQLの制御フロー関数で嵌まる

node.jsでmySQLを使ってると非同期コールバックだらけでselectしてupdateしてまたselectしてといったように処理が煩雑になりがちです。
joinを避けてクエリーを発行していくとなおさら。

そういった事を極力避ける為、制御フロー関数(IF)なんかを使い倒して一つのクエリで処理させる事が多いのですが、このIFの挙動で嵌まってしまった。

やりたい事は、member_idが0だったら、更新したばかりのupdated_idの値でmember_idで更新してやる。それ以外だったら99を入れる。

元々のデータはこんな感じ。
mysql> select updated_id, member_id from sample where id = 5;
+------------+----------------+
| updated_id | member_id |
+------------+----------------+
|      10      |           0         |
+------------+----------------+

下記のようなIFを使ったクエリでUPDATEしてみると、member_idに10が入ると思いきや77が入った。
mysql> UPDATE sample SET updated_id = 77, member_id = IF(member_id=0, updated_id, 99) WHERE id = 5;

mysql> select updated_id, member_id from sample where id = 5;
+------------+----------------+
| updated_id | member_id |
+------------+----------------+
| 77 | 77 |
+------------+----------------+

なんでもう77入ってるの?
updated_id = 77としてるものが先に更新されてるような結果になった。
されてるようなでなくて更新されてた。

クエリを少し変えて、updated_id = 77を後にもってきたら想定してた通りの動きになった。
mysql> UPDATE sample SET member_id = IF(member_id=0, updated_id, 99), updated_id = 77 WHERE id = 4;

mysql> select updated_id, member_id from sample where id = 4;
+------------+----------------+
| updated_id | member_id |
+------------+----------------+
| 77 | 10 |
+------------+----------------+

同じクエリを続けて発行すると、すでに77が入ってるupdated_idの値がmember_idに入った。これは当然だし納得。
mysql> UPDATE sample SET member_id = IF(member_id=0, updated_id, 99), updated_id = 77 WHERE id = 4;

mysql> select updated_id, member_id from sample where id = 4;
+------------+----------------+
| updated_id | member_id |
+------------+----------------+
| 77 | 77 |
+------------+----------------+

クエリが実行される前に、値が更新されてるというのが理解できなかったけど、そういうものらしい。
やはり内部の動きまで知らないとこういうところで無駄な時間を食ってしまう。
phpの挙動がおかしいなと思ったらcのコード追って原因を究明するくらいにならないとダメと言われた事があったけど、今回の一件で納得した。

大阪のWEB屋です。

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です