Mengenal Database di Python (Bagian 1): Fondasi SQLite dan Operasi CRUD Pertama
Ketika kamu membuat program kalkulator, game mini, atau pengolah teks di level dasar, semua data yang kamu simpan di dalam variabel akan musnah seketika begitu program ditutup atau komputermu dimatikan. Data tersebut hanya hidup sementara di memori RAM.
Di dunia nyata, aplikasi membutuhkan penyimpanan data permanen (*persistent storage*). Baik kamu membangun aplikasi toko online, sistem pendaftaran siswa, maupun bot media sosial, Basis Data (Database) adalah jantung yang menyimpan seluruh informasi penting tersebut.
Artikel ini adalah Bagian 1 dari trilogi panduan lengkap Database di Python:
- Bagian 1 (Sedang Dibaca): Fondasi SQLite dan Operasi CRUD Pertama (Koneksi, pembuatan tabel, penyimpanan permanen, dan operasi Create, Read, Update, Delete).
- Bagian 2: Relasi Multi-Tabel (JOIN), Agregasi & Keamanan Query (Foreign key, query multi-tabel, sqlite3.Row, dan bahaya SQL Injection vs Parameterized Query).
- Bagian 3: Arsitektur Python OOP + Database: Mini Inventory App (Integrasi Class Repository, context manager with, error handling, dan antarmuka menu CLI).
1. Mengapa SQLite Sangat Ideal untuk Memulai?
Berbeda dengan sistem database seperti MySQL atau PostgreSQL yang mewajibkan instalasi server terpisah, pengaturan port jaringan, dan kata sandi pengguna yang rumit, SQLite adalah mesin database mandiri (*serverless*) yang menyimpan seluruh tabel ke dalam satu file tunggal di komputermu (misalnya inventaris.db).
Kabar terbaiknya: Python sudah menyertakan modul sqlite3 secara bawaan! Kamu tidak perlu menginstal pustaka tambahan apa pun lewat pip. Cukup ketik import sqlite3 dan kamu sudah memiliki kekuatan penuh standar database relasional SQL.
2. Membuka Koneksi dan Membuat Tabel Pertama
Untuk berinteraksi dengan database, kita membutuhkan dua hal:
- Koneksi (
Connection): Jembatan penghubung antara skrip Python dan file database fisik di disk. - Kursor (
Cursor): Objek yang bertugas mengirimkan instruksi SQL dan menampung hasil query yang dikembalikan oleh database.
Mari kita buat file skrip 01-buat-koneksi-dan-tabel.py untuk mendefinisikan tabel produk:
# 01-buat-koneksi-dan-tabel.py
import sqlite3
# 1. Buka koneksi (jika file belum ada, SQLite otomatis membuatnya)
conn = sqlite3.connect("inventaris.db")
cursor = conn.cursor()
# 2. Definisikan tabel produk dengan bahasa SQL DDL
query_buat_tabel = """
CREATE TABLE IF NOT EXISTS produk (
id INTEGER PRIMARY KEY AUTOINCREMENT,
kode TEXT UNIQUE NOT NULL,
nama TEXT NOT NULL,
kategori TEXT NOT NULL,
harga REAL NOT NULL,
stok INTEGER NOT NULL DEFAULT 0
)
"""
cursor.execute(query_buat_tabel)
conn.commit()
print("[OK] Database 'inventaris.db' berhasil dibuka.")
print("[OK] Tabel 'produk' berhasil dibuat dan siap digunakan!")
conn.close()

Perhatikan sintaks PRIMARY KEY AUTOINCREMENT: klausa ini membuat kolom id bertambah nilainya secara otomatis (1, 2, 3, dst.) setiap kali data baru dimasukkan, menjamin identitas unik bagi setiap barang.
3. Menambahkan Data: Operasi Create (INSERT)
Untuk menyisipkan data, kita menggunakan perintah SQL INSERT INTO. Terdapat dua metode utama yang sering digunakan:
cursor.execute(): Untuk menyisipkan 1 baris data tunggal.cursor.executemany(): Untuk menyisipkan banyak baris data sekaligus (*Batch Insert*) dari sebuah list Python secara efisien.
# 02-tambah-data-create.py
import sqlite3
conn = sqlite3.connect("inventaris.db")
cursor = conn.cursor()
# 1. Menambahkan 1 data tunggal
sql_tambah = "INSERT OR IGNORE INTO produk (kode, nama, kategori, harga, stok) VALUES (?, ?, ?, ?, ?)"
produk_baru = ("PRD-001", "Keyboard Mekanikal TKL", "Aksesoris", 450000.0, 15)
cursor.execute(sql_tambah, produk_baru)
print(f"[OK] 1 produk ditambahkan: {produk_baru[1]}")
# 2. Menambahkan banyak data sekaligus (executemany)
daftar_produk_baru = [
("PRD-002", "Mouse Gaming Nirkabel", "Aksesoris", 280000.0, 24),
("PRD-003", "Monitor IPS 24 Inci 144Hz", "Layar", 1850000.0, 8),
("PRD-004", "Headset Bluetooth Noise-Cancelling", "Audio", 620000.0, 12),
("PRD-005", "Webcam Full HD 1080p", "Kamera", 350000.0, 18),
]
cursor.executemany(sql_tambah, daftar_produk_baru)
print(f"[OK] {len(daftar_produk_baru)} produk massal berhasil ditambahkan!")
# Simpan perubahan secara permanen ke hard drive
conn.commit()
conn.close()

