MySQL
ORACLE
POSTGRESQL
SQL
SQL SERVER

A Complete Guide to NOT EXISTS in SQL

intro

Let's everything you need to know about NOT EXISTS in SQL—an operator used to check whether certain rows do not exist in a dataset.

Tools used in the tutorial
Tool Description Link
Dbvisualizer DBVISUALIZER
TOP RATED DATABASE MANAGEMENT TOOL AND SQL CLIENT

In the real world, sometimes the easiest way to identify objects is to think of them as something that does not exist or fall into a specific category. This is exactly why databases provide NOT EXISTS in SQL!

The NOT EXISTS SQL operator helps you find elements that do not exist in a sub-dataset. In this guide, you will learn what the operator is, how it works, when to use it, and what alternatives SQL offers.

Let’s dive in!

What is the NOT EXISTS SQL Operator?

In SQL, the NOT EXISTS operator checks if a subquery returns no rows. In other words, it tests for the existence of no records in a subquery. Specifically, it evaluates to:

  • true if the subquery produces an empty result set; or
  • false if the subquery finds any matching rows.

Generally, the SQL NOT EXISTS operator is used in WHERE clauses to filter records that do not have corresponding entries in another table.

SQL NOT EXISTS: Syntax and Usage

This is the syntax of NOT EXISTS in SQL:

Copy
        
1 NOT EXISTS (subquery)

Where subquery is an arbitrary SELECT statement. For more details, read our guide on SQL subqueries.

Just like any other operator, NOT EXISTS can be used in SELECT, DELETE, UPDATE, and INSERT queries. In particular, it typically appears in the WHERE clause as in the following NOT EXISTS SQL query example:

Copy
        
1 DELETE FROM customers 2 WHERE NOT EXISTS ( 3 SELECT * FROM orders 4 WHERE orders.customer_id = customers.id 5 );

This query removes customers who have never placed an order, while the subquery checks if a customer has any corresponding rows in the orders table. If no matching rows exist, NOT EXISTS evaluates to true, and the customer is deleted.

Thus, the subquery following the SQL NOT EXISTS operator is evaluated to check if it returns any rows. If at least one row is found, NOT EXISTS evaluates to false; if no rows are returned, it evaluates to true.

Notes:

  • The subquery typically references values and columns from the outer query.
  • The subquery is executed only until the database determines whether at least one row is returned, rather than running it to completion.
  • Since NOT EXISTS only checks for the presence of rows, not their contents, the subquery is usually written as SELECT *, as selecting specific columns makes no difference.
  • If the subquery returns any rows, even if they contain only NULL values, NOT EXISTS evaluates to false. In other words, the content of the returned row is irrelevant. What matters is its presence.
  • NOT EXISTS can be nested within another NOT EXISTS condition in the WHERE clause.

An Example of Using NOT EXISTS in SQL

You now know what the SQL NOT EXISTS operator is, how it works, and how to use it. Still, to fully understand it, the best approach is through a complete walkthrough.

Note 1: The sample queries below are written in MySQL, but they can easily be adapted for PostgreSQL, SQL Server, Oracle, or any other database.

Note 2: The sample queries will be executed in DbVisualizer, a powerful, top-rated multi-database client. However, any other database client will work.

Let’s see NOT EXISTS in SQL in action!

Data Presentation

Suppose you have a simple company database with the following two tables:

  • employees contain data on the employees working at the company.
  • departments represent the different areas within the company.

employees contain the following data:

The data in the employees table in DbVisualizer
The data in the employees table in DbVisualizer

While departments store the following data:

The data in the departments table in DbVisualizer
The data in the departments table in DbVisualizer

As you can tell, the two tables are connected by a foreign key via the department_id

column. The relationship is visualized in the ERD-like schema generated by DbVisualizer Pro:

The ERD-like graph generated by DbVisualizer
The ERD-like graph generated by DbVisualizer

Note that not all employees are assigned to a department and not all departments have at least one employee.

Example #1: Checking If an Employee Is NOT in a Department

