Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Базы";
Текущий архив: 2002.06.03;
Скачать: [xml.tar.bz2];

Вниз

Еще одна ерунда с FOREIGN KEY   Найти похожие ветки 

 
kaif   (2002-05-10 17:06) [0]

Имеется 2 таблицы, ссылающиеся друг на друга, например:
create table TABLE1(ID integer not null, NAME varchar(20),
primary key (ID));

create table TABLE2(ID integer not null, NAME varchar(20),
primary key (ID));

alter table TABLE2 add foreign key(ID) references TABLE1(ID);
Если добавить сейчас еще одну таблицу в цепочку (и т.д.), то все будет происходить нормально:

create table TABLE3(ID integer not null, NAME varchar(20),
primary key (ID));

alter table TABLE3 add foreign key(ID) references TABLE2(ID);

Однако, если сделать Backup и Restore базы, то добавление еще одной таблицы станет невозможным. Любая попытка создать FOREIGN KEY не на TABLE1, а на зависящие от нее TABLE2 или TABLE3 создаст ситуацию:

STORE RDB$REF_CONSTRAINTS FAILED
action cancelled by trigger (1) to preserve data integrity
Name of Referential Constraint not defined in constraints table

Ошибка явно в Backup - Restore, потому что до того вся такая цепочка связей и даже дерево таких связей работают безупречно.

Кто-нибудь может объяснить мне смысл сообщения об ошибке?
Кто такой триггер (1) и что вообще происходит?


 
suds   (2002-05-10 23:46) [1]

данные в таблицах есть ?


 
Slawik   (2002-05-11 10:05) [2]

Что то не совсем пойму зачем тебе такое прстроение связей:
таб1 <- таб2 (связь 1=1) <- таб3 (связь 1=1) <- табХХ (связь 1=1)
зачем же делать такие связки?
ведь ты связываешь табл. по первичному ключу и исключает множественные связи т.е. нет никакой разницы для связи между таб1 <- таб2 и таб1 <- таб3

По поводу триггера отслеживание связи в IB происходит тоже на триггерах (системных), на них и ругаеться.

Может я что то упустил, но по моему это не совсем корректно!


 
Desdechado   (2002-05-11 10:21) [3]

что за изврат?! Первичный ключ одновременно не может быть внешним!
учите матчасть, коллега


 
Slawik   (2002-05-11 10:34) [4]

>Desdechado
Что изврат согласен!
Но то что "Первичный ключ одновременно не может быть внешним!" - нет.
Такая связка достаточно редко бывет необходима, но все же она имеет право на существование.



 
kaif   (2002-05-11 15:00) [5]

Изврата нет.
Я привел упрощенный (тестовый) пример того, как возникает этот сбой.
Первичный ключ может полностью быть внешним. Это корректно. На ER-диаграммах такие сущности обычно обозначаются прямоугольниками с закругленными краями.
Если бы это противоречило какой-либо логике, то почему все это прекрасно работает до первого backup-restore?
Теперь о самой задаче.
Представьте себе, например "Справочник контрагентов"
CAGENT(ID, CODE)
Теперь представьте себе "Справочник фирм" FIRM(ID, NAME), элементы которого являются подмножеством множества всех контрагентов. (Представьте себе, что существуют и иные подмножества, например, еще "Справочник физ.лиц"
PERSON(ID, FIRST_NAME, SECOND_NAME, PASSP_NUMBER), элементы которого также являются подмножеством множества контрагентов. Так я устроил справочную систему. Подробнее объяснять, зачем - здесь будет длинно.)
Ну вот.Соответственно, каждая фирма имеет вхождение в таблицу CAGENT и FIRM. Установлен FOREIGN KEY FIRM(ID) -> CAGENT(ID).
Я не вижу тут никакого криминала.
Теперь, представим себе таблицу документов "Накладные", работабщую только со "Справочником фирм"
NAKL(NAKL_ID, NAKL_DATE, NAKL_NUM, FIRM_ID)
Установим FOREIGN KEY NAKL(FIRM_ID) -> FIRM(ID). Что тут преступного?
Так вот, если перед тем, как сделать такое изменение метаданных, я имел несчастье употребить backup-restore, то IB не даст создать FOREIGN KEY NAKL(FIRM_ID) -> FIRM(ID), а если не делать backup-restore, то даст.
Я поставил Firebird (FB-Win32-Snapshot-1.0.0.608RC1.zip).
Картина та же.
А теперь представьте себе, что проект - гибкая бухгалтерская система, в которой система справочников и документов создается на ходу, развивается и модифицируется автоматически. Я не хочу отказываться FOREIGN KEY и делать ссылочную целостность руками, прописывая сотни триггеров и всякие IF EXESITS(SELECT... на все таблицы, использующие такие ссылки. Достаточно того, что я и так отслеживаю связи на то, чтобы не возникало циклических ссылок, чтобы мочь корректо переносить данные в следующий бухгалтерский период.
Но самые простые FOREIGN KEY на вторичный индекс должны работать. Нигде в руководстве по IB я не нашел никаких таких ограничений...
И наконец, если я откажусь даже от FOREIGN KEY на вторичный индекс в справочной системе, то где гарантия, что где-то опять меня не подведет точно так же другой вторичный FOREIGN KEY?Например, при ссылке документа на документ...
Повторяю, база не жесткая - система конфигурирует ее на ходу.
Я не могу допустить "вероятности" таких ошибок. Мне нужно их исключить априори.


 
kaif   (2002-05-11 15:04) [6]

>suds © (10.05.02 23:46)
>данные в таблицах есть ?

Есть или нет - неважно. Та же хрень.
Прбовал именовать все CONSTRAINTS (PRIMARY KEY и FOREIGN KEY). Картина не меняется.
Ничего не помогает. ошибка прячется где-то в процессе Restore...


 
Desdechado   (2002-05-11 16:12) [7]

Попробуй все-таки сделать уникальный индекс вместо первичного ключа там, где ключ внешний и ссылается на другую таблицу.
От гибкости не убудет, а стройность появится. Глядишь, и ошибка уйдет :)


 
kaif   (2002-05-11 16:47) [8]

