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

Dav*_*Yen 1 python sqlalchemy subquery

我正在使用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 )
Run Code Online (Sandbox Code Playgroud)

然后,插入代码应如下所示:

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()
Run Code Online (Sandbox Code Playgroud)

这个问题是,在运行此代码时它会产生一个非常有趣的错误,它正在尝试运行以下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}
Run Code Online (Sandbox Code Playgroud)

这看起来很合理,除了它在SELECT调用周围缺少括号.当我手动运行SQL查询时,它给了我与sqlalchemy给我的完全相同的错误,直到我手动输入括号中的所有错误.看起来像sqlalchemy在需要时会忘记放置括号的一个不太可能的错误,所以我的问题是我在使用sqlalchemy添加行时错过了正确使用子查询的函数吗?

Den*_*ach 7

而不是使用subquery()调用as_scalar()方法:

返回此Query表示的完整SELECT语句,转换为标量子查询.

例:

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

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)
Run Code Online (Sandbox Code Playgroud)

代码更新counter字段:

parent.counter = session.query(func.count(Child.id))\
                    .filter_by(parent=parent).as_scalar()
Run Code Online (Sandbox Code Playgroud)

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

UPDATE parents SET counter=(SELECT count(children.id) AS count_1 
FROM children
WHERE ? = children.parent_id) WHERE parents.id = ?
Run Code Online (Sandbox Code Playgroud)