Menulis DataFrames ke Tabel Basis Data
Simpan DataFrame yang telah dibersihkan ke tabel baru atau yang sudah ada dengan DataFrame.to_sql(), serta kendalikan if_exists dan chunksize.
Menulis DataFrames ke Tabel Basis Data adalah pelajaran Pandas & NumPy Academy gratis di CoddyKit. Ini adalah pelajaran 3 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Pandas & NumPy Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Pandas & NumPy Academy mencakup 4 pelajaran total.
Mengapa Menulis DataFrame ke Basis Data?
Setelah membersihkan dan mengubah data di Pandas, Anda sering perlu menyimpan hasil secara permanen kembali ke basis data: agar hasil tersebut tersedia bagi aplikasi lain, dasbor, atau anggota tim; untuk menyimpan hasil analisis bertahap; atau untuk membangun data mart dari data lake mentah. DataFrame.to_sql() adalah metode standar Pandas untuk menulis data ke basis data apa pun yang didukung SQLAlchemy dalam satu pemanggilan.
Penggunaan Dasar to_sql()
df.to_sql('table_name', con=engine, if_exists='replace', index=False) menulis DataFrame ke tabel basis data. Parameter if_exists mengatur tindakan jika tabel tersebut sudah ada: 'fail' menghasilkan kesalahan, 'replace' menghapus lalu membuat ulang tabel, dan 'append' menambahkan baris baru tanpa mengubah baris yang sudah ada. Selalu tetapkan index=False kecuali Anda memang ingin menyimpan indeks DataFrame sebagai kolom di basis data.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///results.db')
df = pd.DataFrame({
'date': pd.date_range('2024-01-01', periods=5),
'revenue': [1200.0, 980.5, 1450.0, 760.3, 1100.0],
'region': ['North', 'South', 'East', 'West', 'North']
})
df.to_sql('daily_revenue', con=engine,
if_exists='replace', index=False)
print('Table written successfully')Penjelasan Parameter if_exists
Ketiga nilai if_exists digunakan untuk kebutuhan yang berbeda. 'replace' digunakan dalam pengembangan: hapus tabel lama dan buat tabel baru — perubahan skema dilakukan secara otomatis, tetapi semua data lama hilang. 'append' digunakan untuk pemuatan bertahap: tambahkan baris baru ke tabel yang sudah ada tanpa mengubah strukturnya — berguna untuk pekerjaan batch harian. 'fail' adalah pengaman: gunakan untuk melindungi tabel penting agar tidak tertimpa secara tidak sengaja oleh alur kerja yang memiliki kesalahan.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///results.db')
new_batch = pd.DataFrame({
'date': ['2024-06-01', '2024-06-02'],
'revenue': [1500.0, 1300.0],
'region': ['North', 'East']
})
# Append new rows without losing existing data
new_batch.to_sql('daily_revenue', con=engine,
if_exists='append', index=False)
print('Appended new rows')Mengontrol Tipe Data Kolom
Secara bawaan, to_sql() memetakan tipe data Pandas ke tipe SQLAlchemy secara otomatis. Terkadang nilai bawaan tersebut tidak tepat — misalnya, kolom datetime64 dapat disimpan sebagai TEXT di SQLite. Gunakan parameter dtype untuk menentukan tipe SQL yang tepat menggunakan objek tipe SQLAlchemy. Hal ini memastikan penyimpanan yang benar, pengindeksan yang tepat, dan penanganan tipe yang akurat ketika data dibaca kembali. Selalu verifikasi skema setelah penulisan dengan PRAGMA table_info() atau inspector.get_columns() secara singkat.
import pandas as pd
import sqlalchemy as sa
from sqlalchemy import types
engine = sa.create_engine('sqlite:///results.db')
df = pd.DataFrame({
'id': [1, 2, 3],
'name': ['Alice', 'Bob', 'Carol'],
'score': [0.95, 0.87, 0.91],
'created_at': pd.to_datetime(['2024-01-01', '2024-01-02', '2024-01-03'])
})
df.to_sql('users', con=engine, if_exists='replace', index=False,
dtype={'id': types.Integer(),
'score': types.Float(),
'created_at': types.DateTime()})Menulis dalam Potongan dengan chunksize
Untuk DataFrame berukuran besar, to_sql() tanpa chunksize mencoba menyisipkan semua baris dalam satu pernyataan, yang dapat gagal karena waktu tunggu basis data habis atau terjadi kesalahan memori. Tentukan chunksize=N untuk menyisipkan N baris per transaksi. Dengan demikian, basis data dapat melakukan commit secara bertahap dan penggunaan memori puncak berkurang. Nilai chunksize sebesar 10.000–50.000 baris biasanya menyeimbangkan kecepatan penyisipan dan penggunaan memori, tetapi nilai optimalnya bergantung pada basis data dan latensi jaringan Anda.
import pandas as pd
import sqlalchemy as sa
import numpy as np
engine = sa.create_engine('sqlite:///results.db')
# Large DataFrame
df = pd.DataFrame({
'id': range(500000),
'value': np.random.randn(500000)
})
# Insert in chunks of 10,000 rows at a time
df.to_sql('large_table', con=engine,
if_exists='replace',
index=False,
chunksize=10000)
print('Written 500,000 rows')Upsert: Menyisipkan atau Memperbarui
to_sql() milik Pandas tidak mendukung upsert secara bawaan (menyisipkan jika baru, memperbarui jika sudah ada). Untuk menerapkan upsert, gunakan Core SQLAlchemy dengan pernyataan INSERT OR REPLACE (SQLite) atau ON CONFLICT DO UPDATE (PostgreSQL). Solusi umum dalam Pandas adalah menulis ke tabel penahapan sementara dengan if_exists='replace', lalu menjalankan SQL mentah untuk menggabungkan tabel penahapan ke tabel produksi, kemudian menghapus tabel penahapan.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///results.db')
new_data = pd.DataFrame({
'id': [1, 2, 5],
'value': [99.9, 88.8, 77.7]
})
# Write to staging table
new_data.to_sql('staging', con=engine,
if_exists='replace', index=False)
# Merge into production (SQLite syntax)
with engine.connect() as conn:
conn.execute(sa.text(
'INSERT OR REPLACE INTO production SELECT * FROM staging'
))
conn.commit()
print('Upsert complete')Memverifikasi Penulisan
Setelah menulis, selalu verifikasi hasilnya dengan membaca kembali jumlah ringkasan dan jumlah baris. Bandingkan keduanya dengan DataFrame sumber. Langkah ini mendeteksi kegagalan tersembunyi yang disebabkan oleh ketidakcocokan tipe data (misalnya, NaN dalam kolom bilangan bulat yang menyebabkan penyisipan sebagian) atau batasan basis data (misalnya, pelanggaran kunci unik yang secara diam-diam melewati beberapa baris dalam konfigurasi tertentu). SELECT COUNT(*) FROM table secara singkat setelah setiap pemanggilan to_sql menambah beban yang sangat kecil dan mencegah kehilangan data secara diam-diam.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///results.db')
df = pd.DataFrame({'id': range(1000), 'value': range(1000)})
df.to_sql('my_table', con=engine, if_exists='replace', index=False)
# Verify
with engine.connect() as conn:
count = conn.execute(sa.text('SELECT COUNT(*) FROM my_table')).scalar()
print(f'Source rows: {len(df)}, DB rows: {count}')
assert count == len(df), 'Row count mismatch!'Menambahkan Kunci Utama Setelah Penulisan
to_sql() menulis data, tetapi tidak menambahkan kunci utama atau batasan basis data — fungsi ini membuat tabel biasa. Untuk tabel produksi, tambahkan batasan kunci utama secara terpisah menggunakan SQL mentah yang dijalankan melalui SQLAlchemy. SQLite mengharuskan tabel dibuat ulang untuk menambahkan batasan setelah pembuatan, sedangkan PostgreSQL mendukung ALTER TABLE ADD PRIMARY KEY. Sebagai alternatif, tentukan skema lengkap sejak awal dan gunakan if_exists='append' untuk menyisipkan data ke tabel yang sudah ada dan didefinisikan dengan benar.
import pandas as pd
import sqlalchemy as sa
from sqlalchemy import Table, Column, Integer, Float, MetaData
engine = sa.create_engine('sqlite:///results.db')
meta = MetaData()
# Define table with primary key
my_table = Table('defined_table', meta,
Column('id', Integer, primary_key=True),
Column('value', Float)
)
meta.create_all(engine) # Create table with constraints
# Then insert data using append
df = pd.DataFrame({'id': range(5), 'value': [1.1, 2.2, 3.3, 4.4, 5.5]})
df.to_sql('defined_table', con=engine,
if_exists='append', index=False)Penulisan Transaksional
Untuk menjaga konsistensi data, bungkus to_sql() dalam transaksi eksplisit. Jika salah satu langkah dalam penulisan ke beberapa tabel gagal, Anda dapat membatalkan semua perubahan. Tanpa transaksi, penulisan sebagian dapat membuat basis data berada dalam keadaan tidak konsisten. Pengelola konteks koneksi SQLAlchemy dengan conn.begin() memungkinkan pengendalian transaksi secara manual. Sebagai alternatif, gunakan engine.begin() untuk blok commit otomatis yang melakukan rollback jika terjadi pengecualian.
import pandas as pd
import sqlalchemy as sa
engine = sa.create_engine('sqlite:///results.db')
df_orders = pd.DataFrame({'id': [1, 2], 'amount': [100.0, 200.0]})
df_summary = pd.DataFrame({'total': [300.0], 'count': [2]})
try:
with engine.begin() as conn: # Auto-rollback on exception
df_orders.to_sql('orders_v2', con=conn,
if_exists='replace', index=False)
df_summary.to_sql('summary_v2', con=conn,
if_exists='replace', index=False)
print('Both tables written atomically')
except Exception as e:
print(f'Write failed, rolled back: {e}')Performa: Metode Penyisipan Massal
Secara bawaan, to_sql() menyisipkan satu baris per pernyataan SQL, yang sangat lambat untuk DataFrame berukuran besar. Teruskan method='multi' untuk menggunakan satu INSERT dengan beberapa tuple nilai — biasanya 10–100 kali lebih cepat. Untuk PostgreSQL, teruskan fungsi method khusus yang menggunakan protokol COPY (melalui copy_expert milik psycopg2) untuk pemuatan massal tercepat. Metode yang optimal bergantung pada versi basis data dan pengaturan jaringan Anda.
import pandas as pd
import sqlalchemy as sa
import numpy as np
import time
engine = sa.create_engine('sqlite:///perf.db')
df = pd.DataFrame({'a': range(100000), 'b': np.random.randn(100000)})
# Default (one row per INSERT) — slow
start = time.time()
df.to_sql('test_default', con=engine, if_exists='replace', index=False)
print(f'Default: {time.time()-start:.2f}s')
# multi-row INSERT — faster
start = time.time()
df.to_sql('test_multi', con=engine, if_exists='replace',
index=False, method='multi', chunksize=1000)
print(f'Multi: {time.time()-start:.2f}s')Pencatatan dan Audit Penulisan
Dalam alur kerja produksi, lacak apa yang ditulis dan kapan dengan memelihara tabel catatan audit. Setelah setiap to_sql() berhasil, sisipkan satu baris ke catatan audit yang berisi nama tabel, jumlah baris, cap waktu, dan ID eksekusi alur kerja. Dengan demikian, eksekusi yang hilang, penulisan ganda, atau perubahan skema dari waktu ke waktu dapat dideteksi dengan mudah. Catatan audit itu sendiri merupakan DataFrame Pandas yang ditulis melalui to_sql — teknik yang sama diterapkan secara rekursif untuk pemantauan operasional.
import pandas as pd
import sqlalchemy as sa
from datetime import datetime
engine = sa.create_engine('sqlite:///results.db')
def write_with_audit(df, table_name, engine, run_id):
df.to_sql(table_name, con=engine, if_exists='append', index=False)
audit = pd.DataFrame([{
'run_id': run_id,
'table_name': table_name,
'rows_written': len(df),
'written_at': datetime.utcnow().isoformat()
}])
audit.to_sql('audit_log', con=engine, if_exists='append', index=False)
print(f'Wrote {len(df)} rows to {table_name}')
df = pd.DataFrame({'id': [1, 2], 'val': [10, 20]})
write_with_audit(df, 'my_table', engine, run_id='run_001')Pemeriksaan Singkat
Uji pemahaman Anda tentang konsep Analisis Data dari pelajaran ini.
Ringkasan Pelajaran
Dalam pelajaran ini Anda mempelajari bahwa df.to_sql() menulis DataFrame ke tabel basis data apa pun yang terhubung melalui SQLAlchemy, dengan parameter if_exists yang mengatur perilaku pembuatan/penambahan/penggantian; chunksize dan method='multi' meningkatkan performa untuk DataFrame berukuran besar; dan penulisan transaksional dengan engine.begin() memastikan pembaruan atomik ke beberapa tabel yang dibatalkan jika terjadi kegagalan. Selanjutnya, kita akan membandingkan Pandas dan SQL untuk memahami kapan masing-masing alat menjadi pilihan yang lebih baik.
Pertanyaan yang Sering Diajukan
Apakah pelajaran “Menulis DataFrames ke Tabel Basis Data” gratis?
Ya — teks lengkap “Menulis DataFrames ke Tabel Basis Data” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Pandas & NumPy Academy, upgrade ke CoddyKit PRO. Kursus Pandas & NumPy Academy mencakup 4 pelajaran total.
Apa yang akan aku pelajari di “Menulis DataFrames ke Tabel Basis Data”?
Simpan DataFrame yang telah dibersihkan ke tabel baru atau yang sudah ada dengan DataFrame.to_sql(), serta kendalikan if_exists dan chunksize. Kamu berlatih Pandas & NumPy Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.
Apakah aku perlu pengalaman untuk memulai Pandas & NumPy Academy?
Tidak diperlukan pengalaman sebelumnya. Pandas & NumPy Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 3 dari 4.
Berapa lama pelajaran “Menulis DataFrames ke Tabel Basis Data” memakan waktu?
Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.
Bisakah aku menulis dan menjalankan kode dalam pelajaran Pandas & NumPy Academy ini?
Ya. Setiap pelajaran Pandas & NumPy Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.
Semua pelajaran dalam kursus ini
- Menghubungkan ke Basis Data dengan SQLAlchemy
- Menjalankan Kueri SQL dari Pandas
- Menulis DataFrames ke Tabel Basis Data
- Pandas vs. SQL: Memilih Alat yang Tepat