UPDATE dan DELETE

Mengubah dan menghapus data dengan pola yang aman serta disiplin klausa WHERE.

Daftar isi

Topik ini membahas UPDATE dan DELETE, dua pernyataan yang mengubah data yang sudah ada, beserta pola kerja yang menjaganya dari kesalahan mahal. Klausa WHERE menjadi disiplin utamanya, karena tanpa WHERE kedua pernyataan menyasar seluruh tabel tanpa peringatan.

Blok penyiapan dataset#

bash
# siapkan ulang tabel dan data contoh untuk topik ini
PGOPTIONS='-c client_min_messages=warning' psql -q -U postgres -d perpustakaan <<'SQL'
DROP TABLE IF EXISTS peminjaman, buku, anggota, kategori CASCADE;
CREATE TABLE kategori (id SERIAL PRIMARY KEY, nama TEXT NOT NULL UNIQUE);
CREATE TABLE anggota (id SERIAL PRIMARY KEY, nama TEXT NOT NULL, email TEXT UNIQUE, bergabung DATE NOT NULL, aktif BOOLEAN NOT NULL DEFAULT TRUE);
CREATE TABLE buku (id SERIAL PRIMARY KEY, judul TEXT NOT NULL, penulis TEXT NOT NULL, tahun INTEGER NOT NULL, kategori_id INTEGER REFERENCES kategori(id));
CREATE TABLE peminjaman (id SERIAL PRIMARY KEY, anggota_id INTEGER NOT NULL REFERENCES anggota(id), buku_id INTEGER NOT NULL REFERENCES buku(id), tanggal_pinjam DATE NOT NULL, tanggal_kembali DATE);
INSERT INTO kategori (nama) VALUES ('Pemrograman'), ('Sains'), ('Sejarah'), ('Fiksi'), ('Statistika');
INSERT INTO anggota (nama, email, bergabung, aktif) VALUES ('Ali Rahman', '[email protected]', '2024-01-15', TRUE), ('Budi Santoso', '[email protected]', '2024-03-02', TRUE), ('Citra Kirana', '[email protected]', '2024-05-20', FALSE), ('Dewi Lestari', '[email protected]', '2024-08-11', TRUE), ('Eka Pratama', NULL, '2025-01-30', TRUE);
INSERT INTO buku (judul, penulis, tahun, kategori_id) VALUES ('Dasar Basis Data', 'Sari Wulandari', 2021, 1), ('Jaringan Komputer', 'Ahmad Fauzi', 2019, 1), ('Fisika untuk Pemula', 'Rina Marlina', 2020, 2), ('Kimia Organik', 'Rina Marlina', 2022, 2), ('Sejarah Nusantara', 'Bambang Wijaya', 2018, 3), ('Cerita Kota Lama', 'Nur Aisyah', 2023, 4), ('Statistika Terapan', 'Sari Wulandari', 2022, 5), ('Algoritma dan Struktur Data', 'Ahmad Fauzi', 2021, 1);
INSERT INTO peminjaman (anggota_id, buku_id, tanggal_pinjam, tanggal_kembali) VALUES (1, 1, '2025-03-01', '2025-03-15'), (1, 7, '2025-03-05', '2025-03-20'), (2, 3, '2025-03-10', NULL), (3, 5, '2025-02-20', '2025-03-01'), (2, 1, '2025-04-02', NULL), (4, 6, '2025-04-07', NULL), (5, 8, '2025-04-09', '2025-04-25'), (4, 2, '2025-05-01', NULL);
SQL

UPDATE dengan WHERE dan RETURNING#

UPDATE mengubah kolom pada baris yang lolos WHERE, dan statusnya menyebut jumlah baris yang benar-benar berubah. Blok berikut mengisi email Eka Pratama yang masih kosong, lalu membaca hasilnya melalui RETURNING.

bash
# isi email anggota yang belum memiliki email
psql -U postgres -d perpustakaan -c "UPDATE anggota SET email = '[email protected]' WHERE id = 5 RETURNING nama, email;"
text Keluaran
    nama     |      email
-------------+-----------------
 Eka Pratama | [email protected]
(1 row)

UPDATE 1

Satu baris berubah sesuai status UPDATE 1, dan RETURNING menampilkan nilai setelah perubahan. Klausa SET menerima beberapa kolom sekaligus dipisahkan koma, serta ekspresi yang membaca nilai lama barisnya sendiri, misalnya SET judul = judul || ' (edisi revisi)'.

