2

考虑这个树状表结构:

CREATE TABLE nodes(
  id INTEGER PRIMARY KEY AUTOINCREMENT,
  name TEXT NOT NULL,
  parent INTEGER,
  descendant_count INTEGER NOT NULL DEFAULT 0,
  FOREIGN KEY(parent) REFERENCES nodes(id) ON DELETE CASCADE
);

descendant_count列存储后代记录的数量。

现在我正在手动维护它,通过增加每个新插入的值(或在删除时减少它)。本质上我一直在获取父记录,然后运行

 UPDATE nodes SET descendant_count = (descendant_count + 1) ? WHERE...

在每个父母身上,直到我到达根源。显然,这在深度嵌套的结构上相当慢。

是否可以使用触发器来实现这一点?或者有没有更快、更可靠的方法呢?


更新 - 11.08.03

SQLite 似乎支持递归触发器。因此,如果我只更新单个节点的计数,那么触发器应该能够更新所有父节点的计数:

CREATE TRIGGER setCounts AFTER UPDATE ON nodes
WHEN (NEW.descendant_count <> OLD.descendant_count)
BEGIN

  -- subtract old counts
  UPDATE nodes
    SET descendant_count = descendant_count - OLD.descendant_count
    WHERE id = NEW.parent;

  -- add new counts
  UPDATE nodes
    SET descendant_count = descendant_count + NEW.descendant_count
    WHERE id = NEW.parent;
END;

我测试了它,似乎数字是正确的,所以这到底是可能的吗?

4

4 回答 4

3

SQLite 没有递归查询;您必须在代码中执行此循环。

请注意,SQLite 是一个嵌入式数据库,没有客户端/服务器通信开销,因此在应用程序中执行此逻辑并不比在触发器中或直接在数据库中支持时慢。

于 2013-10-17T07:37:27.333 回答
3

您可以使用嵌套集模型。计算后代的成本要低得多,但删除和插入节点的成本要高得多。

于 2013-11-11T20:52:46.443 回答
2

您可以按如下方式优化您的解决方案。由于更新会递归地向上级联您的树,因此可以节省大量资金......

CREATE TRIGGER setCounts AFTER UPDATE ON nodes
WHEN (NEW.descendant_count <> OLD.descendant_count)
BEGIN
  IF NEW.parent_id IS NOT NULL THEN
      UPDATE nodes
      SET descendant_count = descendant_count 
          + NEW.descendant_count - OLD.descendant_count
      WHERE id = NEW.parent;
  END IF;
END;

此外,您必须处理重新分配父母的情况。例如:

update node set parent_id = 20 WHERE parent_id = 10

为此,您需要另一个触发器

CREATE TRIGGER setCounts2 AFTER UPDATE ON nodes
WHEN (NEW.parent_id <> OLD.parent_id)
BEGIN
  IF OLD.parent_id IS NOT NULL THEN
      UPDATE nodes SET descendant_count = descendant_count - OLD.descendant_count
      WHERE id = OLD.parent;
  END IF;

  IF NEW.parent_id IS NOT NULL THEN
      UPDATE nodes SET descendant_count = descendant_count + NEW.descendant_count
      WHERE id = NEW.parent;
  END IF;
END;
于 2013-11-12T17:44:14.760 回答
1

在邻接列表模型(这是您正在使用的)下,很难保持表的完整性。

考虑类似嵌套集模型的东西。某些操作在速度上有一些折衷,但对于相当多的操作,性能也有很大的提升。

于 2013-11-14T22:23:05.753 回答