【SQL】比較演算子・論理演算子とNULL
比較演算子の記号
| 説明 | 記号 | 例 |
|---|---|---|
| 等しい | = |
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版 ゼロからはじめるデータベース操作』(翔泳社)