|  | 
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Было бы интересно узнать, кто сталкивался с задачей "наследования" таблиц, а также различными методами ее решения. Задача уже понятна, я думаю: есть набор полей, который надо раскидать по таблицам таким образом, чтобы некий базовый набор располагался в одной таблице, а "расширяющие" его поля в других таблицах. Простое связывание 1:М не является допустимым по двум причинам: 1. На самом деле это ведь отношение 1:1, что в РБД не приветствуется. 2. Такая схема не исключает принадлежность одного и того же расширяющего набора полей разным объектам. До сих пор не приходилось сталкиваться с MS SQL Server, обходился PostgreSQL, где этой проблемы не существует, поскольку наследование таблиц поддерживается самим сервером (native). При разработке схемы данных в Visio 2002 также использовал объект "Category" с соответствующими коннекторами "Parent to category" и "Category to child". Но как-то не задумывался, каким образом это реализуется в РБД. В результате нахожусь если не в тупике, то в замешательстве. Собственные идеи проблему не решают, а поиск пока не увенчался успехом. Буду рад дельным советам и идеям. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 03.06.2003, 14:21 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Alisher H. Abdurahmanov,  Не могли бы Вы привести пример того, как используется это "наследование таблиц". Некоторые (я в том числе) даже не слышали про такое. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 03.06.2003, 18:33 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Если надо хранить данные о незначительно разных (в смысле наборов полей) классах объектов, то можно пойти одним из двух "лобовых" путей: 1. Организовать таблицу с набором атрибутов, который является объединением множества полей всех классов. 2. Организовать в каждой таблице полные наборы полей для каждого класса (тогда некоторый базовый набор будет дублироваться в каждой такой таблице). Но было бы удобнее иметь базовый набор в одной таблице, а расширяющие его наборы для каждого дочернего класса в других таблицах. По крайней мере, это представляется более логичным решением. Например, представим, что в больнице надо организовать хранение данных о пациентах и результатах некоторых анализов. Представим также, что наборы анализов для мужчин и женщин разные (ведь это легко представить). Имеем три сущности: пациент, пациент-мужчина, пациент-женщина. В родительской таблице я хочу хранить ID, пол, полное имя, возраст etc. В дочерних - специфичные для каждого пола данные. В PostgreSQL я бы реализовал это примерно следующим образом. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. После чего смог бы обращаться как ко всем пациентам через родительскую таблицу, так и к пациентам отдельного пола через дочерние таблицы. Причем за "кухней" следит сам PostgreSQL, то есть мне не надо волноваться, например, о том, что я могу завести одного пациента как мужчину и женщину одновременно. Могу описать и концептуальную модель, как я ее обычно рисую в Visio, но и так уже большое сообщение получилось, поэтому лучше почитать прямо в Microsoft в MSDN Library: "Visio-Based Database Modeling in Visual Studio .NET Enterprise Architect (Part 5)". Все понятно с концепцией, но вот с реализацией толком не разобрался. Вопрос о согласованности данных так и остался открытым. Каким образом поле-дискриминатор (в нашем примере это поле Sex) может гарантировать эту согласованность... P.S. Чувствую, что где-то что-то у меня в голове зациклилось, вот и не получается увидеть очевидное. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 07:00 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ мне не надо волноваться, например, о том, что я могу завести одного пациента как мужчину и женщину одновременно.  Я не специалист в PostgreSQL, но каким образом Вы не сможете этого сделать? Я так понимаю, что БД не разрешит сделать следующее: Код: plaintext 1. 2. 3. Но разрешит: Код: plaintext 1. 2. 3. ? ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 09:45 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ По отображению объектов на реляционную базу данных много различных статей. Например: www.agiledata.org : The Fundamentals of Mapping Objects to Relational Databases. by Scott W.Ambler ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 12:00 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Нет, имелась ввиду другая ситуация. Если я в PostgreSQL вставляю запись в дочернюю таблицу, то запись уже будет иметь PatID и поля как родительской, так и дочерней таблицы: Код: plaintext 1. После этого я не смогу вставить запись в таблицу FemalePatient с таким же PatID. То есть PostgreSQL поддерживает "настоящее" наследование. Например, все следующие запросы верны: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. Если же говорить о модели, предлагаемой в статье Microsoft (см. мое предыдущее сообщение), то я не совсем понимаю, каким образом можно запретить делать следующее: Код: plaintext 1. Да, PatID присутствует во всех трех таблицах. Да, PatID является первичным ключом в каждой из таблиц. Получается, что выбирая пациентов, я всегда должен помнить, с какой из дочерних таблиц надо выполнять JOIN, в зависимости от того, информация о пациентах какого пола мне нужна: Код: plaintext 1. 2. Это ли удобно? ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 12:30 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Это ли удобно?  А может поговорим, удобно ли это: INSERT INTO MalePatients (PatID, ProstateStatus) VALUES (1, 'fine'); INSERT INTO FemalePatients (PatID, PapSmear) VALUES (1, TRUE); С какой силы перепоя нужно быть, чтобы завести две разных таблицы для разных полов? И что-то я сомневаюсь, что просто так, сама Postgre, не разрешит внести по записи в этой ситуации: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. Явно ты опустил определение того, что запись может быть только в одной из этих таблиц. Потому что другого логического объяснения нет - от одно й таблицы можно отнаследовать хоть 10 таблиц, и никто не ставит условий, что в них должна быть однотипная информация. А если будет еще таблица: Код: plaintext 1. 2. 3. 4. То по твоему утверждению и сюда БД не даст вставить строку. Ну? Где промах у тебя, мож расскажешь? ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 12:47 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Хорошо, давай обсудим и это.  =8-) Разные таблицы заведены не собственно для пациентов, а для хранения информации о их состоянии и анализах. В самом деле, мало ли сколько всего может быть у женщин и мужчин разного в этом плане, верно? Таблица Patients хранит информацию о пациентах, вне зависимости от их пола (имя, возраст etc), а две дочерние - те самые данные о состоянии их органов и результатах анализов (сколько раз еще повториться придется). Можно хранить все эти поля и в одной таблице, но тогда заполнение записей будет "разреженным": для мужчин будут всегда пустыми "женские поля" и наоборот. Хорошо, давайте просто назовем дочерние таблицы иначе. Далее. Промаха нет. PostgreSQL действительно следит за наследованными таблицами. Можно даже думать, что на самом деле работаешь с одной таблицей, но в зависимости от того, по какому имени к ней обращаешься, имеешь разные наборы полей. В том примере, который Вы привели, не удастся вставить запись в таблицу CrazyPatioents с уже существующим PatID в таблице Patients. В этой таблице на самом деле есть и поля таблицы Patients, поскольку она от нее наследована, так что ограничение PRIMARY KEY не даст совершить такую операцию. Эх-х-х... но я-то хотел получить ответы на свои вопросы, а не объяснять, как я бы я решил эту задачу раньше. Сейчас мне надо решать ее на Microsoft SQL Server 2000. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 13:04 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Спасибо за статью "The Fundamentals of Mapping Objects to Relational Databases"! Очень интересно было почитать, но там ровно то, о чем я уже говорил и к чему уже пришел. Видимо, придется оставлять решение таким и надеяться, что когда-нибудь потом мне посчастливится придумать или найти то самое, о котором мечтаю. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 13:05 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ 2Alisher H. Abdurahmanov Вы можете реализовать требуемую функциональность в реляционной БД следующим образом: [src] CREATE TABLE Patients ( PatID int PRIMARY KEY, Sex char(1), Name varchar(64) ) CREATE TABLE MalePatients ( PatID int PRIMARY KEY REFERENCES Patients, ProstateStatus varchar(32) ) CREATE TABLE FemalePatients ( PatID int PRIMARY KEY REFERENCES Patients, PregnancyCount int, PapSmear bit ) [src] Здесь видно преимущество реляционной БД перед "постреляционной", т.е. реляционной с урезанной функциональностью, БД PostgreSQL - мы можем учесть ситуацию, когда пациент имеет и те, и другие первичные ПП, а так-же когда пациент имел сначала ж. ППП, а потом стал иметь м. ППП, или, к примеру, вообще не иметь таковых изначально. Конечно, поле Sex в Patients не имеет смысла, и Sex должен определятся по наличию записей в MalePatients и FemalePatients как одно из четырёх значений: М Ж МЖ n/a ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 14:02 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Далее. Промаха нет. PostgreSQL действительно следит за наследованными таблицами. Можно даже думать, что на самом деле работаешь с одной таблицей, но в зависимости от того, по какому имени к ней обращаешься, имеешь разные наборы полей. В том примере, который Вы привели, не удастся вставить запись в таблицу CrazyPatioents с уже существующим PatID в таблице Patients. В этой таблице на самом деле есть и поля таблицы Patients, поскольку она от нее наследована, так что ограничение PRIMARY KEY не даст совершить такую операцию.   Странно - и отчего же тогда наследовать CrazyPatients? Странная логика у БД - хорошо, что не с ней работаю. Разные таблицы заведены не собственно для пациентов, а для хранения информации о их состоянии и анализах. В самом деле, мало ли сколько всего может быть у женщин и мужчин разного в этом плане, верно? Таблица Patients хранит информацию о пациентах, вне зависимости от их пола (имя, возраст etc), а две дочерние - те самые данные о состоянии их органов и результатах анализов (сколько раз еще повториться придется). Можно хранить все эти поля и в одной таблице, но тогда заполнение записей будет "разреженным": для мужчин будут всегда пустыми "женские поля" и наоборот. Хорошо, давайте просто назовем дочерние таблицы иначе. Это все понятно. Уже :) Эх-х-х... но я-то хотел получить ответы на свои вопросы, а не объяснять, как я бы я решил эту задачу раньше. Сейчас мне надо решать ее на Microsoft SQL Server 2000. Ну и на SQL сервере можно решить. Такие же таблицы: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. Дочерние таблицы вяжем через foreign на Родительскую по PatID В триггере каждой дочерней таблицы делаем проверку - для MalePatients если пол М, то можно вставить, если Ж, то нельзя. Так же и для FemalePatients . Выборки придется самому писать - join на родительскую таблицу. Все. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 14:07 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ :)) ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 14:15 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Алексей, именно к этому решению я и пришел уже во второй попытке. Значит, моя голова все еще на месте, чему несказанно рад. Сначала возникло подозрение именно на потерю крыши.  =8-) Моя же проблема как раз заключается в том, чтобы запретить пациенту быть "двуполым" или "никем". ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 14:17 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Оппаньки, Тигра уже помог и с этой проблемой справиться. Триггеры... мое слабое место. Но все равно справлюсь, несомненно. Большущее спасибище, Тигра! Что ж, а выборки организуем в представления, так что ничего особо страшного не предвидится. Задача решена полностью. Это очень хорошо. P.S. На experts-exchange для Тигры не пожалел бы баллов за ответы. =8-) ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 14:25 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Я бы на вашем месте не был бы столь оптимистичным. Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. Логика логикой, а хранение данных - другой вопрос. И никаких джойнов и триггеров. Для верности можно констрейнты навернуть. Код: plaintext 1. 2. 3. 4. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 14:46 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Ладно-уж, подскажу решение без триггеров для противников пола "МЖ" и "n/a" :-) Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16. 17. 18. 19. 20. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 15:04 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Но было бы удобнее иметь базовый набор в одной таблице, а расширяющие его наборы для каждого дочернего класса в других таблицах. По крайней мере, это представляется более логичным решением.   Что мешает для одной таблицы пользоваться View??? Имхо, они именно для этого и предназначены. А дублировать одинаковую информацию в разных таблицах - не есть хорошо, накладные затраты на поддержание целостности могут быть немаленькими. Я бы вашу задачу решал так - таблица, содержащая общие данные, плюс две таблицы по внешнему ключу ссылающиеся на первую. Впрочем, об этом alexeyvg уже написал, не буду повторяться. Кстати. Я незнаком с реализацией механизма наследования в PostgreSQL, но, имхо, из общих сооображений рискну предположить что join в каком-то виде все равно используется - информацию-то откуда-то надо получать. Другой вопрос, что это может быть скрыто от програмиста. Если неправ - поправьте. Что касается триггеров - я бы их не стали использовать там, где без них вполне можно обойтись. akuz тоже еуже рассказал, как. 2 akuz Все это конечно будет работать, но только как вот быть с нормализацией-то???.... ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 15:06 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Akuz, в "The Fundamentals of Mapping Objects to Relational Databases" и "Visio-Based Database Modeling in Visual Studio .NET Enterprise Architect (Part 5)" этот подход тоже описывается, равно как и три других. Он меня не устраивает. Предлагаете использовать ту же "разреженную" структуру, о которой уже говорили выше. P.S. Не устраивает потому, что на самом деле модель с пациентами выбрал показательно. В моей базе и типов, и полей как в родительской, так и в дочерних таблицах, гораздо больше. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 15:06 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Кот, не могу сообразить, где Вы углядели дублирование данных в разных таблицах (кстати, и этот подход тоже описан в "Mapping..."). Предложенный Вами подход к решению - как раз тот, к которому пришли уже в самом начале обсуждения.  =8-) Подход от Алексея к решению проблемы жесткой типизации объектов очень даже ничего смотрится. Надо будет и его попробовать, и триггеры. P.S. Приятно, что разработчики бывают такими отзывчивыми. Я-то думал, что дня два-три придется ждать ответов. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 15:18 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ Alisher H. Abdurahmanov  Эх-х-х... но я-то хотел получить ответы на свои вопросы, а не объяснять, как я бы я решил эту задачу раньше. Сейчас мне надо решать ее на Microsoft SQL Server 2000 Тебя просто попросили конкретизировать задачу. Сама задача несложная, и решить ее можно в четыре таблицы, но что ты дальше будешь делать с таким знанием РСУБД? Лучше почитай книжки, начиная с "ликбезовских". А решение ниже. Patients (Table) Pat_ID integer (PK) Pat_Name varchar Sex integer Analise_Type (Table) Type_ID integer (PK) An_Name varchar Analise (Table) An_ID integer (PK) Type_ID integer (FK) An_Name varchar Analise_Detail (Table) Pat_ID integer (FK) An_ID integer (FK) An_Date date An_Value varchar Примерно так. Можно (и нужно!) все это дело расширить и дополнить для полной картины (анамнеза), но это уже твоя забота :-) ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 15:30 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ 2 A.H.A. Где я его углядел???.... Имхо, это не я, а вы его углядели: Организовать в каждой таблице полные наборы полей для каждого класса (тогда некоторый базовый набор будет дублироваться в каждой такой таблице). сегодня, 07:00 Не так ли???... ЗЫ. А вообще интересно, как будет выглядеть решение на ANSI SQL-92 ??? :o) ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 04.06.2003, 16:23 |  | ||
| 
Таблицы категорий (category tables) | |||
|---|---|---|---|
| #18+ to Alisher H. Abdurahmanov Нет, имелась ввиду другая ситуация. Если я в PostgreSQL вставляю запись в дочернюю таблицу, то запись уже будет иметь PatID и поля как родительской, так и дочерней таблицы: INSERT INTO MalePatients (PatID, Sex, Name, ProstateStatus) VALUES (1, 'M', 'John', 'fine'); Но PostgreSQL не помешает сделать так: INSERT INTO MalePatients (PatID, Sex, Name, ProstateStatus) VALUES (1, 'F', 'John', 'fine'); Если БД не помешает это сделать, то помоему мы все же немного по разному понимаем условие задачи. ... | |||
| : 
 Нравится:
     Не нравится:
     | |||
| 05.06.2003, 03:09 |  | ||
|  | 

| start [/forum/topic.php?fid=32&msg=32176033&tid=1546948]: | 0ms | 
| get settings: | 9ms | 
| get forum list: | 13ms | 
| check forum access: | 4ms | 
| check topic access: | 4ms | 
| track hit: | 41ms | 
| get topic data: | 11ms | 
| get forum data: | 3ms | 
| get page messages: | 59ms | 
| get tp. blocked users: | 2ms | 
| others: | 12ms | 
| total: | 158ms | 

| 0 / 0 | 
