Форум: "Базы";
Текущий архив: 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