Гость
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / foreign key on update cascade / 25 сообщений из 45, страница 1 из 2
10.02.2018, 11:19
    #39599942
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Привет.

Вопрос по каскадным обновлениям внешнего ключа.

Структура БД:

Таблица поставщиков:
Код: sql
1.
2.
3.
4.
5.
6.
7.
create table SUPPLIER (
    SUPPLIER  varchar( 10 ) not null
);

alter table SUPPLIER
  add constraint PK_SUPPLIER
      primary key ( SUPPLIER );



Таблица продукции (обновляемый внешний ключ на поставщиков):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
create table PRODUCT (
    SUPPLIER  varchar( 10 ) not null,
    PRODUCT   varchar( 10 ) not null
);

alter table PRODUCT
  add constraint PK_PRODUCT
      primary key ( SUPPLIER, PRODUCT );

alter table PRODUCT
  add constraint FK_PRODUCT_SUPPLIER
      foreign key ( SUPPLIER )
      references SUPPLIER ( SUPPLIER ) on update cascade;



Таблица поставок продукции (обновляемый внешний ключ на поставщиков):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
create table DELIVERY (
    SUPPLIER     varchar( 10 ) not null,
    DELIVERY_NO  integer not null
);

alter table DELIVERY
  add constraint PK_DELIVERY
      primary key ( SUPPLIER, DELIVERY_NO );

alter table DELIVERY
  add constraint FK_DELIVERY_SUPPLIER
      foreign key ( SUPPLIER )
      references SUPPLIER ( SUPPLIER ) on update cascade;



Таблица стоимости продукции в рамках поставок (обновляемый внешний ключ на поставки и продукцию):
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
create table COST (
    SUPPLIER     varchar( 10 ) not null,
    PRODUCT      varchar( 10 ) not null,
    DELIVERY_NO  integer not null,
    PRICE        float
);

alter table COST
  add constraint PK_COST
      primary key ( DELIVERY_NO, PRODUCT, SUPPLIER );

alter table COST
  add constraint FK_COST_DELIVERY
      foreign key ( SUPPLIER, DELIVERY_NO )
      references DELIVERY ( SUPPLIER, DELIVERY_NO ) on update cascade;

alter table COST
  add constraint FK_COST_PRODUCT
      foreign key ( SUPPLIER, PRODUCT )
      references PRODUCT ( SUPPLIER, PRODUCT ) on update cascade;



Добавим данные:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
insert into SUPPLIER (
    SUPPLIER )
values ( 'ITNEL' );

insert into PRODUCT (
    SUPPLIER,
    PRODUCT )
values ( 'ITNEL', 'PENTIUM-1' );

insert into PRODUCT (
    SUPPLIER,
    PRODUCT )
values ( 'ITNEL', 'CORE I7' );

insert into DELIVERY (
    SUPPLIER,
    DELIVERY_NO )
values ( 'ITNEL', 1 );

insert into COST (
    SUPPLIER,
    PRODUCT,
    DELIVERY_NO,
    PRICE )
values ( 'ITNEL', 'PENTIUM-1', 1, 100 );

insert into COST (
    SUPPLIER,
    PRODUCT,
    DELIVERY_NO,
    PRICE )
values ( 'ITNEL', 'CORE I7', 1, 280 );

commit;



Ошибка в имени поставщика, пытаемся исправить 'ITNEL' на 'INTEL':
Код: sql
1.
2.
3.
update SUPPLIER
   set SUPPLIER = 'INTEL'
 where SUPPLIER = 'ITNEL';



Ошибка:
Код: powershell
1.
2.
3.
4.
5.
6.
violation of FOREIGN KEY constraint "".
violation of FOREIGN KEY constraint "FK_COST_DELIVERY" on table "COST".
Foreign key reference target does not exist.
Problematic key value is ("SUPPLIER" = 'INTEL', "DELIVERY_NO" = 1).
At trigger 'CHECK_4'
At trigger 'CHECK_1'.



Видимо, при последовательном обновлении одного из внешних ключей таблицы COSTS возникает "violation of FOREIGN KEY constraint" для другого внешнего ключа.

Удаляем любой из внешних ключей (например, FK_COST_DELIVERY), обновляем поставщика, восстанавливаем внешний ключ:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
alter table COST
  add drop FK_COST_DELIVERY;

update SUPPLIER
   set SUPPLIER = 'INTEL'
 where SUPPLIER = 'ITNEL';

alter table COST
  add constraint FK_COST_DELIVERY
      foreign key ( SUPPLIER, DELIVERY_NO )
      references DELIVERY ( SUPPLIER, DELIVERY_NO ) on update cascade;


