🦑
SQLの三値論理の罠
はじめに
SQLユーザーのみなさんこんにちは。
みなさんはSQLの三値論理という用語を知っていますでしょうか?
SQLの入門書を読んだことがある方なら聞いたことがあるかもしれません。
SQLにおける三値論理とは、真(TRUE)・偽(FALSE)・不明(UNKNOWN)の3つの論理値を扱う論理体系のことです。
このUNKNOWNについて実務で知っておくべき知識を共有します。
実例
顧客(customer)テーブル
id | customer_name |
---|---|
1 | AAA株式会社 |
2 | 【見積済み】BBB株式 |
3 | NULL |
4 |
顧客テーブルには顧客名(customer_name)列が存在しますが、この列はNULLが許容となっています。
このテーブルに対して以下のような要件があるとします。
- 【見積済み】という文字列が含まれていないデータを取得したい。
この場合、真っ先に思いつくクエリは以下の通りだと思います。
SELECT
id
, customer_name
FROM
customer
WHERE
customer_name NOT LIKE '%【見積済み】%'
このとき取得されるのは
- AAA株式会社(マッチする)
- 【見積済み】BBB株式(除外される)
- NULL(除外される)
- ''(空文字)(マッチする)
NULLの値は取得されません!!
なぜNULLの値は取得されないのか?
ここで登場するのがSQLにおける三値論理のうちのひとつUNKNOWNです。
SQLではNULLは「不明な値(UNKNOWN)」 として扱われるため、
NULL NOT LIKE '%【見積済み】%' はTRUEでもFALSEでもなくUNKNOWNとなります。
そしてWHERE句ではTRUEのレコードだけが取得されるため、
NULLが入っているレコードは条件にマッチせず、除外されるという結果になるのです。
今回は【見積済み】という文字列が含まれていないデータを取得したいので、
以下のようにカラムの値がNULLの場合も取得できるように書き換えましょう。
SELECT
id
, customer_name
FROM
customer
WHERE
customer_name NOT LIKE '%【見積済み】%'
OR customer_name IS NULL
OR customer_name = '' -- この条件は無くても良いが、明示的に書いておくとクエリが読みやすくなる
まとめ
- SQLには「真(TRUE)」「偽(FALSE)」に加えて「不明(UNKNOWN)」という論理値が存在し、これを三値論理と呼ぶ。
- NULLは「値が不明」を意味し、比較演算(=, LIKE, NOT LIKEなど)を行うとUNKNOWNとなる。
- WHERE句ではTRUEのレコードだけが抽出対象になるため、UNKNOWNやFALSEのレコードは除外される。
- NULLを含めたい場合は、明示的にIS NULLを加える必要がある。
Discussion