Post Detail

September 13, 2026 in Python Lanjutan

Mengenal Database di Python (Bagian 1): Fondasi SQLite dan Operasi CRUD Pertama

Panduan Dasar Database SQLite dan Operasi CRUD di Python
Panduan praktis manajemen data SQLite di Python: Operasi CRUD, parameter query, dan eksekusi terminal.

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:

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()
Tangkapan Layar Terminal: Membuat koneksi database dan tabel inventaris produk di SQLite
Tangkapan layar terminal: Berhasil membuka koneksi database dan membuat file ‘inventaris.db’ secara lokal.

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:

  1. cursor.execute(): Untuk menyisipkan 1 baris data tunggal.
  2. 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()
Tangkapan Layar Terminal: Menyisipkan data tunggal dan massal (batch insert) ke tabel produk
Tangkapan layar terminal: Berhasil menyisipkan data tunggal dan kumpulan data produk massal.

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()
Tangkapan Layar Terminal: Membaca data inventaris dalam format tabel rapi dan query berfilter
Tangkapan layar terminal: Menampilkan hasil query data inventaris dalam format tabel kolom yang rapi.

💡 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()
Tangkapan Layar Terminal: Memperbarui harga dan menghapus data produk dari tabel
Tangkapan layar terminal: Memperbarui stok barang dan menghapus produk usang dengan konfirmasi ‘cursor.rowcount’.

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! ===")
Animasi Terminal: Demonstrasi siklus utuh operasi CRUD SQLite Python
Animasi langsung hasil eksekusi terminal: Siklus utuh operasi CRUD berjalan otomatis dari pembuatan tabel, penambahan produk, pembacaan daftar, hingga penghapusan.

Ringkasan Materi

  • Modul bawaan sqlite3 memungkinkan 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.Row untuk 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

Your email address will not be published. Required fields are marked *