2013-10-16 2 views
1

모든 쿼리 결과를 검색하고 싶습니다. 내가 query.count() == 3000를 참조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() 

,하지만 난 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

'execute()'에서 반환되는 몇 가지 레코드와 함께 전체 "Something"클래스 정의를 게시 할 수 있습니까? –

+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은 한 걸음 더 나아갑니다. "things"테이블을 쿼리하기 위해 ORM을 사용할 때 결과는 Something 개체로 바뀝니다. 또한 ID 맵을 사용하여 SQLAlchemy를 추적했습니다. 첫 번째 레코드 ("래리")를 개체로 변환 한 후 두 번째 레코드 ("Moe", ID 1)를 찾습니다. ID 1은 정확히 같기 때문에 레코드가 첫 번째 레코드와 동일한 개체를 나타내는 것으로 가정합니다. 따라서 새 Something 개체를 인스턴스화하지 않고 다음 레코드로 이동합니다.

the docs에서 : 가장 일반적인 의미에서

, 세션은 데이터베이스와의 모든 대화를 설정하고 당신은 그것의 수명 중에로드 또는 관련 한 모든 객체에 대해 "보유 영역"을 나타냅니다 . Entrypoint는 Query 객체를 얻기위한 진입 점을 제공합니다.이 객체는 세션 객체의 현재 데이터베이스 연결을 사용하여 데이터베이스에 쿼리를 보내고 결과 행을 Identity Map이라는 구조 내부의 Session에 저장되는 객체로 채 웁니다. 각 개체의 고유 복사본. "고유"는 "특정 기본 키가있는 하나의 개체"를 의미합니다.

"ID 맵"이이 동작을 보는 이유입니다. 기본 키가 "ID"필드라고 말하면 SQLAlchemy가이 약속을 지키고 같은 ID로 여러 레코드가 반환되는 것을 확인하면 모두 동일한 개체로 간주합니다.

기본 키가 고유한지 확인하는 것이 해결책입니다.