【问题标题】:How to insert multiple values with subquery using SQLAlchemy Core?如何使用 SQLAlchemy Core 使用子查询插入多个值?
【发布时间】:2011-12-22 06:18:11
【问题描述】:

使用 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'))

但我似乎只能在对 insert() 子句使用 values() 方法时使用子查询,该子句只允许我一次插入一个。我想一次插入多个值,方法是将它们全部传递给Connectionexecute() 方法作为绑定参数列表,但这似乎不受支持。

是否可以在一次调用 execute() 时完成我想做的事情?

这是一个独立的演示。请注意,这使用了doesn't support multiple inserts in the same way as MySQL 的 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 Core,这意味着所有 SQL 都将完全按照您提供的方式执行。
  • @plaes 是的,这正是我想要做的(对每条记录执行一个子查询),你只需要相信我,它在实际应用程序:) 中更有意义。但问题是 SQLAlchemy 没有完全执行我提供的内容,并且拒绝处理 Select 表达式 :(

标签: python sqlalchemy


【解决方案1】:

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

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'},
])

【讨论】:

  • 太棒了,谢谢。让我不必多次往返数据库 - 现在我可以在一个查询中完成所有操作,当您的数据库位于世界的另一端时,这可以节省 很多 时间。
  • 如果type_select 有两个字段怎么办?
猜你喜欢
  • 2021-11-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-11-21
  • 1970-01-01
  • 1970-01-01
  • 2015-05-11
  • 2012-03-30
相关资源
最近更新 更多