Pertanyaan paling sederhana dalam desain database sering berbentuk ya/tidak: apakah member masih aktif, apakah pesanan sudah dibayar, apakah artikel sudah dipublikasikan. MySQL tidak punya tipe boolean sungguhan seperti bahasa pemrograman — melainkan sebuah alias cerdas di atas tipe integer. Pada Chapter ini kita akan membuktikan lewat DESC bahwa BOOLEAN sebenarnya TINYINT(1), melihat bagaimana TRUE dan FALSE disimpan sebagai 1 dan 0, memakai kolom boolean langsung di SELECT dan IF(), lalu menutup dengan trik menghitung data ya/tidak dalam satu query.

BOOLEAN Adalah TINYINT(1) #

Saat kita menulis BOOLEAN (atau BOOL) pada definisi kolom, MySQL menerjemahkannya menjadi TINYINT(1) — bilangan bulat 1 byte. Kita buktikan langsung dengan tabel latihan:

sql
DROP DATABASE IF EXISTS belajar_tipe;
CREATE DATABASE belajar_tipe;
USE belajar_tipe;

Output yang Dihasilkan:

text
Query OK, 0 rows affected, 1 warning (0.00 sec)

Query OK, 1 row affected (0.00 sec)

Database changed
sql
CREATE TABLE anggota (
  id SMALLINT UNSIGNED,
  nama VARCHAR(40),
  aktif BOOLEAN,
  langganan BOOLEAN
);

DESC anggota;

Output yang Dihasilkan:

text
Query OK, 0 rows affected (0.00 sec)

+-----------+-------------------+------+-----+---------+-------+
| Field     | Type              | Null | Key | Default | Extra |
+-----------+-------------------+------+-----+---------+-------+
| id        | smallint unsigned | YES  |     | NULL    |       |
| nama      | varchar(40)       | YES  |     | NULL    |       |
| aktif     | tinyint(1)        | YES  |     | NULL    |       |
| langganan | tinyint(1)        | YES  |     | NULL    |       |
+-----------+-------------------+------+-----+---------+-------+
4 rows in set (0.00 sec)

Kolom Type pada hasil DESC menampilkan tinyint(1) untuk kedua kolom boolean — bukti bahwa BOOLEAN hanyalah nama lain. Angka (1) di situ adalah satu-satunya display width integer yang masih dipertahankan MySQL 8.4 karena sudah menjadi konvensi boolean sejak lama; pengecualian ini tidak berlaku untuk tipe integer lain seperti yang kita buktikan pada chapter INTEGER. Membaca TINYINT(1) pada skema orang lain artinya sama dengan BOOLEAN. Konvensi ini juga berlaku terbalik: kolom aktif milik aplikasi bisa kita isi dengan TRUE maupun 1 dan keduanya menghasilkan data yang sama.

TRUE dan FALSE Adalah 1 dan 0 #

MySQL mendefinisikan konstanta TRUE dan FALSE sebagai sinonim angka — bukan tipe data baru:

sql
SELECT TRUE AS nilai_true, FALSE AS nilai_false;

Output yang Dihasilkan:

text
+------------+-------------+
| nilai_true | nilai_false |
+------------+-------------+
|          1 |           0 |
+------------+-------------+
1 row in set (0.00 sec)

Nilai TRUE dikembalikan sebagai 1 dan FALSE sebagai 0; keduanya adalah angka biasa yang bisa dijumlah, dibandingkan, dan disimpan. Sekarang kita isi tabel anggota dengan campuran penulisan — sebagian memakai konstanta logika, sebagian angka:

sql
INSERT INTO anggota (id, nama, aktif, langganan) VALUES
  (1, 'Budi Santoso', TRUE, FALSE),
  (2, 'Siti Aminah', false, true),
  (3, 'Ayu Lestari', 1, 0),
  (4, 'Rudi Hartono', 0, 0);

SELECT id, nama, aktif, langganan FROM anggota ORDER BY id;

Output yang Dihasilkan:

text
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

+------+--------------+-------+-----------+
| id   | nama         | aktif | langganan |
+------+--------------+-------+-----------+
|    1 | Budi Santoso |     1 |         0 |
|    2 | Siti Aminah  |     0 |         1 |
|    3 | Ayu Lestari  |     1 |         0 |
|    4 | Rudi Hartono |     0 |         0 |
+------+--------------+-------+-----------+
4 rows in set (0.00 sec)

Keempat baris tersimpan mulus — TRUE dan 1 menghasilkan nilai identik, begitu pula false dan 0 (konstanta ini tidak peka huruf besar-kecil). Saat dibaca kembali, semua nilai tampil sebagai angka 1 dan 0 di kolom aktif dan langganan. Tidak ada format khusus “boolean” pada hasil query; aplikasi pembaca yang menafsirkan 1 sebagai benar dan 0 sebagai salah. Pola penyimpanan ini menjadikan data ya/tidak sangat murah: satu kolom hanya memakan 1 byte per baris.