Ошибок не возникает, внешний ключ накладывается.

Скрипт воспроизведения:

create table SUPPLIER (
SUPPLIER varchar( 10 ) not null
);

alter table SUPPLIER
add constraint PK_SUPPLIER
primary key ( SUPPLIER );

create table PRODUCT (
SUPPLIER varchar( 10 ) not null,
PRODUCT varchar( 10 ) not null
);

alter table PRODUCT
add constraint PK_PRODUCT
primary key ( SUPPLIER, PRODUCT );

alter table PRODUCT
add constraint FK_PRODUCT_SUPPLIER
foreign key ( SUPPLIER )
references SUPPLIER ( SUPPLIER ) on update cascade;

create table DELIVERY (
SUPPLIER varchar( 10 ) not null,
DELIVERY_NO integer not null
);

alter table DELIVERY
add constraint PK_DELIVERY
primary key ( SUPPLIER, DELIVERY_NO );

alter table DELIVERY
add constraint FK_DELIVERY_SUPPLIER
foreign key ( SUPPLIER )
references SUPPLIER ( SUPPLIER ) on update cascade;

create table COST (
SUPPLIER varchar( 10 ) not null,
PRODUCT varchar( 10 ) not null,
DELIVERY_NO integer not null,
PRICE float
);

alter table COST
add constraint PK_COST
primary key ( DELIVERY_NO, PRODUCT, SUPPLIER );

alter table COST
add constraint FK_COST_DELIVERY
foreign key ( SUPPLIER, DELIVERY_NO )
references DELIVERY ( SUPPLIER, DELIVERY_NO ) on update cascade;

alter table COST
add constraint FK_COST_PRODUCT
foreign key ( SUPPLIER, PRODUCT )
references PRODUCT ( SUPPLIER, PRODUCT ) on update cascade;


insert into SUPPLIER (
SUPPLIER )
values ( 'ITNEL' );

insert into PRODUCT (
SUPPLIER,
PRODUCT )
values ( 'ITNEL', 'PENTIUM-1' );

insert into PRODUCT (
SUPPLIER,
PRODUCT )
values ( 'ITNEL', 'CORE I7' );

insert into DELIVERY (
SUPPLIER,
DELIVERY_NO )
values ( 'ITNEL', 1 );

insert into COST (
SUPPLIER,
PRODUCT,
DELIVERY_NO,
PRICE )
values ( 'ITNEL', 'PENTIUM-1', 1, 100 );

insert into COST (
SUPPLIER,
PRODUCT,
DELIVERY_NO,
PRICE )
values ( 'ITNEL', 'CORE I7', 1, 280 );

commit;

update SUPPLIER
set SUPPLIER = 'INTEL'
where SUPPLIER = 'ITNEL';

/*
violation of FOREIGN KEY constraint "".
violation of FOREIGN KEY constraint "FK_COST_DELIVERY" on table "COST".
Foreign key reference target does not exist.
Problematic key value is ("SUPPLIER" = 'INTEL', "DELIVERY_NO" = 1).
At trigger 'CHECK_4'
At trigger 'CHECK_1'.
*/

alter table COST
add drop FK_COST_DELIVERY;


update SUPPLIER
set SUPPLIER = 'INTEL'
where SUPPLIER = 'ITNEL';

alter table COST
add constraint FK_COST_DELIVERY
foreign key ( SUPPLIER, DELIVERY_NO )
references DELIVERY ( SUPPLIER, DELIVERY_NO ) on update cascade;


Вопрос: это ошибка каскадного обновления внешних ключей или кривая структура БД?

Если кривая структура БД, какой структурой можно обеспечить каскадное обновление внешних ключей?

С уважением, Poleosv.
...
Рейтинг: 0 / 0
10.02.2018, 11:43
    #39599945
Ivan_Pisarevsky
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
PolesovЕсли кривая структура БД, какой структурой можно обеспечить каскадное обновление внешних ключей?Если в принципе требуется каскадный апдейт ключей - такая структура никуда не годится.

Первичный ключ не должен нести на себе никаких других функций, кроме ключа, никаких названий, намеков, ИНН-ов и прочей ерунды. Ключ это просто 64 битной число - идентификатор. Его апдейтить не надо ни при каких обстоятельствах.
...
Рейтинг: 0 / 0
10.02.2018, 11:54
    #39599950
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Ivan_PisarevskyЕсли в принципе требуется каскадный апдейт ключей - такая структура никуда не годится.
Понятно, в такой структуре исправление ошибки э-э-э ... весьма затруднительно.

