1

クエリのすべての結果を取得したいと思います。私のコードは次のようになります:

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()、1行しか表示されません(つまり、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) であるため、問題を引き起こしました。

4

1 に答える 1

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

3 つの結果が得られます。それがexecute、SQLAlchemy の関数が行うことです。

ただし、ORM はさらに一歩進んでいます。「things」テーブルのクエリに ORM を使用すると、結果がSomethingオブジェクトに変換されます。また、ID マップを使用して SQLAlchemy によって追跡されました。最初のレコード ("Larry") をオブジェクトに変換した後、2 番目のレコード ("Moe"、ID も 1) を調べます。1 の ID はまったく同じであるため、このレコードは最初のレコードと同じオブジェクトを表していると見なされます。したがって、新しいSomethingオブジェクトをインスタンス化せず、次のレコードに移動するだけです。

ドキュメントから:

最も一般的な意味では、セッションはデータベースとのすべての会話を確立し、その存続期間中にロードまたは関連付けられたすべてのオブジェクトの「保持ゾーン」を表します。Query オブジェクトを取得するためのエントリポイントを提供します。このオブジェクトは、Session オブジェクトの現在のデータベース接続を使用してデータベースにクエリを送信し、結果行をオブジェクトに入力してから、Session 内の Identity Map と呼ばれる構造内に格納します。各オブジェクトの一意のコピー。「一意」とは、「特定の主キーを持つ 1 つのオブジェクトのみ」を意味します。

「アイデンティティ マップ」が、この動作が見られる理由です。主キーが「ID」フィールドであると言うと、SQLAlchemy はこの約束を守り、複数のレコードが同じ ID で返されることを確認すると、それらはすべて同じオブジェクトであると想定します。

主キーが一意であることを確認することが解決策です。

于 2013-10-16T18:47:35.513 に答える