LOAD DATA membaca baris dari sebuah berkas dan menyisipkannya ke dalam tabel dalam satu pernyataan, sehingga impor data massal jauh lebih cepat daripada ratusan pernyataan INSERT terpisah. Varian LOAD DATA LOCAL INFILE membaca berkas dari sisi klien, yaitu mesin tempat klien mysql dijalankan, bukan dari server. Topik ini membahas impor berkas CSV berisi catatan peminjaman perpustakaan, mulai dari penyiapan tabel sasarannya, penanganan baris judul dan pemetaan kolom, penulisan nilai NULL, sampai verifikasi hasil impor.
Tabel sasaran dan berkas CSV#
Tabel sasarannya adalah tabel peminjaman pada basis data sirkulasi, yang menyimpan catatan pinjam meminjam buku. Setiap baris memuat nomor kartu anggota, kode buku, tanggal pinjam, dan tanggal kembali. Kolom tanggal_kembali boleh NULL karena buku yang masih dipinjam belum memiliki tanggal kembaliannya. Skema berikut membuat ulang basis data tersebut dari nol.
-- tidak-dijalankan
DROP DATABASE IF EXISTS sirkulasi;
CREATE DATABASE sirkulasi;
USE sirkulasi;
CREATE TABLE peminjaman (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
nomor_kartu VARCHAR(12) NOT NULL,
kode_buku VARCHAR(12) NOT NULL,
tanggal_pinjam DATE NOT NULL,
tanggal_kembali DATE NULL
);# membuat ulang basis data sirkulasi beserta tabel peminjaman
mysql -u root < skema-peminjaman.sqlBerkas yang diimpor adalah peminjam.csv, hasil ekspor dari sistem sirkulasi lama. Baris pertamanya adalah baris judul (header) yang berisi nama kolom, sedangkan baris berikutnya adalah data. Tanggal kembali yang belum ada ditulis \N, yaitu penanda NULL standar untuk LOAD DATA. Tanda ini juga dipakai oleh SELECT INTO OUTFILE ketika mengekspor tabel yang berisi NULL. Berkas tersebut disimpan di samping index.md dalam topik ini, dan perintah impor dijalankan dari direktori yang memuat berkas itu.
nomor_kartu,kode_buku,tanggal_pinjam,tanggal_kembali
K-0001,B-101,2026-10-20,2026-10-27
K-0002,B-102,2026-10-22,\N
K-0003,B-101,2026-10-24,\N
K-0001,B-103,2026-10-25,2026-11-02
K-0004,B-102,2026-10-26,\NMengimpor dengan LOAD DATA LOCAL INFILE#
Impor berkas dari sisi klien memerlukan izin pada dua sisi sekaligus. Sisi server mengizinkannya melalui variabel sistem local_infile, sedangkan sisi klien mengizinkannya melalui opsi --local-infile=1. Nilai variabel server diperiksa lebih dahulu sebelum mengimpor.
# memeriksa izin impor lokal pada sisi server
mysql -t -u root -e "SHOW VARIABLES LIKE 'local_infile';"+---------------+-------+
| Variable_name | Value |
+---------------+-------+
| local_infile | ON |
+---------------+-------+Sintaks inti pernyataannya menyebut sumber berkas, tabel sasaran, opsi format, jumlah baris yang dilewati, dan daftar kolom. Klausa FIELDS TERMINATED BY ',' menyesuaikan pemisah dengan berkas CSV, sedangkan IGNORE 1 LINES melewati baris judul. Daftar kolom memetakan setiap bidang berkas ke kolom tabel sesuai urutannya, dan kolom id tidak disebutkan karena diisi otomatis oleh AUTO_INCREMENT.
-- tidak-dijalankan
LOAD DATA LOCAL INFILE 'nama_berkas.csv' INTO TABLE nama_tabel
FIELDS TERMINATED BY ',' IGNORE 1 LINES
(kolom_1, kolom_2, kolom_3);# mengimpor peminjam.csv ke tabel peminjaman
mysql -u root --local-infile=1 -e "LOAD DATA LOCAL INFILE 'peminjam.csv' INTO TABLE sirkulasi.peminjaman FIELDS TERMINATED BY ',' IGNORE 1 LINES (nomor_kartu, kode_buku, tanggal_pinjam, tanggal_kembali);"# memeriksa isi tabel hasil impor
mysql -t -u root sirkulasi -e "SELECT id, nomor_kartu, kode_buku, tanggal_pinjam, tanggal_kembali FROM peminjaman ORDER BY id;"+----+-------------+-----------+----------------+-----------------+
| id | nomor_kartu | kode_buku | tanggal_pinjam | tanggal_kembali |
+----+-------------+-----------+----------------+-----------------+
| 1 | K-0001 | B-101 | 2026-10-20 | 2026-10-27 |
| 2 | K-0002 | B-102 | 2026-10-22 | NULL |
| 3 | K-0003 | B-101 | 2026-10-24 | NULL |
| 4 | K-0001 | B-103 | 2026-10-25 | 2026-11-02 |
| 5 | K-0004 | B-102 | 2026-10-26 | NULL |
+----+-------------+-----------+----------------+-----------------+Seluruh baris data masuk dengan id 1 sampai 5, dan tiga baris bertanda \N benar-benar tersimpan sebagai NULL pada kolom tanggal_kembali.
Nilai NULL dan opsi format#
Penanda \N adalah satu-satunya bentuk yang dibaca LOAD DATA sebagai NULL. Bidang kosong memiliki arti yang berbeda, yaitu string kosong. Apabila string kosong masuk ke kolom DATE, MySQL mengisinya dengan tanggal nol 0000-00-00 pada server yang permisif atau menolak barisnya dengan error pada server yang menjalankan mode ketat. Karena itu, nilai NULL pada berkas impor sebaiknya selalu ditulis \N secara eksplisit. Pernyataan berikut memeriksa baris peminjaman yang bukunya belum kembali.
# menyaring baris dengan tanggal kembali NULL
mysql -t -u root sirkulasi -e "SELECT id, nomor_kartu, kode_buku FROM peminjaman WHERE tanggal_kembali IS NULL ORDER BY id;"+----+-------------+-----------+
| id | nomor_kartu | kode_buku |
+----+-------------+-----------+
| 2 | K-0002 | B-102 |
| 3 | K-0003 | B-101 |
| 5 | K-0004 | B-102 |
+----+-------------+-----------+Tiga baris lolos saringan IS NULL, yaitu tepat tiga baris yang bertanda \N pada berkasnya. Hasil ini sekaligus membuktikan bahwa pemetaan kolom berjalan sesuai urutan yang dituliskan.
Opsi format LOAD DATA dapat disesuaikan dengan bentuk berkas yang diimpor. Berkas dengan pemisah titik koma, bidang yang diapit tanda kutip, akhir baris Windows, atau lebih dari satu baris judul masing-masing memerlukan opsi yang berbeda.
-- tidak-dijalankan
LOAD DATA LOCAL INFILE 'data.csv' INTO TABLE nama_tabel
CHARACTER SET utf8mb4
FIELDS TERMINATED BY ';' ENCLOSED BY '"' ESCAPED BY '\\'
LINES TERMINATED BY '\r\n' IGNORE 2 LINES
(kolom_1, kolom_2, kolom_3);Klausa CHARACTER SET utf8mb4 menetapkan charset berkas, ENCLOSED BY '"' memperhitungkan bidang yang diapit tanda kutip, dan ESCAPED BY mengatur karakter pelolosnya. LINES TERMINATED BY '\r\n' menyesuaikan berkas dengan akhir baris Windows, sedangkan angka pada IGNORE 2 LINES disesuaikan dengan jumlah baris judul yang harus dilewati.
Impor ulang dan data ganda#
LOAD DATA melakukan penyisipan massal tanpa memeriksa duplikasi terhadap data yang sudah ada. Menjalankan pernyataan impor yang sama dua kali menambah seluruh barisnya sekali lagi, dan tabel yang semula berisi lima baris menjadi memuat sepuluh baris dengan data identik.
# mengimpor berkas yang sama untuk kedua kalinya
mysql -u root --local-infile=1 -e "LOAD DATA LOCAL INFILE 'peminjam.csv' INTO TABLE sirkulasi.peminjaman FIELDS TERMINATED BY ',' IGNORE 1 LINES (nomor_kartu, kode_buku, tanggal_pinjam, tanggal_kembali);"
# menghitung baris setelah dua kali impor
mysql -t -u root sirkulasi -e "SELECT COUNT(*) AS jumlah_baris FROM peminjaman;"+--------------+
| jumlah_baris |
+--------------+
| 10 |
+--------------+Perilaku ini wajar untuk impor ke tabel kosong, tetapi berbahaya apabila impor dijalankan ulang setelah gagal sebagian atau setelah lupa bahwa tabelnya sudah terisi. Pola yang aman untuk pengulangan penuh adalah mengosongkan tabel dengan TRUNCATE TABLE terlebih dahulu, lalu mengimpor ulang dari awal. TRUNCATE mengosongkan tabel sekaligus mengembalikan penghitung AUTO_INCREMENT, sehingga id yang dihasilkan sama dengan impor pertama.
Perlindungan lainnya ada pada sisi skema. UNIQUE KEY pada kombinasi kolom yang menentukan keunikan baris, misalnya (nomor_kartu, kode_buku, tanggal_pinjam), membuat baris ganda ditolak dengan error duplikasi alih-alih tersimpan diam-diam. Pengosongan dengan TRUNCATE tetap diperlukan sebelum impor diulang, tetapi penggandaan yang tidak disengaja setidaknya berhenti sebagai error, bukan sebagai data yang terlihat normal.
# mengosongkan tabel lalu mengimpor ulang dari awal
mysql -t -u root --local-infile=1 sirkulasi <<'SQL'
TRUNCATE TABLE peminjaman;
LOAD DATA LOCAL INFILE 'peminjam.csv' INTO TABLE peminjaman
FIELDS TERMINATED BY ',' IGNORE 1 LINES
(nomor_kartu, kode_buku, tanggal_pinjam, tanggal_kembali);
SELECT COUNT(*) AS jumlah_baris FROM peminjaman;
SQL+--------------+
| jumlah_baris |
+--------------+
| 5 |
+--------------+Kesalahan umum#
Kesalahan pertama adalah menjalankan LOAD DATA LOCAL tanpa opsi --local-infile=1 pada klien, misalnya karena perintahnya dipindahkan dari satu skrip ke skrip lain tanpa opsinya. Meskipun variabel local_infile pada server sudah ON, klien menolak permintaan berkas dari server dan impor berhenti dengan error.
# menjalankan impor tanpa opsi --local-infile pada klien
mysql -u root -e "LOAD DATA LOCAL INFILE 'peminjam.csv' INTO TABLE sirkulasi.peminjaman FIELDS TERMINATED BY ',' IGNORE 1 LINES (nomor_kartu, kode_buku, tanggal_pinjam, tanggal_kembali);"ERROR 2068 (HY000) at line 1: LOAD DATA LOCAL INFILE file request rejected due to restrictions on access.Pesan errornya menyatakan bahwa permintaan berkas ditolak karena batasan akses. Perbaikannya dengan menambahkan opsi --local-infile=1 pada perintah mysql, sebagaimana contoh pada bagian sebelumnya.
Kesalahan kedua adalah melupakan IGNORE 1 LINES pada berkas yang memiliki baris judul. Baris judul ikut terimpor sebagai data, dan kolom tanggalnya diisi teks judul. Pada server yang permisif, baris semacam itu tersimpan dengan tanggal nol dan mengotori isi tabel, sedangkan pada server dengan mode ketat, nilai yang tidak sah menghentikan impor dengan error konversi. Jumlah baris selalu diperiksa setelah impor agar kejadian ini terlihat.
Kesalahan ketiga adalah menganggap bidang kosong sebagai NULL. Bidang kosong berarti string kosong, sedangkan NULL harus ditulis \N. Keduanya menghasilkan isi tabel yang berbeda, sebagaimana dibahas pada bagian tentang nilai NULL dan opsi format.
Ringkasan#
- LOAD DATA LOCAL INFILE mengimpor berkas dari sisi klien dan memerlukan izin pada dua sisi, yaitu variabel
local_infilepada server dan opsi--local-infile=1pada klien. IGNORE 1 LINESmelewati baris judul, sedangkan daftar kolom memetakan bidang berkas ke kolom tabel secara berurutan.- NULL pada berkas impor ditulis
\N, karena bidang kosong berarti string kosong dan bukan NULL. - LOAD DATA tidak memeriksa duplikasi, sehingga impor ulang menggandakan data. Kosongkan tabel dengan TRUNCATE TABLE sebelum mengulang impor dari awal.
Referensi#
- LOAD DATA Statement — Oracle — Dokumentasi resmi LOAD DATA, termasuk penanganan NULL, ESCAPED BY, dan IGNORE.
- Security Considerations for LOAD DATA LOCAL — Oracle — Risiko keamanan LOAD DATA LOCAL dan alasan izinnya dibatasi pada dua sisi.
- mysql Command Options — Oracle — Daftar opsi klien mysql, termasuk –local-infile untuk mengizinkan impor berkas dari sisi klien.