【问题标题】:Multiple linked list with SQLAlchemy and MySQL使用 SQLAlchemy 和 MySQL 的多链表
【发布时间】:2012-03-08 23:24:27
【问题描述】:

我想在一个 SQL 表中有多个链表,使用 MySQL 和 SQLAlchemy (0.7)。所有列表的第一个节点,父节点为 0,子节点为 0。id 代表列表,而不是独立元素。元素由PK标识

如果有一些省略的语法(与问题无关),它应该看起来像这样:

id(INT, PK)
content (TEXT)
parent(INT, FK(id), PK)
child(INT, FK(id), PK)

由于表有多个链表,我如何从数据库中返回整个列表,我选择一个特定的 ID 并且父级为 0?

例如:

SELECT * FROM ... WHERE id = 3 AND parent = 0   

【问题讨论】:

  • 我不明白。 id 是一个特定链表的唯一标识符,还是一个特定元素的唯一标识符?你想提取什么:列表的所有元素?还是列表中的所有元素按正确顺序
  • 元素是唯一的,我将更新问题以反映这一点。
  • 回顾;这是个坏主意,所以 ID 标识了整个列表。
  • 对,然后提取整个列表很简单,不是吗?你只是做SELECT * FROM table WHERE id = 3;,不是吗?这会给你随机顺序的元素。不过,将它们整理好会更加困难。我想这将涉及为每个元素发出一个 SQL 查询,每次将 id 设置为包含前一个元素的 child 字段。
  • 你提出了一个很好的观点,我可以SELECT * FROM table WHERE... 把它放在一个字典中,然后递归地遍历它。那么项目的顺序就无关紧要了。

标签: python mysql sqlalchemy linked-list


【解决方案1】:

鉴于您在同一个表中存储了多个链表,我假设您将这些链表的 HEAD 和/或 TAIL 存储在其他一些表中。几个想法:

1) 保留链表: 从数据查询的角度来看,第一个重大改进(也在 cmets 中提出)是在同一个列表中的所有节点都有一些通用标识符(我们称之为 ListID)。这里有几个选项:

  • 如果每个列表仅从 一个 对象(数据行)引用[我什至会用类似“列表属于单个对象吗?”这样的问题,那么这个ListID 可以简单地是持有者对象的(主要)标识符,顶部带有ForeignKey 以确保数据完整性。 在这种情况下,查询所有列表非常简单。事实上,您可以定义relationship 并像my_object.my_list_items 一样导航它。
  • 如果该列表被多个对象使用/引用,则可以创建另一个表,该表将仅包含一列 ListID (PK),并且每个节点/项目将再次有一个 ForeignKey 或类似的东西
  • 否则,可以在两个查询/SQL 语句中加载大型列表:
    1. 通过 ID 查询 HEAD/TAIL
    2. 根据收到的 HEAD/TAIL 的ListID 查询整个列表
      实际上,这可以通过如下所示的一个查询来完成(单查询示例),从 IO 的角度来看这更有效,但分两步完成的好处是您立即拥有对 HEAD(或 TAIL)节点的引用。

单查询示例:

# single-query using join (not tested)
Head = alias(Node)
qry = session.query(Node).join(Head, Node.ListID == Head.ListID).filter(Head.ID == head_node_id)

无论如何,为了遍历链表,您必须通过其 ID 获取 HEAD/TAIL,然后像往常一样遍历。
注意:这里我不确定 SA 是否会识别引用对象已经加载到会话中,或者将为其中的每一个发出其他 SQL 语句,这将破坏批量加载的目的。


2) 用Ordering List扩展替换链表:
请阅读Ordering List 文档。很可能Ordering List 实现足以让您使用而不是链表

【讨论】:

  • 感谢您的反馈,在我之前与@jogojapan 的对话之后,我更改了每个列表元素的标识。当涉及到 HEADS 和 TAILS 时,这是 0,它是不可变的并且在同一个表中。识别列表的方式就像您使用包含此信息的单独表格的目的,我称之为元。看来我们也有类似的想法。
  • @Chrizmo:你在这个表中有没有 PK=0 的行?或者您不强制执行 ForeignKey 约束?
  • 我强制执行 ForeignKey 约束并且我有 PK=0。
猜你喜欢
  • 1970-01-01
  • 2013-02-03
  • 2019-04-15
  • 1970-01-01
  • 2010-11-04
  • 2016-12-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多