Skip to main content
Documents
Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Toggle Dark/Light/Auto mode Back to homepage

判断数据是否存在

下面给你 PostgreSQL + SQLAlchemy 2.0 下常用的 “判断数据是否存在” 的最佳实践,分别包含:

  • ✅ 原生 SQL 查询是否存在
  • ✅ ORM 查询是否存在
  • ✅ 推荐写法(性能最优)
  • ❌ 低效写法(避免)

✅ 一、使用 原生 SQL 判断是否存在

1.1 使用 EXISTS(性能最佳)

SELECT EXISTS (
    SELECT 1 FROM users WHERE email = 'test@example.com'
);

返回:

exists
true

1.2 只取一行来判断(次优)

SELECT 1 
FROM users 
WHERE email = 'test@example.com'
LIMIT 1;
  • 如果返回行 -> 存在
  • 如果无返回 -> 不存在

✅ 二、SQLAlchemy 2.0 ORM 判断是否存在

2.1 使用 select + exists()(官方推荐)

from sqlalchemy import select, exists
from models import User

stmt = select(
    exists().where(User.email == "test@example.com")
)

result = await session.scalar(stmt)
print(result)  # True / False

特点:

  • 不返回实体,不扫描全表
  • 性能最好
  • PostgreSQL 会用 EXISTS(…) 执行

2.2 使用 select(1).where(…).limit(1)

stmt = select(1).where(User.email == "test@example.com").limit(1)
exists_ = await session.scalar(stmt) is not None

✅ 三、判断数据存在并返回数据

如果需要「判断存在且获取具体行」,用:

3.1 .first()

stmt = select(User).where(User.email == "test@example.com")
row = await session.scalar(stmt)

if row:
    print("存在", row)
else:
    print("不存在")

3.2 .one_or_none()

更严格的写法:

row = await session.scalar(select(User).where(User.id == 1))

if row is None:
    print("不存在")
else:
    print("存在")

❌ 四、低效写法(不要这样做)

4.1 不应该 count 全部数据

stmt = select(func.count()).where(User.email == "test@example.com")
count = await session.scalar(stmt)

exists = count > 0

⚠️ 性能差,因为 COUNT 会扫描满足条件的全部行。

🔥 五、总结成一句话

  • PostgreSQL 中判断是否存在,用 EXISTS 是性能最优
  • SQLAlchemy 2.0 中用 select(exists().where(…))

🧩 示例:封装一个通用的 exists() 工具函数

支持 ORM model 与任意 where 条件。

from sqlalchemy import exists, select
from sqlalchemy.ext.asyncio import AsyncSession

async def exists_row(session: AsyncSession, model, *conditions) -> bool:
    stmt = select(exists().where(*conditions))
    return await session.scalar(stmt)

使用

exists_ = await exists_row(
    session,
    User,
    User.email == "test@example.com"
)

print(exists_)  # True / False