【SQL】比較演算子・論理演算子とNULL

  • #SQL

比較演算子の記号

説明 記号 例
等しい = SELECT shohin_mei, shohin_bunrui FROM Shohin WHERE hanbai_tanka = 500;
等しくない <> SELECT shohin_mei, shohin_bunrui FROM Shohin WHERE hanbai_tanka <> 500;
〜以上 >= SELECT shohin_mei, shohin_bunrui, hanbai_tanka FROM Shohin WHERE hanbai_tanka >= 1000;
〜より大きい > SELECT shohin_mei, hanbai_tanka FROM Shohin WHERE hanbai_tanka > 1000;
〜以下 <= SELECT shohin_mei, hanbai_tanka FROM Shohin WHERE hanbai_tanka <= 1000;
〜より小さい/〜より前 < SELECT shohin_mei, shohin_bunrui, torokubi FROM Shohin WHERE torokubi < '2009-09-27';

文字列の比較は「辞書式順序」

INSERT INTO Chars VALUES('1');
INSERT INTO Chars VALUES('2');
INSERT INTO Chars VALUES('3');
INSERT INTO Chars VALUES('10');
INSERT INTO Chars VALUES('11');
INSERT INTO Chars VALUES('222');

/* 前提:chrは文字列型 */
SELECT chr FROM Chars WHERE chr > '2';

 chr
-----
 3
 222

 /*
 辞書式順序だとこの並び方になる
 1, 10, 11, 2, 222, 3
 */

NULLの行は比較演算子で拾えない

/* 前提:商品テーブル */
SELECT shohin_mei, shiire_tanka
FROM Shohin;

   shohin_mei   | shiire_tanka
----------------+--------------
 Tシャツ        |          500
 穴あけパンチ   |          320
 カッターシャツ |         2800
 包丁           |         2800
 圧力鍋         |         5000
 フォーク       |              -- NULL
 おろしがね     |          790
 ボールペン     |               -- NULL

shiire_tanka = 2800を探す

SELECT shohin_mei, shiire_tanka
FROM Shohin
WHERE shiire_tanka = 2800;

/* shiire_tanka = 2800 の商品が選択できた */
   shohin_mei   | shiire_tanka
----------------+--------------
 カッターシャツ |         2800
 包丁           |         2800

shiire_tanka <> 2800を探す

/* <>→「一致しない」という意味 */
SELECT shohin_mei, shiire_tanka
FROM Shohin
WHERE shiire_tanka <> 2800;

/* shiire_tanka <> 2800の商品が選択できた */
  shohin_mei  | shiire_tanka
--------------+--------------
 Tシャツ      |          500
 穴あけパンチ |          320
 圧力鍋       |         5000
 おろしがね   |          790

NULLの行が出てこない

/* 上記のどちらのSELECT文でも出てこない2行 */

   shohin_mei   | shiire_tanka
----------------+--------------
 フォーク       |              -- NULL
 ボールペン     |               -- NULL

NULLを使った条件指定ができない

=, <>ではNULLを使用できない

SELECT shohin_mei, shiire_tanka
FROM Shohin
WHERE shiire_tanka = NULL;

SELECT shohin_mei, shiire_tanka
FROM Shohin
WHERE shiire_tanka <> NULL;

/* なにも選択できない(0行) */
 shohin_mei | shiire_tanka
------------+--------------
(0 rows)

【解決策】IS NULL、IS NOT NULLを使う

SELECT shohin_mei, shiire_tanka
FROM Shohin
WHERE shiire_tanka IS NULL;

/* NULLの行が選択できる */
 shohin_mei | shiire_tanka
------------+--------------
 フォーク   |
 ボールペン |
SELECT shohin_mei, shiire_tanka
FROM Shohin
WHERE shiire_tanka IS NOT NULL;

/* NULL以外の6行が正しく選択できている */
   shohin_mei   | shiire_tanka
----------------+--------------
 Tシャツ        |          500
 穴あけパンチ   |          320
 カッターシャツ |         2800
 包丁           |         2800
 圧力鍋         |         5000
 おろしがね     |          790

論理演算子

NULLは真でも偽でもない、第三の値「不明(UNKNOWN)」になる

  • 通常の論理演算は2値論理(真偽)だが、SQLだけは3値論理(真偽不)と呼ばれている
  • 2値論理だと4通りで済んだのに、3値論理だと9通りになる NULLが存在すると条件判定が複雑になる

【参考】真理値表(NULL(不明)あり)

ANDの真理値表

A B A AND B
真 真 真
真 偽 偽
真 不明 不明
偽 真 偽
偽 偽 偽
偽 不明 偽 ← 注目
不明 真 不明
不明 偽 偽 ← 注目
不明 不明 不明

ORの真理値表

A B A OR B
真 真 真
真 偽 真
真 不明 真 ← 注目
偽 真 真
偽 偽 偽
偽 不明 不明
不明 真 真 ← 注目
不明 偽 不明
不明 不明 不明

【要注意】「NULLが混ざる=全部『不明』になる」は違う

  • 不明 AND 偽 → 偽になる
  • 不明 OR 真 → 真になる

NOT NULL制約

テーブル定義(CREATE TABLE)の際、必須項目には NOT NULL を入れる → なるべくNULLを扱わないようにすること


関連記事:【SQL】NOT・AND・ORの優先順位とNULL

参考書籍:ミック『SQL 第2版 ゼロからはじめるデータベース操作』(翔泳社)