cv.cm

Pemrograman · Bahasa pemrograman

Tutorial SQL untuk pemula

7 menit baca

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 client
SELECT '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');
TipeMenyimpanCatatan
INTEGER, BIGINTbilangan bulatgunakan BIGINT untuk ID yang besar
DECIMAL(p, s)desimal eksakgunakan untuk uang, jangan pernah FLOAT
VARCHAR(n), TEXTstringTEXT tidak ada di standar tetapi didukung secara luas
DATE, TIMESTAMPtanggal dan waktutulis literal sebagai '2026-01-05'
BOOLEANtrue atau falseMySQL 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%'; -- Ann

JOIN: 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
JoinHasil
INNER JOINbaris yang cocok di kedua tabel
LEFT JOINsemua baris kiri, ditambah yang cocok dari kanan atau NULL
RIGHT JOINsemua baris kanan, ditambah yang cocok dari kiri atau NULL
FULL OUTER JOINsemua baris dari kedua sisi; tidak didukung MySQL
CROSS JOINsetiap 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 | 2

COUNT(*) 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 | 2

CTE 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.50

Perbedaan PostgreSQL, MySQL, dan SQLite

Inti SQL bersifat portabel, tetapi setiap engine berbeda dalam detail. Berikut perbedaan yang pertama kali ditemui pemula.

FiturPostgreSQLMySQLSQLite
ID auto-incrementGENERATED ALWAYS AS IDENTITY atau SERIALAUTO_INCREMENTINTEGER PRIMARY KEY
Penulisan nama dengan kutip"name"backtick di sekitar nama"name"
Batasi jumlah barisLIMIT n or FETCH FIRST n ROWS ONLYLIMIT nLIMIT n
Penggabungan stringa || bCONCAT(a, b)a || b
Booleantipe BOOLEAN asliTINYINT(1)disimpan sebagai 0 dan 1
Pengetikanketatketat pada strict mode defaultfleksibel, kecuali tabel dideklarasikan STRICT
UpsertON CONFLICT ... DO UPDATEON DUPLICATE KEY UPDATEON 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 BY maupun di dalam fungsi agregat.
  • Memakai FLOAT untuk uang alih-alih DECIMAL.
  • Lupa membuat index pada kolom yang dipakai di join dan filter; CREATE INDEX idx_orders_customer ON orders(customer_id); dan EXPLAIN membantu 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.

Semua tutorial pemrograman