SQLite中禁止插入不在rowid中的整数(保持有向无环图table一致)

Forbidding insertion of integer not in rowid in SQLite (keep directed acyclic graph table consistent)

我要表达:

“禁止插入具有 'parent' 值但未包含在 'rowid' AFTER INSERTION 中的记录。”

我的意图是保持 table 作为有向无环图的内部一致性,每条记录都是引用其父节点的节点(根节点是它们自己的父节点)。我该怎么做?

这是我的(使用 rowid 作为主键):

CREATE TABLE Heap (                                                                                                       
                   name   TEXT     CHECK(typeof(name) = 'text')                                                           
                                   NOT NULL                                                                               
                                   UNIQUE                      ,                                       
                   parent INTEGER  DEFAULT rowid               ,                                       
                   color  INTEGER  CHECK(color BETWEEN 0 AND 2)                                                           
                  );                                                                                                    
                                                                                                                      
CREATE TRIGGER parent_not_in_rowid                                                                                        
BEFORE INSERT ON Heap                                                                                                     
BEGIN                                                                                                                     
 SELECT RAISE(FAIL, 'parent id inconsistent') FROM Heap                                                                   
 WHERE NOT EXISTS(SELECT 1 FROM Heap WHERE NEW.rowid = NEW.parent);                                                       
END;

我建议对根节点使用 parent 列中的 null 值,因为这样您所要做的就是为 table 添加参照完整性。

添加定义为 INTEGER PRIMARY KEY 的列 id,使其成为 rowid 的别名,并使列 parent 引用 id:

CREATE TABLE Heap ( 
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL UNIQUE CHECK(typeof(name) = 'text'),
  parent INTEGER REFERENCES Heap(id),                                       
  color INTEGER CHECK(color BETWEEN 0 AND 2)                                                           
); 

现在,打开外键支持:

PRAGMA foreign_keys = ON;

并插入行:

INSERT INTO Heap (name, parent, color) VALUES ('name1', null, 1);
INSERT INTO Heap (name, parent, color) VALUES ('name2', 1, 1);

这会失败:

INSERT INTO Heap (name, parent, color) VALUES ('name3', 5, 2);

因为 table 中没有包含 id = 5 的行。

参见demo