Cara aman menjalankan UPDATE dan DELETE di production
Untuk menjalankan UPDATE atau DELETE dengan aman di production, tulis klausa WHERE lebih dulu, jalankan SELECT dengan WHERE yang persis sama untuk melihat baris mana yang cocok, lalu jalankan perubahan di dalam transaksi, cocokkan jumlah baris yang terkena, dan baru kemudian COMMIT. Perubahan besar dijalankan dalam batch terbatas. Di Selekta, tandai koneksinya sebagai Production agar statement yang merusak meminta Anda mengetik nama koneksi dan tab SQL dimulai dalam manual commit.
Kebiasaan di bawah berlaku di client mana pun dan di engine apa pun. Paruh kedua menunjukkan bagaimana Selekta menerapkannya untuk Anda.
Rutinitasnya, langkah demi langkah
- Tulis WHERE sebelum kata kerjanya. Mulai dari kondisi, bukan dari
DELETE FROM.DELETE FROM ordersyang baru setengah diketik lalu tidak sengaja dijalankan akan menghapus semuanya;WHERE status = 'test'yang setengah jadi tidak melakukan apa-apa. - SELECT dengan predikat yang sama. Salin WHERE ke sebuah SELECT, lalu lihat baris dan jumlahnya.
- Buka transaksi. Jalankan perubahan di antara
BEGINdanCOMMITsupaya masih bisa di-rollback. - Jalankan perubahan dan bandingkan jumlah baris yang dilaporkan server dengan hasil langkah 2. Kalau berbeda, rollback.
- Periksa hasilnya dengan SELECT di dalam transaksi yang sama.
- COMMIT, atau ROLLBACK jika ada yang terlihat janggal.
- Pecah perubahan besar menjadi batch. Ubah puluhan ribu baris sekali jalan, bukan jutaan, supaya lock tetap singkat dan replika tidak tertinggal.
Rutinitas tersebut dalam SQL:
-- 2. apa yang akan berubah?
SELECT id, status, created_at
FROM orders
WHERE status = 'pending' AND created_at < '2026-01-01';
-- 1,284 rows
-- 3. sampai 6.
BEGIN;
UPDATE orders
SET status = 'expired'
WHERE status = 'pending' AND created_at < '2026-01-01';
-- UPDATE 1284 (sama dengan hasil SELECT, jadi lanjut)
SELECT count(*) FROM orders WHERE status = 'expired' AND created_at < '2026-01-01';
COMMIT; -- atau ROLLBACK;
Di SQL Server pakai BEGIN TRANSACTION dan COMMIT TRANSACTION; di MySQL START TRANSACTION atau BEGIN. DDL MySQL seperti ALTER TABLE melakukan commit implisit, jadi jangan campurkan perubahan skema ke dalam transaksi ini.
Dua kebiasaan lain juga membantu: pakai RETURNING (PostgreSQL, SQLite 3.35+) atau OUTPUT (SQL Server) untuk melihat baris yang berubah, dan simpan salinan dari apa yang Anda hapus:
CREATE TABLE orders_deleted_20261023 AS
SELECT * FROM orders WHERE status = 'test';
DELETE FROM orders WHERE status = 'test' RETURNING id;
Membatasi batch di setiap engine
Perubahan besar lebih aman dilakukan per batch. Sintaksnya berbeda di tiap engine.
MySQL dan MariaDB mengizinkan LIMIT pada UPDATE dan DELETE satu tabel. Tambahkan ORDER BY pada key supaya setiap batch bisa diprediksi, lalu ulangi sampai 0 baris terkena:
DELETE FROM events WHERE created_at < '2025-01-01' ORDER BY id LIMIT 10000;
PostgreSQL tidak punya LIMIT pada UPDATE atau DELETE. Pilih key-nya di subquery:
DELETE FROM events
WHERE id IN (
SELECT id FROM events WHERE created_at < '2025-01-01' ORDER BY id LIMIT 10000
);
SQL Server memakai TOP. Urutan baris yang diambil tidak dijamin, dan itu tidak masalah untuk pembersihan data:
DELETE TOP (10000) FROM dbo.Events WHERE CreatedAt < '2025-01-01';
SQLite hanya mendukung LIMIT pada DELETE jika di-build dengan opsi khusus, jadi pakai pola PostgreSQL dengan rowid atau primary key.
Commit setelah setiap batch, jangan menahan satu transaksi panjang.
Tandai koneksi sebagai Production
Di dialog koneksi, atur Environment ke Production. Teks bantuannya merangkum: "Production shows a red ENV cell and asks you to type the connection name before destructive statements run." Staging menampilkan sel STAGING bergaris tepi dan meminta konfirmasi sederhana. Local dan None tidak menambah konfirmasi selain konfirmasi dasar di bawah.
Anda juga bisa mencentang Read-only untuk koneksi yang hanya dipakai membaca. Koneksi read-only langsung menolak operasi tulis ("Nothing ran"), sementara SELECT, EXPLAIN dan SHOW tetap jalan.
Yang diperiksa Selekta sebelum statement dijalankan
Selekta mem-parse setiap statement sebelum mengirimnya. Tidak ada yang dikirim sebelum Anda mengonfirmasi. Di semua koneksi, termasuk Local, Selekta bertanya sebelum:
DELETEatauUPDATEtanpa klausa WHERE (termasuk di dalam statementWITH),TRUNCATE,DROP.
Di Production dan Staging, Selekta juga bertanya sebelum ALTER … DROP, blok DO, CALL, EXEC dan blok T-SQL, MERGE yang meng-update atau menghapus, WITH yang mengubah data, dan UPDATE atau DELETE berfilter yang menurut estimasi planner akan mengenai lebih dari 1.000 baris.
Dialog konfirmasi menampilkan statement, koneksi dan user, alasannya ("UPDATE without WHERE", "DELETE matching about 1284 rows"), estimasi baris dari planner, dan mode commit. Di Production Anda harus mengetik nama koneksi di Type orders-prod to confirm sebelum tombolnya, misalnya Delete about 1,284 rows, aktif. Fokus awal ada di Cancel, Esc membatalkan, dan ↵ tidak pernah mengonfirmasi. Explain first menampilkan rencana eksekusi sebelum Anda memutuskan.

