【问题标题】:How do I INSERT INTO t1 (SELECT * FROM t2) in SQLAlchemy?如何在 SQLAlchemy 中插入到 t1 (SELECT * FROM t2)?
【发布时间】:2018-04-17 03:53:20
【问题描述】:

在 SQLAlchemy 中,如何从 SELECT 语句填充或更新表?

【问题讨论】:

    标签: python sqlalchemy


    【解决方案1】:

    SQLalchemy 不会为您构建这个结构。您可以使用文本查询。

    session.execute('INSERT INTO t1 (SELECT * FROM t2)')
    

    编辑:

    一年多过去了,但现在在 sqlalchemy 0.6+ you can create it:

    from sqlalchemy.ext import compiler
    from sqlalchemy.sql.expression import Executable, ClauseElement
    
    class InsertFromSelect(Executable, ClauseElement):
        def __init__(self, table, select):
            self.table = table
            self.select = select
    
    @compiler.compiles(InsertFromSelect)
    def visit_insert_from_select(element, compiler, **kw):
        return "INSERT INTO %s (%s)" % (
            compiler.process(element.table, asfrom=True),
            compiler.process(element.select)
        )
    
    insert = InsertFromSelect(t1, select([t1]).where(t1.c.x>5))
    print insert
    

    生产:

    "INSERT INTO mytable (SELECT mytable.x, mytable.y, mytable.z FROM mytable WHERE mytable.x > :x_1)"
    

    另一个编辑:

    现在,4 年后,该语法被合并到 SQLAlchemy 0.9 中,并向后移植到 0.8.3;您可以创建任何select(),然后使用Insert 对象的新from_select() 方法:

    >>> from sqlalchemy.sql import table, column
    >>> t1 = table('t1', column('a'), column('b'))
    >>> t2 = table('t2', column('x'), column('y'))
    >>> print(t1.insert().from_select(['a', 'b'], t2.select().where(t2.c.y == 5)))
    INSERT INTO t1 (a, b) SELECT t2.x, t2.y
    FROM t2
    WHERE t2.y = :y_1
    

    More information in the docs.

    【讨论】:

    • 你会建议 session.execute('INSERT INTO t1 (%s)' % str(sqlalchemy_select_expression)) 吗?
    • 当然,为什么不呢 - 不需要str(),因为%s 已经这样做了。
    • @hadrien:现在你有了sqlalchemy.org/docs/core/…,你可以在其中编译它。
    • 我喜欢你随着时间的推移更新了这个,但如果它被分成最新到最旧的版本会很好,并调用 sqlalchemy 版本而不是编辑之间的年份;)跨度>
    • 如果你不想select *,而只想select x, y(在许多列中),一种方法是from sqlalchemy import select,然后你可以使用这个select([t2,x, t2,y])而不是t2.select()
    【解决方案2】:

    从 0.8.3 开始,您现在可以直接在 sqlalchemy 中执行此操作:Insert.from_select:

    sel = select([table1.c.a, table1.c.b]).where(table1.c.c > 5)
    ins = table2.insert().from_select(['a', 'b'], sel)
    

    【讨论】:

    • 谢谢。我会将其添加到原始答案中。
    • 范围会话怎么样?
    • 我需要导入insert()吗?如果是,我该如何导入?我得到AttributeError: type object 'table2' has no attribute 'insert'
    • @VamshiPulluri 听起来您的 table2 是一个类,而不是 SQL 表达式的表对象。请参阅下面nosklo 的关于构造表对象的答案(在 Another EDIT 下)或按照此处的 SQLAlchemy 教程进行操作:docs.sqlalchemy.org/en/14/core/…
    【解决方案3】:

    正如 Noslko 在评论中指出的那样,您现在可以摆脱原始 sql: http://www.sqlalchemy.org/docs/core/compiler.html#compiling-sub-elements-of-a-custom-expression-construct

    from sqlalchemy.ext.compiler import compiles
    from sqlalchemy.sql.expression import Executable, ClauseElement
    
    class InsertFromSelect(Executable, ClauseElement):
        def __init__(self, table, select):
            self.table = table
            self.select = select
    
    @compiles(InsertFromSelect)
    def visit_insert_from_select(element, compiler, **kw):
        return "INSERT INTO %s (%s)" % (
            compiler.process(element.table, asfrom=True),
            compiler.process(element.select)
        )
    
    insert = InsertFromSelect(t1, select([t1]).where(t1.c.x>5))
    print insert
    

    生产:

    INSERT INTO mytable (SELECT mytable.x, mytable.y, mytable.z FROM mytable WHERE mytable.x > :x_1)
    

    【讨论】:

    • 现在您不必创建自己的 ClauseElement。您可以使用新的Insert.from_select 方法!看我的回答。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多