|
|
|
Целостность
|
|||
|---|---|---|---|
|
#18+
Здравствуйте. Возник такой вопрос. Допустим есть две таблицы документов. Table 1 PKname1'a'...2'b'... Table 2 PKFK_TABLE1people_id11...21...32...42... т.е. шапка и тело документа. Есть другая пара таблиц, в которых так же храняться документы. Table_h PKfk_table1 name11'a'... Table_b PKFK_TABLE_hpeople_id11...21...32...42... Table_h.fk_table1 - ссылка на документ-основание из первой таблицы. Как можно обеспечить, чтобы если документ-основание равен единице , то в table_b невозможно было бы добавить people_id, которого нет в теле документа-основания? Только на триггерах с вызовом исключения? Спасибо ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.12.2011, 10:21 |
|
||
|
Целостность
|
|||
|---|---|---|---|
|
#18+
sergqTable 2 PKFK_TABLE1people_id11...21...32...42... Table_b PKFK_TABLE_hpeople_id11...21...32...42... Если Table 2(FK_TABLE1,people_id) - уникально, то: 1. добавляем альтернативный ключ Table 2(FK_TABLE1,people_id) 2. добавляем альтернативный ключ Table h(pk, FK_TABLE1) 3. Добавляем поле Table_b(FK_TABLE1) 4. Добавляем внешний ключ Table_b(FK_TABLE_h,FK_TABLE1) на Table h(pk, FK_TABLE1). 5. Добавляем внешний ключ Table_b(FK_TABLE1,people_id) на Table 2(FK_TABLE1,people_id). Где-то так :). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.12.2011, 11:29 |
|
||
|
Целостность
|
|||
|---|---|---|---|
|
#18+
2 sergq Ну и гадко же задан вопрос. Вместо красивых табличек. вы бы лучше привели скрипты на создание и заполнение таблиц с конкретными именами и значениями. АнатоЛой, я в восхищении, вы смогли через это продратся. sergq чтобы если документ-основание равен единице Что именно в документе основании равно единице sergq невозможно было бы добавить people_id,В таблицу вставляются записи а не поля sergq которого нет в теле документа-основания?Что есть тело документа - основания. Можно предположить что это Table 2? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.12.2011, 18:25 |
|
||
|
Целостность
|
|||
|---|---|---|---|
|
#18+
АнатоЛойsergqTable 2 PKFK_TABLE1people_id11...21...32...42... Table_b PKFK_TABLE_hpeople_id11...21...32...42... Если Table 2(FK_TABLE1,people_id) - уникально, то: 1. добавляем альтернативный ключ Table 2(FK_TABLE1,people_id) 2. добавляем альтернативный ключ Table h(pk, FK_TABLE1) 3. Добавляем поле Table_b(FK_TABLE1) 4. Добавляем внешний ключ Table_b(FK_TABLE_h,FK_TABLE1) на Table h(pk, FK_TABLE1). 5. Добавляем внешний ключ Table_b(FK_TABLE1,people_id) на Table 2(FK_TABLE1,people_id). Где-то так :). Сильно ) Спасибо ) Работает) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.12.2011, 20:17 |
|
||
|
Целостность
|
|||
|---|---|---|---|
|
#18+
но вот тут 5. Добавляем внешний ключ Table_b(FK_TABLE1,people_id) на Table 2(FK_TABLE1,people_id). получается избыточность в Table_b, так как появляется FK_TABLE1 ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.12.2011, 20:52 |
|
||
|
Целостность
|
|||
|---|---|---|---|
|
#18+
А если ситуация такая? DDL CREATE TABLE DOC1_HEADER ( C INTEGER NOT NULL, NAME CHAR(100), SP_YEAR_ID INTEGER, PARAM1 INTEGER, PARAM2 INTEGER, PARAM3 INTEGER, PARAM4 INTEGER ); CREATE TABLE DOC2_HEADER ( C INTEGER NOT NULL, NAME CHAR(100), SP_YEAR_ID INTEGER, PEOPLE_ID INTEGER ); CREATE TABLE DOC2_BODY ( C INTEGER NOT NULL, DOC2_HEADER_ID INTEGER, DOC1_HEADER_ID INTEGER ); /******************************************************************************/ /*** Unique Constraints ***/ /******************************************************************************/ ALTER TABLE DOC1_HEADER ADD CONSTRAINT UNQ1_DOC1_HEADER UNIQUE (SP_YEAR_ID, PARAM1, PARAM2, PARAM3, PARAM4); ALTER TABLE DOC2_HEADER ADD CONSTRAINT UNQ1_DOC2_HEADER UNIQUE (SP_YEAR_ID, PEOPLE_ID); /******************************************************************************/ /*** Primary Keys ***/ /******************************************************************************/ ALTER TABLE DOC1_HEADER ADD CONSTRAINT PK_DOC1_HEADER PRIMARY KEY (C); ALTER TABLE DOC2_BODY ADD CONSTRAINT PK_DOC2_BODY PRIMARY KEY (C); ALTER TABLE DOC2_HEADER ADD CONSTRAINT PK_DOC2_HEADER PRIMARY KEY (C); /******************************************************************************/ /*** Foreign Keys ***/ /******************************************************************************/ ALTER TABLE DOC2_BODY ADD CONSTRAINT FK_DOC2_BODY_1 FOREIGN KEY (DOC2_HEADER_ID) REFERENCES DOC2_HEADER (C); ALTER TABLE DOC2_BODY ADD CONSTRAINT FK_DOC2_BODY_2 FOREIGN KEY (DOC1_HEADER_ID) REFERENCES DOC1_HEADER (C); необходимо контролировать чтобы в таблицу DOC2_BODY нельзя было бы вставить запись из DOC1_HEADER (DOC2_BODY.DOC1_HEADER_ID) НЕ удовлетворяющую условию DOC2_HEADER.SP_YEAR_ID = DOC1_HEADER.SP_YEAR_ID ? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.12.2011, 21:25 |
|
||
|
Целостность
|
|||
|---|---|---|---|
|
#18+
sergq, про ограничения и нормальные формы в постановке задачи не было :). У тебя самого в таблицах небось суррогатные ключи, нет?! :) Что есть тоже "избыточность" ибо дублирование информации... Смотри, как выглядит кратко постановка: 1. Есть таблицы 1,2,h,b, где связаны (наложены ограничения) 1 и 2, h и b, 1 и h. 2. Требуется наложить ограничение между 2 и b, при чём для формулировки ограничения на текущей организации данных нужны данные из 1 и h, и вариант с триггерами уже известен. Кратко схема решения: 1) Сам логично замечаешь, что задачу можно решить триггерами. А почему? Потому что они позволят для построения проверки залезть в 1 и h. 2) Какие ещё есть средства ограничений целостности, кроме триггеров? check constraint и foreign key. а) check constraint работает на одной таблице и не позволит лазить в другие таблицы, а нам нужно увязать две. б) foreign key - связывает поля одной таблицы с ключом в другой, но нам не хватает данных для связи... Формулировка ограничения : "в table_b невозможно было бы добавить people_id, которого нет в теле документа-основания (Table2)". Значит нужно в table_b получить идентификаторы из Table2, по которым можно сослаться на этот Table2. Я сделал предположение, что в table_2 кроме pk есть ещё альтернативный ключ (fk_table_1, people_id). В соответствии с предположением вариант с протягиванием ид FK_table_1 в Table_h я и озвучил. Кстати, из расуждений выплывает и второй вариант: храни в Table_b не people_id, а Table2.pk - ссылку на строку документа-основания :). А чтобы не было дубляжа, грохни people_id в table_b. А в UI для Table_b можешь отображать соответствующий Table2.people_id. Т.е. что-то типа: Код: plaintext 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. Все три варианты (включая триггера) имеют свои плюсы и минусы. Выбираешь всё-равно ты. Отакэ :)... ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.12.2011, 21:32 |
|
||
|
Целостность
|
|||
|---|---|---|---|
|
#18+
sergqнеобходимо контролировать чтобы в таблицу DOC2_BODY нельзя было бы вставить запись из DOC1_HEADER (DOC2_BODY.DOC1_HEADER_ID) НЕ удовлетворяющую условию DOC2_HEADER.SP_YEAR_ID = DOC1_HEADER.SP_YEAR_ID ? Принцип решения я параллельно 2-му вопрому успел описать . 1. Триггера... 2. foreign key: вводи в DOC2_BODY.SP_YEAR_ID + цепочка констрейнтов... думаю, констрейнты сам осилишь ?! :). ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.12.2011, 21:41 |
|
||
|
Целостность
|
|||
|---|---|---|---|
|
#18+
АнатоЛой, Спасибо ) Осилил ) Но буду читать матчасть) Раз уж начал спрашивать - спрошу еще) если возникает такая ситуация есть два типа документов. хранятся соответственно в table1,table2 и в table11 ,table22 соответственно. они совершенно разнородные, поэтому нет возможности из объединить в одну таблицу. А вот table_h может иметь дочерним документом как документ из table1,table2 так и из table11 ,table22 Как быть в данной ситуации? Если приведете пример и матчасть - буду благодарен ) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.12.2011, 22:17 |
|
||
|
Целостность
|
|||
|---|---|---|---|
|
#18+
sergqесть два типа документов. хранятся соответственно в table1,table2 и в table11 ,table22 соответственно. они совершенно разнородные, поэтому нет возможности из объединить в одну таблицу. А вот table_h может иметь дочерним документом как документ из table1,table2 так и из table11 ,table22 Как быть в данной ситуации? Если приведете пример и матчасть - буду благодарен ) Варианты: I. Применить шаблон "тупо в обработке, но всё-таки контролируемо со стороны БД". Варианты реализации: I.1. В table_h заводим обычные два поля с внешними ключами, накладываем check-констрейнт, что одно и только одно из них должно быть заполнено. II. Применить шаблон "эксклюзивное наследование". Необходимо каким-то образом (триггера, клиент, sequence, общая таблица-"предок") обеспечить уникальность для совокупности ключей из t1 и t11. Тогда варианты реализации: II.1. Общая таблицв-"предок". Вводим таблицу table0 с одним только первичным ключом. Неплохо добавить table0 поле-признак, по которому будет понятно, в какой таблице "наследник". Первичные ключи наследников table1 и table11 являются также и внешними ключами на table0. У table_h внешний ключ делаем на table0. II.2. Обеспечен уникальный ключ. У table_h есть одно поле с ид. без внешнего ключа. Контроль на триггерах. Неплохо добавить table_h поле-признак, по которому будет понятно, на какую таблицу ссылаемся. ... Чужая практика: http://www.databaseanswers.org/data_models/index.htm Теория: Кнут и ещё раз Кнут, и немного кнута на реальньіх проектах :). "Теория": поиск "шаблоны проектирования баз данных", "Data Model Patterns". Неплохо ьбв вообще про "шаблоны проектирования" и Фаулера "Шаблоны корпоративных приложений" Книги: 1. Hay, D., Data Model Patterns: Conventions of Thought, Dorset House Publishing:New York, 1996. 2. Len Silverston , The Data Model Resource Book. 3. Vadim Tropashko, Donald K. Burleson, SQL Design Patterns. 4. Joe Celko's SQL for Smarties: Advanced SQL Programming Second Edition ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.12.2011, 15:25 |
|
||
|
|

start [/forum/topic.php?fid=32&fpage=54&tid=1541911]: |
0ms |
get settings: |
5ms |
get forum list: |
10ms |
check forum access: |
2ms |
check topic access: |
2ms |
track hit: |
34ms |
get topic data: |
8ms |
get forum data: |
2ms |
get page messages: |
42ms |
get tp. blocked users: |
1ms |
| others: | 199ms |
| total: | 305ms |

| 0 / 0 |