Manual commit di tab Production
Tab SQL baru pada koneksi Production terbuka dalam Manual commit (Settings › Editor › Start Production tabs in manual commit, aktif secara default). Setiap statement yang dijalankan masuk ke transaksi yang terbuka. Action bar menampilkan Manual commit dengan hitungan seperti "2 pending", dan statement yang tertunda didaftar di bawah editor sebagai "executed in an open transaction · not committed".
- Tekan ⌥⌘↵ untuk Commit, atau ⌥⌘⌫ untuk Rollback.
- Menutup tab, atau mengalihkannya ke Auto, saat masih ada statement tertunda akan memunculkan "Close with 2 uncommitted statements?" dengan pilihan Roll back and close atau Commit and close. Tidak ada cara menutup tanpa memutuskan.
- Jika koneksi terputus, server me-rollback transaksinya. Selekta memberi tahu hal itu dan memulihkan statement Anda sebagai revisi tertunda, dengan tombol Run again dan Copy as SQL.
- Statement yang di-rollback tetap ada di History dengan tanda VOID, jadi Anda bisa melihat apa yang pernah dicoba.

Mengedit baris di grid: revisi dan Review SQL
Mengubah beberapa baris secara manual sering lebih aman lewat grid data daripada lewat SQL, karena klausa WHERE dibuat dari primary key. Buka tabel, edit sel, tambah baris dengan ⌥⌘N atau hapus dengan ⌫. Belum ada yang dikirim: setiap perubahan menjadi revisi bernomor yang disorot warna amber.

Tekan Apply (⌘S) dan Review SQL terbuka, di semua environment. Dialog ini mendaftar setiap UPDATE, INSERT dan DELETE sesuai urutan eksekusi beserta koneksi tujuannya. Dengan Run in one transaction tercentang (default), jika ada statement yang gagal atau mengenai 0 baris, semuanya di-rollback dan revisi Anda tetap tersimpan. Ini menangkap baris yang sempat diubah atau dihapus orang lain. Copy SQL menyalin statement ke clipboard untuk tiket perubahan.

Kalau gagal
UPDATE without WHERE atau DELETE without WHERE di dialog konfirmasi: statement tidak punya filter dan akan mengubah semua baris. Klik Cancel dan tambahkan klausa WHERE, kecuali memang itu yang Anda mau.
DELETE matching about 48210 rows: planner memperkirakan jauh lebih banyak baris dari yang mungkin Anda maksud. Batalkan, jalankan SELECT-nya, dan pecah perubahan menjadi batch.
These revisions cannot be applied: muncul di Review SQL saat revisi tidak bisa diubah menjadi SQL. Alasannya tertulis setelah titik dua. Perbaiki nilai yang diedit, atau klik Discard di strip Revisions dan mulai lagi.
Reconnected to orders-prod. The server rolled back the open transaction. Tidak ada yang ter-commit. Statement Anda dipulihkan sebagai revisi tertunda; jalankan lagi atau salin.
Nothing ran dengan "Use a read-write connection for this change, or turn off read-only on orders-prod.": koneksinya read-only. Memang begitu rancangannya.