Pemrograman · Bahasa pemrograman
Tutorial SQL untuk pemula
Jawaban singkat
SQL adalah bahasa standar untuk membuat, meng-query, dan mengubah data di database relasional seperti PostgreSQL, MySQL, dan SQLite. Anda menulis pernyataan deklaratif seperti SELECT, INSERT, UPDATE, dan DELETE, lalu database yang menentukan cara menjalankannya. Halaman ini mengajarkan desain tabel, filter, join, pengelompokan, subquery, window function, dan transaksi, serta menyajikan perbedaan utama antara PostgreSQL, MySQL, dan SQLite.
Apa itu SQL dan untuk apa digunakan
SQL (Structured Query Language) adalah bahasa standar untuk bekerja dengan database relasional, tempat data disimpan dalam tabel berisi baris dan kolom. Anda mendeskripsikan data yang diinginkan, dan engine database yang menentukan cara menemukannya. SQL distandarkan oleh ISO/IEC 9075, dan setiap database besar mengimplementasikan inti standar tersebut ditambah ekstensinya sendiri.
Developer, analis data, data engineer, dan administrator database memakai SQL setiap hari: untuk menyimpan data aplikasi, menjawab pertanyaan bisnis, membuat laporan, dan mengalirkan data ke pipeline. Engine open source yang paling umum adalah PostgreSQL, MySQL (dan fork-nya MariaDB), serta SQLite; yang komersial mencakup Microsoft SQL Server dan Oracle Database.
Siapkan database dan jalankan query pertama
Cara termudah untuk memulai adalah SQLite, database tanpa server yang disimpan dalam satu file. SQLite sudah terpasang di macOS dan sebagian besar sistem Linux. PostgreSQL dan MySQL berjalan sebagai server dan dilengkapi klien command line psql dan mysql.
sqlite3 shop.db # SQLite: opens or creates a file
psql -U postgres -d shop # PostgreSQL client
mysql -u root -p shop # MySQL clientSELECT 'Hello, world!' AS greeting;
-- greeting
-- Hello, world!Keyword SQL tidak peka huruf besar-kecil. Menulis keyword dengan huruf kapital dan nama dengan huruf kecil adalah konvensi umum yang membuat query lebih mudah dibaca. Pernyataan diakhiri titik koma, dan -- memulai komentar.
Membuat tabel: tipe data dan constraint
Definisi tabel mencantumkan kolom, tipenya, dan constraint yang menjaga data tetap valid. Halaman ini memakai dua tabel, customers dan orders, di setiap contoh.
CREATE TABLE customers (
id INTEGER PRIMARY KEY,
name VARCHAR(100) NOT NULL,
city VARCHAR(50)
);
CREATE TABLE orders (
id INTEGER PRIMARY KEY,
customer_id INTEGER NOT NULL REFERENCES customers(id),
amount DECIMAL(10, 2) NOT NULL,
ordered_on DATE NOT NULL
);
INSERT INTO customers (id, name, city) VALUES
(1, 'Ann', 'Oslo'), (2, 'Bo', 'Rome'), (3, 'Cy', 'Oslo');
INSERT INTO orders (id, customer_id, amount, ordered_on) VALUES
(1, 1, 30.00, '2026-01-05'),
(2, 1, 45.50, '2026-02-10'),
(3, 2, 12.00, '2026-02-11');| Tipe | Menyimpan | Catatan |
|---|---|---|
INTEGER, BIGINT | bilangan bulat | gunakan BIGINT untuk ID yang besar |
DECIMAL(p, s) | desimal eksak | gunakan untuk uang, jangan pernah FLOAT |
VARCHAR(n), TEXT | string | TEXT tidak ada di standar tetapi didukung secara luas |
DATE, TIMESTAMP | tanggal dan waktu | tulis literal sebagai '2026-01-05' |
BOOLEAN | true atau false | MySQL memperlakukannya sebagai TINYINT(1) |
Constraint mencakup PRIMARY KEY (pengenal baris yang unik), NOT NULL, UNIQUE, CHECK (condition), dan FOREIGN KEY / REFERENCES (nilai harus ada di tabel lain). String memakai tanda kutip tunggal; tanda kutip ganda untuk identifier dalam SQL standar.
SELECT: filter, urutkan, dan batasi
SELECT membaca data. WHERE memfilter baris, ORDER BY mengurutkannya, dan LIMIT (atau FETCH FIRST n ROWS ONLY yang standar) membatasi jumlah yang dikembalikan.
SELECT name, city
FROM customers
WHERE city = 'Oslo'
ORDER BY name;
-- Ann | Oslo
-- Cy | Oslo
SELECT id, amount,
CASE WHEN amount >= 40 THEN 'large'
WHEN amount >= 20 THEN 'medium'
ELSE 'small' END AS size
FROM orders
WHERE amount BETWEEN 10 AND 50
ORDER BY amount DESC
LIMIT 2;
-- 2 | 45.50 | large
-- 1 | 30.00 | medium
SELECT name FROM customers WHERE city IS NULL; -- not: city = NULL
SELECT name FROM customers WHERE name LIKE 'A%'; -- AnnJOIN: menggabungkan tabel
Join mencocokkan baris dari dua tabel memakai sebuah kondisi, biasanya foreign key. INNER JOIN (atau cukup JOIN) hanya mempertahankan baris yang cocok; LEFT JOIN mempertahankan setiap baris tabel kiri dan mengisi kolom yang kosong dengan NULL.
SELECT c.name, o.amount
FROM customers AS c
JOIN orders AS o ON o.customer_id = c.id
ORDER BY o.amount DESC;
-- Ann | 45.50
-- Ann | 30.00
-- Bo | 12.00
SELECT c.name, o.id AS order_id
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
WHERE o.id IS NULL; -- customers with no orders
-- Cy | NULL| Join | Hasil |
|---|---|
INNER JOIN | baris yang cocok di kedua tabel |
LEFT JOIN | semua baris kiri, ditambah yang cocok dari kanan atau NULL |
RIGHT JOIN | semua baris kanan, ditambah yang cocok dari kiri atau NULL |
FULL OUTER JOIN | semua baris dari kedua sisi; tidak didukung MySQL |
CROSS JOIN | setiap kombinasi baris (produk Cartesian) |
GROUP BY dan fungsi agregat
Fungsi agregat seperti COUNT, SUM, AVG, MIN, dan MAX meringkas banyak baris menjadi satu. GROUP BY membuat satu baris hasil per grup, dan HAVING memfilter grup setelah agregasi, sedangkan WHERE memfilter baris sebelum agregasi.
SELECT c.name,
COUNT(o.id) AS orders,
COALESCE(SUM(o.amount), 0) AS total
FROM customers AS c
LEFT JOIN orders AS o ON o.customer_id = c.id
GROUP BY c.id, c.name
ORDER BY total DESC;
-- Ann | 2 | 75.50
-- Bo | 1 | 12.00
-- Cy | 0 | 0
SELECT city, COUNT(*) AS n
FROM customers
GROUP BY city
HAVING COUNT(*) > 1;
-- Oslo | 2COUNT(*) menghitung baris, sedangkan COUNT(column) hanya menghitung nilai non-null, itulah sebabnya Cy mendapat 0 pesanan di atas. COALESCE mengembalikan argumen non-null pertamanya.
Subquery, CTE, dan window function
Subquery adalah query di dalam query lain. Common table expression (CTE), ditulis dengan WITH, memberi nama pada subquery dan membuat query panjang mudah dibaca. Window function seperti ROW_NUMBER, RANK, dan SUM(...) OVER menghitung nilai di seluruh baris terkait tanpa meruntuhkannya menjadi grup.
SELECT name FROM customers
WHERE id IN (SELECT customer_id FROM orders WHERE amount > 20);
-- Ann
WITH totals AS (
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
)
SELECT c.name, t.total,
RANK() OVER (ORDER BY t.total DESC) AS rnk
FROM totals AS t
JOIN customers AS c ON c.id = t.customer_id;
-- Ann | 75.50 | 1
-- Bo | 12.00 | 2CTE dan window function didukung oleh PostgreSQL, SQLite 3.25 ke atas, dan MySQL 8.0 ke atas.
Mengubah data: INSERT, UPDATE, DELETE, dan transaksi
UPDATE dan DELETE memengaruhi setiap baris yang cocok dengan klausa WHERE. Transaksi mengelompokkan beberapa pernyataan agar semuanya berhasil atau semuanya gagal bersama.
UPDATE customers SET city = 'Paris' WHERE id = 2;
DELETE FROM orders WHERE amount < 15;
BEGIN;
UPDATE orders SET amount = amount - 10 WHERE id = 1;
UPDATE orders SET amount = amount + 10 WHERE id = 2;
COMMIT; -- or ROLLBACK; to undo both
SELECT id, amount FROM orders;
-- 1 | 20.00
-- 2 | 55.50Perbedaan PostgreSQL, MySQL, dan SQLite
Inti SQL bersifat portabel, tetapi setiap engine berbeda dalam detail. Berikut perbedaan yang pertama kali ditemui pemula.
| Fitur | PostgreSQL | MySQL | SQLite |
|---|---|---|---|
| ID auto-increment | GENERATED ALWAYS AS IDENTITY atau SERIAL | AUTO_INCREMENT | INTEGER PRIMARY KEY |
| Penulisan nama dengan kutip | "name" | backtick di sekitar nama | "name" |
| Batasi jumlah baris | LIMIT n or FETCH FIRST n ROWS ONLY | LIMIT n | LIMIT n |
| Penggabungan string | a || b | CONCAT(a, b) | a || b |
| Boolean | tipe BOOLEAN asli | TINYINT(1) | disimpan sebagai 0 dan 1 |
| Pengetikan | ketat | ketat pada strict mode default | fleksibel, kecuali tabel dideklarasikan STRICT |
| Upsert | ON CONFLICT ... DO UPDATE | ON DUPLICATE KEY UPDATE | ON CONFLICT ... DO UPDATE |
Perbedaan lainnya mencakup fungsi tanggal (NOW() di PostgreSQL dan MySQL, datetime('now') di SQLite), sensitivitas huruf pada perbandingan string, dan dukungan full outer join, yang tidak dimiliki MySQL.
Kesalahan umum dan langkah selanjutnya
- Membangun query dengan menggabungkan input pengguna, yang membuka celah SQL injection. Selalu gunakan parameterized query (placeholder seperti
?atau$1) dari bahasa pemrograman Anda. - Memilih kolom dalam query ber-grup yang tidak ada di
GROUP BYmaupun di dalam fungsi agregat. - Memakai
FLOATuntuk uang alih-alihDECIMAL. - Lupa membuat index pada kolom yang dipakai di join dan filter;
CREATE INDEX idx_orders_customer ON orders(customer_id);danEXPLAINmembantu di sini. - Mengira baris dikembalikan dalam urutan tetap tanpa
ORDER BY.
Untuk belajar lebih lanjut, baca manual resmi: tutorial PostgreSQL, MySQL Reference Manual, dan SQLite SQL language reference. Berlatihlah pada dataset nyata dengan menulis pertanyaan dalam bahasa sehari-hari lalu mengubah tiap pertanyaan menjadi query.
FAQ
Apakah SQL bahasa pemrograman?
SQL adalah bahasa query deklaratif: Anda mendeskripsikan hasil yang diinginkan, bukan langkah-langkah menghitungnya. Ekstensi vendor seperti PL/pgSQL dan T-SQL menambahkan variabel, loop, dan prosedur.
Database apa yang sebaiknya dipakai pemula untuk memulai?
SQLite tidak membutuhkan server dan ideal untuk belajar. PostgreSQL adalah pilihan kuat untuk mempelajari SQL yang sesuai standar bagi aplikasi nyata, dan MySQL umum di web hosting.
Apa perbedaan WHERE dan HAVING?
WHERE memfilter baris individual sebelum pengelompokan, dan HAVING memfilter grup setelah fungsi agregat dihitung.
Apa perbedaan INNER JOIN dan LEFT JOIN?
INNER JOIN hanya mengembalikan baris yang punya pasangan di kedua tabel. LEFT JOIN mengembalikan setiap baris dari tabel kiri dan mengisi kolom tabel kanan dengan NULL bila tidak ada yang cocok.
Bagaimana cara mencegah SQL injection?
Jangan pernah memasukkan input pengguna ke dalam teks SQL. Gunakan parameterized query atau prepared statement, saat database menerima query dan nilainya secara terpisah.