Вопрос по БД.

 

Vit

новичок
Проектирую базу данных, возникла следующая проблема: есть две таблицы, одна описывает людей, вторая организации. Также есть поле, корое может указывать на обе таблицы (объект может принадлежать как организации так и отдельным товарищам). Как сделать?
:unsure:
 
+
-
edit
 

-exec-

опытный

хм.
я бы сделал две ссылки - на физиков и на юриков.
для строгости можно триггеров навесить или чеков.

code text
  1. create table juridical_persons (id int primary key)
  2. create table natural_persons (id int primary key)
  3.  
  4. create table properties
  5. (
  6.   id                int,
  7.   name              varchar(20),
  8.   natural_owner     int             null
  9.                     references natural_persons(id),
  10.   juridical_owner   int             null
  11.                     references juridical_persons(id)
  12. )
  13.  
  14. alter table properties
  15.   add constraint properties_owner
  16.     check (not((natural_owner is not null) and (juridical_owner is not null)))
  17.  
  18. insert into juridical_persons values (1)
  19. insert into natural_persons values (1)
  20.  
  21. insert into properties values (1, 'spoon', 1, null)
  22. insert into properties values (2, 'pen', null, 1)
  23. insert into properties values (3, 'book', null, null)
  24. insert into properties values (4, 'ink', 1, 1) --облом
  25. update properties set natural_owner = 1 where id = 3 --экспроприация книжки - ok
  26. update properties set natural_owner = 1 where id = 2 --экспроприация ручки - облом
  27. update properties set juridical_owner = null, natural_owner = 1 where id = 2 --кража ручки - ok
  28. update properties set juridical_owner = 1, natural_owner = null where id = 2 --возврат ручки - ok


примерно так.
триггерами, конечно можно более тонко условиями управлять
 
Это сообщение редактировалось 19.05.2004 в 10:22
+
-
edit
 

-exec-

опытный

если требуется ровно одна колона на владельца,
то другой вариант - сделать таблицу owners, кратко туда записать имя и сослаться на неё.

а из таблицы owners сделать две ссылки на физиков и юриков с более детальными данными.

может быть это даже правильнее, потому, что лица могут быть не только владельцами, но ещё и кредиторами, авторами, подрядчиками...

можно даже попробовать вьюху сделать вместо таблицы, если база сможет её на union all построить. посмотрел. позволяет. тока ссылаться на неё нельзя.
 

hcube

старожил
★★
IMHO проще сделать ОДНУ таблицу, и в ней - ключ, физ или юр лицо. ТОгда и запросы будут единообразные.
Убей в себе зомби!  
+
-
edit
 

-exec-

опытный

повлечёт за собой избыточность структуры этой единственной таблицы - у физиков будут пустыми юриковские поля и наоборот.
если смысл базы только в описании владельцев, трюк может иметь смысл. если же лица в базе играют сколько нибудь более разнообразные роли - объединять их некрасиво.
 
+
-
edit
 

Balancer

администратор
★★★★★
Vit, 19.05.2004 09:51:42 :
Проектирую базу данных, возникла следующая проблема: есть две таблицы, одна описывает людей, вторая организации. Также есть поле, корое может указывать на обе таблицы (объект может принадлежать как организации так и отдельным товарищам). Как сделать?
:unsure:
 


Я бы сделал две таблицы и третью, связывающую объект и записи в других таблицах.
 
?? Andy-Andrei #19.05.2004 17:35
+
-
edit
 

Andy-Andrei

втянувшийся

Если я правильно понял Балансера, он предлагает использовать коммутационную таблицу. Это довольно-таки широко применяемый способ.
Допустим, есть

FIZ (ID, NAME)
JUR (ID, NAME)

и некий третий объект, скажем, DOC, коий должен ссылаться на обе вышеприведенные таблицы. Для DOC делаем коммутирующую таблицу:

DOC_BIND (ID, DOC_ID, REF_ID, TAB_ID)

Поле DOC_ID ссылается на DOC.ID, а REF_ID либо на FIZ.ID, либо на JUR.ID в зависимости от значения в TAB_ID (это просто флажок, код связи).

Единственный недостаток способа - констрейнт не положишь, но он на фиг не нужен.
Ты не смотри, что у меня вечно штраф висит... Я не буйный...  
US Сергей-4030 #19.05.2004 18:32
+
-
edit
 

Сергей-4030

