Може ли SQLite да поддържа тази схема?

представете си, че имам тази таблица, наречена Отдел. Всеки отдел може да има дъщерни отдели.

Мислех да имам колона, наречена ParentDepartmentID, като външен ключ към друг отдел. Ако този ключ е нула, това означава, че е родителски отдел от най-висок клас, а не дъщерен на който и да е друг отдел.

Предполагам, че можете да наречете това саморефериращ идентификатор. SQLite поддържа ли това? Имате външен ключ, но също така позволявате нули?

Как бихте разрешили този случай на употреба?


person Community    schedule 31.10.2010    source източник


Отговори (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> 
person msw    schedule 31.10.2010

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

Въпреки това, проблемът с модела на списъка на съседство е, че рекурсивните операции са много трудни за писане, освен ако СУБД не може да прави рекурсивни заявки.

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

Може да ви е интересно да разгледате следната статия, която описва алтернативен модел (модел на вложен набор< /em>), което прави рекурсивните операции много по-лесни, въпреки че моделът на вложен набор определено е по-сложен от списъка със съседство:

Освен това предлагам също така да разгледате следната презентация и публикации от @Bill Karwin, редовен участник в Stack Overflow 2:

Моделът на затваряща таблица, описан в тези връзки, е много валидна алтернатива на модела на вложен набор. Бил описва допълнително този модел в своята книга SQL Antipatterns (извадка от главата по тази тема [PDF]).

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


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

2 Можете също така да разгледате следната публикация за препълване на стека: производителност на рекурсивна обработка на данни с помощта на Java и SQLite, обсъждайки тази тема.

person Daniel Vassallo    schedule 31.10.2010
comment
Изпреварихте ме :P Ето страница за поддръжка на sqlite за външен ключ: sqlite.org/foreignkeys.html - person Endy Tjahjono; 31.10.2010
comment
Мисля, че моделът тук е по-точно дърво. Списък със съседство се използва за представяне на графики (кои дървета обаче са)... - person jetru; 31.10.2010