Logika Lebih Luas dari TRUE dan FALSE #

MySQL menilai kebenaran dengan aturan yang lebih longgar dari sekadar TRUE/FALSE: setiap angka selain nol dianggap benar, nol dianggap salah, dan NULL dianggap bukan keduanya. Kita bisa mengujinya dengan fungsi IF(kondisi, nilai_benar, nilai_salah) yang mengembalikan nilai pertama bila kondisi benar dan nilai kedua bila salah:

sql
SELECT IF(5, 'benar', 'salah') AS angka_lima,
       IF(-3, 'benar', 'salah') AS angka_negatif,
       IF(0, 'benar', 'salah') AS angka_nol,
       IF(NULL, 'benar', 'salah') AS nilai_null;

Output yang Dihasilkan:

text
+------------+---------------+-----------+------------+
| angka_lima | angka_negatif | angka_nol | nilai_null |
+------------+---------------+-----------+------------+
| benar      | benar         | salah     | salah      |
+------------+---------------+-----------+------------+
1 row in set (0.00 sec)

Hasilnya memperlihatkan tiga tingkatan: 5 dan -3 sama-sama dianggap benar (tampil benar), 0 dianggap salah, dan NULL dianggap tidak benar sehingga cabang salah yang terpilih. Perilaku nilai nol-bukan-nol ini membuat kolom TINYINT(1) fleksibel — kode lama yang kebetulan menyimpan 2 tetap dibaca sebagai “aktif”. Fungsi IF() sendiri baru kita perkenalkan secara ringkas di sini karena bermanfaat untuk membaca kolom boolean; logika bersyarat lengkap (CASE, IFNULL, operator AND/OR) akan dibedah tuntas pada Section Fungsi SQL.

Kolom boolean juga bisa langsung dipakai sebagai kondisi. Perhatikan dua query berikut:

sql
SELECT nama FROM anggota WHERE aktif = TRUE ORDER BY id;

SELECT nama, IF(aktif, 'aktif', 'nonaktif') AS status
FROM anggota
ORDER BY id;

Output yang Dihasilkan:

text
+--------------+
| nama         |
+--------------+
| Budi Santoso |
| Ayu Lestari  |
+--------------+
2 rows in set (0.00 sec)

+--------------+----------+
| nama         | status   |
+--------------+----------+
| Budi Santoso | aktif    |
| Siti Aminah  | nonaktif |
| Ayu Lestari  | aktif    |
| Rudi Hartono | nonaktif |
+--------------+----------+
4 rows in set (0.00 sec)

Query pertama menyaring anggota dengan WHERE aktif = TRUE — pembanding = TRUE berperan sama dengan = 1. Query kedua memakai kolom aktif langsung sebagai kondisi IF() tanpa pembanding sama sekali, lalu menerjemahkannya menjadi teks yang enak dibaca manusia. Menulis WHERE aktif saja juga sah dan artinya sama; banyak programmer memilih bentuk singkat itu karena terbaca seperti kalimat: “anggota yang aktif”.

Trik Menghitung Data Ya/Tidak #

Nilai 1/0 membuka trik agregasi yang rapi: karena SUM() menjumlahkan angka, menjumlahkan kolom boolean langsung menghasilkan banyaknya nilai benar. Kombinasikan dengan COUNT(*) untuk mendapatkan gambaran lengkap dalam satu query:

sql
SELECT COUNT(*) AS total_anggota,
       SUM(aktif) AS anggota_aktif,
       SUM(langganan) AS anggota_berlangganan
FROM anggota;

Output yang Dihasilkan:

text
+---------------+---------------+----------------------+
| total_anggota | anggota_aktif | anggota_berlangganan |
+---------------+---------------+----------------------+
|             4 |             2 |                    1 |
+---------------+---------------+----------------------+
1 row in set (0.00 sec)

Dari empat anggota, hasilnya menunjukkan dua yang aktif dan satu yang berlangganan — persis seperti data yang kita isi. Trik SUM(kolom_boolean) ini menggantikan query COUNT(*) ... WHERE aktif = TRUE terpisah untuk setiap kombinasi, dan sangat berguna saat membutuhkan rekap banyak flag sekaligus dalam satu laporan. Karena nilainya angka, kolom boolean juga bisa diindeks, dijumlah, dan di-average seperti kolom TINYINT lainnya.

Terakhir, kita bereskan database latihan:

sql
DROP DATABASE belajar_tipe;

Output yang Dihasilkan:

text
Query OK, 1 row affected (0.00 sec)

Referensi #

Nilai ya/tidak kini tersimpan hemat dan bisa direkap dengan satu SUM. Bab berikutnya melangkah ke tipe modern yang menyimpan data semi-terstruktur: JSON — kolom yang memvalidasi formatnya sendiri dan menyimpannya dalam bentuk biner.