2013-10-16 114 views
1

我想檢索查詢的所有結果。我的代碼如下所示:查詢SQLAlchemy中的所有結果0.7.10

engine = sqlalchemy.create_engine(...) 
Base = declarative_base() 
class Something(Base): 
    ... 
Session = sessionmaker(bind=engine) 
session = Session() 
query = session.query(Something).filter(...).all() 

我看到query.count() == 3000,但是當我嘗試results = query.all(),我得到一個單行只(即len(results) == 1)。

我的理解是,query.all()執行查詢並返回所有結果的列表。我在這裏錯過了什麼嗎?計數的行數會大於返回的行數,有哪些可能的原因?

編輯(更多細節):

以原始的SQL(例如看str(query),使替換參數),並將其傳遞到session.execute似乎就好了工作:

# this gives 3000 rows 
for row in session.execute(raw_sql, {'param1': val1, 'param2': val2}): 
    print(row) 

解決方案

原來問題是我的主鍵不是唯一的。獲得的經驗:建立你的班級時要非常小心!就我而言,我有:

class Something(Base): 
    row_id_1 = Column(Integer, primary_key=True) 
    row_id_2 = Column(Integer) # PROBLEM! Need to specify primary_key=True 
    value = Column(Float) 

這導致問題,因爲主鍵是組合(row_id_1,row_id_2)。

+0

您可以發佈完整的「Something」類定義以及從execute()返回的幾條記錄嗎? –

+0

啊哈,實際上你的建議幫我解決了這個問題,當我試圖製作一個我的班級玩具的例子。 問題是我的主鍵不是唯一的。這對count()是可以的,但顯然SQL Alchemy只會返回主鍵的第一個實例,如果它不是唯一的。我並不期待這種行爲。 謝謝! – Max

+0

沒問題,我認爲這是問題所在。對於未來發生在這個問題上的人,我寫了一個稍微更復雜的答案。 –

回答

1

您的問題與您的主鍵不唯一有關。假設你的映射是......

class Something(Base): 
    __tablename__ = 'things' 

    id = Column(Integer, primary_key=True) 
    name = Column(String(50)) 

而且你必須在你的數據庫中的以下數據...

| ID| Name | 
| 1 | Larry | 
| 1 | Moe | 
| 1 | Curly | 

如果你沒有...

SELECT * FROM names 

你會得到三個結果。這就是SQLAlchemy中的execute函數的作用。

但是,ORM超越了一步。當使用ORM查詢「東西」表時,結果會變成Something對象。此外,他們使用Identity Map來跟蹤SQLAlchemy。在將第一條記錄(「Larry」)轉換爲對象後,它會查看第二條記錄(「Moe」,也是1的ID)。由於1的ID完全相同,因此它假定該記錄表示與第一條記錄相同的對象。因此,它不會實例化一個新的Something對象,然後轉到下一條記錄。

the docs

在最一般的意義上說,會話建立與數據庫中的所有對話,並表示您已其壽命期間加載或與之相關聯的所有對象「保持區」 。它提供了獲取查詢對象的入口點,該對象使用會話對象的當前數據庫連接向數據庫發送查詢,並將結果行填充到對象中,然後將這些結果存儲在會話中,稱爲身份映射的結構 - 維護數據結構每個對象的唯一副本,其中「唯一」表示「只有一個具有特定主鍵的對象」。

「身份地圖」是您看到此行爲的原因。當你說主鍵是「ID」字段時,SQLAlchemy會讓你遵守這個承諾,如果它看到多個記錄用相同的ID返回,它假定它們都是同一個對象。

確保您的主鍵是唯一的解決方案。