2011-11-04 74 views
5

使用SQLAlchemy核心(而不是ORM),我想要在值中使用子查詢插入多行。對於MySQL,實際的SQL會是這個樣子:如何使用SQLAlchemy Core在子查詢中插入多個值?

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()方法,但似乎不支持。

是否可以在​​的單個調用中執行我想要的操作?

這是一個獨立的演示。請注意,這使用了sqlite引擎,其中doesn't support multiple inserts in the same way as 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}, 
    ) 

運行它,它死在最後​​通話用:

sqlalchemy.exc.InterfaceError: (InterfaceError) Error binding parameter 1 - probably unsupported type. u'INSERT INTO widgets (name, type) VALUES (?, ?)' (('Raspberry', <sqlalchemy.sql.expression.Select at 0x19f14d0; Select object>), ('Lychee', <sqlalchemy.sql.expression.Select at 0x19f1a50; Select object>))

+0

我有一種直覺,認爲你做錯了 - 目前你想爲每一條記錄執行一個子查詢。而且由於您使用的是SQLAlchemy Core,這意味着所有的SQL都會按照您提供的那樣執行。 – plaes

+0

@plaes yep這正是我想要做的(對每條記錄執行一個子查詢),你只需要相信我在真實應用程序':)'中更有意義。但問題是,SQLAlchemy **不是正在執行我正在執行的內容,而是拒絕處理'Select'表達式':(' – Day

回答

4

提供的子查詢語句的參數值,而不是,你必須把它嵌入到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'}, 
]) 
+0

非常讚賞,謝謝你的幫助。讓我不必做多次往返到數據庫 - 我現在可以在單個查詢中做所有事情,當你的數據庫位於世界的另一端時,可以節省大量時間。 – Day

+2

如果'type_select'有兩個字段會怎麼樣? –

相關問題