mysql SqlAlchemy查询表对象时不返回所有行,但查询表对象列时返回所有行

0dxa2lsx  于 2023-02-11  发布在  Mysql
关注(0)|答案(3)|浏览(210)
    • 更新-下面的解决方案**

我对SqlAlchemy还是个新手,所以如果这是一个明显的问题,请原谅。当我查询Table对象时,我只得到一个结果(数据库中的第一个,使用我的过滤器有600多个)。当我按表中的列查询时,它返回了我期望的所有数据。我做错了什么?
仅返回1个结果应为百位

for row in edb_alchemy.session.query(FtSite).filter(FtSite.serial_si == 200134444):
        print(row.s_sequence)

结果如下所示:1
返回所有结果

for row in edb_alchemy.session.query(FtSite.s_sequence).filter(FtSite.serial_si == 200134444):
        print(row)

结果如下所示:一、二、三、四...
为FtSite表返回1个结果,为列返回所有结果

for row in edb_alchemy.session.query(FtSite, FtSite.s_sequence).filter(FtSite.serial_si == 200134444):
        print(row.FtSite.s_sequence, row.s_sequence)

结果看起来像(1,1)、(1,2)、(1,3)、(1,4)....
SQLAlchemy说它使用的SQL是

"SELECT ft_site.serial_si AS ft_site_serial_si, ft_site.partition_id AS ft_site_partition_id, ft_site.s_sequence AS ft_site_s_sequence, ft_site.value AS ft_site_value" + \
    " FROM ft_site" + \
    " WHERE ft_site.serial_si = 200134444"

当只在SQLAlchemy之外使用SQL查询时,它可以正常工作。

    • 更新**

谢谢Ilja的评论。由于某种原因,我以为这个表有一个id主键。它没有,我只是这个数据库的一个消费者,应该更细心一些。你是对的。这个表没有唯一键,并在FtSite. serial_si下列出了MUL。
这是table的实际样子。

+------------+----------+------+-----+---------+----------------+
| Field      | Type     | Null | Key | Default | Extra          |
+------------+----------+------+-----+---------+----------------+
| p_id       | int(10)  | NO   |     | NULL    |                |
| serial_si  | int(10)  | NO   | MUL | NULL    |                |
| s_sequence | int(10)  | NO   |     | NULL    |                |
| value      | double   | YES  |     | NULL    |                |
+------------+----------+------+-----+---------+----------------+

我的原始表描述为

class FtSite(Base):
    __tablename__ = "ft_site"

    id = Column(INTEGER, primary_key=True)
    serial_si = Column(INTEGER)
    partition_id = Column(INTEGER)
    s_sequence = Column(INTEGER)
    value = Column(DOUBLE)

我对此进行了修改,使SQLAlchemy中的组合键(s_sequence,serial_si)是唯一的,即使它没有在数据库中定义。这是在SQLAlchemy中处理这个问题的最佳方式吗?它现在返回预期的结果。

class FtSite(Base):
    __tablename__ = "ft_site"

    serial_si = Column(INTEGER, primary_key=True)
    partition_id = Column(INTEGER)
    s_sequence = Column(INTEGER, primary_key=True)
    value = Column(DOUBLE)
eaf3rand

eaf3rand1#

我遇到过类似的情况,SQLAlchemy查询对象的.all()没有返回表中的所有行(总是缺少一些)但是.count()调用确实给予了正确的计数,在进一步挖掘之后,我意识到模型声明偏离了那个数据库中的实际表模式,首先,数据库在模式中只有一个主键列,但是模型声明有一个组合主键(与您的情况相反),而且我还遗漏了一个3列唯一约束,而表模式有它。
在我的例子中,每当SQLAlchemy查询数据库时,它确实获得了幕后的所有行,但是由于我的模型声明中的组合主键不正确,阻止了一些行加载到SQLAlchemy的会话中(主键通过定义唯一地标识对象并且其不会在会话中加载具有相同主键的两个对象作为结果,因此它会丢弃那些具有相同值的组合列,即使在数据库中它们具有不同的PK。)
总之,对模型声明和数据库模式进行双重检查以确保它们是同步的,这是对此类问题的第一个响应。

wvt8vs2t

wvt8vs2t2#

这是与SQLAlchemy模型中指定的主键的模式不匹配,并且在基础数据库表中没有主键。
来自SQLAlchemy ORM文档:
大多数ORM要求对象定义了某种主键,因为内存中的对象必须对应于数据库表中唯一可标识的行
解决方案是定义一个组合主键:

class SomeClass(Base):
     __tablename__ = "some_table_with_no_pk"

     uid = Column(Integer, primary_key=True)
-    bar = Column(String)
+    bar = Column(String, primary_key=True)

一个相关的主要关键问题:How to define a table without primary key with SQLAlchemy?

d7v8vwbk

d7v8vwbk3#

是的,无论Devy提到什么都是正确的。我遇到过同样的问题,它得到了解决。请检查SQLAlchemy模型声明和数据库模式。如果你想使用“Sqlacodegen”快速检查

sqlacodegen --outfile models.py mysql+pymysql://<username><password>@<hostname/ip of database>:<dbport>/<databasename>

https://pypi.org/project/sqlacodegen/(有关详细信息,请检查此选项)。
如果你需要什么,请告诉我。

相关问题