【问题标题】:sqlalchemy exists for querysqlalchemy 存在用于查询
【发布时间】:2011-11-30 13:31:30
【问题描述】:

如何检查查询中的数据是否存在?

例如:

users_query = User.query.filter_by(email='x@x.com')

如何检查是否存在使用该电子邮件的用户?

我可以用

来检查
users_query.count()

但是如何用exists检查它?

【问题讨论】:

    标签: python sqlalchemy exists


    【解决方案1】:

    下面的解决方案稍微简单一点:

    from sqlalchemy.sql import exists
    
    print session.query(exists().where(User.email == '...')).scalar()
    

    【讨论】:

    • 请注意,这会给多态类型提供错误的结果。当同时过滤父属性和子属性时,生成的查询将从表的笛卡尔积(外连接)中进行选择。要修复它,您应该通过select_from手动设置FROM子句:e = exists(select([1]).select_from(User).where(and_(User.email == '...', ...))).select()
    • @aikoven:您的建议导致Every derived table must have its own alias 错误。添加exists(…).select().alias('foo') 修复它(参见alias() 函数)。
    【解决方案2】:

    对我来说最容易接受和可读的选项是

    session.query(<Exists instance>).scalar()
    

    喜欢

    session.query(User.query.filter(User.id == 1).exists()).scalar()
    

    返回TrueFalse

    【讨论】:

    • 另外,请注意某些数据库(如 SQL Server)不允许 EXISTS 表达式出现在 SELECT 的列子句中。要基于存在作为 WHERE 选择一个简单的布尔值,请使用 sqlalchemy.literal:session.query(literal(True)).filter(q.exists()).scalar()
    • 这会引发以下异常:AttributeError: type object 'User' has no attribute 'query'
    • .query 属性特定于 Flask-SQLAlchemy。你会使用session.query(session.query(User).filter(User.id == 1).exists()).scalar()
    【解决方案3】:

    据我所知,使用 orm 查询 api 无法做到这一点。但是你可以降到一个更低的级别并使用来自 sqlalchemy.sql.expression 的exists

    from sqlalchemy.sql.expression import select, exists
    
    users_exists_select = select((exists(users_query.statement),)) 
    print engine.execute(users_exists_select).scalar()
    

    【讨论】:

      【解决方案4】:

      2021 年 SqlAlchemy 1.4 答案

      避免调用.query 方法,并使用select 语句直接与.exists 方法链接,如下所示:

      from sqlalchemy import select
      
      user = select(User).where(email="x@x.com").exists()
      

      来源:https://docs.sqlalchemy.org/en/14/core/selectable.html?highlight=exists#sqlalchemy.sql.expression.exists

      【讨论】:

      • 这是 SqlAlchemy 1.4
      【解决方案5】:

      对于 SQL Server,我必须这样做:

      from sqlalchemy.sql.expression import literal
      
      result = session.query(literal(True)).filter(
          session.query(User)
          .filter_by(email='...')
          .exists()
      ).scalar()
      print(result is not None)
      
      # Resulting query:
      # SELECT 1
      # WHERE EXISTS (SELECT 1 
      # FROM User
      # WHERE User.email = '...')
      

      但如果没有EXISTS,它会更简单

      result = (
          session.query(literal(True))
          .filter(User.email == '...')
          .first()
      )
      print(result is not None)
      
      # Resulting query:
      # SELECT TOP 1 1
      # FROM User
      # WHERE User.email = '...'
      

      【讨论】:

      • Oracle 12c 相同。感谢您的解决方案
      • session.query(cls).filter_by(**kwargs).first() is not None 也可以工作,无需导入literal,至少对于 MySQL 8.0
      猜你喜欢
      • 2017-11-05
      • 2022-06-24
      • 2013-03-01
      • 2013-04-12
      • 1970-01-01
      • 2021-08-04
      • 1970-01-01
      • 2014-09-11
      • 2021-08-13
      相关资源
      最近更新 更多