1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

RDBのBOOLEAN型の3値論理について

Last updated at Posted at 2021-07-24

記事の内容

リレーショナルデータベースのBOOLEAN型の3値論理について説明します。

説明

RDBのBOOLEAN型は、TRUE、FALSEに加えてNULLの状態にもなり得ます。
BOOLEAN型のNULLは、意味的には「TRUEかFALSEか分からない」なので、以下Unknownという値を導入します。
すなわち、RDBのBOOLEAN型はTRUE、FALSE、Unknownの3つの値を使った3値論理です。

今、customerテーブルに以下のデータが入っているとしましょう。
「三郎」の電話番号は不明なので、NULLにしてあります。


(customerテーブル)
 id    name      tel
-------------------------------
  1    '一郎'    '03-1111-1111'
  2    '次郎'    '03-2222-2222'
  3    '三郎'    NULL
  4    '史郎'    '03-4444-4444'

customerテーブルに対して、以下の SQL文を投げてやります。
検索結果はどうなるでしょうか?


SELECT *
FROM customer
WHERE tel != '03-1111-1111'

「三郎」の電話番号は、'03-1111-1111'かもしれないし、そうでないかもしれません。
従って、WHERE句の評価結果(3値論理)は以下のようになります。


 id    name      tel               WHERE句の評価結果
----------------------------------------------------
  1    '一郎'    '03-1111-1111'    FALSE
  2    '次郎'    '03-2222-2222'    TRUE
  3    '三郎'    NULL              Unknown
  4    '史郎'    '03-4444-4444'    TRUE

結果表に含まれるのは、WHERE句の評価結果がTRUEの行のみです。
従って上記のSQL文で検索されるのは、「次郎」と「史郎」の2件です

では、以下の SQL文ではどうでしょうか。


SELECT *
FROM customer
WHERE tel != '03-1111-1111'
   OR tel IS NULL

直感では「次郎」「三郎」「史郎」の3件が検索されそうです。
そして実際にそうなります。

では、このWHERE句が「三郎」の行に適用された場合について、厳密にみていきましょう。

「tel != '03-1111-1111'」の評価結果はUnknownです。
「tel IS NULL」の評価結果はTRUEです。
従って、三郎のデータでのWHERE句は「Unknown OR TRUE」となります。
ここから最終結果を得るのはやっかいですが、「UnknownをTRUEとFALSEで置き換える」という技があります。
その結果が両方TRUEであればTRUE、両方FALSEであればFALSE、それ以外はUnknownです。

実際に置き換えてみると、「TRUE OR TRUE」も「FALSE OR TRUE」もTRUEですから、両方TRUEということで最終結果はTRUEになり、「三郎」も検索されるということになります。


TRUE    AND Unknown → Unknown(TRUE AND TRUE → TRUE、TRUE AND FALSE → FALSE)

FALSE   AND Unknown → FALSE  (FALSE AND TRUE → FALSE、FALSE AND FALSE → FALSE。両方FALSE)

Unknown AND Unknown → Unknown

TRUE    OR  Unknown → TRUE   (TRUE OR TRUE → TRUE、TRUE OR FALSE → TRUE。両方TRUE)

FALSE   OR  Unknown → Unknown(FALSE OR TRUE → TRUE、FALSE OR FALSE → FALSE)

Unknown OR  Unknown → Unknown

NOT Unknown         → Unknown(NOT TRUE → FALSE、NOT FALSE → TRUE)

これらのことから得られる教訓があります。
それは、スキーマ定義の時「列はデフォルトでNOT NULL制約を付けよ」ということです。
NULLが絡むとSQL文が複雑になり、面倒です。
NULLを可にする理由がなければ、NOT NULL制約を付けるべきです。

1
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?