DROP dan TRUNCATE

Menghapus tabel dan seluruh isinya dengan memahami perbedaan DROP, TRUNCATE, dan risiko CASCADE.

Daftar isi

Topik ini menutup modul definisi data dengan operasi destruktif, yaitu DROP TABLE yang menghapus tabel bersama strukturnya dan TRUNCATE yang mengosongkan isinya dengan cepat. Pembahasan mencakup perbedaan keduanya dengan DELETE, perilaku CASCADE, dan satu sifat PostgreSQL yang menolong, yaitu DDL yang berjalan di dalam transaksi.

DROP TABLE dan CASCADE#

DROP TABLE menghapus definisi tabel, datanya, indexnya, dan izinnya sekaligus, sehingga operasinya tidak dapat dibatalkan oleh pemulihan biasa kecuali dijalankan di dalam transaksi yang di-ROLLBACK. Bentuk IF EXISTS membuat skrip tetap dapat diulang tanpa error ketika tabelnya memang belum ada.

Ketika ada objek yang bergantung pada tabel, misalnya foreign key dari tabel lain, server menolak penghapusan biasa dengan pesan yang mendaftar ketergantungannya. Kata CASCADE memerintahkan penghapusan berantai pada objek yang bergantung itu, dan blok berikut memperlihatkan penolakan serta jalur CASCADE dalam satu rangkaian.

bash
# penolakan penghapusan lalu penghapusan berantai
psql -U postgres -d perpustakaan <<'SQL'
SET client_min_messages = notice;
CREATE TABLE induk (id SERIAL PRIMARY KEY);
CREATE TABLE anak (id SERIAL PRIMARY KEY, induk_id INTEGER REFERENCES induk(id));
DROP TABLE induk;
DROP TABLE induk CASCADE;
SELECT to_regclass('anak') AS tabel_anak;
DROP TABLE anak;
RESET client_min_messages;
SQL
text Keluaran
SET
CREATE TABLE
CREATE TABLE
ERROR:  cannot drop table induk because other objects depend on it
DETAIL:  constraint anak_induk_id_fkey on table anak depends on table induk
HINT:  Use DROP ... CASCADE to drop the dependent objects too.
NOTICE:  drop cascades to constraint anak_induk_id_fkey on table anak
DROP TABLE
 tabel_anak
------------
 anak
(1 row)

DROP TABLE
RESET

Keluaran pertama menegaskan penolakan dengan DETAIL yang menyebut constraint peminjamnya, sedangkan jalur CASCADE menghapus ketergantungan itu lalu menampilkan NOTICE-nya. Perilaku yang penting dipahami adalah sasarannya, yaitu CASCADE pada DROP TABLE menghapus objek yang bergantung, seperti constraint foreign key milik tabel anak, tetapi tidak menghapus tabel anaknya, dan to_regclass menegaskan tabel anak masih ada. Dengan demikian CASCADE diperlakukan sebagai keputusan yang ditinjau, bukan kebiasaan mengetik, dan daftar NOTICE-nya dibaca sebelum diterima.

TRUNCATE dan pembandingnya dengan DELETE#

TRUNCATE mengosongkan seluruh tabel dalam satu operasi, tanpa memicu per baris dan tanpa meninggalkan baris mati untuk dibersihkan, sehingga jauh lebih cepat daripada DELETE tanpa WHERE pada tabel besar. Klausa RESTART IDENTITY mengembalikan sequence pengenalnya ke awal, sedangkan CASCADE mengizinkan tabel yang dirujuk foreign key ikut dikosongkan.

AspekDELETETRUNCATE
Lingkupbaris yang lolos WHEREseluruh tabel
Kecepatan pada tabel besarlambat, per bariscepat, operasi berkas
Pemicu per barisberjalantidak berjalan
Reset sequencetidakdengan RESTART IDENTITY
Syarat FKharus tidak melanggar rujukantabel yang dirujuk perlu CASCADE

DELETE tetap menjadi pilihan ketika hanya sebagian baris yang dibuang, sedangkan TRUNCATE untuk pengosongan total seperti pengaturan ulang data latihan. Keduanya tetap tunduk pada foreign key, dan TRUNCATE terhadap tabel yang dirujuk menuntut CASCADE secara eksplisit, sejalan dengan prinsip bahwa penghapusan berantai harus dinyatakan dengan sadar.

DDL berjalan dalam transaksi#

Berbeda dari banyak basis data lain, pernyataan DDL pada PostgreSQL berjalan di dalam transaksi dan dapat dibatalkan. Sifat ini mengubah cara kerja perbaikan yang keliru, karena tabel yang terhapus dalam transaksi kembali utuh ketika transaksinya di-ROLLBACK.

bash
# DROP TABLE di dalam transaksi yang dibatalkan
psql -U postgres -d perpustakaan <<'SQL'
CREATE TABLE arsip_uji (id INTEGER);
BEGIN;
DROP TABLE arsip_uji;
ROLLBACK;
SELECT to_regclass('arsip_uji') AS tabel_kembali;
DROP TABLE arsip_uji;
SQL
text Keluaran
CREATE TABLE
BEGIN
DROP TABLE
ROLLBACK
 tabel_kembali
---------------
 arsip_uji
(1 row)

DROP TABLE

Fungsi to_regclass mengembalikan nama tabel apabila tabelnya ada, dan keluarannya menegaskan tabel kembali setelah ROLLBACK. Sifat ini juga melandasi pola migration yang aman, yaitu satu berkas perubahan dieksekusi dalam satu transaksi sehingga separuh terpasang tidak pernah terjadi.

Kesalahan umum#

Kesalahan pertama adalah mengetik CASCADE tanpa membaca NOTICE-nya, sehingga dependensi yang ikut terhapus baru disadari berhari-hari kemudian. Kesalahan kedua adalah memakai TRUNCATE pada tabel yang dirujuk tanpa menimbang CASCADE-nya, karena pengosongan induk ikut mengosongkan seluruh tabel anak. Kesalahan ketiga adalah mengira TRUNCATE memicu trigger per baris sebagaimana DELETE, padahal pemicunya adalah trigger TRUNCATE khusus, dan logika pembersihan yang menumpang DELETE diam-diam tidak berjalan.

Kesalahan keempat adalah menulis DROP TABLE tanpa IF EXISTS pada skrip yang berulang, sehingga eksekusi kedua selalu gagal di awal. Pola IF EXISTS berpasangan dengan blok penyiapan yang idempoten, kebiasaan yang dipakai konsisten sepanjang jalur ini.

Ringkasan#

  • DROP TABLE menghapus tabel beserta data, index, dan izinnya, dengan IF EXISTS agar skrip tetap dapat diulang.
  • CASCADE menghapus berantai objek yang bergantung dan selalu diiringi NOTICE, sehingga daftarnya dibaca sebelum diterima.
  • TRUNCATE mengosongkan tabel secara cepat tanpa pemicu per baris, dengan RESTART IDENTITY untuk mengembalikan pengenalnya.
  • DDL PostgreSQL berjalan di dalam transaksi, sehingga DROP yang keliru masih dapat di-ROLLBACK dan migration dapat bersifat atomik.

Referensi#