Начало » Использование СУБД » Firebird, HQbird, InterBase » Как построить FK на PK?
Как построить FK на PK? [сообщение #3489] |
Mon, 23 October 2023 18:55 |
shalamyansky
Сообщений: 150 Зарегистрирован: August 2022
|
Senior Member |
|
|
CREATE TABLE MASTER (
ID BIGINT NOT NULL
);
ALTER TABLE MASTER ADD CONSTRAINT PK_MASTER PRIMARY KEY (ID);
CREATE TABLE SLAVE (
ID BIGINT NOT NULL,
ADDITION VARCHAR(100)
);
ALTER TABLE SLAVE ADD CONSTRAINT PK_SLAVE PRIMARY KEY (ID);
ALTER TABLE SLAVE ADD CONSTRAINT FK_SLAVE FOREIGN KEY (ID) REFERENCES MASTER (ID);
В результате имеем 2 идентичных по содержанию индекса PK_SLAVE и FK_SLAVE, что выглядит напрасной тратой ресурсов.
Попытка
ALTER TABLE SLAVE ADD CONSTRAINT FK_SLAVE FOREIGN KEY (ID) REFERENCES MASTER(ID) USING INDEX PK_SLAVE;
приводит к
ALTER TABLE SLAVE failed. Index PK_SLAVE already exists.
Возможно, в случае, когда индекс FK_SLAVE таки вроде бы создался, он на самом деле не создается, а неявно используется PK_SLAVE, это было бы красиво и утешительно. Но возможно, что и нет. Как оно на самом деле, и как обойтись одним индексом?
|
|
|
|
|
|
|
|
|
Re: Как построить FK на PK? [сообщение #3506 является ответом на сообщение #3505] |
Tue, 24 October 2023 15:01 |
shalamyansky
Сообщений: 150 Зарегистрирован: August 2022
|
Senior Member |
|
|
А если (см. топик) вообще не создавать первичный ключ? У меня вполне прошло
CREATE TABLE SLAVE (
ID BIGINT NOT NULL,
ADDITION VARCHAR(100)
);
ALTER TABLE SLAVE ADD CONSTRAINT FK_SLAVE FOREIGN KEY (ID) REFERENCES MASTER (ID);
select
*
from
SLAVE
where
ID = :ID
----
PLAN (S INDEX (FK_SLAVE))
То есть, если нет PK, то, когда необходимо, подхватится FK. Все вроде бы хорошо, но индекс FK_SLAVE создается неуникальным, как хотелось бы. Но если уникальность поддерживать на логическом уровне, то вроде должно работать, нет?
|
|
|
Re: Как построить FK на PK? [сообщение #3507 является ответом на сообщение #3506] |
Tue, 24 October 2023 15:29 |
МП
Сообщений: 889 Зарегистрирован: August 2022 Географическое положение: бурятский тун...
|
Senior Member |
|
|
shalamyanskyТо есть, если нет PK, то, когда необходимо, подхватится FK. Все вроде бы хорошо, но индекс FK_SLAVE создается неуникальным, как хотелось бы. Но если уникальность поддерживать на логическом уровне, то вроде должно работать, нет? движок IB/FB умеет поддерживать уникальность только посредством соответствующего индекса.
нет UNIQUE INDEX -- нет уникальности.
зы: у Оракела есть возможность "пристегнуть" существующий индекс к создаваемому CONSTRAINT при помощи предиката USING INDEX.
у нас же, USING INDEX позволяет только задать имя создаваемого индекса для создаваемого CONSTRAINT.
|
|
|
|
|
|
|
|
Re: Как построить FK на PK? [сообщение #3513 является ответом на сообщение #3511] |
Tue, 24 October 2023 17:31 |
shalamyansky
Сообщений: 150 Зарегистрирован: August 2022
|
Senior Member |
|
|
МП писал(а) Tue, 24 October 2023 16:52
при наличии конкурирующих транзакций придётся каждый раз блокировать таблицу целиком.
Почему? Не понял. В какой момент происходит блокировка таблицы и почему? Там 2 операции - проверка (select) и вставка. Select вообще не может блокировать, а вставка... Вставка без первичного ключа блокирует всю таблицу, так, что ли? А при наличии первичного ключа не блокирует?
Провел эксперимент. Таблица без PK. В одном коннекте добавил запись, транзакцию не закрыл, в другом коннекте добавил запись, подтвердил транзакцию по второму коннекту, подтвердил транзакцию по первому коннекту. Никаких конфликтов. Не видно, чтобы кто-то что-то блокировал.
Или слово "придется" относится не к алгоритмам сервера, а к собственной "ручной" логике? Тогда не вижу необходимости блокировать, по-крайней мере, для своих задач.
[Обновления: Tue, 24 October 2023 17:36] Известить модератора
|
|
|
|
|
Re: Как построить FK на PK? [сообщение #3516 является ответом на сообщение #3489] |
Tue, 24 October 2023 18:30 |
shalamyansky
Сообщений: 150 Зарегистрирован: August 2022
|
Senior Member |
|
|
Не понимаю. Я стараюсь, но я не понимаю. Вот такая процедура для вставки
Показать скрытый текст
create or alter procedure INSERT_INTO_SLAVE(
ID bigint
)
as
begin
if( not exists(
select
ID
from
SLAVE
where
ID = :ID
) )then begin
insert into
SLAVE
( ID )
values ( :ID )
;
end
end
Все клиенты вместо
вызывают
Что тут может пойти не так? С любым уровнем изоляции и без всяких RESERVING?
P.S.
Все, понял. Виноват, протупил. Легко могут быть созданы 2 одинаковые записи. Даже проверил, могут. Вопрос снимаю.
[Обновления: Tue, 24 October 2023 18:39] Известить модератора
|
|
|
Переход к форуму:
Текущее время: Wed Dec 18 13:42:11 GMT+3 2024
Общее время, затраченное на создание страницы: 0.00949 секунд
|