Может ли SQLite поддерживать эту схему? - PullRequest
4 голосов
/ 31 октября 2010

представьте, у меня есть этот стол, который называется Отдел.У каждого отдела могут быть дочерние отделы.

Я думал о том, чтобы столбец с именем ParentDepartmentID был внешним ключом для другого отдела.Если этот ключ имеет значение null, это означает, что он является родительским отделом высшего класса, а не дочерним по отношению к какому-либо другому отделу.

Я полагаю, вы можете назвать это самообращающимся IDSQLite поддерживает это?Наличие внешнего ключа, но также допускает пустые значения?

Как бы вы решили этот вариант использования?

Ответы [ 2 ]

6 голосов
/ 31 октября 2010

Да, sqlite поддерживает это. Вы можете легко установить внешний ключ, который ссылается на ту же таблицу. Модель, которую вы описываете, называется моделью списка смежностей , и, как очень популярна.

Однако проблема с моделью списка смежности заключается в том, что рекурсивные операции очень трудно писать, если СУБД не может выполнять рекурсивные запросы.

Некоторые СУБД, такие как SQL Server 2005, Postgres 8.4 и Oracle 11g 1 , поддерживают рекурсивные запросы с общими табличными выражениями с использованием ключевого слова WITH). Эта функция позволяет легко писать рекурсивные запросы, но sqlite и MySQL пока не поддерживают рекурсивные запросы.

Вас может заинтересовать следующая статья, в которой описывается альтернативная модель (модель вложенного набора ), которая значительно упрощает рекурсивные операции, даже если Модель вложенного множества определенно сложнее, чем список смежности :

Кроме того, я также предлагаю ознакомиться со следующей презентацией и сообщениями @ Билла Карвина , постоянного участника переполнения стека 2 :

Модель таблицы закрытия *1053*, описанная в этих ссылках, является очень допустимой альтернативой модели вложенного набора . Далее Билл описывает эту модель в своей книге SQL Antipatterns ( отрывок из главы по этой теме [PDF]).

В противном случае вы также можете придерживаться простой модели списка смежностей , а затем выполнять рекурсивную часть в вашем приложении, загружая все данные, создавая дерево и просматривая его.


1 Oracle также может выполнять рекурсивные запросы, используя CONNECT BY, что поддерживается начиная с версии 2.

2 Вы также можете проверить следующую публикацию переполнения стека: Производительность рекурсивной обработки данных с использованием Java и SQLite , обсуждение этой темы.

2 голосов
/ 31 октября 2010

Почему бы и нет?

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> 
...