Important
The SingleStore 9.1 release candidate (RC) gives you the opportunity to preview, evaluate, and provide feedback on new and upcoming features prior to their general availability. In the interim, SingleStore 9.0 is recommended for production workloads, which can later be upgraded to SingleStore 9.1.
DELETE . . . RETURNING
On this page
The DELETE . statement allows you to delete rows and return data from the deleted rows in a single statement.SELECT to see which rows were removed, reduces duplicate table scans, and simplifies application logic.
In transactional workloads, DELETE . participates in transactions like any other DML statement.
Syntax:
DELETE FROM table_name
[WHERE <where_condition>]
[LIMIT row_count]
[RETURNING * | column_name [AS alias] [, column_name [AS alias] ...]];In the above syntax:
RETURNING * - returns all columns of each deleted row.
RETURNING <column_ - returns only the listed columns from each deleted row.
RETURNING <column_ - assigns an alias to a returned column.
For information on other arguments in the syntax refer DELETE
Remarks
Supported on both rowstore and columnstore tables.
Supported in both single- and multi-host deployments.
Works for both rowstore and columnstore tables, but very large deletes may still be subject to the same memory and performance considerations as standard DELETE (for example, use LIMIT in batches when deleting many rows from narrow rowstore tables).
The RETURNING clause accepts only * or column names (with optional aliases).
Expressions such as t.RETURNING list are not supported.
DELETE . produces a result set that clients consume the same way as a SELECT result:
-
Each row in the result set corresponds to a deleted row.
-
The columns of the result set are exactly those listed in the
RETURNINGclause, in the specified order. -
If you use * all columns from the deleted table are returned.
-
Column names in the result set reflect any aliases specified in the
RETURNINGclause.
The data visible in the RETURNING result set corresponds to the state of each row at the moment it is deleted.
For DELETE, all rows that appear in the result set are actually deleted from the table once the transaction commits.
Integration with Client Libraries - Because DELETE . uses the same protocol shape as SELECT (metadata + rows), client drivers and ORMs that support "DML with RETURNING" can consume the returned rows as a standard result set.
Any DELETE that involves more than one table (joins, multi-table deletes, or subselects in the target for returning multiple tables) is not supported with RETURNING.
Not supported in stored procedures or CTEs.
Examples
Example 1: The following example deletes expired products and returns all deleted rows for logging or auditing.
DELETE FROM productsWHERE expiration_date <= CURDATE()RETURNING *;
Example 2: The following example deletes a limited number of events.LIMIT applies both to the number of rows deleted and the rows returned (similar to UPDATE . with LIMIT).
DELETE FROM eventsWHERE created_at < '2026-01-01'LIMIT 100RETURNING id, created_at;
Example 3: The following example deletes specific employees and return selected columns.
DELETE FROM employeesWHERE name IN ('Diana', 'Frank')RETURNING id AS employee_id, name, salary;
Example 4: The following example deletes all employees in the 'Research' team and returns only the columns needed by the application, with aliases that match the client-side model.
DELETE FROM employeesWHERE team = 'Research'RETURNING name AS employee_name, salary, manager_id AS manager;
Example 5: The following example shows the traditional pattern vs.DELETE ..RETURNING, an application that needs to determine which rows were deleted typically runs two statements:
BEGIN;SELECT *FROM productsWHERE expiration_date <= CURDATE()FOR UPDATE;DELETE FROM productsWHERE expiration_date <= CURDATE();COMMIT;
With DELETE ., the same workflow becomes a single statement, thereby avoids scanning the table twice and reduces the risk of anomalies related to re-identifying rows (e.
DELETE FROM productsWHERE expiration_date <= CURDATE()RETURNING *;
Last modified: February 17, 2026