🐬
MySQL“TINYINT(1)=BOOLEAN”の罠──0/1制約で完全ガード
1️⃣ “BOOLEAN = 真偽値” は都市伝説? ― まずは素手で SQL 実験
ステップ0: 準備
# 作業用フォルダ(任意)
mkdir mysql-tinybool && cd mysql-tinybool
ステップ1: MySQL 8.3 コンテナを起動
docker run -d --name tinybool-test \
-e MYSQL_ROOT_PASSWORD=root \
-p 33060:3306 \
mysql:8.3
ステップ2: MySQL クライアントで接続
コンテナ内から直接 client を叩くと楽です。
docker exec -it tinybool-test mysql -uroot -proot
ステップ3: SQL を実行して “しれっと入る” を検証
コピー&ペーストで一気にどうぞ👇
-- 1. テスト用 DB とテーブル
CREATE DATABASE IF NOT EXISTS demo;
USE demo;
DROP TABLE IF EXISTS tiny_bool_raw;
CREATE TABLE tiny_bool_raw (
id INT AUTO_INCREMENT PRIMARY KEY,
flag TINYINT(1) NOT NULL -- いわゆる BOOLEAN
);
-- 2. 普通に 0 / 1 を入れてみる
INSERT INTO tiny_bool_raw(flag) VALUES (0), (1);
-- 3. あえて -128 や 127 を入れてみる
INSERT INTO tiny_bool_raw(flag) VALUES (-128), (127);
-- 4. 結果を確認
SELECT * FROM tiny_bool_raw;
実行結果 (例)
+----+------+
| id | flag |
+----+------+
| 1 | 0 |
| 2 | 1 |
| 3 | -128 | ← しれっと入る
| 4 | 127 | ← これも入る
+----+------+
😱 実は TINYINT(1)
は実質 -128~127 が入ってしまう。
BOOLEAN
型エイリアスでも 保存レイヤ では制限されません。
2️⃣ MySQL 8 の CHECK 制約 で 0 / 1 にロックする
ステップ1: 新しいテーブルを作成
-- 既存テーブルがあれば削除
DROP TABLE IF EXISTS tiny_bool_chk;
-- CHECK 制約付きテーブルを作成
CREATE TABLE tiny_bool_chk (
id INT AUTO_INCREMENT PRIMARY KEY,
flag TINYINT(1) NOT NULL,
CONSTRAINT chk_flag_bool CHECK (flag IN (0,1)) -- ★ここがポイント
);
-
CHECK (flag IN (0,1))
が “0 または 1 以外は拒否” というルール - MySQL 8.0.16 以降で正式サポート(それ以前は無視されるので要注意)
ステップ2: INSERT して動作確認
-- ✅ OK になるケース
INSERT INTO tiny_bool_chk(flag) VALUES (0), (1);
-- ❌ NG をわざと入れてみる
INSERT INTO tiny_bool_chk(flag) VALUES (2);
結果:
ERROR 3819 (HY000): Check constraint 'chk_flag_bool' is violated.
これで DB レイヤだけでも誤値をシャットアウト!
ステップ3: まとめ
やったこと | 効果 |
---|---|
CHECK (flag IN (0,1)) を付与 |
0/1 以外を SQL レベルで拒否 |
NG データの INSERT を検証 | 3819 エラーで弾かれることを確認 |
Discussion