PostgreSQL adalah salah satu sistem manajemen basis data relasional (RDBMS) open source paling populer di dunia. Berbeda dengan SQLite yang menyimpan data dalam satu file lokal, PostgreSQL berjalan sebagai server mandiri (arsitektur client-server) yang dirancang untuk menangani data dalam skala besar, banyak pengguna sekaligus, dan kebutuhan produksi yang serius. Di artikel ini, kamu akan belajar cara menjalankan PostgreSQL, menghubungkannya dengan Python menggunakan psycopg, lalu menguasai operasi dasar sampai lanjutan seperti transaksi dan connection pooling.
Apa Itu PostgreSQL dan Kenapa Memilihnya?
PostgreSQL (sering disingkat Postgres) sudah ada sejak 1996 dan terus dikembangkan secara aktif. Ia mendukung fitur-fitur canggih seperti JSON, full-text search, hingga ekstensi geospasial (PostGIS). Jika sebelumnya kamu pernah belajar SQLite dengan Python, konsep SQL-nya serupa, tetapi arsitekturnya berbeda: SQLite cocok untuk aplikasi ringan dan embedded, sedangkan PostgreSQL adalah pilihan utama untuk aplikasi web, API, dan sistem produksi.
Menyiapkan PostgreSQL dengan Docker
Cara paling cepat untuk mencoba PostgreSQL tanpa repot instalasi manual adalah dengan Docker. Jika kamu belum familier, kami punya panduan lengkap Belajar Docker untuk Pemula. Jalankan perintah berikut untuk menjalankan container PostgreSQL:
docker run --name postgres-belajar \
-e POSTGRES_USER=admin \
-e POSTGRES_PASSWORD=rahasia123 \
-e POSTGRES_DB=tokoonline \
-p 5432:5432 \
-d postgres:16
Jangan lupa tambahkan volume agar data tetap tersimpan meski container dihapus: tambahkan flag -v postgres-data:/var/lib/postgresql/data. Tanpa volume, semua data akan hilang ketika container dihapus.
Instalasi Psycopg dan Koneksi Pertama
Psycopg (psycopg3) adalah driver PostgreSQL untuk Python yang paling populer dan terus dikelola. Instal dengan pip:
pip install "psycopg[binary]"
Setelah terpasang, kita bisa langsung membuat koneksi pertama. Berikut contoh sederhana untuk memastikan semuanya berjalan:
import psycopg
# Membuka koneksi ke PostgreSQL
conn = psycopg.connect(
host="localhost",
port=5432,
dbname="tokoonline",
user="admin",
password="rahasia123",
)
# Mengeksekusi query sederhana
with conn.cursor() as cur:
cur.execute("SELECT version();")
print(cur.fetchone()[0])
conn.close()
Simpan kredensial database di environment variable, jangan di-hardcode di kode. Kamu bisa memakai os.environ.get('DB_PASSWORD') atau library seperti python-dotenv untuk membacanya dari file .env.
Membuat Tabel dan Operasi CRUD
Setelah koneksi berhasil, mari buat tabel dan praktikkan empat operasi dasar: Create, Read, Update, Delete (CRUD). Kita akan membuat tabel produk sederhana terlebih dahulu:
import psycopg
conn = psycopg.connect(
host="localhost", port=5432, dbname="tokoonline",
user="admin", password="rahasia123",
)
with conn.cursor() as cur:
# CREATE TABLE
cur.execute("""
CREATE TABLE IF NOT EXISTS produk (
id SERIAL PRIMARY KEY,
nama VARCHAR(100) NOT NULL,
harga NUMERIC(10, 2) NOT NULL,
stok INTEGER DEFAULT 0
)
""")
conn.commit()
print("Tabel produk berhasil dibuat")
conn.close()
Selanjutnya, praktikkan operasi CRUD lengkap. Perhatikan penggunaan placeholder %s untuk meneruskan nilai:
conn = psycopg.connect(
host="localhost", port=5432, dbname="tokoonline",
user="admin", password="rahasia123",
)
with conn.cursor() as cur:
# CREATE — menambah data
cur.execute(
"INSERT INTO produk (nama, harga, stok) VALUES (%s, %s, %s)",
("Keyboard Mekanik", 750000, 25),
)
# READ — membaca data
cur.execute("SELECT id, nama, harga, stok FROM produk")
for row in cur.fetchall():
print(row)
# UPDATE — mengubah data
cur.execute(
"UPDATE produk SET harga = %s WHERE nama = %s",
(699000, "Keyboard Mekanik"),
)
# DELETE — menghapus data
cur.execute("DELETE FROM produk WHERE nama = %s", ("Keyboard Mekanik",))
conn.commit()
conn.close()
Parameterized Query: Melindungi Diri dari SQL Injection
Perhatikan pada contoh di atas, kita selalu memakai placeholder %s dan meneruskan nilai sebagai parameter terpisah. Teknik ini disebut parameterized query dan sangat penting untuk keamanan. Jangan pernah menyusun string SQL dengan menggabungkan input pengguna secara langsung:
nama = "Keyboard'; DROP TABLE produk; --"
# BERBAHAYA — rentan SQL injection (JANGAN DITIRU)
cur.execute(f"SELECT * FROM produk WHERE nama = '{nama}'")
# AMAN — parameterized query
cur.execute("SELECT * FROM produk WHERE nama = %s", (nama,))
SQL injection adalah salah satu celah keamanan paling umum dan berbahaya di aplikasi web. Dengan menggabungkan input user langsung ke query, penyerang bisa membaca, mengubah, bahkan menghapus seluruh data. Selalu gunakan parameterized query.
Transaksi: Commit dan Rollback
Transaksi memastikan serangkaian operasi database berjalan “semua atau tidak sama sekali”. Jika satu langkah gagal, kamu bisa membatalkan semuanya dengan rollback sehingga data tetap konsisten. Contoh klasiknya adalah transfer saldo antar rekening:
import psycopg
conn = psycopg.connect(
host="localhost", port=5432, dbname="tokoonline",
user="admin", password="rahasia123",
)
try:
with conn.cursor() as cur:
cur.execute(
"UPDATE rekening SET saldo = saldo - 100000 WHERE id = %s",
(1,),
)
cur.execute(
"UPDATE rekening SET saldo = saldo + 100000 WHERE id = %s",
(2,),
)
conn.commit() # simpan semua perubahan
print("Transfer berhasil")
except Exception as e:
conn.rollback() # batalkan semua perubahan
print(f"Transfer gagal, rollback dilakukan: {e}")
finally:
conn.close()
Connection Pooling dengan psycopg_pool
Membuka dan menutup koneksi database berulang kali itu mahal. Pada aplikasi nyata (misalnya API yang menerima banyak request), gunakan connection pool agar koneksi dipakai ulang. Psycopg menyediakan modul psycopg_pool untuk ini. Instal dulu dependensinya:
pip install psycopg-pool
Lalu gunakan pool sebagai pengganti koneksi langsung:
from psycopg_pool import ConnectionPool
# Pool dengan 10 koneksi (min 1, max 10)
pool = ConnectionPool(
conninfo="host=localhost port=5432 dbname=tokoonline user=admin password=rahasia123",
min_size=1,
max_size=10,
)
# Ambil koneksi dari pool, otomatis dikembalikan setelah blok selesai
with pool.connection() as conn:
with conn.cursor() as cur:
cur.execute("SELECT COUNT(*) FROM produk")
print("Jumlah produk:", cur.fetchone()[0])
pool.close()
Menyimpan Data JSON dengan JSONB
Salah satu keunggulan PostgreSQL adalah dukungan tipe data JSONB, yang memungkinkan kamu menyimpan dan melakukan query terhadap data JSON secara efisien — berguna untuk data yang strukturnya fleksibel:
conn = psycopg.connect(
host="localhost", port=5432, dbname="tokoonline",
user="admin", password="rahasia123",
)
with conn.cursor() as cur:
cur.execute("""
CREATE TABLE IF NOT EXISTS event_log (
id SERIAL PRIMARY KEY,
payload JSONB
)
""")
cur.execute(
"INSERT INTO event_log (payload) VALUES (%s)",
('{"aksi": "login", "user_id": 42, "berhasil": true}',),
)
# Query ke dalam JSONB
cur.execute(
"SELECT payload->>'aksi' FROM event_log WHERE payload->>'user_id' = %s",
("42",),
)
print(cur.fetchone()) # ('login',)
conn.commit()
conn.close()
Jika kamu lebih suka bekerja dengan objek Python (class) daripada menulis SQL manual, pertimbangkan ORM. Kami punya panduan lengkap Belajar SQLAlchemy ORM dengan Python yang bisa kamu gunakan di atas PostgreSQL.
Kesimpulan
PostgreSQL dipadukan dengan psycopg adalah fondasi yang kuat untuk aplikasi backend Python. Kamu telah belajar menjalankan PostgreSQL lewat Docker, melakukan koneksi, operasi CRUD, melindungi aplikasi dari SQL injection, mengelola transaksi, menggunakan connection pooling, hingga memanfaatkan JSONB. Dengan dasar ini, kamu siap membangun aplikasi yang lebih tangguh dan siap produksi.
Apa bedanya PostgreSQL dengan MySQL?
Keduanya sama-sama RDBMS populer. PostgreSQL unggul dalam kepatuhan standar SQL, dukungan tipe data lanjutan (JSONB, array, PostGIS), dan ekstensibilitas. MySQL sering dipilih karena kemudahan dan ekosistem hosting yang luas. Untuk proyek baru dengan kebutuhan fitur kompleks, PostgreSQL umumnya direkomendasikan.
Apakah psycopg2 dan psycopg3 berbeda?
Ya. psycopg2 adalah versi lama yang masih banyak dipakai, sedangkan psycopg3 (modul psycopg) adalah versi modern dengan API lebih bersih, dukungan async, dan connection pool bawaan lewat psycopg_pool. Untuk proyek baru, gunakan psycopg3.
Kapan sebaiknya memakai ORM seperti SQLAlchemy daripada SQL mentah?
Jika aplikasimu banyak berurusan dengan model data kompleks dan relasi, ORM seperti SQLAlchemy bisa menghemat banyak waktu. Namun, memahami SQL mentah tetap penting untuk optimasi query dan debugging. Keduanya bisa dipakai bersamaan di proyek yang sama.