Setiap orang yang mengelola basis data pada akhirnya berhadapan dengan tabel yang perlu dikosongkan. Bisa tabel data uji yang isinya sudah tercampur aduk. Bisa tabel log yang membengkak sampai jutaan baris. Bisa juga tabel sementara yang diisi ulang setiap malam.

Cara paling jelas adalah menjalankan DELETE FROM nama_tabel tanpa syarat apa pun. Perintah itu bekerja. Masalahnya muncul saat tabelnya besar: basis data menghapus baris satu per satu, lalu mencatat setiap penghapusan itu ke dalam log transaksi. Pada tabel berisi sepuluh juta baris, prosesnya bisa berjalan berpuluh menit dan membuat log transaksi ikut membengkak.

Truncate adalah perintah SQL yang mengosongkan seluruh isi tabel sekaligus, tanpa menyentuh struktur tabelnya. Ia menyelesaikan pekerjaan yang sama dengan pecahan waktu yang dibutuhkan DELETE. Artikel ini membahas apa itu truncate, mekanisme yang membuatnya cepat, dan bedanya dengan DELETE serta DROP. Kita juga akan melihat perbedaan perilakunya di tiap basis data dan hal yang perlu Anda pertimbangkan sebelum menjalankannya.

Truncate Adalah Perintah untuk Mengosongkan Tabel

Kata truncate berasal dari bahasa Latin truncare yang berarti memotong atau memangkas. Akar katanya adalah truncus, yaitu batang pohon — bagian yang tersisa setelah semua cabangnya dipangkas. Kata trunk dalam bahasa Inggris berasal dari akar yang sama.

Arti itu menggambarkan dengan tepat apa yang dilakukan perintahnya. Yang dipangkas adalah isi tabel, bukan tabelnya. Setelah TRUNCATE dijalankan, tabel Anda tetap ada di basis data lengkap dengan seluruh kolomnya, tipe datanya, indeksnya, dan aturan constraint yang menempel padanya. Yang hilang hanya barisnya.

Sintaksnya sesederhana mungkin karena memang tidak ada yang bisa diatur:

SQL
TRUNCATE TABLE pelanggan;

Tidak ada klausa WHERE di sini. TRUNCATE bekerja pada seluruh tabel atau tidak sama sekali. Kalau Anda perlu menghapus sebagian baris berdasarkan syarat tertentu, DELETE adalah satu-satunya pilihan.

Satu hal lagi membedakan TRUNCATE dari perintah penghapusan lain. MySQL mengklasifikasikannya sebagai DDL (Data Definition Language), yaitu kelompok perintah yang mengubah struktur basis data. Ia bukan DML (Data Manipulation Language) yang mengolah isi data. Penggolongan itu terdengar seperti urusan istilah saja, tetapi konsekuensinya nyata.

Kalau Anda belum familier dengan pembagian DDL, DML, DCL, dan TCL, penjelasan lengkapnya ada di artikel tentang query.

Cara Kerja TRUNCATE: Kenapa Bisa Jauh Lebih Cepat

Hasil akhir DELETE dan TRUNCATE sama-sama tabel kosong. Yang membuat waktunya berbeda jauh adalah cara kedua perintah itu bekerja di tingkat penyimpanan, dan mekanismenya berbeda antar basis data.

MySQL menjatuhkan lalu membuat ulang tabelnya. Dokumentasi resminya menyebut TRUNCATE bekerja dengan cara drop and re-create the table. Definisi tabel disimpan, berkas data dan indeksnya dibuang, lalu tabel kosong dibuat kembali dari definisi itu. Basis data tidak pernah membaca satu baris pun.

SQL Server melepaskan halaman datanya. Microsoft mendokumentasikan bahwa TRUNCATE men-dealokasi halaman data yang dipakai tabel. Yang dicatat ke log transaksi hanya pelepasan halaman itu. Bandingkan dengan DELETE yang, menurut dokumentasi sama, menghapus baris satu per satu dan mencatat satu entri log untuk tiap baris.

Diagram alur: DELETE mengunjungi tiap baris dan mencatat satu entri log per baris, TRUNCATE melepas halaman data.Diagram alur: DELETE mengunjungi tiap baris dan mencatat satu entri log per baris, TRUNCATE melepas halaman data.

