Mengubah dan Merancang · Pelajaran 9 dari 9
Memakai SQL dari Python
9 menit baca · BelajarCode
Aplikasi sungguhan mengirim perintah SQL dari kode programnya. Python menyediakan modul sqlite3 bawaan, dan pustaka untuk MySQL atau PostgreSQL bekerja dengan pola yang sama.
1import sqlite323db = sqlite3.connect(":memory:")4db.execute("CREATE TABLE catatan (id INTEGER PRIMARY KEY, tanggal TEXT, jenis TEXT, jumlah INTEGER, keterangan TEXT)")56transaksi = [7 ("2026-09-01", "masuk", 2500000, "uang saku bulanan"),8 ("2026-09-02", "keluar", 35000, "makan siang"),9 ("2026-09-03", "keluar", 150000, "buku kuliah"),10 ("2026-09-05", "keluar", 20000, "fotokopi"),11]12db.executemany("INSERT INTO catatan (tanggal, jenis, jumlah, keterangan) VALUES (?, ?, ?, ?)", transaksi)13db.commit()1415for jenis, total in db.execute("SELECT jenis, SUM(jumlah) FROM catatan GROUP BY jenis ORDER BY jenis"):16 print(f"{jenis:<7} Rp{total}")1718saldo = db.execute("SELECT SUM(CASE WHEN jenis = 'masuk' THEN jumlah ELSE -jumlah END) FROM catatan").fetchone()[0]19print("Saldo: Rp", saldo, sep="")keluar Rp205000 masuk Rp2500000 Saldo: Rp2295000
connectmembuka basis data. Di komputermu,sqlite3.connect("keuangan.db")membuat file basis data sungguhan.executemenjalankan satu perintah,executemanymenjalankan perintah yang sama untuk banyak data.commitmenyimpan perubahan.- Hasil
SELECTbisa langsung dipakai dalam perulangan, atau diambil denganfetchone()danfetchall().
Bahaya SQL injection
Jangan pernah menyusun SQL dengan menggabungkan teks dari pengguna. Lihat apa yang terjadi:
1import sqlite323db = sqlite3.connect(":memory:")4db.execute("CREATE TABLE pengguna (nama TEXT, peran TEXT)")5db.executemany("INSERT INTO pengguna VALUES (?, ?)", [("andi", "siswa"), ("admin", "admin")])67masukan = "x' OR '1'='1"89query_berbahaya = f"SELECT nama, peran FROM pengguna WHERE nama = '{masukan}'"10print("Digabung langsung:", db.execute(query_berbahaya).fetchall())1112aman = db.execute("SELECT nama, peran FROM pengguna WHERE nama = ?", (masukan,)).fetchall()13print("Dengan parameter :", aman)Digabung langsung: [('andi', 'siswa'), ('admin', 'admin')]
Dengan parameter : []Masukan x' OR '1'='1 mengubah arti query sehingga semua pengguna, termasuk admin, ikut tampil. Inilah SQL injection, salah satu celah keamanan paling umum di aplikasi web. Dengan parameter ?, nilai masukan selalu diperlakukan sebagai data, tidak pernah sebagai bagian perintah SQL.
Aturan yang tidak boleh dilanggar
Setiap nilai yang berasal dari pengguna, formulir, atau sumber luar harus dikirim lewat parameter (? di sqlite3, %s di beberapa pustaka lain), bukan digabungkan ke teks SQL dengan f-string atau +.
Membaca hasil sebagai dictionary
1import sqlite323db = sqlite3.connect(":memory:")4db.row_factory = sqlite3.Row5db.execute("CREATE TABLE buku (judul TEXT, stok INTEGER)")6db.executemany("INSERT INTO buku VALUES (?, ?)", [("Algoritma Dasar", 3), ("Basis Data", 0)])78for baris in db.execute("SELECT judul, stok FROM buku ORDER BY judul"):9 status = "tersedia" if baris["stok"] > 0 else "habis"10 print(f"{baris['judul']}: {status}")Algoritma Dasar: tersedia Basis Data: habis
Dengan row_factory = sqlite3.Row, kolom bisa diakses dengan namanya, sehingga kode lebih mudah dibaca dan tidak bergantung pada urutan kolom.
Cek pemahaman
Kenapa query f"SELECT * FROM pengguna WHERE nama = '{masukan}'" berbahaya?
Latihan
Pengeluaran terbesar
Dari tabel catatan keuangan di contoh pertama, tampilkan tiga pengeluaran terbesar beserta keterangannya, memakai query dengan parameter untuk jenis transaksi.
Pembahasan
1import sqlite323db = sqlite3.connect(":memory:")4db.execute("CREATE TABLE catatan (tanggal TEXT, jenis TEXT, jumlah INTEGER, keterangan TEXT)")5db.executemany("INSERT INTO catatan VALUES (?, ?, ?, ?)", [6 ("2026-09-01", "masuk", 2500000, "uang saku bulanan"),7 ("2026-09-02", "keluar", 35000, "makan siang"),8 ("2026-09-03", "keluar", 150000, "buku kuliah"),9 ("2026-09-05", "keluar", 20000, "fotokopi"),10])1112query = "SELECT keterangan, jumlah FROM catatan WHERE jenis = ? ORDER BY jumlah DESC LIMIT ?"13for keterangan, jumlah in db.execute(query, ("keluar", 3)):14 print(f"Rp{jumlah:>7} {keterangan}")Rp 150000 buku kuliah Rp 35000 makan siang Rp 20000 fotokopi
Bahkan nilai LIMIT pun dikirim lewat parameter. Kebiasaan ini membuat kode aman secara konsisten.