查询SQLAlchemy 0.7.10中的所有结果

时间:2013-10-16 16:56:05

标签: python sqlalchemy

我想检索查询的所有结果。我的代码如下:

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

1 个答案:

答案 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”,也是ID为1)。由于ID为1完全相同,因此它假定记录表示与第一个记录相同的对象。因此,它不会实例化新的Something对象,只会转到下一条记录。

来自the docs

  

在最一般意义上,会话建立与数据库的所有对话,并代表您在其生命周期内加载或与之关联的所有对象的“保留区域”。它提供了获取Query对象的入口点,Query对象使用Session对象的当前数据库连接将查询发送到数据库,将结果行填充到随后存储在Session中的对象中,称为Identity Map的结构 - 维护的数据结构每个对象的唯一副本,其中“唯一”表示“只有一个具有特定主键的对象”。

“身份地图”是您看到此行为的原因。当您说主键是“ID”字段时,SQLAlchemy会将您带到此承诺,如果它看到返回的多个记录具有相同的ID,则它会认为它们都是同一个对象。

确保您的主键是唯一的是解决方案。