Dari satu mekanisme ini, hampir semua sifat TRUNCATE yang lain bisa Anda turunkan sendiri:

  1. Trigger tidak ikut berjalan: Karena tidak ada baris yang dikunjungi satu per satu, tidak ada peristiwa penghapusan baris yang bisa memicu trigger. MySQL menyatakan TRUNCATE tidak memanggil trigger ON DELETE, dan Microsoft menjelaskan alasannya secara langsung — operasinya tidak mencatat penghapusan baris individual.
  2. Jumlah baris terhapus tidak dilaporkan: MySQL meminta hasil "0 rows affected" pada TRUNCATE dibaca sebagai "tidak ada informasi", bukan "tidak ada baris yang terhapus". Basis data memang tidak pernah menghitungnya.
  3. Penghitung nomor otomatis direset: Nilai AUTO_INCREMENT kembali ke nilai awalnya. Ini masuk akal karena di MySQL tabelnya memang dibuat ulang dari nol.
  4. Kunci yang dipakai lebih sedikit: SQL Server mengunci tabel dan halaman, tetapi tidak mengunci setiap baris seperti yang dilakukan DELETE.

TRUNCATE, DELETE, dan DROP: Tiga Perintah yang Sering Tertukar

Ketiganya sama-sama menghilangkan sesuatu, tetapi yang dihilangkan berbeda. Cara paling mudah mengingatnya: DELETE membuang baris terpilih, TRUNCATE membuang semua baris, DROP membuang tabelnya sekalian.

Perbandingan tiga keadaan tabel: DELETE menyisakan sebagian baris, TRUNCATE menyisakan tabel kosong, DROP menghapus tabel.Perbandingan tiga keadaan tabel: DELETE menyisakan sebagian baris, TRUNCATE menyisakan tabel kosong, DROP menghapus tabel.

AspekDELETETRUNCATEDROP
Kategori perintahDMLDDLDDL
Yang tersisaTabel + baris yang tidak dihapusTabel kosong, struktur utuhTidak ada
Bisa pakai WHEREYaTidakTidak
Kecepatan pada tabel besarLambatCepatCepat
Trigger ON DELETEBerjalanTidak berjalanTidak berjalan
Penghitung AUTO_INCREMENTTetapDireset (MySQL)Ikut hilang
Jumlah baris dilaporkanYaTidakTidak berlaku

Sebagai panduan memilih, tiga kalimat berikut sudah mencakup hampir semua kasus. Pakai DELETE kalau Anda hanya perlu membuang sebagian baris, atau kalau trigger dan pencatatan per baris memang dibutuhkan. Pakai TRUNCATE kalau seluruh isi tabel memang harus hilang dan strukturnya akan dipakai lagi. Pakai DROP kalau tabelnya sendiri sudah tidak diperlukan.

Huruf D dalam CRUD merujuk pada DELETE, bukan TRUNCATE — karena operasi harian sebuah aplikasi hampir selalu membutuhkan penghapusan yang selektif. Untuk langkah praktis menjalankan DROP lewat antarmuka grafis, panduannya tersedia di artikel cara drop table database di phpMyAdmin.

Satu Perintah, Perilaku Berbeda di Tiap Basis Data

Bagian ini penting dan sering diabaikan. Anda mungkin pernah membaca bahwa TRUNCATE tidak bisa dibatalkan. Pernyataan itu benar untuk sebagian basis data dan salah untuk sebagian yang lain.

MySQL dan MariaDB. Dokumentasi MySQL menyatakan operasi truncate menyebabkan implicit commit (penyimpanan permanen yang terjadi otomatis) sehingga tidak bisa dibatalkan. Menjalankannya di dalam blok transaksi tidak menolong. Nilai AUTO_INCREMENT selalu direset, bahkan pada MyISAM dan InnoDB yang normalnya tidak pernah mendaur ulang nomor urut. Hak akses yang dibutuhkan adalah DROP, bukan DELETE.

PostgreSQL. Dokumentasi resminya menyebut TRUNCATE sebagai operasi yang aman terhadap transaksi — pemotongan akan dibatalkan dengan selamat kalau transaksi di sekelilingnya tidak jadi di-commit. PostgreSQL juga punya dua opsi yang tidak dimiliki MySQL:

SQL
TRUNCATE pesanan CASCADE;
TRUNCATE pelanggan RESTART IDENTITY;

CASCADE ikut mengosongkan semua tabel yang punya referensi foreign key ke tabel tersebut. RESTART IDENTITY mereset sequence. Perhatikan bahwa perilaku bawaan PostgreSQL adalah CONTINUE IDENTITY, artinya nomor urut justru tidak direset kecuali Anda memintanya. Ini kebalikan dari MySQL. Satu lagi yang khas: trigger ON DELETE tidak menyala, tetapi trigger ON TRUNCATE menyala.