Assume you want to retrieve all employees who do not belong to a department that exists in the departments table. This is the NOT EXISTS SQL query you should run:

Copy
        
1 SELECT first_name, last_name 2 FROM employees e 3 WHERE NOT EXISTS ( 4 SELECT * 5 FROM departments d 6 WHERE e.department_id = d.department_id 7 );

This query checks if there is no corresponding department for each employee by using NOT EXISTS in SQL. Then, it returns employees whose department_id does not exist in the departments table.

As expected, the result will be “Alice Green”:

Executing the query in DbVisualizer
Executing the query in DbVisualizer

Sure, you could have achieved the same result with a simple IS NOT NULL query on the department_id column. But what if the foreign key constraint is not set, and some department_id values no longer refer to valid records in the departments table? In this case, the NOT EXISTS query would be the go-to solution.

Example 2: Checking If a Department Has No Employees

Consider a scenario where you want to get all departments that do not have any employees assigned to them. Achieve that with NOT EXISTS :

Copy
        
1 SELECT department_name 2 FROM departments d 3 WHERE NOT EXISTS ( 4 SELECT * 5 FROM employees e 6 WHERE e.department_id = d.department_id 7 );

The result will be “Finance”, as it is the only department with no employees:

Launching the query in DbVisualizer
Launching the query in DbVisualizer

Et voilà! You now understand NOT EXISTS in SQL.

Alternatives to NOT EXISTS in SQL

Thinking about the non-existence of something can be counterintuitive, so are there alternatives to NOT EXISTS? Well, it depends on the specific scenario, but there are often other, more intuitive solutions…

For example, consider the query that uses NOT EXISTS to find departments without employees:

Copy
        
1 SELECT d.department_id, d.department_name 2 FROM departments d 3 WHERE NOT EXISTS ( 4 SELECT 1 5 FROM employees e 6 WHERE e.department_id = d.department_id 7 );

Let's explore equivalent queries using different approaches!

Alternative #1: Using NOT IN

Copy
        
1 SELECT d.department_id, d.department_name 2 FROM departments d 3 WHERE d.department_id NOT IN ( 4 SELECT COALESCE(e.department_id, 0) 5 FROM employees e 6 );

This query uses the SQL NOT IN operator to filter departments where the department_id is not found in the list of department IDs that have employees. It selects all departments that do not have any employees by checking the employees table.

Note: Be cautious when using NOT IN, as it may behave incorrectly if the subquery returns NULL values (it might return no rows due to how NULL values are handled in NOT IN). To prevent that, the SQL COALESCE function is used to replace any NULL values in the department_id column with a default value (like 0), guaranteeing that the query executes correctly even if NULL values are encountered in the subquery (as it happens in this scenario.)

Alternative #2: Using EXCEPT

Copy
        
1 SELECT d.department_id, d.department_name 2 FROM departments d 3 EXCEPT 4 SELECT d.department_id, d.department_name 5 FROM departments d 6 JOIN employees e ON d.department_id = e.department_id;

The SQL EXCEPT operator returns the result of the first query, excluding the rows returned by the second query. In this case, it selects all departments and subtracts the ones that have employees (identified by a JOIN with the employees table).

This approach is useful for finding departments without employees, but it can be less efficient than NOT EXISTS for larger datasets since it requires two queries.

Alternative #3: Using a LEFT JOIN

Copy
        
1 SELECT d.department_id, d.department_name 2 FROM departments d 3 LEFT JOIN employees e ON d.department_id = e.department_id 4 WHERE e.department_id IS NULL;

The above query uses a LEFT JOIN to join the departments table with the employees table. It selects departments where there is no matching employee (e.department_id IS NULL).

This may appear as the most intuitive method to find departments without employees because it clearly shows the relationship between the two tables and handles the case of unmatched rows effectively.

Conclusion

In this guide, you learned about the SQL NOT EXISTS operator, how it works, and how to use it. As you saw, working with such operators becomes much easier with a visual database tool that allows you to explore data interactively—just like DbVisualizer.