Заменим primary key на unique not null - смена шила на мыло?
...
Рейтинг: 0 / 0
10.02.2018, 11:59
    #39599951
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Polesovсмена шила на мыло?

Вовсе нет.

Но вопрос остается открытым - каскадное обновление внешних ключей на некоторых структурах не возможно?

P.S. Вопрос прямоты/кривизны структуры не рассматривается.
...
Рейтинг: 0 / 0
10.02.2018, 12:39
    #39599957
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Polesov,

бывают случаи, что так увлекаются каскадами, что зацикливают каскадные ФК, например на удаление. Эффект потрясающий - удаляем одну запись, и в результате удаляется почти ВСЁ.

Сам вопрос про каскадные ключи, конечно, интересный, но так не делают, потому что
- в реальной БД изменение одного значения в SUPPLIER приводит к каскадному апдейту миллионов записей в разных таблицах
- потому естественные ПК и не используют. Абстрактный ПК нет смысла изменять, потому что он ничего не значит. А следовательно, необходимость в каскадном обновлении отпадает.
...
Рейтинг: 0 / 0
10.02.2018, 12:47
    #39599959
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Polesov,

собственно, ошибка структуры в том, что COST ссылается на ДВЕ таблицы, которые зависят от SUPPLIER, и при каскадном обновлении от SUPPLIER не могут быть обновлены ОДНОВРЕМЕННО.
Так что тут нет ошибки с ФК, есть ошибка структуры.
...
Рейтинг: 0 / 0
10.02.2018, 12:48
    #39599960
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
kdvбывают случаи, что так увлекаются каскадами
Вопрос не про излишнее увлечение каскадными обновлениями, а про факт возникновения ошибки при каскадном обновлении внешних ключей.

P.S. Вопрос - при использовании некой фичи FB возникает ошибка. Ответ - не используй эту фичу. (!!!!!!!)

Народ, вопрос не про ошибки в структуре БД, а про ошибки FB.
Feel difference, какгриться.
...
Рейтинг: 0 / 0
10.02.2018, 12:53
    #39599961
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
kdvCOST ссылается на ДВЕ таблицы, которые зависят от SUPPLIER
FB каскадное обновление таки внешних ключей не поддерживает?
Это отображено где-нибудь в документации?
...
Рейтинг: 0 / 0
10.02.2018, 13:37
    #39599969
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
PolesovFB каскадное обновление таки внешних ключей не поддерживает?
а кто поддерживает? Что значит "поддерживает"? Я вот тебя спрашиваю - как ты обновишь две таблицы одновременно?
Или как - парсер должен отвергать второй ФК на таблицу COST, потому что парсер обнаружит ссылку на одну и ту же таблицу через 2 косвенных ФК? А через 3 ФК?
С точки зрения ФК вообще - он построен нормальным образом. Другое дело, что ты связал таблицы таким образом, что каскадное обновление ФК в данном случае приводит к ошибке.
PolesovЭто отображено где-нибудь в документации?
мне интересно, каким образом это может или должно быть отражено.
...
Рейтинг: 0 / 0
10.02.2018, 13:41
    #39599970
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
kdvмне интересно, каким образом...Понятно - не используй эту фичу.


Я думаю, ответ на этот вопрос могут дать только разработчики.

Все остальные - от лукавого.
...
Рейтинг: 0 / 0
10.02.2018, 13:42
    #39599971
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
PolesovНарод, вопрос не про ошибки в структуре БД, а про ошибки FB.
это не ошибка ФБ. ФК в данном случае отрабатываются поочередно. Потому что это "системные триггеры". Если на таблице 5 триггеров, то они не срабатывают все одновременно. Они отрабатывают по одному. Да, у ФБ вот такая реализация. Ты напоролся на нее.
PolesovОтвет - не используй эту фичу.
да, потому что в такой схеме, которую ты построил, так - не работает.

Даже если бы работало, у тебя все равно, с моей точки зрения, ФК с COST неправильные.
...
Рейтинг: 0 / 0
10.02.2018, 13:44
    #39599972
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
kdvс моей точки зрения, ФК с COST неправильные
Polesovкакой структурой можно обеспечить каскадное обновление внешних ключей?
...
Рейтинг: 0 / 0
10.02.2018, 13:49
    #39599973
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Каскадные ФК - зло. Их не надо использовать нигде и никогда.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
10.02.2018, 13:55
    #39599977
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Dimitry SibiryakovКаскадные ФК - зло. Их не надо использовать нигде и никогда.

