2012-03-06 34 views
8

tôi có thể tạo ra một bảng tạm thời theo cách này:tạo ra một bảng tạm thời từ một truy vấn sử dụng SQLAlchemy ORM

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

nhưng bảng mới không thể đọc được vì nó nói nó không có khóa chính. existingtable.id là khóa chính của exisitingtable, vì vậy tôi mong đợi nó để có được điều trị tương tự trong bảng tạm thời.

Tuy nhiên, tôi thà tìm cách nào đó để thực hiện điều này. Đưa ra:

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() 

Làm thế nào tôi có thể cư temp_table với một số nội dung được lựa chọn của existingtable mà không làm 100000 session.query.add(TempTable(...)) lệnh? Hoặc là có một cách để tạo bảng từ một truy vấn tương tự như phiên bản SQL đơn giản ở trên?

+1

Chỉ curios .. nó sẽ làm việc nếu bạn tạo định nghĩa của bảng temp với cách tiếp cận đầu tiên? ví dụ tạo bảng tablename (id primarykey, column1) Chèn vào tablename select id, column2 từ bảng hiện tại, nơi ... – AJP

+0

@AJP Vâng, tôi nghĩ đây là câu trả lời. Thật không may, không có SA ORM tương đương với INSERT INTO và không có cách nào dễ dàng để tôi biên dịch truy vấn tương đối phức tạp của tôi thành một câu lệnh sql. – Paul

Trả lời

11

Không chính xác ORM, nhưng để tạo bảng ban đầu, tôi sẽ sao chép cấu trúc bảng (xem cloneTable trong ví dụ bên dưới). Để sao chép dữ liệu, tôi sẽ sử dụng InsertFromSelect example.

Chỉnh sửa:Kể từ phiên bản 0.8.3, SqlAlchemy hỗ trợ Insert.from_select() ngoài hộp. Do đó, lớp InsertFromSelect và khách truy cập tương ứng trong ví dụ bên dưới có thể được thay thế trực tiếp và không còn cần thiết nữa. Tôi để nguyên ví dụ ban đầu không thay đổi vì lý do lịch sử.

Dưới đây là một ví dụ làm việc

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 
+0

Thật không may, tôi nhận được một importerror khi chạy này: ImportError: không thể nhập tên UpdateBase. Lỗi nhập tương tự bằng cách sử dụng ví dụ InsertFromSelect. Tôi đang sử dụng SA 0.5.7 – Paul

+0

@Paul: ah, chức năng này chỉ khả dụng kể từ SA 0.6. Tôi đã thử nghiệm nó với 0.7.5 – stephan

+0

Câu trả lời rất hay. Tôi thực sự cần giải pháp này. Tôi có câu hỏi này cho bạn. http://stackoverflow.com/questions/30575111/how-to-create-a-new-table-from-select-statement-in-sqlalchemy Phương pháp của bạn là cách tốt nhất để đến đây. Như trong tạo bảng đầu tiên và sau đó làm chèn từ chọn? –

Các vấn đề liên quan