apache

2011年09月27日

MySQLにおけるnullの取り扱い

MySQLでデータを取り出す際にちょっとはまったので覚え書き。
前提:
担当者名を入れるフィールド「charge」があり、担当者名が入っているかnullかのどちらかです。
またアクセス者名を入れる変数$userがあり、これは必ずアクセス者名が入っています。

ここで、「自分が担当者でない」データを検索するとき

〜 and charge != '$user' and 〜

としたところ、chargeがnullのデータは一切ヒットしなくなりました。

Google先生によると出てきた解は、MySQLの比較は比較物がnullの時は必ず「偽」を返す、というものでした。(これも嘘というか私の解釈違いな訳ですが)

そこで次のように変更してみます。

〜 and not(charge = '$user') and 〜

偽のnotなのでこれでうまくいくと思いましたが、結果は先ほどと全く同じ。どうもnullの扱いがよくわかりません。

さらに調べていくと…、ありました。「nullセーフ」というんだそうです。
MySQLの比較演算子「=」はnullセーフではないとのこと。「=」に相当するnullセーフな比較演算子は「<=>」なんだそうです。

つまり私の期待した答えを得られる式は

〜 and not(charge <=> '$user') and 〜

ということです。

正確な仕様は、

  1. MySQLの真偽は「真=1」「偽=0」と考えるとわかりやすい。
  2. 通常の(nullセーフでない)比較演算子は、比較対象がnullの時必ず「null」を返す。(nullは「0」(つまり偽)ではない。)
  3. nullセーフな比較演算子「<=>」で期待する結果が得られる。

ということの様です。(参考資料:MySQL 6.3.1.2. 比較演算子)

まとめてみると

chargeの中身期待値charge != '$user'
not(charge = '$user')
not(charge <=> '$user')
アクセス者名
他のユーザ名
null

こんな感じでしょうか。

ここでいう「nullセーフな比較」という概念そのものを知らなかった(全ての比較演算子がnullセーフだと思っていた)ため、ここを疑うまでに結構かかりました。

思い込みって怖いですね。


静かで安くてコストパフォーマンス最高。
Linuxサーバに最適。



abm55608 at 12:50|PermalinkComments(0)TrackBack(0)