Kembali ke Artikel

Belajar Database dari Nol #5: INSERT, Menambah Data ke Tabel

Solusi IT

Cara paling dasar untuk insert data MySQL adalah perintah INSERT INTO nama_tabel (kolom1, kolom2) VALUES (nilai1, nilai2);. Satu perintah bisa memasukkan satu baris, bisa juga puluhan baris sekaligus dengan memisahkan tiap baris pakai koma. Di MySQL 8.4, perintah ini juga yang paling sering dipakai di dunia kerja, baik lewat terminal langsung maupun lewat kode aplikasi.

Artikel ini bagian kelima dari seri Belajar Database dari Nol. Di bagian ini kita tidak cuma belajar sintaks. Kita sekalian menyiapkan dataset studi kasus toko online berisi tabel produk, pelanggan, dan pesanan. Dataset ini akan dipakai terus sampai akhir seri, jadi kerjakan bagian ini sampai selesai supaya bagian berikutnya tinggal jalan.

Prasyarat: MySQL 8.4 dan Database Kosong

Kamu butuh MySQL Server 8.4 yang sudah jalan dan bisa login lewat terminal. Kalau belum, mundur dulu ke bagian pertama seri untuk instalasi. Kamu juga sebaiknya sudah paham kenapa kolom harga pakai DECIMAL dan bukan FLOAT. Itu dibahas tuntas di Belajar Database dari Nol #4: Tipe Data MySQL yang Tepat.

Supaya semua pembaca mulai dari titik yang sama, kita buat database baru khusus studi kasus. Login dulu ke MySQL, lalu jalankan ini:

CREATE DATABASE IF NOT EXISTS toko_online;
USE toko_online;

Sekarang buat tiga tabel utamanya. Relasi antar tabel dengan foreign key baru kita pasang di bagian 11, jadi untuk sekarang kolom pelanggan_id dan produk_id di tabel pesanan masih berupa angka biasa:

CREATE TABLE produk (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  nama VARCHAR(100) NOT NULL,
  kategori VARCHAR(50) NOT NULL,
  harga DECIMAL(12,2) NOT NULL,
  stok INT UNSIGNED NOT NULL DEFAULT 0
);

