SQLite adalah salah satu database engine paling banyak digunakan di dunia. Ia tersimpan di dalam ponsel, browser, dan aplikasi desktop yang kamu pakai setiap hari. Kabar baiknya, Python sudah menyediakan modul sqlite3 bawaan sehingga kamu tidak perlu menginstal server database terpisah untuk mulai menyimpan data. Dalam tutorial ini kamu akan belajar membuat database dan tabel, menjalankan operasi CRUD (Create, Read, Update, Delete), melindungi query dari SQL injection, hingga membangun studi kasus aplikasi pencatat buku sederhana yang siap dijalankan.
Apa Itu SQLite dan Kenapa Memilihnya?
SQLite adalah database relasional yang tersimpan dalam satu file saja. Tidak seperti MySQL atau PostgreSQL yang membutuhkan proses server berjalan terus-menerus, SQLite bersifat serverless: aplikasi membaca dan menulis langsung ke file .db. Ini membuatnya sangat cocok untuk aplikasi kecil, prototyping, alat CLI, hingga aplikasi mobile, karena tidak ada konfigurasi yang rumit.
Kapan sebaiknya beralih ke PostgreSQL atau MySQL? Ketika aplikasimu mulai melayani banyak pengguna yang menulis data secara bersamaan (concurrent writes) atau membutuhkan fitur lanjutan seperti replikasi. Untuk kebutuhan tersebut, kamu bisa menjalankan server database di dalam container — konsepnya sudah dijelaskan di artikel Belajar Docker untuk Pemula. Namun untuk belajar dan membangun aplikasi kecil, SQLite adalah pilihan tercepat dan paling ramah pemula.
Menyiapkan Lingkungan
Kamu hanya membutuhkan Python 3 (semua versi modern sudah menyertakan sqlite3). Jika Python belum terpasang di komputermu, ikuti dulu panduan Cara Install Python dan Menulis Program Pertamamu. Setelah itu, cek versi Python-mu dengan perintah berikut:
python3 --version
# Python 3.11.15 (atau versi lain)
Membuat Koneksi dan Tabel
Langkah pertama adalah membuat koneksi ke file database. Jika file belum ada, SQLite akan membuatkannya secara otomatis. Selanjutnya kita buat sebuah tabel bernama buku untuk contoh kali ini.
import sqlite3
# Membuka (atau membuat) file database
conn = sqlite3.connect("perpustakaan.db")
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS buku (
id INTEGER PRIMARY KEY AUTOINCREMENT,
judul TEXT NOT NULL,
penulis TEXT NOT NULL,
tahun INTEGER,
sudah_dibaca INTEGER DEFAULT 0
)
""")
# Simpan perubahan ke file database
conn.commit()
print("Tabel 'buku' berhasil dibuat.")
conn.close()
Objek cursor adalah perantara yang kita pakai untuk mengirim perintah SQL dan membaca hasilnya. Perhatikan bahwa setiap perubahan data harus diakhiri dengan conn.commit() agar tersimpan permanen, lalu conn.close() untuk menutup koneksi.
Menambahkan Data (INSERT)
Untuk memasukkan banyak baris sekaligus, gunakan executemany() dengan placeholder ?. Cara ini lebih efisien daripada memanggil execute() berulang kali.
import sqlite3
conn = sqlite3.connect("perpustakaan.db")
cursor = conn.cursor()
daftar_buku = [
("Clean Code", "Robert C. Martin", 2008, 1),
("Refactoring", "Martin Fowler", 2018, 0),
("The Pragmatic Programmer", "David Thomas & Andrew Hunt", 1999, 1),
]
cursor.executemany(
"INSERT INTO buku (judul, penulis, tahun, sudah_dibaca) VALUES (?, ?, ?, ?)",
daftar_buku,
)
conn.commit()
print(f"{cursor.rowcount} baris berhasil ditambahkan.")
conn.close()
Membaca Data (SELECT)
Setelah data tersimpan, kita ambil kembali dengan perintah SELECT. Gunakan fetchall() untuk mengambil semua baris hasil query.
import sqlite3
conn = sqlite3.connect("perpustakaan.db")
cursor = conn.cursor()
cursor.execute("SELECT id, judul, penulis, tahun FROM buku ORDER BY tahun DESC")
rows = cursor.fetchall()
for row in rows:
print(f"{row[0]}. {row[1]} — {row[2]} ({row[3]})")
conn.close()
Mengubah Data (UPDATE)
Misalnya kita baru selesai membaca buku Refactoring dan ingin menandainya sudah dibaca. Gunakan UPDATE dengan klausa WHERE agar hanya baris yang tepat yang berubah.
import sqlite3
conn = sqlite3.connect("perpustakaan.db")
cursor = conn.cursor()
cursor.execute(
"UPDATE buku SET sudah_dibaca = 1 WHERE judul = ?",
("Refactoring",),
)
conn.commit()
print(f"{cursor.rowcount} baris berhasil diperbarui.")
conn.close()
Menghapus Data (DELETE)
Terakhir dari rangkaian CRUD, kita hapus sebuah baris. Sekali lagi, selalu sertakan WHERE — tanpa klausa ini seluruh isi tabel akan terhapus.
import sqlite3
conn = sqlite3.connect("perpustakaan.db")
cursor = conn.cursor()
cursor.execute("DELETE FROM buku WHERE judul = ?", ("Refactoring",))
conn.commit()
print(f"{cursor.rowcount} baris berhasil dihapus.")
conn.close()
Melindungi Data dari SQL Injection
Ini bagian paling penting. Jika kamu menyusun query dengan menggabungkan string secara langsung (string interpolation), aplikasimu rawan serangan SQL injection — penyerang bisa memanipulasi input untuk menjalankan perintah SQL yang tidak diinginkan.
judul_dari_user = "Clean Code'; DROP TABLE buku;--"
# BURUK: menyusun string query langsung (rawan SQL injection)
cursor.execute(f"SELECT * FROM buku WHERE judul = '{judul_dari_user}'")
# BAIK: gunakan parameter placeholder (?) — nilai di-escape otomatis
cursor.execute("SELECT * FROM buku WHERE judul = ?", (judul_dari_user,))
Jangan pernah menyisipkan input pengguna langsung ke dalam string SQL. Selalu gunakan placeholder ? dan lewatkan nilainya sebagai tuple kedua. Python akan meng-escape nilainya secara otomatis sehingga input berbahaya hanya diperlakukan sebagai teks biasa.
Menggunakan Context Manager dan Row Factory
Alih-alih memanggil commit() dan close() secara manual, gunakan pernyataan with. Context manager akan otomatis commit saat berhasil dan rollback saat terjadi error, lalu menutup koneksi. Selain itu, row_factory memungkinkan kita mengakses kolom berdasarkan nama, bukan indeks angka.
import sqlite3
# with otomatis commit (atau rollback saat error) dan menutup koneksi
with sqlite3.connect("perpustakaan.db") as conn:
conn.row_factory = sqlite3.Row # akses kolom berdasarkan nama
cursor = conn.cursor()
cursor.execute(
"INSERT INTO buku (judul, penulis, tahun) VALUES (?, ?, ?)",
("Designing Data-Intensive Applications", "Martin Kleppmann", 2017),
)
with sqlite3.connect("perpustakaan.db") as conn:
conn.row_factory = sqlite3.Row
for row in conn.execute("SELECT judul, penulis FROM buku"):
print(f"{row['judul']} oleh {row['penulis']}")
Biasakan memakai with sqlite3.connect(...) sebagai gaya default. Ini mengurangi risiko lupa commit atau lupa menutup koneksi, dan membuat kode lebih ringkas serta lebih aman saat terjadi pengecualian.
Studi Kasus: Aplikasi Pencatat Buku Sederhana
Sekarang mari gabungkan semua konsep di atas menjadi satu program utuh. Aplikasi kecil ini punya fungsi untuk menambah buku, menampilkan daftar buku, dan mencari buku berdasarkan kata kunci.
import sqlite3
DB = "perpustakaan.db"
def init_db():
with sqlite3.connect(DB) as conn:
conn.execute("""
CREATE TABLE IF NOT EXISTS buku (
id INTEGER PRIMARY KEY AUTOINCREMENT,
judul TEXT NOT NULL,
penulis TEXT NOT NULL,
tahun INTEGER,
sudah_dibaca INTEGER DEFAULT 0
)
""")
def tambah_buku(judul, penulis, tahun):
with sqlite3.connect(DB) as conn:
conn.execute(
"INSERT INTO buku (judul, penulis, tahun) VALUES (?, ?, ?)",
(judul, penulis, tahun),
)
print(f"Buku '{judul}' ditambahkan.")
def daftar_buku():
with sqlite3.connect(DB) as conn:
conn.row_factory = sqlite3.Row
rows = conn.execute("SELECT * FROM buku ORDER BY judul").fetchall()
if not rows:
print("Belum ada buku. Tambahkan dulu!")
return
for r in rows:
status = "sudah dibaca" if r["sudah_dibaca"] else "belum dibaca"
print(f"[{r['id']}] {r['judul']} — {r['penulis']} ({r['tahun']}) — {status}")
def cari_buku(kata_kunci):
with sqlite3.connect(DB) as conn:
conn.row_factory = sqlite3.Row
return conn.execute(
"SELECT * FROM buku WHERE judul LIKE ? OR penulis LIKE ?",
(f"%{kata_kunci}%", f"%{kata_kunci}%"),
).fetchall()
if __name__ == "__main__":
init_db()
tambah_buku("Clean Code", "Robert C. Martin", 2008)
tambah_buku("Refactoring", "Martin Fowler", 2018)
print("\nDaftar buku:")
daftar_buku()
print("\nHasil pencarian 'Martin':")
for r in cari_buku("Martin"):
print(f"- {r['judul']} oleh {r['penulis']}")
Langkah Selanjutnya
SQLite adalah fondasi yang bagus sebelum melangkah ke database yang lebih besar. Jika kamu ingin mengubah aplikasi ini menjadi sebuah API, pelajari cara membangun endpoint-nya dengan framework modern di artikel Cara Membuat REST API dengan FastAPI. Dan agar kode yang mengakses database tetap terjamin kualitasnya, biasakan menulis tes otomatis lewat panduan Belajar Testing Python dengan Pytest.
Kesimpulan
Kamu sekarang sudah memahami dasar-dasar SQLite dengan Python: membuat koneksi dan tabel, menjalankan operasi CRUD, melindungi query dari SQL injection, serta memanfaatkan context manager dan row_factory. Semua ini tanpa perlu menginstal server tambahan apa pun. Selanjutnya, coba perluas studi kasus di atas dengan fitur baru — misalnya kolom rating, filter berdasarkan tahun, atau ekspor data ke CSV.
Pertanyaan yang Sering Diajukan
Kapan sebaiknya memakai SQLite dibanding PostgreSQL atau MySQL?
Gunakan SQLite untuk aplikasi kecil, prototyping, alat CLI, dan aplikasi dengan satu penulis atau lalu lintas rendah. Beralihlah ke PostgreSQL atau MySQL saat aplikasi melayani banyak pengguna yang menulis data secara bersamaan atau membutuhkan fitur seperti replikasi dan pengaturan hak akses pengguna.
Apakah SQLite aman digunakan untuk aplikasi web production?
Untuk aplikasi web dengan lalu lintas baca yang dominan dan sedikit penulisan, SQLite bisa mencukupi. Namun SQLite menangani penulisan secara berurutan, sehingga performanya menurun saat banyak penulisan terjadi bersamaan. Django sendiri menggunakan SQLite sebagai database pengembangan default, tetapi umumnya PostgreSQL direkomendasikan untuk production.
Bagaimana cara melihat isi database SQLite tanpa menulis kode?
Kamu bisa menggunakan CLI bawaan dengan perintah sqlite3 perpustakaan.db, lalu menjalankan query langsung di dalamnya. Alternatif yang lebih ramah pengguna adalah aplikasi grafis seperti DB Browser for SQLite yang tersedia untuk Windows, macOS, dan Linux.