如何使用SQLAlchemy Core使用子查询插入多个值?

时间:2011-11-04 18:00:14

标签: python sqlalchemy

使用SQLAlchemy Core(而不是ORM),我正在尝试使用值中的子查询来插入多行。对于MySQL,实际的SQL看起来像这样:

INSERT INTO widgets (name, type) VALUES
('Melon', (SELECT type FROM widgetTypes WHERE type='Squidgy')),
('Durian', (SELECT type FROM widgetTypes WHERE type='Spiky'))

但是我在values()子句中使用insert()方法时似乎只能使用子查询,这只允许我一次执行一次插入。我想一次性插入多个值,将它们作为绑定参数列表传递给Connection的{​​{3}}方法,但这似乎不受支持。

是否可以通过一次调用execute()来完成我想要的工作?

这是一个独立的演示。请注意,这使用了execute()的sqlite引擎,但SQLAlchemy代码仍然以与真正的MySQL应用程序相同的方式失败。

from sqlalchemy import *

if __name__ == "__main__":
    # Construct database
    metadata = MetaData()
    widgetTypes = Table('widgetTypes', metadata,
        Column('id', INTEGER(), primary_key=True),
        Column('type', VARCHAR(), nullable=False),
    )
    widgets = Table('widgets', metadata,
        Column('id', INTEGER(), primary_key=True),
        Column('name', VARCHAR(), nullable=False),
        Column('type', INTEGER(), nullable=False),
        ForeignKeyConstraint(['type'], ['widgetTypes.id']),
    )
    engine = create_engine("sqlite://")
    metadata.create_all(engine)

    # Connect and populate db for testing
    conn = engine.connect()
    conn.execute(widgetTypes.insert(), [
        {'type': 'Spiky'},
        {'type': 'Squidgy'},
    ])

    # Some select queries for later use.
    select_squidgy_id = select([widgetTypes.c.id]).where(
        widgetTypes.c['type']=='Squidgy'
    ).limit(1)
    select_spiky_id = select([widgetTypes.c.id]).where(
        widgetTypes.c['type']=='Squidgy'
    ).limit(1)

    # One at a time works via values()
    conn.execute(widgets.insert().values(
        {'name': 'Tomato', 'type': select_squidgy_id},
    ))

    # And multiple values work if we avoid subqueries
    conn.execute(
        widgets.insert(),
        {'name': 'Melon',  'type': 2},
        {'name': 'Durian', 'type': 1},
    )

    # Check above inserts did actually work
    print conn.execute(widgets.select()).fetchall()

    # But attempting to insert many at once with subqueries does not work.
    conn.execute(
        widgets.insert(),
        {'name': 'Raspberry', 'type': select_squidgy_id},
        {'name': 'Lychee',    'type': select_spiky_id},
    )

运行它并在最后一次execute()调用时死于:

  

sqlalchemy.exc.InterfaceError:(InterfaceError)绑定错误   参数1 - 可能不受支持的类型。 u'INSERT INTO小工具(姓名,   type)VALUES(?,?)'(('Raspberry',< sqlalchemy.sql.expression.Select   在0x19f14d0;选择对象>),('Lychee',   < sqlalchemy.sql.expression.Select at 0x19f1a50;选择对象>))

1 个答案:

答案 0 :(得分:5)

不必将subselect语句作为参数值提供,而是必须将其嵌入到INSERT语句中:

type_select = select([widgetTypes.c.id]).where(
        widgetTypes.c.type==bindparam('type_name'))

insert = widgets.insert({'type': type_select})

conn.execute(insert, [
    {'name': 'Melon',  'type_name': 'Squidgy'},
    {'name': 'Lychee', 'type_name': 'Spiky'},
])