Savepoints
Named markers within a transaction that allow partial rollback without aborting the entire transaction.
savepoint SAVEPOINT ROLLBACK TO SAVEPOINT nested transaction
transaction savepoint rollback error recovery
| Database | Status | Syntax Family | Min Version |
|---|---|---|---|
| PostgreSQL | full | sql-standard | - |
| MySQL | full | sql-standard | - |
| MariaDB | full | sql-standard | - |
| Oracle | full | sql-standard | - |
| SQL Server | full | tsql-save | - |
| SQLite | full | sql-standard | - |
| Redshift | none | - | - |
| DB2 | full | sql-standard | - |
| Snowflake | none | - | - |
| BigQuery | none | - | - |
Compare Databases
Database Details
PostgreSQL
full
BEGIN;
INSERT INTO orders (id, total) VALUES (1, 100);
SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 999);
-- Oops, rollback just the item insert
ROLLBACK TO SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 42);
COMMIT;- Reusing a savepoint name replaces the previous marker of that name.
- Required for error recovery in PL/pgSQL: any error aborts the transaction otherwise, and BEGIN ... EXCEPTION blocks are built on savepoints under the hood.
Docs: SAVEPOINT
MySQL
full
START TRANSACTION;
INSERT INTO orders (id, total) VALUES (1, 100);
SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 999);
ROLLBACK TO SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 42);
COMMIT;- InnoDB (and other transactional engines) only; MyISAM has no savepoints.
- DDL causes an implicit commit, which discards any open savepoints.
Docs: SAVEPOINT
MariaDB
full
START TRANSACTION;
INSERT INTO orders (id, total) VALUES (1, 100);
SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 999);
ROLLBACK TO SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 42);
COMMIT;- InnoDB only. DDL implicit-commits and discards savepoints, same as MySQL.
Docs: SAVEPOINT
Oracle
full
INSERT INTO orders (id, total) VALUES (1, 100);
SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 999);
ROLLBACK TO SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 42);
COMMIT;- No RELEASE SAVEPOINT; savepoints release implicitly at COMMIT.
- Transactions start implicitly on the first statement, so there is no BEGIN keyword.
Docs: SAVEPOINT
SQL Server
full
BEGIN TRANSACTION;
INSERT INTO orders (id, total) VALUES (1, 100);
SAVE TRANSACTION sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 999);
ROLLBACK TRANSACTION sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 42);
COMMIT;- Syntax is SAVE TRANSACTION <name> and ROLLBACK TRANSACTION <name>, not the SQL-standard SAVEPOINT / ROLLBACK TO.
- No RELEASE equivalent; markers are dropped at COMMIT.
Docs: SAVE TRANSACTION
SQLite
full
BEGIN;
INSERT INTO orders (id, total) VALUES (1, 100);
SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 999);
ROLLBACK TO SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 42);
RELEASE SAVEPOINT sp1;
COMMIT;- A SAVEPOINT outside an explicit BEGIN starts a transaction implicitly.
- RELEASE of the outermost savepoint commits the transaction up to that point.
Docs: SAVEPOINT
Redshift
none
- No SAVEPOINT, despite the PostgreSQL lineage.
- For partial rollback, split the work across separate transactions or use staging tables.
Docs: SQL Commands (Redshift)
DB2
full
BEGIN;
INSERT INTO orders (id, total) VALUES (1, 100);
SAVEPOINT sp1 ON ROLLBACK RETAIN CURSORS;
INSERT INTO order_items (order_id, product_id) VALUES (1, 999);
ROLLBACK TO SAVEPOINT sp1;
INSERT INTO order_items (order_id, product_id) VALUES (1, 42);
COMMIT;- SAVEPOINT requires an ON ROLLBACK clause: RETAIN CURSORS or RETAIN LOCKS.
- ROLLBACK TO SAVEPOINT releases locks acquired since the savepoint unless ON ROLLBACK RETAIN LOCKS was set.
Docs: SAVEPOINT
Snowflake
none
- Transactions expose only COMMIT and ROLLBACK. For nested error handling, use exception blocks in Snowflake Scripting.
Docs: Transaction Commands
BigQuery
none
- Multi-statement transactions support only COMMIT and ROLLBACK. No partial rollback.
Docs: Transactions in BigQuery