2011-04-12 79 views
1

一個「假」的對象,我不知道這就是所謂的,因爲它是新的給我,但這裏是我想做的事:映射SQLAlchemy的

我在我的數據庫中的兩個表:表A和表B。 TableA有pk a_id和另一個稱爲a_code的字段。 TableB具有pk b_id和另一個稱爲b_code的字段。

我有這些表映射在我的sqlalchemy代碼,他們工作正常。我想創建一個名爲表C第三個對象,實際上並不在我的數據庫存在,但包含a_code和b_code的組合,這樣的事情:

class TableC: 
    a_code = String 
    b_code = String 

然後我想查詢表C,如:

TableC.query.filter(and_(
     TableC.a_code == x, 
     TableC.b_code == y)).all() 

問題1)這種類型的東西是否有名字? 2)我如何做映射(使用聲明會很好)?

+0

你的問題毫無意義。您無法使用未映射的表或任何其他數據查詢數據庫。你的問題有什麼奇怪的用例?如果你有N:M的關係,那麼正確的建模。否則,你的方法看起來像設計中斷。你正在試圖打擊這個框架。 – 2011-04-12 19:00:28

+0

假表數據在哪裏?你的意思是映射到JOIN-ed查詢(這是SQLAlchemy支持的)還是你想處理內存中的一些數據? – 2011-04-13 13:52:21

回答

5

我真的不具備查詢你試圖表達一個完整的瞭解,天氣這是一個工會或加入或一些第三件事,而是放在一邊,那肯定可能映射任意可選(任何可以傳遞給返回行的數據庫)。

我首先假設您需要TableA和TableB的某種聯合,這將是A中的所有行,並且還包含B中的所有行。這很容易更改爲如果您透露更多關於您所表達的數據的形狀的信息,則可以使用不同的概念。

我們將從聲明式風格開始,設置真實的表格和類來映射它們。

from sqlalchemy import * 
import sqlalchemy.ext.declarative 

Base = sqlalchemy.ext.declarative.declarative_base() 

class TableA(Base): 
    __tablename__ = 'a' 
    id = Column(Integer, primary_key=True) 
    a_code = Column(String) 

class TableB(Base): 
    __tablename__ = 'b' 
    id = Column(Integer, primary_key=True) 
    b_code = Column(String) 

由於我們使用了聲明,我們實際上沒有表實例工作從,這是neccesary下一個部分。訪問表的方法有很多種,但我更喜歡使用sqlalchemy映射內省方法,因爲無論類如何映射,該方法都可以工作。

from sqlalchemy.orm.attributes import manager_of_class 
a_table = manager_of_class(TableA).mapper.mapped_table 
b_table = manager_of_class(TableB).mapper.mapped_table 

接下來,我們需要一個代表,我們感興趣的是數據的實際SQL表達式。 這是一個聯盟,這導致看起來一樣在第一類中定義的列,id列和a_code 。我們可以重命名它,但這不是示例中非常重要的一部分。

ab_view_sel = sqlalchemy.alias(a_table.select().union(b_table.select())) 

最後,我們將一個類映射到此。有可能爲此使用聲明式,但實際上更多的代碼是這樣做的,而不是傳統的映射風格,而不是更少。請注意,從類繼承object,不base

class ViewAB(object): 
    pass 

sqlalchemy.orm.mapper(ViewAB, ab_view_sel) 

而這幾乎是它。當然這有一些限制;最明顯的是沒有(簡單)的方法將ViewAB的實例保存回數據庫。

1

實際上並沒有「虛擬表」的概念,但可以發送一個查詢來「聯合」來自多個表的數據。這可能和你想要的一樣接近。

例如,在SQLAlchemy中要做到這一點單程/靈藥是(這是不是遠離你們已經證明什麼,我們只是不查詢「虛擬」表):

result = session.query(TableA, TableB).filter(TableA.a_code==x).filter(TableB.b_code==y).all() 

這與SQL內部連接類似,在過濾器語句中具有一些限定條件。這不會給你一個sqlalchemy表對象,但會給你一個來自每個真實表的對象列表。

0

看起來像SQLAlchemy允許您將任意查詢映射到類。例如從SQLAlchemy: one classes – two tables

usersaddresses = sql.join(t_users, t_addresses, 
          t_users.c.id == t_addresses.c.user_id) 
class UserAddress(object): 
    def __repr__(self): 
     return "<FullUser(%s,%s,%s)" % (self.id, self.name, self.address) 

mapper(UserAddress, usersaddresses, properties={ 
     'id': [t_users.c.id, t_addresses.c.user_id], 
     }) 

f = session.query(UserAddress).filter_by(name='Hagar').one()