создание временной таблицы из запроса с использованием sqlalchemy orm - PullRequest
8 голосов
/ 07 марта 2012

Я могу создать временную таблицу следующим образом:

session.execute("CREATE TABLE temptable SELECT existingtable.id, "
    "existingtable.column2 FROM existingtable WHERE existingtable.id<100000")

, но новая таблица не читается, так как в ней говорится, что у нее нет первичного ключа.existingtable.id является первичным ключом exisitingtable, поэтому я ожидал, что он получит такую ​​же обработку в временной таблице.

Тем не менее, я бы все равно нашел какой-нибудь ORM способ сделать это.Дано:

temp_table = Table('temptable', metadata, 
    Column('id', Integer, primary_key=True),
    Column('column2', Integer),
    useexisting=True )
class TempTable(object):
    pass
mapper(TempTable, temp_table)
temp_table.create(bind=session.bind, checkfirst=True)
if session.query(TempTable).delete(): #make sure it's empty
    session.commit()

Как я могу заполнить temp_table некоторым выбранным содержимым existingtable без выполнения команд 100000 session.query.add(TempTable(...))?Или есть способ создать таблицу из запроса, аналогичного простой версии SQL выше?

1 Ответ

11 голосов
/ 07 марта 2012

Это не совсем ORM, но для первоначального создания таблицы я бы клонировал структуру таблицы (см. cloneTable в приведенном ниже примере).Для копирования данных я бы тогда использовал пример InsertFromSelect .

Редактировать: Начиная с версии 0.8.3, SqlAlchemy поддерживает Insert.from_select () из коробки.Следовательно, класс InsertFromSelect и соответствующий посетитель в приведенном ниже примере могут быть заменены напрямую и больше не нужны.Я оставляю исходный пример без изменений по историческим причинам.

Вот рабочий пример

from sqlalchemy import Table
from sqlalchemy.ext.compiler import compiles
from sqlalchemy.sql.expression import UpdateBase

class InsertFromSelect(UpdateBase):
    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)
    )

def cloneTable(name, table, metadata):
    cols = [c.copy() for c in table.columns]
    constraints = [c.copy() for c in table.constraints]
    return Table(name, metadata, *(cols + constraints))

# test data
from sqlalchemy import MetaData, Column, Integer
from sqlalchemy.engine import create_engine
e = create_engine('sqlite://')
m = MetaData(e)
t = Table('t', m, Column('id', Integer, primary_key=True),
          Column('number', Integer))
t.create()
e.execute(t.insert().values(id=1, number=3))
e.execute(t.insert().values(id=9, number=-3))

# create temp table
temp = cloneTable('temp', t, m)
temp.create()

# copy data
ins = InsertFromSelect(temp, t.select().where(t.c.id>5))
e.execute(ins)

# print result
for r in e.execute(temp.select()):
    print r
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...