sqlcmd.net validated sql reference
advanced deleting MySQL MariaDB SQL Server PostgreSQL SQLite

Delete Rows Based On A Condition In Another Table

Remove rows from one table when a matching row exists in another table using a subquery.

Docker-validated Not currently validation-green

Remove sessions belonging to banned users

User 2 appears in banned_users, so both of their sessions (ids 2 and 4) are deleted. Users 1 and 3 have no match in banned_users and their sessions remain. The correlated EXISTS subquery re-evaluates for each row in sessions, stopping as soon as a match is found.

Rows loaded before the example query runs.
Setup
CREATE TABLE sessions (id INT, user_id INT);

CREATE TABLE banned_users (user_id INT);

INSERT INTO
  sessions (id, user_id)
VALUES
  (1, 1),
  (2, 2),
  (3, 3),
  (4, 2);

INSERT INTO
  banned_users (user_id)
VALUES
  (2);
Shared across supported engines.
SQL
DELETE FROM sessions
WHERE
  EXISTS (
    SELECT
      1
    FROM
      banned_users
    WHERE
      banned_users.user_id = sessions.user_id
  );

SELECT
  id,
  user_id
FROM
  sessions
ORDER BY
  id;
Returned rows for the shared example.
iduser_id
11
33

Output is identical across all engines.

Where this command helps.

  • removing session or activity rows when the associated user has been banned
  • cleaning up child records when the parent matches a condition in a separate table

What the command is doing.

Deleting rows conditionally based on related data uses a subquery in the WHERE clause. The IN form checks whether a column value appears in a set returned by the subquery. The EXISTS form uses a correlated subquery and is often more efficient when the inner table is large, because the database stops evaluating after the first match.