Как вставить несколько значений с помощью подзапроса, используя SQLAlchemy Core?

Используя SQLAlchemy Core (не ORM), я пытаюсь выполнить INSERT нескольких строк с использованием подзапросов в значениях. Для 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 метод execute() как список параметров привязки, но это, похоже, не поддерживается.

Можно ли сделать то, что я хочу, одним вызовом execute()?

Вот самодостаточная демонстрация. Обратите внимание, что здесь используется движок sqlite, который не поддерживает множественные вставки так же, как MySQL, но код 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 widgets (name, type) VALUES (?, ?)' (('Raspberry', ), ('Lychee', ))

6
задан Community 23 May 2017 в 10:34
поделиться