DbVisualizer is a powerful database client that fully supports NOT EXISTS and all other SQL operators. It also offers advanced features like query optimization, SQL formatting, and schema visualization with ERD-like diagrams. Download DbVisualizer for free today!

FAQ

Is the NOT EXISTS SQL operator part of standard SQL?

Yes, the NOT EXISTS operator is part of standard ANSI SQL. That is the reason why it is widely supported by major relational database management systems such as MySQL, PostgreSQL, SQL Server, and Oracle.

What is the difference between EXISTS and NOT EXISTS in SQL?

This is the main difference between EXISTS and NOT EXISTS in SQL:

  • EXISTS: Returns true if the subquery returns one or more rows, indicating the existence of matching records.
  • NOT EXISTS: Returns true if the subquery returns no rows, indicating the non-existence of matching records.

These two clauses are opposites of each other.

SQL NOT EXISTS vs NOT IN: What is the difference?

See the difference in the SQL NOT EXISTS vs NOT IN table below:

FeatureNOT EXISTSNOT IN
PurposeChecks for non-existence of rows in a subqueryChecks if a value is not in a list of values or subquery results
Subquery typeOften used with correlated subqueriesWorks with both correlated and non-correlated subqueries
Use CaseIdeal for checking the non-existence of related rowsSuitable for static values or checking against a list of values
Behavior with **NULL**Safely deals with NULLs in the subqueryLead to unexpected behavior if the subquery returns NULLs

Can the SQL NOT EXISTS operator be used outside of a WHERE clause?

Yes, like any other SQL operator, the NOT EXISTS operator can be used in the SELECT clause and other parts of a query. Still, it is primarily used within the WHERE clause, as it is most effective for filtering results based on the existence (or non-existence) of rows returned by a subquery.

What does "NOT EXISTS" do in CREATE TABLE IF NOT EXISTS in SQL?

In the context of CREATE TABLE IF NOT EXISTS, the NOT EXISTS is not the same as the NOT EXISTS SQL operator used in subqueries. There, it checks whether a table already exists in the database. If the table does not exist, the query will create it. If the table already exists, no action is taken.

Dbvis download link img
About the author
Antonello Zanini

Antonello is a software engineer, and often refers to himself as a technology bishop. His mission is to spread knowledge through writing.

The Table Icon
Sign up to receive The Table's roundup
More from the table
Title Author Tags Length Published
title

SQL Server CHARINDEX Function (Find Substring Position)

author TheTable tags SQL SERVER 6 min 2025-06-11
title

pg_dumpall: How to Dump All Your PostgreSQL Databases

author Antonello Zanini tags POSTGRESQL 7 min 2025-06-10
title

Database Security: The Most Common Mistakes to Avoid

author Lukas Vileikis tags MARIADB MySQL SECURITY SQL 6 min 2025-06-09
title

How to Compare Datetimes in SQL: Multiple Approaches

author TheTable tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 5 min 2025-06-04
title

The Complete Guide to CONCAT in SQL Queries: Syntax, Examples, and Best Practices

author Leslie S. Gyamfi tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 7 min 2025-06-03
title

How Often Should SQL Transaction Logs Be Backed Up?

author Antonello Zanini tags MySQL POSTGRESQL SQL SQL SERVER 7 min 2025-06-02
title

How to Fix Oracle ORA-00933 Error: SQL Command Not Properly Ended

author TheTable tags ORACLE 4 min 2025-05-28
title

What Is a Database Catalog?

author Antonello Zanini tags MySQL ORACLE POSTGRESQL SQL SQL SERVER 6 min 2025-05-27
title

The Most Common MySQL Error Codes (and How to Avoid Them)

author Lukas Vileikis tags MARIADB MySQL SQL 5 min 2025-05-26
title

Top SQL Performance Tuning Interview Questions and Answers

author TheTable tags SQL 13 min 2025-05-21

The content provided on dbvis.com/thetable, including but not limited to code and examples, is intended for educational and informational purposes only. We do not make any warranties or representations of any kind. Read more here.