想象我有这个名为Department的表。每个部门都可以有子部门。
我在考虑将一个名为ParentDepartmentID的列作为另一个部门的外键。如果此键为空,则表示它是父级顶级部门,而不是任何其他部门的子级。
我猜你可以称之为自引用ID。 SQLite支持这个吗?有外键,但也允许空值?
您如何解决此用例?
答案 0 :(得分:6)
是的,sqlite支持这一点。您可以轻松设置引用同一个表的外键。您描述的模型称为adjacency list model,并且非常受欢迎。
然而,邻接列表模型的问题是除非DBMS可以进行递归查询,否则递归操作很难编写。
某些DBMS(如SQL Server 2005,Postgres 8.4和Oracle 11g 1 )支持使用WITH
关键字common table expressions的递归查询。此功能允许轻松编写递归查询,但sqlite和MySQL不支持递归查询。
您可能有兴趣查看以下描述替代模型(nested set model)的文章,这使得递归操作更加容易,即使嵌套集模型肯定更多复杂而不是邻接列表:
此外,我还建议查看以下演示文稿和@Bill Karwin的帖子,这是Stack Overflow 2 的定期撰稿人:
这些链接中描述的闭包表模型是嵌套集模型的一个非常有效的替代方法。 Bill在他的SQL Antipatterns书(excerpt from the chapter on this topic [PDF])中进一步描述了这个模型。
否则,您还可以坚持使用简单的邻接列表模型,然后在应用程序中执行递归部分,下载所有数据,构建树并遍历它。
1 Oracle也可以使用CONNECT BY
进行递归查询,从版本2开始支持。
2 您可能还想查看以下Stack Overflow帖子:Recursive data processing performance using Java and SQLite,讨论此主题。
答案 1 :(得分:2)
为什么不呢?
sqlite> create table selfref (id integer primary key,
name string, parent integer references selfref (id));
sqlite> .schema
CREATE TABLE selfref (id integer primary key, name string,
parent integer references selfref (id));
sqlite> insert into selfref values (null, "alice", null);
sqlite> insert into selfref values (null, "bob", null);
sqlite> insert into selfref values (null, "charlie",
(select id from selfref where name = "alice"));
sqlite> select * from selfref;
1|alice|
2|bob|
3|charlie|1
sqlite>