SQL Server. Microsoft menyatakan operasi TRUNCATE TABLE dapat dibatalkan di dalam sebuah transaksi, dan dokumentasinya bahkan menyertakan contoh resmi yang memperagakan hal tersebut. Hak akses minimum yang dibutuhkan adalah ALTER pada tabel. Sejak SQL Server 2016 tersedia pilihan mengosongkan partisi tertentu saja:

SQL
TRUNCATE TABLE penjualan WITH (PARTITIONS (2, 4, 6 TO 8));

Oracle. Paling tegas di antara semuanya. Dokumentasi Oracle menyatakan Anda tidak bisa membatalkan pernyataan TRUNCATE TABLE, dan juga tidak bisa memakai FLASHBACK TABLE untuk mengambil kembali isi tabel yang sudah dipangkas. Oracle menyediakan CASCADE untuk tabel anak, serta pilihan REUSE STORAGE yang mempertahankan ruang penyimpanan yang sudah dialokasikan.

SQLite. Basis data ini sama sekali tidak mengenal perintah TRUNCATE. Menjalankannya menghasilkan galat sintaks:

Code
Error: in prepare, near "TRUNCATE": syntax error

Sebagai gantinya, SQLite menerapkan truncate optimization. Saat Anda menjalankan DELETE tanpa WHERE, tanpa RETURNING, pada tabel yang tidak punya trigger, isi tabel dihapus tanpa mengunjungi tiap baris. Perlu dicatat bahwa optimasi ini tidak mereset penghitung AUTOINCREMENT — setelah tiga baris pertama dihapus, baris berikutnya tetap mendapat nomor 4.

Ringkasan perilakunya:

Basis dataBisa dibatalkanPenghitung ID diresetHak akses
MySQL / MariaDBTidakSelaluDROP
PostgreSQLYaHanya dengan RESTART IDENTITYTRUNCATE
SQL ServerYaSelaluALTER
OracleTidak
SQLiteTidak ada perintahnyaTidak

Kenapa TRUNCATE Anda Ditolak

Perintah ini punya cukup banyak larangan, dan galat yang muncul kadang membingungkan. Berikut penyebab yang paling sering ditemui.

Tabel direferensikan foreign key dari tabel lain. Ini penyebab nomor satu. MySQL menolaknya dengan galat berikut:

Code
ERROR 1701 (42000): Cannot truncate a table referenced in a foreign key constraint

Foreign key yang menunjuk ke kolom di tabel yang sama masih diizinkan. Yang dilarang adalah referensi dari tabel lain. Oracle memberlakukan aturan serupa untuk tabel induk dengan constraint yang aktif.

Cara menyiasatinya yang paling sering beredar adalah SET FOREIGN_KEY_CHECKS=0. Cara itu memang berhasil, tetapi Anda sedang mematikan penjaga integritas data. Kalau tabel anak masih menunjuk ke induk yang sudah dikosongkan, hasilnya adalah data yatim. Gunakan hanya kalau tabel anaknya juga akan Anda kosongkan.

Kondisi lain yang membuat SQL Server menolak. Microsoft mendaftarkan beberapa larangan lain. TRUNCATE ditolak pada tabel yang ikut dalam indexed view, dipublikasikan lewat replikasi transaksional atau merge, bertipe system-versioned temporal, atau direferensikan constraint EDGE. Untuk semua kasus itu, DELETE adalah jalan keluarnya.

Hak akses kurang. Karena TRUNCATE tergolong DDL, hak DELETE biasa tidak cukup. MySQL menuntut hak DROP, SQL Server menuntut ALTER, dan PostgreSQL punya hak TRUNCATE tersendiri. Akun aplikasi yang hanya diberi hak baca-tulis normal akan ditolak, dan itu justru perilaku yang sehat.

Hal yang Perlu Anda Pertimbangkan Sebelum Memakai TRUNCATE