Penting: Mengapa harus conn.commit()?
Di database relasional, setiap perubahan data ditempatkan dalam transaksi sementara. Jika program terhenti sebelum conn.commit() dipanggil, data tersebut tidak akan pernah tertulis ke disk. Perintah commit() adalah tombol konfirmasi “Simpan Permanen”.
4. Membaca Data: Operasi Read (SELECT)
Untuk mengambil data yang telah tersimpan, gunakan perintah SELECT. Secara default, SQLite mengembalikan setiap baris sebagai Tuple angka indeks (row[0], row[1]). Namun, kita dapat mengaktifkan fitur conn.row_factory = sqlite3.Row agar data bisa dibaca menggunakan nama kolom seperti Dictionary Python:
# 03-baca-data-read.py
import sqlite3
conn = sqlite3.connect("inventaris.db")
conn.row_factory = sqlite3.Row # Membaca kolom dengan nama: row["nama"]
cursor = conn.cursor()
print("
--- DAFTAR SEMUA PRODUK INVENTARIS ---")
cursor.execute("SELECT id, kode, nama, kategori, harga, stok FROM produk ORDER BY id ASC")
semua_produk = cursor.fetchall()
# Format tabel di terminal
garis = "+" + "-"*6 + "+" + "-"*10 + "+" + "-"*35 + "+" + "-"*14 + "+" + "-"*14 + "+" + "-"*8 + "+"
header = f"| {'ID':<4} | {'Kode':<8} | {'Nama Produk':<33} | {'Kategori':<12} | {'Harga (Rp)':<12} | {'Stok':<6} |"
print(garis)
print(header)
print(garis)
for p in semua_produk:
harga_fmt = f"{int(p['harga']):,}".replace(",", ".")
print(f"| {p['id']:<4} | {p['kode']:<8} | {p['nama']:<33} | {p['kategori']:<12} | {harga_fmt:<12} | {p['stok']:<6} |")
print(garis)
print(f"Total Produk Terdaftar: {len(semua_produk)} item
")
# Menggunakan filter WHERE
print("--- PRODUK KATEGORI AKSESORIS DENGAN HARGA < Rp 300.000 ---")
cursor.execute("SELECT nama, harga FROM produk WHERE kategori = ? AND harga < ?", ("Aksesoris", 300000.0))
for row in cursor.fetchall():
print(f"-> {row['nama']} (Rp {int(row['harga']):,})")
conn.close()

💡 Mau Coba Query SQL Langsung di Browser?
Kamu bisa bereksperimen mengeksekusi query tabel inventaris ini secara instan tanpa install apapun di SQL Playground Interaktif (Klik di Sini)!
5. Memperbarui dan Menghapus Data: Update & Delete
Data bisnis terus berubah: harga barang naik, stok berkurang, atau produk tertentu dihentikan penjualannya. Di SQL, kita menggunakan UPDATE untuk memperbarui nilai dan DELETE untuk menghapus baris:
# 04-ubah-dan-hapus-update-delete.py
import sqlite3
conn = sqlite3.connect("inventaris.db")
cursor = conn.cursor()
# 1. UPDATE: Perbarui harga dan stok Keyboard PRD-001
sql_update = "UPDATE produk SET harga = ?, stok = ? WHERE kode = ?"
cursor.execute(sql_update, (425000.0, 20, "PRD-001"))
print(f"[UPDATE] Berhasil memperbarui {cursor.rowcount} data untuk kode 'PRD-001'.")
# 2. DELETE: Hapus produk Webcam PRD-005
sql_delete = "DELETE FROM produk WHERE kode = ?"
cursor.execute(sql_delete, ("PRD-005",))
print(f"[DELETE] Berhasil menghapus {cursor.rowcount} data untuk kode 'PRD-005'.")
conn.commit()
# Verifikasi sisa produk
cursor.execute("SELECT COUNT(*) FROM produk")
print(f"[STATUS] Jumlah produk aktif di database sekarang: {cursor.fetchone()[0]} item.")
conn.close()

Atribut cursor.rowcount sangat berguna dalam aplikasi nyata untuk memverifikasi apakah ada baris yang benar-benar terpengaruh oleh perintah query kita.
6. Praktik Terbaik: Menjalankan Siklus CRUD Lengkap
Alih-alih memanggil connect() dan close() secara manual di setiap fungsi, cara paling bersih dan aman dalam standar Python modern adalah memanfaatkan Context Manager (pernyataan with).
Dengan with sqlite3.connect(...) as conn:, Python secara otomatis menangani proses commit() jika blok kode berhasil, dan melakukan rollback() (membatalkan transaksi) jika terjadi kesalahan (*error*):
# 05-siklus-crud-lengkap.py
import sqlite3
NAMA_DB = "inventaris.db"
def inisialisasi_db():
with sqlite3.connect(NAMA_DB) as conn:
cursor = conn.cursor()
cursor.execute("""
CREATE TABLE IF NOT EXISTS produk (
id INTEGER PRIMARY KEY AUTOINCREMENT,
kode TEXT UNIQUE NOT NULL,
nama TEXT NOT NULL,
kategori TEXT NOT NULL,
harga REAL NOT NULL,
stok INTEGER NOT NULL DEFAULT 0
)
""")
print("[1/4 CREATE] Tabel inventaris siap.")
def tambah_produk(kode, nama, kategori, harga, stok):
with sqlite3.connect(NAMA_DB) as conn:
cursor = conn.cursor()
cursor.execute(
"INSERT OR REPLACE INTO produk (kode, nama, kategori, harga, stok) VALUES (?, ?, ?, ?, ?)",
(kode, nama, kategori, harga, stok)
)
print(f"[2/4 INSERT] Ditambahkan: {nama} ({kode})")
def tampilkan_semua():
with sqlite3.connect(NAMA_DB) as conn:
conn.row_factory = sqlite3.Row
cursor = conn.cursor()
cursor.execute("SELECT kode, nama, harga, stok FROM produk ORDER BY kode ASC")
rows = cursor.fetchall()
print("\n[3/4 READ] Isi Tabel Inventaris:")
print("-" * 55)
for r in rows:
print(f"[{r['kode']}] {r['nama']:<28} | Rp {int(r['harga']):>8,} | Stok: {r['stok']}")
print("-" * 55 + "\n")
def hapus_produk(kode):
with sqlite3.connect(NAMA_DB) as conn:
cursor = conn.cursor()
cursor.execute("DELETE FROM produk WHERE kode = ?", (kode,))
print(f"[4/4 DELETE] Produk dengan kode '{kode}' berhasil dihapus.")
if __name__ == "__main__":
print("=== MEMULAI DEMONSTRASI SIKLUS CRUD SQLITE PYTHON ===\n")
inisialisasi_db()
tambah_produk("PRD-010", "SSD NVMe 1TB Gen4", "Penyimpanan", 1250000.0, 10)
tampilkan_semua()
hapus_produk("PRD-010")
print("\n=== DEMONSTRASI SELESAI DENGAN SUKSES! ===")

Ringkasan Materi
- Modul bawaan
sqlite3memungkinkan aplikasi Python menyimpan data permanen ke dalam file tunggal tanpa konfigurasi server yang rumit. - Empat pilar manipulasi data dasar disingkat sebagai CRUD: Create (INSERT), Read (SELECT), Update (UPDATE), dan Delete (DELETE).
- Selalu gunakan penampung tanda tanya (
?) saat melewatkan nilai variabel ke dalam SQL untuk menjamin keamanan dari celah kejahatan siber (*SQL Injection*). - Manfaatkan
conn.row_factory = sqlite3.Rowuntuk kemudahan mengakses nama kolom dan Context Manager (with) untuk manajemen transaksi yang andal.
Langkah Selanjutnya: Menuju Relasi Tabel & Keamanan Query
Dalam sistem aplikasi yang sesungguhnya, data tidak hanya disimpan dalam satu tabel tunggal. Di artikel berikutnya, kita akan mempelajari cara menghubungkan antar-tabel menggunakan Foreign Key dan klausa JOIN, serta membongkar mengapa manipulasi string SQL mentah bisa membahayakan sistemmu:
👉 Lanjut membaca: Bagian 2: Relasi Multi-Tabel (JOIN), Agregasi & Keamanan Query di Python SQLite

Leave a Reply