![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Еще одна ерунда с FOREIGN KEY [D5, IB6.x]
kaif © (2002-05-10 17:06:00)Имеется 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) и что вообще происходит?
Desdechado (2002-05-14 10:37:00) [1]2 kaif © (14.05.02 00:25)
спасибо. все это мне известно. но повторение - мать учения.
kaif (2002-05-14 00:25:00) [2]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-13 16:46:00) [3]Не хочу спорить, может жизнь научит (и меня в т.ч.)
Просветите - что такое generalization
Shaman_Naydak (2002-05-13 12:37:00) [4]> Desdechado © (13.05.02 11:46)
категорически с вами не согласен, зависит от задачи,например, это обычное явление при реализации generalization
Desdechado (2002-05-13 11:46:00) [5]не нравится primary key = foreign key
выход мне видится в Desdechado © (11.05.02 16:12)
kaif (2002-05-12 16:53:00) [6]2 Desdechado © (11.05.02 19:18)
>Хотя с таким подходом к проектированию БД КАТЕГОРИЧЕСКИ не >согласен :)
А что, собственно, не нравится?
Что, нельзя использовать FOREIGN KEY на таблицу, которая, в свою очередь имеет FOREIGN KEY на иную таблицу? Совершенно неслыханное ограничение. Тогда можно вообще сказать - FOREIGN KEY не использовать - и все тут. Где гарантия, что вдруг таблица, на которую я устанавливаю такое отношение не имеет уже какого-то отношения к другой таблице?
Если я привожу утрированные примеры, то только потому, что так я эту ошибку локализовал...
Desdechado (2002-05-11 19:18:00) [7]> учите матчасть, коллега
Что ж, приношу извинения.
Хотя с таким подходом к проектированию БД КАТЕГОРИЧЕСКИ не согласен :)
kaif (2002-05-11 18:40:00) [8]>Я поставил Firebird (FB-Win32-Snapshot-1.0.0.608RC1.zip).
>Картина та же.
Прошу прощения. Firebird я поставил не в тот каталог...
После правильной установки Firebird ошибка исчезла.
Правда, теперь не работает backup, точнее соответствующий компонент IBX. Но это, я думаю поправимо.
Всем спасибо.
kaif (2002-05-11 16:47:00) [9]>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 таблицы?". А воз и ныне там.
Нет, есть ошибки, которые следует исправлять в системе, а не пытаться обойти.
Desdechado (2002-05-11 16:12:00) [10]Попробуй все-таки сделать уникальный индекс вместо первичного ключа там, где ключ внешний и ссылается на другую таблицу.
От гибкости не убудет, а стройность появится. Глядишь, и ошибка уйдет :)
kaif (2002-05-11 15:04:00) [11]>suds © (10.05.02 23:46)
>данные в таблицах есть ?
Есть или нет - неважно. Та же хрень.
Прбовал именовать все CONSTRAINTS (PRIMARY KEY и FOREIGN KEY). Картина не меняется.
Ничего не помогает. ошибка прячется где-то в процессе Restore...
kaif (2002-05-11 15:00:00) [12]Изврата нет.
Я привел упрощенный (тестовый) пример того, как возникает этот сбой.
Первичный ключ может полностью быть внешним. Это корректно. На 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?Например, при ссылке документа на документ...
Повторяю, база не жесткая - система конфигурирует ее на ходу.
Я не могу допустить "вероятности" таких ошибок. Мне нужно их исключить априори.
Slawik (2002-05-11 10:34:00) [13]>Desdechado
Что изврат согласен!
Но то что "Первичный ключ одновременно не может быть внешним!" - нет.
Такая связка достаточно редко бывет необходима, но все же она имеет право на существование.
Desdechado (2002-05-11 10:21:00) [14]что за изврат?! Первичный ключ одновременно не может быть внешним!
учите матчасть, коллега
Slawik (2002-05-11 10:05:00) [15]Что то не совсем пойму зачем тебе такое прстроение связей:
таб1 <- таб2 (связь 1=1) <- таб3 (связь 1=1) <- табХХ (связь 1=1)
зачем же делать такие связки?
ведь ты связываешь табл. по первичному ключу и исключает множественные связи т.е. нет никакой разницы для связи между таб1 <- таб2 и таб1 <- таб3
По поводу триггера отслеживание связи в IB происходит тоже на триггерах (системных), на них и ругаеться.
Может я что то упустил, но по моему это не совсем корректно!
suds (2002-05-10 23:46:00) [16]данные в таблицах есть ?