Tentang Materi Ini
Sifat: OPSIONAL (Pengayaan). Materi ini tidak diujikan dan bukan bagian dari praktikum wajib. Dikerjakan bagi mahasiswa yang ingin tantangan tambahan, dan bernilai poin bonus.
Prasyarat: sudah menyelesaikan Pertemuan 10 (SQLite Database).
Mengapa materi ini disediakan? Di dunia kerja dan pada penyusunan skripsi, MySQL jauh lebih sering dipakai daripada SQLite. Kabar baiknya, hampir semua yang sudah dipelajari langsung terpakai — yang berubah terutama cara koneksi dan sedikit penulisan tipe data.
Tujuan
Setelah menyelesaikan materi bonus ini, mahasiswa mampu:
- Menjelaskan perbedaan mendasar SQLite dan MySQL.
- Memasang MySQL (melalui XAMPP) dan membuat database.
-
Menghubungkan Python dengan MySQL memakai
mysql-connector-python. - Membuat ulang keempat tabel aplikasi penjualan di MySQL.
-
Memindahkan data dari
toko.db(SQLite) ke MySQL.
Konsep Singkat
SQLite vs MySQL
| Aspek | SQLite | MySQL |
|---|---|---|
| Bentuk | Satu file (toko.db) |
Server (berjalan sebagai layanan) |
| Instalasi | Tidak perlu (bawaan Python) | Perlu dipasang (mis. lewat XAMPP) |
| Pemakaian | Aplikasi kecil, belajar, prototipe | Aplikasi banyak pengguna, web produksi |
| Akses bersamaan | Terbatas | Kuat, banyak pengguna sekaligus |
| Login | Tidak ada | Ada (user & password) |
| Modul Python | sqlite3 (bawaan) |
mysql-connector-python (dipasang) |
Yang Berubah dan Yang Tetap Sama
TETAP SAMA (inilah alasan ilmunya transferable):
-
Perintah SQL:
CREATE TABLE,INSERT,SELECT,UPDATE,DELETE,WHERE,ORDER BY,JOIN. - Konsep Primary Key, Foreign Key, dan relasi master–detail.
-
Pola Python:
cursor.execute(),fetchall(),commit(),close().
BERUBAH (hanya tiga hal):
| Hal | SQLite | MySQL |
|---|---|---|
| Cara koneksi | sqlite3.connect("file.db") |
mysql.connector.connect(host, user, password,
database)
|
| Auto increment | INTEGER PRIMARY KEY AUTOINCREMENT |
INT AUTO_INCREMENT PRIMARY KEY |
| Penanda parameter | ? |
%s |
Tiga perbedaan di atas adalah inti dari seluruh materi bonus ini. Sisanya sama persis.
Langkah 1 - Memasang MySQL dengan XAMPP
Cara termudah memasang MySQL adalah lewat XAMPP (paket yang berisi MySQL dan phpMyAdmin).
-
Unduh XAMPP dari
https://www.apachefriends.org, lalu pasang. - Buka XAMPP Control Panel.
- Klik tombol Start pada baris MySQL (Apache juga di-start bila ingin memakai phpMyAdmin).
- Pastikan statusnya berubah menjadi hijau (berjalan).
Catatan: pengaturan bawaan XAMPP adalah user
root dengan password kosong. Kita
pakai itu untuk latihan.
Langkah 2 - Membuat Database
Cara A - Lewat phpMyAdmin (visual)
-
Buka browser, kunjungi
http://localhost/phpmyadmin. - Klik menu Databases.
-
Ketik nama database:
toko_elektronik, lalu klik Create.
Cara B - Lewat Python
Database juga bisa dibuat dari Python (perhatikan: koneksi awal tanpa menyebut nama database):
import mysql.connector
conn = mysql.connector.connect(
host="localhost",
user="root",
password="",
)
cursor = conn.cursor()
cursor.execute("CREATE DATABASE IF NOT EXISTS toko_elektronik")
print("Database berhasil dibuat.")
conn.close()
Langkah 3 - Memasang Konektor Python
Aktifkan virtual environment project, lalu pasang konektor MySQL:
venv\Scripts\activate
pip install mysql-connector-python
pip freeze > requirements.txt
macOS / Linux: aktifkan dengan
source venv/bin/activate.
Langkah 4 - Menghubungkan Python dengan MySQL
Buat file koneksi_mysql.py. Bandingkan dengan versi
SQLite di Pertemuan 10 — hanya bagian koneksinya yang berbeda.
import mysql.connector
conn = mysql.connector.connect(
host="localhost",
user="root",
password="",
database="toko_elektronik",
)
cursor = conn.cursor()
print("Koneksi MySQL berhasil.")
conn.close()
Jalankan:
python koneksi_mysql.py
Output:
Koneksi MySQL berhasil.
Menyimpan Pengaturan Koneksi
Agar rapi, simpan pengaturan koneksi dalam satu fungsi (nanti dipakai berulang):
import mysql.connector
def get_connection():
return mysql.connector.connect(
host="localhost",
user="root",
password="",
database="toko_elektronik",
)
Langkah 5 - Membuat Tabel di MySQL
Buat file setup_mysql.py. Struktur tabelnya
sama dengan Pertemuan 10; yang berubah hanya
penulisan tipe data dan auto increment.
import mysql.connector
conn = mysql.connector.connect(
host="localhost", user="root", password="", database="toko_elektronik"
)
cursor = conn.cursor()
# --- Tabel produk ---
cursor.execute("""
CREATE TABLE IF NOT EXISTS produk (
id_produk INT AUTO_INCREMENT PRIMARY KEY,
nama_produk VARCHAR(100) NOT NULL,
kategori VARCHAR(50) NOT NULL,
harga INT NOT NULL,
stok INT NOT NULL DEFAULT 0
)
""")
# --- Tabel pelanggan ---
cursor.execute("""
CREATE TABLE IF NOT EXISTS pelanggan (
id_pelanggan INT AUTO_INCREMENT PRIMARY KEY,
nama VARCHAR(100) NOT NULL,
telepon VARCHAR(20),
alamat VARCHAR(255)
)
""")
# --- Tabel penjualan (master) ---
cursor.execute("""
CREATE TABLE IF NOT EXISTS penjualan (
id_penjualan INT AUTO_INCREMENT PRIMARY KEY,
tanggal DATE NOT NULL,
id_pelanggan INT NOT NULL,
total INT NOT NULL DEFAULT 0,
FOREIGN KEY (id_pelanggan) REFERENCES pelanggan(id_pelanggan)
)
""")
# --- Tabel detail_penjualan (detail) ---
cursor.execute("""
CREATE TABLE IF NOT EXISTS detail_penjualan (
id_detail INT AUTO_INCREMENT PRIMARY KEY,
id_penjualan INT NOT NULL,
id_produk INT NOT NULL,
qty INT NOT NULL,
subtotal INT NOT NULL,
FOREIGN KEY (id_penjualan) REFERENCES penjualan(id_penjualan),
FOREIGN KEY (id_produk) REFERENCES produk(id_produk)
)
""")
conn.commit()
conn.close()
print("Empat tabel MySQL berhasil dibuat.")
Perbandingan Tipe Data
| SQLite | MySQL | Keterangan |
|---|---|---|
INTEGER PRIMARY KEY AUTOINCREMENT |
INT AUTO_INCREMENT PRIMARY KEY |
Kunci utama otomatis |
TEXT |
VARCHAR(100) |
Teks — MySQL perlu batas panjang |
TEXT (untuk tanggal) |
DATE |
MySQL punya tipe tanggal khusus |
INTEGER |
INT |
Bilangan bulat |
REAL |
DECIMAL(10,2) |
Bilangan desimal (mis. uang) |
Perbedaan penting: MySQL mewajibkan panjang teks (VARCHAR(100)), sedangkan SQLite tidak. MySQL juga punya tipeDATEsungguhan, sementara di SQLite tanggal disimpan sebagai teks.
Langkah 6 - Mengisi Data (Perhatikan Tanda %s)
Inilah perbedaan ketiga: penanda parameter berubah dari
? menjadi %s.
import mysql.connector
conn = mysql.connector.connect(
host="localhost", user="root", password="", database="toko_elektronik"
)
cursor = conn.cursor()
daftar_produk = [
("Laptop", "Elektronik", 8500000, 10),
("Monitor", "Elektronik", 2000000, 15),
("Printer", "Elektronik", 1500000, 8),
("Mouse", "Aksesoris", 150000, 50),
("Keyboard", "Aksesoris", 250000, 40),
]
# SQLite : VALUES (?, ?, ?, ?)
# MySQL : VALUES (%s, %s, %s, %s)
cursor.executemany(
"INSERT INTO produk (nama_produk, kategori, harga, stok) VALUES (%s, %s, %s, %s)",
daftar_produk,
)
cursor.executemany(
"INSERT INTO pelanggan (nama, telepon, alamat) VALUES (%s, %s, %s)",
[("Budi Santoso", "08123456789", "Jakarta"),
("Siti Aminah", "08234567890", "Tangerang")],
)
conn.commit()
print(cursor.rowcount, "baris terakhir dimasukkan.")
conn.close()
Membaca data — perintah SELECT
sama persis seperti SQLite:
cursor.execute("SELECT * FROM produk")
for baris in cursor.fetchall():
print(baris)
# dengan syarat (perhatikan %s)
cursor.execute("SELECT * FROM produk WHERE kategori = %s", ("Elektronik",))
print(cursor.fetchall())
Jebakan paling sering: lupa mengganti?menjadi%s. Gejalanya muncul error sintaks SQL. Ganti semuanya, maka kode langsung jalan.
Langkah 7 - Memindahkan Data dari SQLite ke MySQL
Inilah inti "migrasi": membaca data lama dari
toko.db, lalu menuliskannya ke MySQL. Buat file
migrasi.py.
import sqlite3
import mysql.connector
# --- sumber: SQLite ---
lite_conn = sqlite3.connect("database/toko.db")
lite_cur = lite_conn.cursor()
# --- tujuan: MySQL ---
my_conn = mysql.connector.connect(
host="localhost", user="root", password="", database="toko_elektronik"
)
my_cur = my_conn.cursor()
# urutan penting: tabel induk lebih dulu, agar Foreign Key tidak gagal
urutan_tabel = ["pelanggan", "produk", "penjualan", "detail_penjualan"]
for tabel in urutan_tabel:
lite_cur.execute(f"SELECT * FROM {tabel}")
baris_data = lite_cur.fetchall()
if not baris_data:
print(f"{tabel}: kosong, dilewati.")
continue
# ambil nama kolom dari hasil query
kolom = [d[0] for d in lite_cur.description]
nama_kolom = ", ".join(kolom)
penanda = ", ".join(["%s"] * len(kolom)) # -> %s, %s, %s, ...
sql = f"INSERT INTO {tabel} ({nama_kolom}) VALUES ({penanda})"
my_cur.executemany(sql, baris_data)
print(f"{tabel}: {len(baris_data)} baris dipindahkan.")
my_conn.commit()
lite_conn.close()
my_conn.close()
print("Migrasi selesai.")
Output:
pelanggan: 2 baris dipindahkan.
produk: 5 baris dipindahkan.
penjualan: 1 baris dipindahkan.
detail_penjualan: 2 baris dipindahkan.
Migrasi selesai.
Mengapa urutan tabel penting? Karenapenjualanmemiliki Foreign Key kepelanggan. Bilapenjualandimasukkan lebih dulu sementarapelangganmasih kosong, MySQL akan menolak datanya. Aturannya: tabel induk dulu, tabel anak kemudian.
Langkah 8 - Membuktikan Relasi Bekerja di MySQL
Uji dengan JOIN — perintahnya
identik dengan Pertemuan 10.
import mysql.connector
conn = mysql.connector.connect(
host="localhost", user="root", password="", database="toko_elektronik"
)
cursor = conn.cursor()
query = """
SELECT p.id_penjualan, p.tanggal, c.nama, pr.nama_produk, d.qty, d.subtotal
FROM penjualan p
JOIN pelanggan c ON p.id_pelanggan = c.id_pelanggan
JOIN detail_penjualan d ON p.id_penjualan = d.id_penjualan
JOIN produk pr ON d.id_produk = pr.id_produk
"""
cursor.execute(query)
for baris in cursor.fetchall():
print(baris)
conn.close()
Output:
(1, datetime.date(2025, 3, 1), 'Budi Santoso', 'Laptop', 1, 8500000)
(1, datetime.date(2025, 3, 1), 'Budi Santoso', 'Mouse', 2, 300000)
Hasilnya sama seperti SQLite. Perbedaannya hanya kolom
tanggal kini bertipe date sungguhan
(bukan teks), karena MySQL memiliki tipe DATE.
Referensi Perintah Penting
Perbandingan Kode SQLite vs MySQL
| Kegiatan | SQLite | MySQL |
|---|---|---|
| Import | import sqlite3 |
import mysql.connector |
| Koneksi | sqlite3.connect("toko.db") |
mysql.connector.connect(host=..., user=..., password=...,
database=...)
|
| Cursor | conn.cursor() |
conn.cursor() |
| Parameter | VALUES (?, ?) |
VALUES (%s, %s) |
| Auto increment | INTEGER PRIMARY KEY AUTOINCREMENT |
INT AUTO_INCREMENT PRIMARY KEY |
| Teks | TEXT |
VARCHAR(100) |
| Id terakhir | cursor.lastrowid |
cursor.lastrowid |
| Simpan | conn.commit() |
conn.commit() |
| Tutup | conn.close() |
conn.close() |
Menangani Error Koneksi
import mysql.connector
try:
conn = mysql.connector.connect(
host="localhost", user="root", password="", database="toko_elektronik"
)
print("Terhubung.")
conn.close()
except mysql.connector.Error as e:
print("Gagal terhubung:", e)
Troubleshooting
| Masalah | Penyebab | Solusi |
|---|---|---|
Can't connect to MySQL server |
MySQL belum dijalankan | Buka XAMPP, klik Start pada MySQL |
Access denied for user 'root' |
Password salah |
Bawaan XAMPP: password
kosong (password="")
|
Unknown database 'toko_elektronik'
|
Database belum dibuat | Buat lewat phpMyAdmin atau Langkah 2 |
You have an error in your SQL syntax |
Masih memakai ? |
Ganti seluruh ? menjadi %s |
Cannot add or update a child row |
Urutan pengisian salah (FK gagal) |
Isi tabel induk (pelanggan,
produk) lebih dulu
|
Duplicate entry for key PRIMARY |
Data sudah pernah dimasukkan | Kosongkan tabel, atau jangan jalankan skrip dua kali |
No module named 'mysql' |
Konektor belum dipasang | pip install mysql-connector-python |
| Port 3306 bentrok | Ada MySQL lain berjalan | Matikan layanan MySQL lain, atau ubah port di XAMPP |
Tugas Bonus
Kerjakan bila ingin memperoleh nilai tambahan.
-
Pasang XAMPP, jalankan MySQL, dan buat database
toko_elektronik. - Buat keempat tabel di MySQL (produk, pelanggan, penjualan, detail_penjualan) beserta relasinya.
-
Pindahkan seluruh data dari
toko.dbke MySQL menggunakan skrip migrasi. - Buktikan migrasi berhasil dengan menampilkan:
- Jumlah baris tiap tabel di MySQL.
-
Hasil query
JOIN(isi nota) — harus sama dengan hasil di SQLite.
- Tantangan: buat satu transaksi baru langsung di MySQL (satu nota berisi 2 barang, stok berkurang, total benar).
Kumpulkan: file .py yang dibuat, tangkapan layar
phpMyAdmin yang memperlihatkan tabel beserta isinya, dan tangkapan
layar hasil menjalankan program.
Kesimpulan
Materi bonus ini memperlihatkan bahwa berpindah dari
SQLite ke MySQL jauh lebih mudah
daripada yang dibayangkan. Struktur database, perintah SQL, konsep
Primary Key dan Foreign Key, serta pola kerja
cursor seluruhnya tetap sama. Yang benar-benar
berubah hanya tiga: cara koneksi, penulisan
auto increment dan tipe data, serta
penanda parameter (? menjadi
%s). Dengan memahami ini, keterampilan database yang
dipelajari di mata kuliah ini dapat langsung diterapkan pada
aplikasi nyata maupun tugas akhir yang umumnya memakai MySQL.