使用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;选择对象>))
答案 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'},
])