Belajar SQL Dasar: CREATE, INSERT, SELECT, JOIN, dan GROUP BY dengan Contoh Database Perpustakaan
Tulisan ini melanjutkan catatan ERD perpustakaan dan normalisasi. Setelah tabel dirancang, saatnya mengisi dan mengambil data dengan SQL (Structured Query Language). Contoh di sini bisa dijalankan di MySQL/MariaDB (misalnya lewat XAMPP), dan sebagian besar juga berjalan di PostgreSQL maupun SQLite.

Foto: StockSnap (CC0)
Jenis perintah SQL
| Kelompok | Perintah | Fungsi |
|---|---|---|
| DDL (Data Definition Language) | CREATE, ALTER, DROP | Membuat dan mengubah struktur tabel |
| DML (Data Manipulation Language) | INSERT, UPDATE, DELETE | Mengubah isi data |
| DQL (Data Query Language) | SELECT | Mengambil data |
| DCL (Data Control Language) | GRANT, REVOKE | Mengatur hak akses |
1. Membuat tabel (CREATE TABLE)
CREATE TABLE anggota ( id_anggota INT PRIMARY KEY AUTO_INCREMENT, nama VARCHAR(100) NOT NULL, kota VARCHAR(50), tgl_daftar DATE NOT NULL ); CREATE TABLE buku ( id_buku INT PRIMARY KEY AUTO_INCREMENT, judul VARCHAR(200) NOT NULL, penerbit VARCHAR(100), tahun_terbit YEAR, stok INT DEFAULT 1 ); CREATE TABLE peminjaman ( id_pinjam INT PRIMARY KEY AUTO_INCREMENT, id_anggota INT NOT NULL, id_buku INT NOT NULL, tgl_pinjam DATE NOT NULL, tgl_kembali DATE NULL, FOREIGN KEY (id_anggota) REFERENCES anggota(id_anggota), FOREIGN KEY (id_buku) REFERENCES buku(id_buku) );
Struktur ini sengaja disederhanakan (satu peminjaman = satu buku) supaya contoh query mudah diikuti. Versi lengkapnya dengan tabel detail ada di tulisan ERD.
2. Mengisi data (INSERT)
INSERT INTO anggota (nama, kota, tgl_daftar) VALUES
('Rina', 'Sukabumi', '2026-01-10'),
('Dedi', 'Cianjur', '2026-02-03'),
('Asep', 'Sukabumi', '2026-03-15');
INSERT INTO buku (judul, penerbit, tahun_terbit, stok) VALUES
('Dasar-Dasar Basis Data', 'Informatika', 2019, 3),
('Algoritma dan Pemrograman', 'Andi', 2020, 2),
('Statistika Dasar', 'Erlangga', 2018, 1);
INSERT INTO peminjaman (id_anggota, id_buku, tgl_pinjam, tgl_kembali) VALUES
(1, 1, '2026-09-01', '2026-09-07'),
(1, 3, '2026-09-20', NULL),
(2, 2, '2026-09-25', NULL);
3. Mengambil data (SELECT)
-- semua kolom SELECT * FROM anggota; -- kolom tertentu dengan syarat SELECT nama, kota FROM anggota WHERE kota = 'Sukabumi'; -- urutkan dan batasi SELECT judul, tahun_terbit FROM buku ORDER BY tahun_terbit DESC LIMIT 2; -- pencarian sebagian teks SELECT judul FROM buku WHERE judul LIKE '%Dasar%';
Hasil query kedua:
| nama | kota |
|---|---|
| Rina | Sukabumi |
| Asep | Sukabumi |
4. Mengubah dan menghapus (UPDATE, DELETE)
-- Dedi mengembalikan buku hari ini UPDATE peminjaman SET tgl_kembali = '2026-10-08' WHERE id_pinjam = 3; -- hapus anggota tertentu DELETE FROM anggota WHERE id_anggota = 3;
Hati-hati: UPDATE atau DELETE tanpa WHERE akan mengubah atau menghapus semua baris di tabel. Biasakan menjalankan SELECT dengan WHERE yang sama terlebih dahulu untuk melihat baris mana yang akan terkena.
5. Menggabungkan tabel (JOIN)
Inilah gunanya normalisasi: data dipecah ke beberapa tabel, lalu digabungkan kembali saat dibutuhkan.
-- siapa meminjam buku apa SELECT a.nama, b.judul, p.tgl_pinjam, p.tgl_kembali FROM peminjaman p JOIN anggota a ON a.id_anggota = p.id_anggota JOIN buku b ON b.id_buku = p.id_buku;
| nama | judul | tgl_pinjam | tgl_kembali |
|---|---|---|---|
| Rina | Dasar-Dasar Basis Data | 2026-09-01 | 2026-09-07 |
| Rina | Statistika Dasar | 2026-09-20 | NULL |
| Dedi | Algoritma dan Pemrograman | 2026-09-25 | NULL |
(Hasil sebelum UPDATE dan DELETE di bagian 4 dijalankan.)
JOIN (atau INNER JOIN) hanya menampilkan baris yang punya pasangan di kedua tabel. Untuk menampilkan semua anggota, termasuk yang belum pernah meminjam, gunakan LEFT JOIN:
SELECT a.nama, COUNT(p.id_pinjam) AS jumlah_pinjam FROM anggota a LEFT JOIN peminjaman p ON p.id_anggota = a.id_anggota GROUP BY a.id_anggota, a.nama;
| nama | jumlah_pinjam |
|---|---|
| Rina | 2 |
| Dedi | 1 |
| Asep | 0 |
6. Fungsi agregat dan GROUP BY
-- jumlah buku yang belum dikembalikan SELECT COUNT(*) AS belum_kembali FROM peminjaman WHERE tgl_kembali IS NULL; -- jumlah anggota per kota SELECT kota, COUNT(*) AS jumlah FROM anggota GROUP BY kota; -- kota dengan lebih dari 1 anggota SELECT kota, COUNT(*) AS jumlah FROM anggota GROUP BY kota HAVING COUNT(*) > 1;
Perbedaan WHERE dan HAVING: WHERE menyaring baris sebelum dikelompokkan, sedangkan HAVING menyaring hasil setelah dikelompokkan. Perhatikan juga bahwa untuk memeriksa nilai kosong, gunakan IS NULL, bukan = NULL.
Urutan penulisan klausa SELECT
SELECT kolom FROM tabel JOIN tabel_lain ON ... WHERE syarat_baris GROUP BY kolom HAVING syarat_kelompok ORDER BY kolom LIMIT jumlah;
Hafalkan urutan ini, karena banyak error SQL di tugas kuliah berasal dari urutan klausa yang tertukar, misalnya WHERE ditulis setelah GROUP BY.