Kecepatan TRUNCATE datang dengan sejumlah konsekuensi. Berikut yang perlu Anda timbang.

  1. Data tidak bisa dikembalikan di MySQL dan Oracle: Tidak ada ROLLBACK yang menolong, dan Oracle secara khusus menutup jalur FLASHBACK TABLE. Satu-satunya penyelamat adalah backup yang Anda ambil sebelumnya.
  2. Tidak bisa selektif: Tidak ada WHERE, sehingga perintah ini hanya cocok saat memang seluruh isi tabel harus hilang.
  3. Seluruh tabel terkunci: PostgreSQL mengambil kunci ACCESS EXCLUSIVE yang memblokir semua operasi lain pada tabel tersebut. Aplikasi yang sedang membaca tabel itu akan tertahan sampai proses selesai.
  4. Nomor urut yang direset bisa memutus referensi: Nomor ID tabel itu mungkin pernah dicatat di sistem lain, misalnya berkas log atau laporan. Setelah direset, pengisian ulang menghasilkan ID yang sama untuk data yang berbeda.
  5. Ruang penyimpanan tidak selalu langsung kembali: SQL Server menunda pelepasan halaman untuk tabel berukuran 128 extent atau lebih sampai transaksinya selesai. Ruang yang dibebaskan mungkin belum langsung tersedia untuk alokasi baru.
  6. Konsistensi baca di PostgreSQL tidak dijamin: Dokumentasinya menyebut TRUNCATE tidak aman terhadap MVCC. Transaksi lain yang sudah mengambil snapshot sebelum pemotongan akan melihat tabel itu kosong.

Untuk tabel berisi puluhan sampai beberapa ratus baris, selisih kecepatannya tidak akan terasa. Di skala itu, DELETE yang bisa dibatalkan dan melaporkan jumlah baris terhapus justru lebih aman dipakai.

Langkah Aman Menjalankan TRUNCATE di Server Produksi

Urutan berikut memakan waktu beberapa menit, jauh lebih murah dibanding memulihkan tabel yang salah dikosongkan.

Langkah #1: Periksa tabel mana saja yang bergantung

Sebelum apa pun, cari tahu apakah ada tabel lain yang mereferensikan tabel target. Pada MySQL, informasi itu tersimpan di skema sistem:

SQL
SELECT TABLE_NAME, CONSTRAINT_NAME
FROM information_schema.KEY_COLUMN_USAGE
WHERE REFERENCED_TABLE_NAME = 'pelanggan';

Kalau hasilnya kosong, tabel Anda aman dari galat 1701. Kalau ada isinya, putuskan dulu apakah tabel anaknya juga akan dikosongkan.

Langkah #2: Ambil backup tabelnya

Jangan mengandalkan backup harian yang mungkin sudah berumur belasan jam. Ambil salinan tabel tersebut saat itu juga:

SQL
CREATE TABLE pelanggan_backup AS SELECT * FROM pelanggan;

Cara ini menyalin barisnya, bukan indeks dan constraint-nya. Untuk salinan yang benar-benar utuh, gunakan mysqldump atau fasilitas backup di panel hosting Anda. Konsep dan strategi pencadangan yang lebih lengkap dibahas di artikel tentang backup, sedangkan langkah praktisnya ada di panduan backup dan restore MySQL melalui Backup Wizard.

Langkah #3: Hitung dulu isinya

Catat jumlah baris sebelum perintah dijalankan. Angka ini berguna sebagai pembanding, karena TRUNCATE sendiri tidak akan melaporkan berapa baris yang terhapus.

SQL
SELECT COUNT(*) FROM pelanggan;

Langkah #4: Jalankan perintahnya

Pastikan nama tabelnya benar sebelum menekan enter. Pada basis data yang mendukung pembatalan, bungkus dengan transaksi supaya masih ada jalan mundur:

SQL
BEGIN TRANSACTION;
TRUNCATE TABLE pelanggan;
SELECT COUNT(*) FROM pelanggan;
-- COMMIT; atau ROLLBACK;

Blok di atas berlaku untuk SQL Server dan PostgreSQL. Di MySQL dan Oracle, perintahnya sudah permanen begitu dijalankan, sehingga membungkusnya dengan transaksi tidak memberi perlindungan apa pun.

Langkah #5: Verifikasi dan bereskan

Pastikan tabelnya kosong, lalu cek aplikasi yang memakainya masih berjalan normal. Setelah yakin, hapus tabel salinan dari Langkah #2 supaya tidak menumpuk.

Truncate di Luar Dunia SQL

Istilah ini juga muncul di beberapa konteks lain, dan pembaca yang menemukannya di luar basis data sering mengira artinya berbeda. Ketiganya sebenarnya memakai arti kata yang sama: memotong sampai habis, menyisakan kerangkanya.

Tiga kartu berlabel BERKAS, ANGKA, dan TEKS: dokumen terpotong garis putus-putus, angka dipotong gunting, teks berelipsis.Tiga kartu berlabel BERKAS, ANGKA, dan TEKS: dokumen terpotong garis putus-putus, angka dipotong gunting, teks berelipsis.

Perintah truncate di terminal Linux dan macOS. Perintah ini mengubah ukuran sebuah berkas. Pemakaian paling umum adalah mengosongkan berkas log yang membengkak:

Bash
truncate -s 0 /var/log/aplikasi.log

Isinya menjadi nol byte, tetapi berkasnya sendiri tetap ada. Inilah bedanya dengan rm. Program yang sedang menulis ke log tersebut masih memegang penunjuk ke berkas yang sama, sehingga ia bisa terus menulis tanpa dijalankan ulang. Menghapusnya dengan rm justru membuat ruang disk tidak kembali sampai program itu direstart.

Fungsi TRUNCATE() di MySQL. Ini bukan perintah, melainkan fungsi matematika yang memotong angka desimal tanpa membulatkannya:

SQL
SELECT TRUNCATE(1.999, 1);   -- hasilnya 1.9
SELECT ROUND(1.999, 1);      -- hasilnya 2.0
SELECT TRUNCATE(122, -2);    -- hasilnya 100

Perhatikan baris pertama dan kedua. ROUND membulatkan ke nilai terdekat, sementara TRUNCATE memangkas digit selebihnya begitu saja. Untuk nilai negatif, pemangkasan selalu mengarah ke nol: TRUNCATE(-1.999, 1) menghasilkan -1.9, bukan -2.0. Jadi satu kata yang sama berarti dua hal berbeda di MySQL, tergantung dipakai sebagai pernyataan atau sebagai fungsi.

Kelas truncate di CSS dan Tailwind. Di sisi tampilan, truncate berarti memotong teks yang terlalu panjang dan menggantinya dengan elipsis. Kelas truncate di Tailwind CSS terkompilasi menjadi tiga properti sekaligus:

CSS
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;

Judul artikel yang panjang di dalam kartu berukuran tetap biasanya memakai teknik ini. Teksnya utuh di dalam HTML, hanya tampilannya yang dipangkas.

Pertanyaan yang Sering Muncul

Apakah data yang sudah di-TRUNCATE bisa dikembalikan? Bergantung pada basis datanya. Di PostgreSQL dan SQL Server, selama masih di dalam transaksi yang belum di-commit, ROLLBACK akan mengembalikannya. Di MySQL, MariaDB, dan Oracle, tidak bisa — satu-satunya jalan adalah memulihkan dari backup.

Apakah TRUNCATE menghapus struktur tabel? Tidak. Kolom, tipe data, indeks, dan constraint tetap utuh. Kalau Anda ingin menghilangkan tabelnya sekalian, perintahnya adalah DROP TABLE.

Kenapa hasilnya "0 rows affected" padahal tabelnya berisi ribuan baris? Karena TRUNCATE memang tidak pernah menghitung barisnya. Dokumentasi MySQL meminta angka nol itu dibaca sebagai "tidak ada informasi", bukan sebagai kegagalan. Hitung jumlah barisnya dengan SELECT COUNT(*) sebelum menjalankan perintah kalau Anda membutuhkan angkanya.

Bisakah TRUNCATE dipakai dengan WHERE? Tidak bisa. Perintah ini hanya mengenal seluruh tabel. Untuk penghapusan bersyarat, gunakan DELETE FROM tabel WHERE kondisi.

Mana yang lebih baik untuk tabel kecil? DELETE, karena selisih kecepatannya tidak terasa di skala itu sementara Anda tetap memegang kemampuan membatalkan.

Kesimpulan

Truncate adalah perintah SQL yang memangkas seluruh isi tabel dan menyisakan strukturnya. Kecepatannya berasal dari cara kerjanya di tingkat penyimpanan, bukan dari penghapusan baris satu per satu seperti DELETE. Dari mekanisme itulah lahir semua sifat khasnya: trigger tidak berjalan, jumlah baris tidak dilaporkan, dan penghitung nomor otomatis ikut direset.

Yang paling penting untuk diingat adalah kemampuan membatalkannya berbeda-beda. PostgreSQL dan SQL Server mendokumentasikan TRUNCATE sebagai operasi yang bisa dibatalkan di dalam transaksi. MySQL, MariaDB, dan Oracle menyimpannya secara permanen begitu perintah dijalankan. Periksa dokumentasi basis data Anda sebelum mengandalkan ROLLBACK sebagai jaring pengaman.

Sebagai pegangan sederhana: pakai TRUNCATE untuk mengosongkan tabel besar yang strukturnya masih dibutuhkan. Pakai DELETE kalau penghapusannya selektif atau Anda membutuhkan jalan mundur, dan DROP kalau tabelnya sendiri sudah tidak diperlukan. Selalu ambil backup sebelum menjalankannya di server produksi.

Semoga artikel ini membantu.