|
|
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
Должны быть три таблицы t1, t2, t3. В t3 есть одно поле, которое внешним ключом ссылается сразу на t1 и t2. Если ключи простые, все нормально. Если оба ключа с каскадным обновлением, матерится (не дает создать t3). Если только один из них каскадный, а другой простой, дает. Говорит: Introducing FOREIGN KEY constraint 'fk_t3_t2_code' on table 't3' may cause cycles or multiple cascade paths. Specify ON DELETE NO ACTION or ON UPDATE NO ACTION, or modify other FOREIGN KEY constraints. Почему? Если уж есть два ключа, то, казалось бы, надо либо не давать обновлять никакие, либо уж давать обновлять все. ???? ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 05.06.2002, 17:13:01 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
У вас случаем связи с использованием каскадного удаления/обновления между t1 и t2 нет ? Если есть, то с t3 не получится к обеим таблицам каскад организовать. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2002, 09:58:46 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
Нет, между t1 и t2 связей нет. Есть еще таблица t0, на которую ссылаются t1 и t2, а на обе из них ссылается t3. Вот структура: -- Таблица t0 create table cd_parthners ( code varchar(20) not null, name varchar(50) not null, constraint pk_cd_parthners primary key (code) ) -- Таблица t1 create table cd_phone_groups ( cd_parthner_code varchar(20) not null, code varchar(20) not null, name varchar(50) not null, constraint pk_cd_phone_groups primary key (cd_parthner_code, code), constraint fk_cd_phone_groups_cd_parthners foreign key (cd_parthner_code) references cd_parthners (code) on update cascade ) -- Таблица t2 create table cd_phone_infos ( cd_parthner_code varchar(20) not null, phone varchar(30) not null, first_name varchar(50) not null, middle_name varchar(50) null, last_name varchar(50) not null, constraint pk_cd_phone_infos primary key (cd_parthner_code, phone), constraint fk_cd_phone_infos_cd_parthner_code foreign key (cd_parthner_code) references cd_parthners (code) on update cascade ) -- Таблица t3 create table cd_gi_rels ( cd_parthner_code varchar(20) not null, cd_phone_group_code varchar(20) not null, phone varchar(30) not null, constraint pk_cd_gi_rels primary key (cd_parthner_code, cd_phone_group_code, phone), constraint fk_cd_gi_rels_cd_groups foreign key (cd_parthner_code, cd_phone_group_code) references cd_phone_groups (cd_parthner_code, code) on update cascade, constraint fk_cd_gi_rels_cd_phones foreign key (cd_parthner_code, phone) references cd_phone_infos (cd_parthner_code, phone) /* вот если здесь поставить on update cascade, не даст, а нужно каскадно обновлять поле cd_phone_infos.phone. */ ) Попробую через триггер instead update на cd_phone_infos. Но почему все-таки он не дает? PS. Спасибо тому, кто не поленится это все читать :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2002, 11:59:58 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
Уважаемый AlexP! Я не поленилась прочесть и даже нарисовать схемку на листочке карандашиком, чего и вам желаю. 1. У вас жуткая избыточнность данных в таблицах. 2. Первичные ключи чаще всего и создаются как INT для того, чтобы при изменении текстовой информации (корректировке), ключ оставался тем же в отношении один ко многим. 3. Я понимаю так: у вас есть № телефона, информация о владельце, а номера телефонов группируются по отделам (районам) и еще по parthner . Если это так, то создаются 2 таблицы (справочные) parthner (id_parthner int not null, code varchar(20) )- это справочник parthner с PK id_parthner Аналогично group (id_group int not null, name varchar(20) ) c PK id_group А третья таблица будет содержать инфо infos (id_parthner int not null,id_group int not null, и далее вся информация: фио, №телефона). id_parthner будет FK на справочник parthner id_group будет FK на справочник group Т.о. при изменении названия группы или parthner в третьей таблице ничего меняться не будет. Всего доброго P.S. ЕСли я неправильно поняла, пишите постановку задачи. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2002, 14:06:08 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
Уважаемая Ольга! Спасибо, что потрудились вникнуть в мою проблему. Задача такая: есть данные о владельцах телефонов (cd_phone_infos), которые могут входить в группы (cd_phone_groups). Связь многие ко многим, поэтому есть еще таблица связей (cd_gi_rels). Но дело в том, что вся информация хранится отдельно для каждого из "партнеров" (это организации). Проблема в том, что и владельцы, и группы должны быть привязаны к партнерам, а это может привести к тому, что появится связь между группой и владельцем телефона (в cd_gi_rels), принадлежащих разным группам. Можно было сделать на триггерах, но хотелось поизящней. Поэтому решил сделать так: PK таблицы владельцев - код партнера + номер телефона, PK таблицы групп - код партнера + код группы. Таблица связей содержит код партнера, код группы и код владельца, и получается, что 3 поля содержат ссылки на 2 ключа из двух элементов каждый. Таким образом, противоречивую информацию ввести невозможно, но поле cd_gi_rels.parthner_code участвует сразу в двух внешних ключах. Поэтому каскадное обновление обоих невозможно. (Почему, не знаю - это и было темой первого вопроса.) И теперь нельзя каскадно менять номер телефона владельца, что плохо. Хотел сделать триггер instead of update, но нельзя, если есть FK с каскадными обновлениями. В общем, плоховато получается. Почему отказался от identity? Дело в том, что identity уникальна в пределах всей таблицы, и, если таблица связей будет ссылаться на код партнера + identity группы, получится ссылка на избыточный ключ, что тоже неизящно. Если ссылаться только на identity, опять же, возможен ввод противоречивых данных. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2002, 15:21:29 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
На самом деле у вас налицо циклическая ссылка cd_parthners->cd_phone_groups ->cd_gi_rels ->cd_phone_infos | ^ |----------------------------------------------| SQL2000 не умеет(пока?) "разруливать" такие ссылки, которые кажутся на первый взгляд простыми. Прдумайте сами, если происходит обновление ключа в cd_phone_infos, то в каком порядке должны обновляться дочерние ключи ? - сразу в cd_phone_infos ? а как же тогда cd_phone_groups ->cd_gi_rels ->cd_phone_infos, и что будет обновляться в этой "цепочке", если cd_phone_infos уже обновлена ? - или наоборот ? Но это не поменяет сути "конфликта" Так что на данный момент придется принять, что такие ссылки с каскадными обновлением/удалением создать невозможно. Что касается вашей задачи, то посоветую следующее. Взгляните на "партнера" как одну обязательную "группу", состоящую только из этого "партнера" и с опционной возможностью входить в другие "группы". Налицо избыточность, которая однако позволит "избавиться" от циклической ссылки и значит импользовать каскадные операции ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2002, 16:16:29 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
Уважаемый AlexP! Пожалуста, давайте сформулируем еще раз. 1.Есть №телефона, у которого один владелец. 2. Телефон входит сразу в несколько групп. 3. Несколько групп входят в одну организацию или же в несколько организаций? >И теперь нельзя каскадно менять номер телефона владельца Да НЕ НАДО каскадно менять номер телефона владельца!!! Я понимаю, что у телефона может помяняться владелец (ФИО), а также телефон можно выбросить из группы, организации или добавить в группу, организацию? >Связь многие ко многим, поэтому есть еще таблица связей (cd_gi_rels). Такие вещи иногда делают как таблицу индексных (ключевых) ссылок, но НЕ ТАЩАТ туда номер телефона владельца, это избыточно!!! Вы же сами пишете:"Таблица связей содержит код партнера, код группы и код владельца" Т.е. эта таблица содержит только ключи (владельца, группы, организации), но не саму информацию о них. А ключики, как договорились INT (id_code, id_group, id_phone) (И триггеров не надо) Т.е сделайте 3 справочные таблицы и одну, реализующую связь многие ко многим. Первая генерирует ключик владельца (правда с оговоркой что все-таки сущность?- владелец или его номер телефона, т.е. или телефон закрепляется за группами и организациями или фио) Вторая генерирует ключик группы Третья ключик организации А последняя все ключики собирает, т.е. какой огранизации, какой группе, какому владельцу. ПРавда, есть и другие классические решения в зависимости от Вашего ответа на третий вопрос. >Поэтому каскадное обновление обоих невозможно Нарисуйте вашу схему и посмотрите. SQL не знает, какое каскадное обновление делать первым. Всего доброго ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2002, 16:32:50 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
Еще раз приветствую. Посмотрела на вашу схему еще раз. Мне кажется, оторвите Вы таблицу cd_phone_infos от cd_parthners , ведь parthner'а для phone всегда найдете по другой ветке. Т.е. есть таблица cd_parthners и cd_phone_infos (уже БЕЗ cd_parthner_code ) . У каждого parthner'а несколько group ( таблица cd_phone_groups ). В таблице cd_phone_groups у Вас есть code (правда, текстовый, я бы дала INT )- вот и уникальный ключ, a cd_gi_rels тоже БЕЗ cd_parthner_code, а только связана с cd_phone_infos по phone, а с cd_phone_groups по code. И делайте КАСКАДНЫЕ ОБНОВЛЕНИЯ телефона!!!! Если хочется.... :-))) Желаю удачи ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 06.06.2002, 17:25:32 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
Ольга, большое спасибо за совет, но дело в том, что таблицу владельцев телефонов нельзя отвязывать от партнеров, т.к. владельцы телефонов могут и не входить ни в какие группы. А информация об одном и том же владельце телефона у разных организаций (партнеров) может быть разная. И каждая группа относится только к одной организации. Так что при связывании группы и владельца, если использовать identity, можно связать владельца и группу разных партнеров. Поэтому и включил в таблицу связей код партнера. А вообще, что касается identity, оно сильно девальвирует понятие первичного ключа. Что это за PK, который не несет НИКАКОЙ информации о сущности? Я сам до недавнего времени злоупотреблял identity, но понял, что оно годится только для таблиц, у которых по сути нет уникальных ключей (например, банковские проводки или неподробная информация о клиентах). Кстати, в книгах о БД в примерах первичные ключи обычно реальные. А больший размер внешних ключей не критичен, если записей не слишком много. Еще раз спасибо за ценные советы. Glory, спасибо большое, по-видимому, сделаю, как Вы советуете. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 07.06.2002, 15:12:11 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
AlexP: Я бы не советовал так горячиться и отказываться от искуственных ключей в пользу естественных. Во первых естественный ключ не стабилен, может изменяться, а значит вам понадобяться каскадные обновления, что есть очень плохо. Во вторых не забывайте, что частенько изменение информации фиксируется по времени. Ну и еще куча всего, что по моему обсуждалось хоть раз на всех форумах, всех сайтов, имеющих хоть какое-то отношений к SQL. Конечно не надо всегда совать в каждую таблицу Identity. Например если в таблица служит для связи обьектов у которых уже стоят искуственные ключи и изменения не фиксируются во времени, то естественно легче все эти поля обьявить ключом, чем совать туда абсолютно бесполезный Identity. Для меня самый оптимальный вариант частенько это Identity в роли первичного ключа, и Естественный ключ в роли дополнительного ключа (уникального индекса). Вариант более менее защищен от неожиданностей и уж точно не требуется никаких каскадных операций :) ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 09.06.2002, 15:15:44 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
To AlexP Мне представляется, что Вы сами неточно поставили задачу. Я Вас спрашивала, что закреплено за партнером- телефон или владелец? Оказалось, что телефоны у партнеров, а владельцы тоже у партнеров, а еще они и группируются. Так разберитесь, группируются владельцы или номера телефонов? Дело в том, что хорошая схема денных сослужит потом огромную службу при выборках по различным критериям. Та первоначальная схема, даже без каскадного обновления, будет не удобна для построения запросов. Вы уже на этапе проектирования столкнулись с проблемами и обратились на формум. Так вот либо в таблице cd_phone_infos или cd_phone_groups теория просит генерации искусственного ключа. (Т.е. все возможные группы всех организаций имеют уникальный номер или телефон вместе с владельцем - это уникум). И против этого трудно уклониться :-( Между прочим как поменять телефоны двум владельцам между собой (или наоборот двум телефонам владельцев) из разных организаций? Что-то мне подсказывает, что может Вам отдельно нужна таблица владельцев, отдельно таблица телефонов, и таблица связей между ними? А организации, группы - это только классифицирующая информация? Желаю успехов ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 10.06.2002, 16:19:06 |
|
||
|
Не догоняю
|
|||
|---|---|---|---|
|
#18+
Добрый день, прошу прощения за молчание: был в отпуске неделю. ASCRUS, Ольга, спасибо за советы. Действительно, искусственный ключ + уникальный индекс - хороший способ, им я до этого и пользовался, но захотел попробовать без избыточных полей. Не получается - сложно и неудобно. Воспользуюсь привычным identity, и группировать будет просто. Еще раз большое спасибо. ... |
|||
|
:
Нравится:
Не нравится:
|
|||
| 17.06.2002, 11:05:39 |
|
||
|
|

start [/forum/topic.php?fid=46&fpage=3465&tid=1822335]: |
0ms |
get settings: |
8ms |
get forum list: |
14ms |
check forum access: |
3ms |
check topic access: |
3ms |
track hit: |
269ms |
get topic data: |
10ms |
get forum data: |
2ms |
get page messages: |
47ms |
get tp. blocked users: |
1ms |
| others: | 197ms |
| total: | 554ms |

| 0 / 0 |