исключающий третье
★★

Проектирую базу данных, возникла следующая проблема: есть две таблицы, одна описывает людей, вторая организации. Также есть поле, корое может указывать на обе таблицы (объект может принадлежать как организации так и отдельным товарищам). Как сделать?
 


Очень зависит от конкретных требований. Как вариант "OOP подхода" ;) будет такой:

Таблица Man, связана с Owner 1:1
(man attribuites)
ownerID

Таблица Beast связана с Owner 1:1
(beast attrs)
ownerID

Таблица Owner
(owner's attribuites)
ownerID - unique key

Таблица Things
(things attribuites)
thingID

Таблица принадлежности - OwnedBy, связана с Owner NxM
ownerID
thingID


Минус - надо использовать inner join'ы на каждую конкретную операцию "владения". Плюс - inner join работает быстро. ;)
 
+
-
edit
 

-exec-

опытный

hcube, 19.05.2004 14:59:32 :
IMHO проще сделать ОДНУ таблицу, и в ней - ключ, физ или юр лицо. ТОгда и запросы будут единообразные.
 


не-а. не будут они единообразными с такой денормализацией.
я это прямо сейчас испытываю - разнородные доки лежат в одной таблице, и это неудобно. причём непересекающихся родов документов (те, группы документов, которые не приходится тянуть одновременно) - таких около десяти типов.
1.расходуется место в ширину, потому, что одни доки не имеют полей других доков - тормоза и условные выражения в выборках.
2.у меня таблица в десять раз длиннее - тормоза и иногда условные выражения в выборках.

п.с.проектировал не я :)
 
US Сергей-4030 #19.05.2004 19:32
+
-
edit
 

Сергей-4030

исключающий третье
★★

не-а. не будут они единообразными с такой денормализацией.
 


Совершенно согласен.
 

Rada

опытный

Подход Сергея самый правильный с алгебраической т.з.
С себя можно начать когда все остальное будет в порядке.  
+
-
edit
 

Mishka

модератор
★★★
Я бы только разрешил (ради обобщения) следующие отношения:
Таблица Man, связана с Owner 0..N:1

Таблица Beast связана с Owner 0..N:1

Может быть человек и без вещей - т.е. не владелец, хотя это можно смоделировать при помощи группы не владеющей ни чем, да и несколько человек могут владеть вещью - поэтом и больше 1.
Аналогично с организацией - может быть и группа организаций.

Хотя, в принципе, таблица связи покрывает группировки. Но отношение 1:1 приводит, что и у Man и у Beast это отношение должно быть определяющим, т.е. ownerID должен стать уникальным в каждой из таблиц. А такое разбиение на две таблицы - не является нормализацией и эти таблицы надо объединить.
 
?? Сергей-4030 #20.05.2004 07:17
+
-
edit
 

Сергей-4030

исключающий третье
★★

Ммм... я именно предлагал уникальный ownerID для каждой таблицы. :) Не нормализовано - плевать, в данном случае это не так опасно. Нормализовать можно введением таблиц-связок "man - owner" и "beast-owner", но уж больно геморройно, а большого смысла и нет вроде. :) То есть, в терминах ОО DB мы должны иметь сущность "владелец", а наследниками выступают "man" и "beast". В этом смысле данная схема - просто попытка реализации OO проектирования на SQL. Как правильно заметил Миша - таковая реализация не является достаточно общей, зато (мне кажется) является достаточно простой и эффективной в смысле будущих запросов.

ЗЫ А если "man" не владеет ничем - у него просто не будет записей в OwnedBy.
 
+
-
edit
 

Mishka

модератор
★★★
Я понял, что ты сделал подклассы владельца. Просто ты не сказал, что эти идентефикаторы в человеке и твари уникальны, а как бы наложил ограничение неявно, введя соотношение 1:1 - в этом случае все действительно нормализованно - просто расширения лежат в разных таблицах и место экономиться. Я хотел сказать, что человеки, группы, организации, департменты и другие объекты, которые появляются в жизни не обязательно должны быть подклассами владельца - поэтому и расширил от 1:1 до 0..N:1, хотя, по хорошему, и этого не хватает - если кто-то может быть владельцем многого - правда можно через группу смоделировать. А так надо смотреть задачу. Может эта общность и не к чему.
 

в начало страницы | новое
 
Поиск
Настройки
Твиттер сайта
Статистика
Рейтинг@Mail.ru