使用SqlAlchemy和PostgreSQL更新.. LIMIT 1

kol*_*pto 4 python postgresql sqlalchemy sql-update sql-limit

使用SqlAlchemy,是否可以构建一个只更新第一个匹配行的查询?

就我而言,我需要更新最新的日志条目:

class Log(Base):
    __tablename__ = 'logs'
    id = Column(Integer, primary_key=True)
    #...
    analyzed = Column(Boolean)

session.query(Log)  \
    .order_by(Log.id.desc())  \
    .limit(1)  \
    .update({ 'analyzed': True })
Run Code Online (Sandbox Code Playgroud)

结果如下:

InvalidRequestError:调用limit()时无法调用Query.update()

这是有道理的,因为它UPDATE ... LIMIT 1是一个仅限MySQL的功能(这里给出了解决方案)

但是我如何对PostgreSQL做同样的事情呢?可能,使用子查询方法

kol*_*pto 8

子查询食谱是做正确的方式,现在我们只需要建立这样的查询与SQLAlchemy的.

让我们从子查询开始:

sq = ssn.query(Log.id)  \
    .order_by(Log.id.desc())  \
    .limit(1)  \
    .with_for_update()
Run Code Online (Sandbox Code Playgroud)

现在使用as_scalar()update()文档中的示例:

from sqlalchemy import update

q = update(Log)  \
    .values({'analyzed': True})  \
    .where(Log.id == sq.as_scalar())
Run Code Online (Sandbox Code Playgroud)

打印查询以查看结果:

UPDATE logs 
SET analyzed=:analyzed 
WHERE logs.id = (
    SELECT logs.id 
    FROM logs ORDER BY logs.id DESC 
    LIMIT :param_1 
    FOR UPDATE
)
Run Code Online (Sandbox Code Playgroud)

请享用!

  • ...如果您正在尝试将其用于排队,请记住并发性.它不是原子的,因此多个会话可以获取并更新同一行. (2认同)