数据库中的EXISTS

12 阅读3分钟

前言

EXISTS 和 NOT EXISTS 是 SQL 中用于存在性判断的谓词,返回布尔值(TRUE/FALSE),常用于 WHERE 子句中过滤数据

使用

准备两张表

-- public.campus_device definition

  


-- Drop table

  


-- DROP TABLE public.campus_device;

  


CREATE TABLE public.campus_device (

id int8 NOT NULL,

create_id int8 NULL,

create_time timestamp NULL,

dr int4 NULL,

last_modify_id int8 NULL,

last_modify_time timestamp NULL,

tenant_id int8 NULL,

"version" int4 NULL,

device_name varchar(255) NULL,

mac varchar(255) NULL,

org_id int8 NULL,

product_id int8 NULL,

saas_device_id int8 NULL,

verify_code varchar(255) NULL,

address varchar(255) DEFAULT NULL::character varying NULL,

createid int8 NULL,

devicename varchar(255) NULL,

orgid int8 NULL,

productid int8 NULL,

saasdeviceid int8 NULL,

verifycode varchar(255) NULL,

CONSTRAINT campus_device_pkey PRIMARY KEY (id)

);

以及

-- public.campus_room_user_rel definition

  


-- Drop table

  


-- DROP TABLE public.campus_room_user_rel;

  


CREATE TABLE public.campus_room_user_rel (

id int8 NOT NULL,

room_id int8 NULL,

user_id int8 NULL,

create_id int8 NULL,

create_time timestamp DEFAULT CURRENT_TIMESTAMP NULL,

last_modify_id int8 NULL,

last_modify_time timestamp NULL,

"version" int4 DEFAULT 0 NULL,

dr int4 DEFAULT 0 NULL,

tenant_id int8 NULL,

admin_status varchar NULL,

user_authored_type varchar NULL,

createid int8 NULL,

adminstatus varchar(255) NULL,

roomid int8 NULL,

userauthoredtype varchar(255) NULL,

userid int8 NULL,

bed_number int4 NULL,

CONSTRAINT campus_room_user_rel_pkey PRIMARY KEY (id)

);

语法使用

-- EXISTS:子查询有结果返回 TRUE 

SELECT * FROM 表A WHERE EXISTS (SELECT 1 FROM 表B WHERE 表B.id = 表A.id);

-- NOT EXISTS:

子查询无结果返回 TRUE

SELECT * FROM 表A WHERE NOT EXISTS (SELECT 1 FROM 表B WHERE 表B.id = 表A.id);

核心特点

只关心"有没有",不关心"是什么":子查询中写 SELECT 1、SELECT * 或 SELECT 字段名 效果完全一样,因为 EXISTS 只判断是否返回了行,不关心具体返回值。

短路评估:找到第一条匹配记录就立即停止扫描,性能优于 COUNT(*) > 0。

相关子查询:子查询通常依赖外层查询的字段做关联条件,对外层每一行都会执行一次子查询。 执行流程

以 NOT EXISTS 为例:

外层查询取出一行记录

将该行字段值代入子查询执行

子查询返回空集 → NOT EXISTS 为 TRUE → 该行保留

子查询返回至少一行 → NOT EXISTS 为 FALSE → 该行过滤掉

重复以上步骤直到外层遍历完

与 NOT IN 的关键区别

表对比维度NOT EXISTSNOT IN
NULL 处理不受 NULL 影响,安全子查询含 NULL 时整个条件可能返回空集
执行方式逐行检查,找到即停需先加载完整子查询结果集再逐一比对
性能通常更优,尤其大数据量场景子查询结果集大时可能全表扫描
⚠️ 如果子查询字段允许 NULL 且未加 IS NOT NULL 过滤,禁止使用 NOT IN,必须用 NOT EXISTS。
常见应用场景
查找有关联数据的记录(EXISTS):如"查询有订单的客户"
查找没有关联数据的记录(NOT EXISTS):如"查询未分配班级的学生"
防重复插入:插入前判断记录是否已存在
替代 COUNT(*) > 0 做存在性判断

语法查询

SELECT c.*

FROM campus_room c

WHERE c.tenant_id = 2031967244505841665

AND c.dr = 0

AND NOT EXISTS (

SELECT 1

FROM campus_room_user_rel l

WHERE l.room_id = c.id and l.dr = 0

);

  


select * from campus_room c where c.id= 2075450553046925314 and

exists (select 1 from campus_room_user_rel u where c.id = u.room_id );

总结

数据库中的EXISTS和not EXISTS在某种情况下查询更优