Alur data tidak berhenti di pembacaan. Setelah data transaksi dibersihkan, diperkaya, atau diagregasi di pandas, hasil kerja itu sering perlu kembali ke database agar bisa dipakai aplikasi, dashboard, atau rekan tim yang bekerja dengan SQL. Menulis perintah INSERT baris demi baris secara manual melelahkan dan rawan salah tipe. Method DataFrame.to_sql() menyelesaikannya: satu panggilan menulis seluruh DataFrame menjadi tabel database, lengkap dengan pembuatan kolom dan tipe data secara otomatis. Chapter ini membahas penulisan tabel pertama, tiga mode parameter if_exists, dan kebiasaan aman saat menulis ke database.

Method to_sql() membutuhkan dua informasi utama: nama tabel tujuan dan koneksi database — dalam praktik kita, SQLAlchemy engine. Bila tabel belum ada, pandas merancang struktur tabel sendiri dari dtype DataFrame: int64 menjadi INTEGER, float64 menjadi FLOAT, str menjadi TEXT, dan datetime64 menjadi TIMESTAMP. Parameter index mengatur nasib index DataFrame: secara default index=True sehingga index ikut disimpan sebagai kolom bernama index; berikan index=False bila kolom penomoran itu tidak dibutuhkan. Parameter dtype tersedia untuk memaksa tipe kolom tertentu, dan chunksize memecah penulisan menjadi beberapa batch. Semua pilihan tersebut terdokumentasi di halaman pandas.DataFrame.to_sql .

Mengatur Mode Penulisan if_exists #

Parameter if_exists menentukan tindakan pandas ketika tabel tujuan sudah ada. Tiga nilainya punya karakter yang berbeda:

NilaiPerilaku ketika tabel sudah ada
"fail" (default)Gagal dengan ValueError; tabel lama tidak disentuh
"append"Baris baru ditambahkan di bawah data lama
"replace"Tabel lama dihapus, lalu dibuat ulang dari DataFrame

Skrip berikut mencoba ketiganya secara berurutan pada database SQLite sementara, termasuk menangkap pesan galat yang muncul pada mode fail. Contoh penulisan data ke SQL lain juga dijelaskan pada halaman IO Tools dokumentasi pandas.

python
from pathlib import Path

import pandas as pd
from sqlalchemy import create_engine

penjualan = pd.DataFrame({
    "produk": ["Kopi Gayo", "Teh Melati", "Gula Aren"],
    "harga": [85000, 32000, 24000],
    "jumlah": [12, 30, 25],
})

db_path = Path("toko.db")
engine = create_engine(f"sqlite:///{db_path}")

penjualan.to_sql("penjualan", engine, index=False)
print("to_sql pertama: tabel 'penjualan' berhasil dibuat")
print()

try:
    penjualan.to_sql("penjualan", engine, index=False, if_exists="fail")
except ValueError as pesan:
    print("if_exists='fail' :", pesan)

penjualan.to_sql("penjualan", engine, index=False, if_exists="append")
df_append = pd.read_sql_table("penjualan", engine)
print("if_exists='append' : jumlah baris =", len(df_append))

penjualan.to_sql("penjualan", engine, index=False, if_exists="replace")
df_replace = pd.read_sql_table("penjualan", engine)
print("if_exists='replace': jumlah baris =", len(df_replace))
print()
print(df_replace)

engine.dispose()
db_path.unlink()
print()
print("File database sementara sudah dihapus:", not db_path.exists())

Output yang Dihasilkan:

text
to_sql pertama: tabel 'penjualan' berhasil dibuat

if_exists='fail' : Table 'penjualan' already exists.
if_exists='append' : jumlah baris = 6
if_exists='replace': jumlah baris = 3

       produk  harga  jumlah
0   Kopi Gayo  85000      12
1  Teh Melati  32000      30
2   Gula Aren  24000      25

File database sementara sudah dihapus: True

Baris demi baris, inilah yang terjadi:

  1. Baris 12-13: database SQLite sementara toko.db dibuat dan SQLAlchemy engine menunjuknya.
  2. Baris 15-16: to_sql() pertama tanpa if_exists — tabel belum ada, sehingga pandas membuat tabel penjualan lalu mengisinya dengan tiga baris.
  3. Baris 19-22: penulisan kedua dengan mode fail memunculkan ValueError: Table 'penjualan' already exists.; blok try/except menangkap pesan tersebut dan menampilkannya.
  4. Baris 24-26: mode append menambah tiga baris lagi, sehingga tabel berisi 6 baris.
  5. Baris 28-32: mode replace mengganti seluruh isi tabel; jumlah baris kembali 3 dan struktur kolom dirancang ulang dari DataFrame.
  6. Baris 34-37: engine ditutup dengan dispose(), file database latihan dihapus, dan keberhasilan pembersihan dikonfirmasi.

Memilih Mode dengan Aman #

Mode append cocok untuk data yang bertambah berkala, misalnya transaksi harian, tetapi perlu diwaspadai: menjalankan ulang skrip yang sama akan menggandakan baris karena pandas tidak memeriksa duplikasi. Mode replace pas untuk snapshot laporan yang selalu mencerminkan kondisi terbaru, sedangkan mode fail berperan sebagai pengaman yang menolak menimpa tabel yang sudah ada tanpa izin eksplisit dari kita.

Database kini masuk daftar sumber sekaligus tujuan data kita. Namun format yang paling sering bertukar tangan sehari-hari tetap CSV, dan membacanya dengan benar menuntut penguasaan parameter. Chapter berikutnya mengulas parameter-parameter read_csv() yang paling sering dipakai.