Я бы не рискнул так заявить моему начальнику.
...
Рейтинг: 0 / 0
10.02.2018, 13:55
    #39599978
foreign key on update cascade
Polesov,

у вас "ромб": таблица cost будет обноалвять двумя каскадами.
В ФБ такой DDL молча пропускается и проблемы лезут позже, а вот в m$ sql - облом сразу .

В общем, это скорее не ошибка, а особенность реализации СУБД.
...
Рейтинг: 0 / 0
10.02.2018, 14:01
    #39599979
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Да кто его разберёт...В ФБ такой DDL молча пропускается и проблемы лезут позжеАпчемиречь...

Да кто его разберёт...В общем, это скорее не ошибка, а особенность реализации СУБД.Понятно, что можно изменить структуру БД (суррогатный PK + not null unique по наименованию), но в случае с естественным PK ...
...
Рейтинг: 0 / 0
10.02.2018, 14:01
    #39599980
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
PolesovЯ бы не рискнул так заявить моему начальнику.

Твоя трусость - твоя проблема.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
10.02.2018, 14:08
    #39599982
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Да кто его разберёт...
http://www.sql.ru/forum/899636/introducing-foreign-key-constraint-on-table-may-cause-cycles-or-multiple-cascade-paths

Хороший вопрос:
Ex_SoftЭто M$ SQL такую структуру штатными средствами одолеть не может или вопрос плавно переходит в Проектирование БД?
...
Рейтинг: 0 / 0
10.02.2018, 14:09
    #39599983
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Dimitry SibiryakovТвоя трусость - твоя проблема.
Предлагаешь сменить меcто работы, храбрец?
...
Рейтинг: 0 / 0
10.02.2018, 14:10
    #39599984
kdv
kdv
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
PolesovЯ бы не рискнул так заявить моему начальнику.
хочешь, я рискну?
Собственно, я уже сказал - 21181802

к тому же, MS SQL сразу посылает с такой хренью. 21181894

PolesovПонятно, что можно изменить структуру БД (суррогатный PK + not null unique по наименованию), но в случае с естественным PK
да не использует никто естественные ПК в здравом уме. Разве что те, кто еще не напоролся на проблемы "начальной школы проектирования БД".
http://www.ibase.ru/natural-keys-versus-atrificial-keys-by-tentser/
https://habrahabr.ru/company/oleg-bunin/blog/348172/#choice

И правило тут простое - если значение столбца может со временем меняться, то это уже не ПК.
...
Рейтинг: 0 / 0
10.02.2018, 14:14
    #39599986
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
kdvда не использует никто естественные ПК
Можно ли сказать, что в системных таблицах FB поля RDB$RELATION_NAME, RDB$FIELD_NAME являются суррогатными, а не естественными ключами?
...
Рейтинг: 0 / 0
10.02.2018, 14:14
    #39599987
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Polesovnot null unique по наименованию

Все нубы стремятся наложить ограничение уникальности на название, имя и т.п. С опытом
эксплуатации таких систем приходит понимание, что это плохая идея и в реальности не работает.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
10.02.2018, 14:15
    #39599988
d7i
d7i
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Структура БД неверна, грубо говоря, в корне.
Если субъект (поставщик, клиент и т.п.) имеет цифровое имя (код) и он может изменяться, это имя должно быть представлено отдельным полем. Его использование в качестве ФК совершенно не нужно.

Внутренний же идентификатор субъекта обычно является первичным ключом (AUTOINCREMENT) и никогда не модифицируется.
Поэтому все ФК на него не должны быть UPDATE, только DELETE. С DELETE тоже есть масса нюансов, но это уже другая песня...
...
Рейтинг: 0 / 0
10.02.2018, 14:16
    #39599989
Dimitry Sibiryakov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
PolesovПредлагаешь сменить меcто работы, храбрец?

Предлагаю разобраться: кто именно проектирует БД - ты или начальник. Если начальник, то
почему на форуме ты а не он?
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
10.02.2018, 14:16
    #39599990
Polesov
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
foreign key on update cascade
Dimitry SibiryakovPolesovnot null unique по наименованию

Все нубы стремятся наложить ограничение уникальности на название, имя и т.п. С опытом
эксплуатации таких систем приходит понимание, что это плохая идея и в реальности не работает.

Ну, сказать, что "все нубы..."
Тогда уж озвучь, как правильно.
...
Рейтинг: 0 / 0
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / foreign key on update cascade / 25 сообщений из 45, страница 1 из 2
Целевая тема:
Создать новую тему:
Автор:
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]