>Desdechado © (11.05.02 16:12)
Конечно, в крайнем случае, мне придется искать обходные пути...
Но я бы хотел, чтобы эту ошибку исправили разработчики. Не знаю, как связаться с кем-нибудь, например, из firebird.
Есть одна такая же чудовищная ошибка в BDE Delphi, которую я локализовал еще 5 назад и долго пытался сообщить о ней на Borland. Но так мне и не ответили. Ошибка так и осталась в D3. Затем перекочевала в D5 и D6. Эта ошибка в драйвере Paradox, приводящая к 100% Index out of date в результате безобидной последовательности 3 действий (обычно их совершает юзер, а не разработчик)
1.нарушение уникального ключа таблицы
2.любой SQL-запрос к ней из TBDEDataSet, напр. TQuery.
3.еще одно нарушение того же уникального ключа.
4 -------индекс уже рухнул. Здесь даже не будет exception...
На форуме в неделю 1 раз я вижу вопрос "Почему рушится индекс Paradox таблицы?". А воз и ныне там.

Нет, есть ошибки, которые следует исправлять в системе, а не пытаться обойти.


 
kaif   (2002-05-11 18:40) [9]

>Я поставил Firebird (FB-Win32-Snapshot-1.0.0.608RC1.zip).
>Картина та же.
Прошу прощения. Firebird я поставил не в тот каталог...
После правильной установки Firebird ошибка исчезла.
Правда, теперь не работает backup, точнее соответствующий компонент IBX. Но это, я думаю поправимо.
Всем спасибо.


 
Desdechado   (2002-05-11 19:18) [10]

> учите матчасть, коллега
Что ж, приношу извинения.
Хотя с таким подходом к проектированию БД КАТЕГОРИЧЕСКИ не согласен :)


 
kaif   (2002-05-12 16:53) [11]

2 Desdechado © (11.05.02 19:18)
>Хотя с таким подходом к проектированию БД КАТЕГОРИЧЕСКИ не >согласен :)

А что, собственно, не нравится?
Что, нельзя использовать FOREIGN KEY на таблицу, которая, в свою очередь имеет FOREIGN KEY на иную таблицу? Совершенно неслыханное ограничение. Тогда можно вообще сказать - FOREIGN KEY не использовать - и все тут. Где гарантия, что вдруг таблица, на которую я устанавливаю такое отношение не имеет уже какого-то отношения к другой таблице?
Если я привожу утрированные примеры, то только потому, что так я эту ошибку локализовал...


 
Desdechado   (2002-05-13 11:46) [12]

не нравится primary key = foreign key
выход мне видится в Desdechado © (11.05.02 16:12)


 
Shaman_Naydak   (2002-05-13 12:37) [13]

> Desdechado © (13.05.02 11:46)
категорически с вами не согласен, зависит от задачи,например, это обычное явление при реализации generalization


 
Desdechado   (2002-05-13 16:46) [14]

Не хочу спорить, может жизнь научит (и меня в т.ч.)
Просветите - что такое generalization


 
kaif   (2002-05-14 00:25) [15]

FOREIGN KEY и есть не что иное, как INDEX плюс триггер, проверяющий вхождение в подчиненную таблицу и, в зависимости от условий ON DELETE CASCADE, ON DELETE SET NULL и т. п. имплементирующий соответствующее действие. По крайней мере именно так работает IB. Наличие первичного ключа желательно в любом случае. Если первичный ключ одновременно и FOREING, я думаю, что IB просто использует его.
Я не вижу необходимости все это руками повторять, когда в IB это уже реализовано. А в IB, ИМХО не реализовано ничего лишнего.
Возможно, нарекания могут быть, если в качестве первичного ключа используется какой-то реальный атрибут, но я использую ТОЛЬКО суррогатные ID, задаваемые глобальным генератором. То есть ID для всех таких таблиц уникальны в принципе и путаницы возникнуть не может.
С Firebird все заработало великолепно, я и не надеялся. Так что это просто баг IB, который плохо заметен, так как проявляется только после backup-restore. Раньше мне просто казалось, что что-то просто нарушилось в базе, так как часть таблиц работала, а часть - нет . И я с трудом догадался, что это происходит после backup - restore.
Да и то, возможно только в том билде, что у меня был...
Интересно, что после замены сервера на Firbird ошибка пропала сразу, я даже не делал backup-restore базы, которая себя так вела... Она просто заработала - и все. И все новые FOREIGN KEY создавались без проблем.


 
Desdechado   (2002-05-14 10:37) [16]

2 kaif © (14.05.02 00:25)
спасибо. все это мне известно. но повторение - мать учения.



Страницы: 1 вся ветка

Форум: "Базы";
Текущий архив: 2002.06.03;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.5 MB
Время: 0.006 c
14-7204
Doom
2002-04-24 23:21
2002.06.03
Что - D6 под NT4 не рассчитаны?


7-7247
Spy
2002-03-08 19:27
2002.06.03
Система


3-6900
Shkolnik
2002-05-13 14:17
2002.06.03
Объясните плиз самое простое самому начинающему


14-7186
Transaero
2002-04-25 11:04
2002.06.03
Добрые люди, окажите помощь.


3-6896
Z-man
2002-05-13 06:24
2002.06.03
Помогите по





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский