【问题标题】:How create a sqlalchemy delete query with multiples parameter from a loop如何从循环中创建具有多个参数的 sqlalchemy 删除查询
【发布时间】:2021-03-06 13:30:13
【问题描述】:

我是 python 和 sqlalchemy 的新手。 如果我手动构建 where 条件,我已经有一个删除方法可以工作。 现在,我需要从 yaml 格式的输入请求中读取列和值并创建 where 条件。

#enter data as yaml
items:
    - item:
        table: [MyTable,OtherTable]
        filters:
            field_id: 1234
            #other_id: null

这是我尝试但无法继续的方法:

for i in use_case_cfg['items']:
    item = i.get('item')
    for t in item['table']:
        if item['filters']:
            filters = item['filters']
            where_conditions = ''
            count = 0
            for column, value in filters.items():
                aux = str(getattr(t, column) == bindparam(value))
                if count == 0:
                    where_conditions += aux
                else:
                    where_conditions += ', ' + aux
                count += 1
            to_delete = inv[t].__table__.delete().where(text(where_conditions))
                #to_delete = t.__table__.delete().where(getattr(t, column) == value)
        else:
            to_delete = inv[t].__table__.delete()
        CoreData.session.execute(to_delete)

对我来说,它看起来不错,但是当我运行时,我收到以下错误: sqlalchemy.exc.StatementError: (sqlalchemy.exc.InvalidRequestError) 绑定参数“9876”需要一个值 [SQL:从MyTable删除“MyTable”.field_id = %(1234)s] [参数: [{}]] (此错误的背景:http://sqlalche.me/e/cd3x

有人可以向我解释什么是错误的或正确的方法吗? 谢谢。

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    代码有两个问题。

    首先,

    str(getattr(t, column) == bindparam(value))
    

    将值绑定为占位符,因此您最终得到

    WHERE f2 = :Bob
    

    但它应该是映射到 filters 中的值的名称(在你的情况下是列名),所以你最终得到

    WHERE f2 = :f2
    

    其次,多个WHERE 条件用逗号连接,但您应该使用ANDOR,具体取决于您要执行的操作。

    给定一个模型Foo

    class Foo(Base):
        __tablename__ = 'foo'
    
        id = sa.Column(sa.Integer, primary_key=True)
        f1 = sa.Column(sa.Integer)
        f2 = sa.Column(sa.String)
    
    

    这是您的一段代码的工作版本:

    filters = {'f1': 2, 'f2': 'Bob'}
    t = Foo
    
    where_conditions = ''
    count = 0
    for column in filters:
        aux = str(getattr(t, column) == sa.bindparam(column))
        if count == 0:
            where_conditions += aux
        else:
            where_conditions += ' AND ' + aux
        count += 1
    to_delete = t.__table__.delete().where(sa.text(where_conditions))
    print(to_delete)
    session.execute(to_delete, filters)
    

    如果您没有义务将WHERE 条件构造为字符串,您可以这样做:

    where_conditions = [(getattr(t, column) == sa.bindparam(column))
                        for column in filters]
    to_delete = t.__table__.delete().where(sa.and_(*where_conditions))
    session.execute(to_delete, filters)
    

    【讨论】:

      猜你喜欢
      • 2021-12-17
      • 2011-02-03
      • 2017-01-17
      • 1970-01-01
      • 2018-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-16
      相关资源
      最近更新 更多