CREATE TABLE pelanggan (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  nama VARCHAR(100) NOT NULL,
  email VARCHAR(100) NOT NULL UNIQUE,
  kota VARCHAR(50),
  terdaftar_pada DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

CREATE TABLE pesanan (
  id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  pelanggan_id INT UNSIGNED NOT NULL,
  produk_id INT UNSIGNED NOT NULL,
  jumlah INT UNSIGNED NOT NULL DEFAULT 1,
  total DECIMAL(12,2) NOT NULL,
  status VARCHAR(20) NOT NULL DEFAULT 'pending',
  tanggal_pesan DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP
);

Kalau ketiga perintah sukses, tiap CREATE TABLE mengembalikan Query OK, 0 rows affected. Cek dengan SHOW TABLES; dan pastikan muncul tiga tabel: pelanggan, pesanan, produk.

INSERT INTO Satu Baris: Bentuk Paling Dasar

Kita mulai dari satu baris. Masukkan satu produk ke tabel produk:

INSERT INTO produk (nama, kategori, harga, stok)
VALUES ('Kaos Polos Hitam', 'Pakaian', 55000, 120);

Output yang diharapkan:

Query OK, 1 row affected (0.01 sec)

Perhatikan strukturnya. Setelah nama tabel ada daftar kolom dalam kurung, lalu VALUES berisi nilai dengan urutan yang sama persis. Nilai teks diapit tanda kutip satu, angka ditulis polos tanpa kutip.

Satu jebakan kecil soal tanda kutip. Kalau nilai teksnya sendiri mengandung tanda kutip satu, misalnya nama produk Kaos Sablon 'Limited', kamu harus menuliskannya dua kali berturut-turut: 'Kaos Sablon ''Limited'''. Alternatifnya pakai garis miring terbalik, 'Kaos Sablon \'Limited\''. Kalau lupa, MySQL menganggap string sudah selesai di kutip pertama dan sisanya dianggap sintaks rusak.

Sebenarnya MySQL mengizinkan kamu melewatkan daftar kolom, seperti INSERT INTO produk VALUES (...);. Jangan dibiasakan. Tanpa daftar kolom, kamu wajib mengisi semua kolom sesuai urutan di tabel, termasuk kolom id. Begitu struktur tabel berubah, misalnya ada kolom baru, query lama langsung error. Menyebut kolom secara eksplisit membuat query tetap jalan dan lebih mudah dibaca orang lain.

INSERT Multi Baris Sekaligus, Lebih Cepat dan Lebih Rapi

Kalau mau memasukkan lima produk, kamu tidak perlu menulis lima perintah. Cukup satu INSERT dengan beberapa kelompok VALUES yang dipisah koma:

INSERT INTO produk (nama, kategori, harga, stok) VALUES
('Kemeja Flanel Kotak', 'Pakaian', 145000, 45),
('Sepatu Lari Ringan', 'Sepatu', 320000, 30),
('Tas Ransel Laptop 15 inci', 'Tas', 210000, 25),
('Topi Baseball Navy', 'Aksesoris', 48000, 80),
('Jaket Hoodie Abu', 'Pakaian', 175000, 60);

Output yang diharapkan:

Query OK, 5 rows affected (0.01 sec)
Records: 5  Duplicates: 0  Warnings: 0

Selain lebih ringkas, cara ini jauh lebih cepat karena server hanya memproses satu perintah untuk banyak baris. Di proyek klien, tim Arrazy memakai pola multi-baris seperti ini untuk seeder, yaitu skrip pengisi data awal, baik lewat migration Laravel maupun program seeding di backend Go. Prinsipnya sama persis dengan yang kamu tulis manual di sini.

Perilaku AUTO_INCREMENT, NULL, dan DEFAULT Saat Kolom Tidak Diisi

Kamu mungkin sadar dari tadi kita tidak pernah mengisi kolom id. Itu bukan kelalaian. Ada tiga mekanisme yang bekerja diam-diam saat sebuah kolom tidak disebut di perintah INSERT:

Mekanisme Kapan aktif Nilai yang diisi
AUTO_INCREMENT Kolom bertanda AUTO_INCREMENT tidak diisi Angka berikutnya, mulai dari 1 lalu naik terus
DEFAULT Kolom punya klausa DEFAULT Nilai default yang ditulis saat membuat tabel
NULL Kolom boleh kosong dan tanpa default NULL, alias tidak ada nilai

Coba buktikan dengan tabel pelanggan. Masukkan satu pelanggan tanpa menyebut id, kota, dan terdaftar_pada:

INSERT INTO pelanggan (nama, email)
VALUES ('Budi Santoso', 'budi@example.com');

SELECT * FROM pelanggan;

Hasilnya kira-kira begini:

+----+--------------+------------------+------+---------------------+
| id | nama         | email            | kota | terdaftar_pada      |
+----+--------------+------------------+------+---------------------+
|  1 | Budi Santoso | budi@example.com | NULL | 2026-07-27 09:15:42 |
+----+--------------+------------------+------+---------------------+

Tiga hal terjadi sekaligus. Kolom id terisi 1 dari AUTO_INCREMENT. Kolom kota jadi NULL karena boleh kosong dan tidak punya default. Kolom terdaftar_pada terisi waktu saat ini karena defaultnya CURRENT_TIMESTAMP.

Kalau kamu butuh id yang baru saja dibuat, misalnya untuk dipakai di tabel lain, panggil SELECT LAST_INSERT_ID(); tepat setelah insert. Untuk memaksa kolom memakai nilai defaultnya secara eksplisit, tulis kata kunci DEFAULT di posisi nilainya, contohnya VALUES ('Sandal Jepit', 'Sepatu', 25000, DEFAULT) yang membuat stok terisi 0.

Satu catatan penting soal NULL. NULL bukan nol dan bukan string kosong. NULL artinya nilainya memang tidak diketahui. Kolom yang ditandai NOT NULL menolak nilai ini, dan itu bagus untuk data yang wajib ada seperti nama produk atau harga.

Mengisi Dataset Studi Kasus Toko Online

Sekarang kita lengkapi dataset yang akan dipakai sepanjang seri. Tabel produk sudah berisi 6 baris. Tambahkan pelanggan dan pesanan berikut apa adanya, jangan diubah dulu, supaya hasil query kamu di bagian-bagian berikutnya sama dengan contoh di artikel:

INSERT INTO pelanggan (nama, email, kota) VALUES
('Siti Rahayu', 'siti@example.com', 'Semarang'),
('Agus Wijaya', 'agus@example.com', 'Purwokerto'),
('Dewi Lestari', 'dewi@example.com', 'Banjarnegara'),
('Rudi Hartono', 'rudi@example.com', NULL);

INSERT INTO pesanan (pelanggan_id, produk_id, jumlah, total, status) VALUES
(1, 1, 2, 110000, 'selesai'),
(1, 4, 1, 48000, 'selesai'),
(2, 3, 1, 320000, 'dikirim'),
(3, 6, 1, 175000, 'pending'),
(4, 2, 2, 290000, 'selesai'),
(5, 5, 3, 630000, 'dibatalkan');

Perhatikan baris Rudi Hartono. Kita sengaja menulis NULL secara eksplisit di kolom kota. Ini sah karena kolom kota memang boleh kosong, dan nanti berguna saat belajar filter IS NULL. Di tabel pesanan, kolom tanggal_pesan kita biarkan terisi otomatis oleh default CURRENT_TIMESTAMP.

Total dataset kamu sekarang: 6 produk, 5 pelanggan, dan 6 pesanan. Struktur toko online sederhana seperti ini juga jadi fondasi sistem yang lebih besar. Pola tabel produk, pelanggan, dan pesanan yang sama kami pakai saat membangun sistem aplikasi untuk klien, tentu dengan kolom dan relasi yang jauh lebih banyak.

Cek Hasil dengan SELECT * Sebelum Lanjut

Biasakan langsung memeriksa hasil setiap selesai memasukkan data. Cara tercepatnya adalah SELECT *, yang artinya tampilkan semua kolom:

SELECT * FROM produk;
SELECT * FROM pelanggan;
SELECT * FROM pesanan;

Untuk tabel produk, hasilnya harus 6 baris dengan id berurutan 1 sampai 6:

+----+---------------------------+-----------+-----------+------+
| id | nama                      | kategori  | harga     | stok |
+----+---------------------------+-----------+-----------+------+
|  1 | Kaos Polos Hitam          | Pakaian   |  55000.00 |  120 |
|  2 | Kemeja Flanel Kotak       | Pakaian   | 145000.00 |   45 |
|  3 | Sepatu Lari Ringan        | Sepatu    | 320000.00 |   30 |
|  4 | Tas Ransel Laptop 15 inci | Tas       | 210000.00 |   25 |
|  5 | Topi Baseball Navy        | Aksesoris |  48000.00 |   80 |
|  6 | Jaket Hoodie Abu          | Pakaian   | 175000.00 |   60 |
+----+---------------------------+-----------+-----------+------+
6 rows in set (0.00 sec)

Kalau jumlah barisnya tidak cocok, hapus isi tabel dengan TRUNCATE TABLE nama_tabel; lalu ulangi insert dari awal. TRUNCATE mengosongkan tabel sekaligus mereset hitungan AUTO_INCREMENT kembali ke 1, jadi id kamu kembali rapi. Untuk sekarang cukup SELECT * saja dulu. Menyaring baris tertentu dengan kondisi adalah materi bagian berikutnya.

Kebiasaan cek cepat seperti ini terlihat sepele, tapi menyelamatkan banyak waktu. Salah ketik satu angka di kolom total jauh lebih murah ditemukan sekarang, saat datanya masih 6 baris, daripada nanti saat kamu bingung kenapa hasil agregasi di bagian 10 tidak masuk akal. Data yang salah sejak insert akan salah terus di semua query di atasnya.

Troubleshooting: Error INSERT yang Paling Sering Muncul

ERROR 1062: Duplicate entry for key PRIMARY

ERROR 1062 (23000): Duplicate entry '1' for key 'produk.PRIMARY'

Penyebab: kamu memasukkan nilai id yang sudah dipakai baris lain, biasanya karena mengisi kolom AUTO_INCREMENT secara manual. Primary key harus unik, jadi MySQL menolak. Error yang sama muncul di kolom UNIQUE, misalnya memasukkan email pelanggan yang sudah terdaftar. Solusi: jangan isi kolom id sama sekali, biarkan AUTO_INCREMENT bekerja. Untuk email duplikat, cek dulu datanya atau pakai email lain.

ERROR 1406: Data too long for column

ERROR 1406 (22001): Data too long for column 'status' at row 1

Penyebab: nilai yang dimasukkan melebihi kapasitas kolom. Kolom status kita bertipe VARCHAR(20), jadi teks 21 karakter atau lebih ditolak. Di MySQL 8.4 dengan pengaturan bawaan (strict mode aktif), data tidak dipotong diam-diam tapi langsung ditolak, dan itu perilaku yang benar. Solusi: perpendek nilainya, atau kalau kebutuhan datanya memang lebih panjang, ubah kolom dengan ALTER TABLE pesanan MODIFY status VARCHAR(50) NOT NULL DEFAULT 'pending';.

ERROR 1364: Field doesn’t have a default value

ERROR 1364 (HY000): Field 'harga' doesn't have a default value

Penyebab: ada kolom NOT NULL tanpa default yang tidak kamu sebut di daftar kolom. MySQL tidak tahu harus mengisi apa, jadi menolak. Solusi: sertakan kolom itu di perintah insert beserta nilainya. Ini alasan lain kenapa daftar kolom eksplisit itu penting, kamu langsung tahu kolom mana yang wajib diisi.

ERROR 1136: Column count doesn’t match value count

ERROR 1136 (21S01): Column count doesn't match value count at row 1

Penyebab: jumlah nilai di VALUES tidak sama dengan jumlah kolom yang disebut. Biasanya gara-gara lupa satu nilai atau kelebihan koma saat menulis insert multi-baris yang panjang. Solusi: hitung ulang pasangan kolom dan nilai. Pesan errornya menyebut nomor baris yang bermasalah, mulai cek dari situ.

Lanjut ke Bagian Berikutnya

Dataset toko online kamu sekarang sudah terisi dan siap dipakai. Kamu sudah bisa insert data MySQL satu baris maupun banyak baris, paham apa yang terjadi pada kolom yang tidak diisi, dan tahu cara membaca error yang paling sering muncul.

Data yang cuma bisa dimasukkan tapi tidak bisa dicari tentu belum berguna. Di bagian berikutnya, Belajar Database dari Nol #6: SELECT & WHERE, Query Dasar, kita mulai menggali data ini dengan query yang sesungguhnya, dari memilih kolom tertentu sampai menyaring baris dengan berbagai kondisi. Artikelnya terbit menyusul, pantau daftar lengkapnya di halaman hub Belajar Database.

Referensi

BACA JUGA

Artikel Lainnya di Kategori Database

Ingin Membaca Artikel Lainnya?

Temukan lebih banyak insight dan tips tentang teknologi dan bisnis digital.

Lihat Semua Artikel