|
Таблицы категорий (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=32176271&tid=1546948]: |
0ms |
get settings: |
10ms |
get forum list: |
15ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
153ms |
get topic data: |
10ms |
get forum data: |
3ms |
get page messages: |
59ms |
get tp. blocked users: |
1ms |
others: | 244ms |
total: | 503ms |
0 / 0 |