Membaca sebelum menulis#

Pola kerja yang aman menjalankan SELECT dengan WHERE yang sama terlebih dahulu, memeriksa daftar baris yang akan tersentuh, lalu baru menjalankan pernyataan perubahannya. Pada tabel yang berubah cepat, pernyataan menulis dijalankan dalam transaksi yang dibuka dengan SELECT terkunci, teknik yang dibahas penuh pada modul transaksi.

Kebiasaan kedua yang menyelamatkan adalah menafsirkan status pernyataan. UPDATE 0 berarti WHERE tidak menemukan apa pun, yang pada skrip pemeliharaan sering menjadi tanda kesalahan penulisan syarat, bukan kondisi yang wajar. Apabila jumlah baris yang berubah berbeda dari harapan, transaksi di-ROLLBACK dan syaratnya ditinjau, bukan dilanjutkan.

DELETE dan penjaga foreign key#

DELETE menghapus baris yang lolos WHERE, dengan status DELETE n yang menyebut jumlahnya. Pada dataset ini, penghapusan kategori yang masih dirujuk buku ditolak oleh foreign key, dan penolakan itu adalah fitur, bukan gangguan.

bash
# coba hapus kategori yang masih dirujuk buku
psql -U postgres -d perpustakaan -c "DELETE FROM kategori WHERE id = 1;"
text Keluaran
ERROR:  update or delete on table "kategori" violates foreign key constraint "buku_kategori_id_fkey" on table "buku"
DETAIL:  Key (id)=(1) is still referenced from table "buku".

Server menolak dengan pesan pelanggaran foreign key, dan keputusan yang benar tidak mematikan aturannya, melainkan menentukan nasib baris penunjuknya, sebagaimana dibahas pada topik foreign key. Penghapusan yang sah menangani anaknya terlebih dahulu, misalnya mengosongkan peminjaman anggota sebelum anggotanya dihapus.

bash
# hapus satu peminjaman yang sudah selesai
psql -U postgres -d perpustakaan -c "DELETE FROM peminjaman WHERE id = 1 RETURNING anggota_id, buku_id;"
text Keluaran
 anggota_id | buku_id
------------+---------
          1 |       1
(1 row)

DELETE 1

RETURNING pada DELETE mengembalikan baris yang baru saja hilang, bermanfaat untuk log audit dan untuk mengembalikan data bila perlu, meskipun pemulihan penuh tetap menjadi wilayah backup.

Truncating pada latihan#

Pengosongan total tabel latihan memakai TRUNCATE sebagaimana dibahas pada modul definisi data, sedangkan data produksi jarang mengosongkan tabel utuh melalui DELETE karena biaya per barisnya. Pemahaman dua perintah ini berpasangan, yaitu DELETE untuk seleksi yang presisi dan TRUNCATE untuk pengosongan yang disengaja.

Kesalahan umum#

Kesalahan pertama adalah UPDATE atau DELETE tanpa WHERE, yang menyasar seluruh tabel seketika. Kebiasaan penangkalnya menulis WHERE lebih dahulu sebelum mengisi SET, dan menjalankan pernyataan dalam transaksi yang di-ROLLBACK bila statusnya tidak sesuai harapan. Kesalahan kedua adalah syarat WHERE yang cocok lebih banyak baris dari perkiraan, misalnya WHERE nama LIKE 'Eka%' pada tabel yang memuat dua Eka, sehingga pembacaan SELECT sebelumnya wajib.

Kesalahan ketiga adalah menganggap UPDATE 0 sebagai kegagalan server. Status itu sah dan berarti tidak ada baris yang cocok, penafsiran yang benar bergantung pada maksud skrip, dan beberapa aplikasi memperlakukannya sebagai kondisi balapan yang perlu ditangani ulang.

Ringkasan#

  • UPDATE dan DELETE selalu disertai WHERE, karena tanpa WHERE keduanya menyasar seluruh tabel.
  • Status pernyataan seperti UPDATE 1 dan DELETE 0 adalah data yang ditafsirkan, bukan dekorasi keluaran.
  • SELECT dengan syarat yang sama dijalankan lebih dahulu, dan perubahan besar dibungkus transaksi agar dapat dibatalkan.
  • RETURNING pada pernyataan tulis mengembalikan baris yang terkena dampak, berguna untuk audit dan konfirmasi.

Referensi#