我有一个使用嵌套集模型表示层次数据的基表。
CREATE TABLE trees (
id INT NOT NULL AUTO_INCREMENT,
rootId INT DEFAULT NULL,
lft INT NOT NULL,
rgt INT NOT NULL,
PRIMARY KEY(id),
FOREIGN KEY(rootId) REFERENCES trees(id)
);
因此,此表可以包含多个单独的树,其中rootId指向每个树的顶部节点。
现在我想添加一个新表来扩展带有子类型的树。例如:
CREATE TABLE happyTrees (
treeId INT NOT NULL,
PRIMARY KEY(treeId),
FOREIGN KEY(treeId) REFERENCES trees(id)
);
插入到happyTrees中的行应该只指向树中的根级节点 - 因此树中的行的rootId为null。
我可以在应用程序级别强制执行此操作,但我想知道:在sql中是否有更优雅的方法来强制执行此约束?因此,如果树中相应的rootId为null,则只能将treeId插入到happyTrees中?
答案 0 :(得分:1)
我会以不同的方式思考设计。
将属性放在trees
表(字段is_happy
)中,或者创建一个引用树结构的单独tree_attributes
表。
因为最终“快乐”的树结构仍然是树结构。
虽然我很欣赏这在插入行时不会创建数据库强制约束。虽然我更喜欢数据库模型,以防止首先插入错误的数据,但有时简单性更好。
答案 1 :(得分:0)
以下适合您的具体情况:
CREATE TABLE trees (
id INT NOT NULL AUTO_INCREMENT,
rootId INT DEFAULT NULL,
lft INT NOT NULL,
rgt INT NOT NULL,
PRIMARY KEY(id),
UNIQUE (rootId, id), -- redundant, but needed for foreign key relationship
FOREIGN KEY(rootId) REFERENCES trees(id)
);
CREATE TABLE happyTrees (
treeId INT NOT NULL,
_rootId INT NULL, -- actually, ALWAYS NULL
PRIMARY KEY(treeId),
FOREIGN KEY(_rootId, treeId) REFERENCES trees(rootId, id);
);
这是添加一个您想要始终为NULL
的虚拟列。然后它可以引用另一个表,保证快乐树只指向根。
这是否比在应用程序中完成工作更优雅(或者,更好的是在我看来,存储过程),这是审美趣味的问题。但它更聪明;)