DatabaseStatusSyntax FamilyMin 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.
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.
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.
BigQuery none
  • Multi-statement transactions support only COMMIT and ROLLBACK. No partial rollback.