Используя 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', ))