SQL RecycleBin: An Undo Button for SQL Server
DEV Community

SQL RecycleBin: An Undo Button for SQL Server

Every DBA has lived this moment: someone runs a DELETE without a WHERE clause on a production table, and the room goes quiet. Oracle has had an answer for this for years - Flashback Query. SQL Server's answer has basically been: hope your backup chain is intact, or pay for a $2,000 transaction-log forensics tool. So I built SQL RecycleBin. It's exactly what it sounds like - a recycle bin for SQL Server. Enable it once per table, and every DELETE or UPDATE gets captured automatically. When something goes wrong, you don't restore a backup and lose every transaction since - you just query it back and undo it.

Core Flow

Turn on capture for a table (one-time setup):

EXEC rb.Enable @Table = 'dbo.Orders';

...someone runs DELETE without a WHERE clause:

DELETE FROM dbo.Orders;

See exactly what was lost, as real typed columns - not raw log bytes:

EXEC rb.Deleted @Table = 'dbo.Orders';

Put it all back. Done.

EXEC rb.UndoLast @Table = 'dbo.Orders';

No log readers, no downtime, no third-party agent sitting in your pipeline.

Examples

Recovering from a bad UPDATE

EXEC rb.Enable @Table = 'dbo.Customers';

A migration script accidentally overwrites everyone's email domain:

UPDATE dbo.Customers SET Email = 'u******@company.com';

Inspect before/after values for recent updates:

EXEC rb.Updated @Table = 'dbo.Customers', @Top = 50;

Revert every captured update since it happened:

EXEC rb.UndoLast @Table = 'dbo.Customers';

Rolling back to a specific point in time, across a whole transaction

Find the transaction ID responsible:

EXEC rb.Status;

Undo everything from that specific transaction, not just the last one:

EXEC rb.UndoTransaction @Table = 'dbo.Orders', @TxId = 48213;

Or roll a table back to how it looked at a timestamp:

EXEC rb.Restore @Table = 'dbo.Orders', @Since = '2026-07-25 09:00';

Excluding capture during bulk jobs or ETL

EXEC rb.BypassOn;

Nightly bulk load - none of this gets captured:

INSERT INTO dbo.Orders SELECT * FROM staging.Orders;
EXEC rb.BypassOff;

Keeping the history store lean

Purge anything older than 14 days (the default retention window):

EXEC rb.Cleanup @KeepDays = 14;

PowerShell Support

Prefer PowerShell over T-SQL? The same engine is wrapped as a module on the PowerShell Gallery:

Install-Module SqlRecycleBin
Install-SqlRecycleBin -Database "MyDb"
Enable-SqlRecycleBinCapture -Table "dbo.Orders"
Restore-SqlRecycleBinLast -Table "dbo.Orders"

What's Actually Happening Under the Hood

  • rb.Enable generates a lightweight AFTER UPDATE, DELETE trigger on the table.
  • Changed rows are captured as JSON into a compressed internal store (rb.ChangeLog) - JSON means an ALTER TABLE on your side never breaks the safety net.
  • Retrieval procs (rb.Deleted, rb.Updated) project that JSON back into real typed columns via OPENJSON, using the table's current schema.
  • Undo procs handle IDENTITY_INSERT and skip primary key collisions automatically.
  • All of it is persistent on disk - it survives restarts and failovers, unlike an in-memory cache.

Honest About Its Limits

  • TRUNCATE TABLE, DROP TABLE, and minimally-logged bulk operations don't fire triggers, so they aren't captured. This is a safety net, not a backup replacement.
  • Tables need a primary key.
  • Trigger capture adds write overhead - measure it on your workload, and use rb.BypassOn around heavy bulk jobs.

Full details are in the README.

Licensing

I'm shipping it as source-available under PolyForm Noncommercial - the complete v1 is free to read, install, and use for personal, educational, and noncommercial work. Commercial use requires a license, and that's what funds the roadmap: a CDC-based capture engine with zero trigger overhead, a Blazor dashboard with a diff viewer and one-click restore, and app-level user identity for who-did-what forensics behind connection pools.

Repo: https://github.com/qmmughal/sql-recyclebin
Live demo + docs: https://sqlrecyclebin.com

If you manage SQL Server databases - or you've ever been the person who had to explain a bad DELETE to your team - I'd love a star, a try, or just your thoughts on what a real "undo" for SQL Server should look like.

SQLServer #DBA #OpenSource #TSQL #DisasterRecovery #DataEngineering

Top comments (0)

Comments

No comments yet. Start the discussion.