Skip to main content
 首页 » 编程设计

python之如何在 sqlalchemy 中使用子查询添加行

2025年05月04日14dudu

我正在将 Postgresql 与 SQLAlchemy 结合使用,但在使用子查询时,sqlalchemy 似乎无法添加行。

在我的示例中,我想更新表中特定标记的计数器。

在 SqlAlchemy 中,测试运行类如下所示:

class TestRun( base ): 
    __tablename__   = 'test_runs' 
 
    id              = sqlalchemy.Column( 'id', sqlalchemy.Integer, sqlalchemy.Sequence('user_id_seq'), primary_key=True ) 
    tag             = sqlalchemy.Column( 'tag', sqlalchemy.String ) 
    counter         = sqlalchemy.Column( 'counter', sqlalchemy.Integer ) 

插入代码应该如下所示:

tag = 'sampletag' 
counterquery = session.query(sqlalchemy.func.coalesce(sqlalchemy.func.max(TestRun.counter),0) + 1).\ 
                            filter(TestRun.tag == tag).\ 
                            subquery() 
 
testrun = TestRun() 
testrun.tag = tag 
testrun.counter = counterquery 
 
session.add( testrun ) 
session.commit() 

问题在于,它在运行这段代码时给出了一个非常有趣的错误,它正在尝试运行以下 SQL 查询:

'INSERT INTO test_runs (id, tag, counter)  
    VALUES (%(id)s,  
            %(tag)s,  
            SELECT coalesce(max(test_runs.counter), %(param_1)s) + %(coalesce_1)s AS anon_1  
               FROM test_runs  
               WHERE test_runs.tag = %(tag_1)s)'  
 {'coalesce_1': 1, 'param_1': 0, 'tag_1': 'mytag', 'tag': 'mytag', 'id': 267L} 

这看起来很合理,只是缺少 SELECT 调用周围的括号。当我手动运行 SQL 查询时,它给了我与 sqlalchemy 给我的完全相同的错误,直到我手动输入括号来修复所有问题。看起来不太可能是 sqlalchemy 在需要时忘记加上括号的错误,所以我的问题是我是否缺少使用 sqlalchemy 添加行时正确使用子查询的函数?

请您参考如下方法:

而不是使用 subquery() 调用 as_scalar() method :

Return the full SELECT statement represented by this Query, converted to a scalar subquery.

示例:

具有分类父子关系的模型:

class Parent(Base): 
    __tablename__ = 'parents' 
    id = Column(Integer, primary_key=True) 
    counter = Column(Integer, nullable=False, default=0) 
 
class Child(Base): 
    __tablename__ = 'children' 
    id = Column(Integer, primary_key=True) 
    parent_id = Column(ForeignKey(Parent.id), nullable=False) 
    parent = relationship(Parent) 

更新 counter 字段的代码:

parent.counter = session.query(func.count(Child.id))\ 
                    .filter_by(parent=parent).as_scalar() 

生成的 SQL(从日志中复制):

UPDATE parents SET counter=(SELECT count(children.id) AS count_1  
FROM children 
WHERE ? = children.parent_id) WHERE parents.id = ?