Как вы управляете отношениями с внешними ключами для вновь созданных ключей? - PullRequest
0 голосов
/ 06 марта 2020

Фон

У меня есть две таблицы Parent и Child. Отношение это один-ко-многим родительским идентификаторам для дочерних идентификаторов. Итак, чтобы оптимизировать стандартные JOIN запросы, я рассматриваю определение внешнего ключа с помощью

ALTER TABLE Child
  ADD CONSTRAINT FOREIGN KEY
  parent_id
  REFERENCES Parent (id);

, где Parent.id - это PRIMARY KEY. Не устанавливая явно условия ON UPDATE или ON DELETE, я считаю, что я неявно установил значение по умолчанию

ON DELETE NO ACTION
ON UPDATE NO ACTION

для MySQL 8.0 Документация . Обратите внимание, что Child.parent_id проиндексирован.

Но ситуация такова, что таблица Child будет часто обновляться до таблицы Parent и иногда будет иметь новые данные, касающиеся Parent с неизвестными внешними ключами Child.parent_id. Это связано с тем, что таблица Child представляет собой почти мгновенный журнал записей, подобных транзакциям, которые являются единственным входом в базу данных; таблица Parent является производной и сводной сводкой таблицы Child, задача которой обновляться каждые несколько часов.

Теперь, читая другие посты, я прочитал, что для FOREIGN KEY требуется ссылка столбец родительской таблицы должен быть уникальным и существовать . Ясно, что у меня нет проблем с уникальностью, поскольку мой родительский столбец, на который есть ссылка, - PRIMARY KEY, моя проблема - существование ссылочного значения. В вопросе: что происходит, когда я вставляю новую запись в таблицу Child, которая содержит невиданное ранее Child.parent_id?

Эксперимент

Я проверил это на двух меньших таблицах, обе созданы по образцу больших таблиц, которые я буду sh оптимизировать (с CREATE TABLE Parent LIKE..., et c .). Наименование этих тестовых таблиц такое, как описано выше. С созданием этих небольших тестовых таблиц я определил FOREIGN KEY в тестовых таблицах точно так же, как и выше.

Итак Parent выглядит примерно так:

| id    | SummaryStat1 | SummaryStat2 | ... | SummaryStatN        |
|-------|--------------|--------------|-----|---------------------|
| 147   | 50.4         | 1999983      | ... | NULL                |
| 99384 | 60.8         | 3592324      | ... | 2018-03-05 00:22:09 |
| ...   |              |              |     |                     |

И Child как:

| id          | parent_id | Stat1 | ... | StatM               |
|-------------|-----------|-------|-----|---------------------|
| 1           | 147       | 18.3  | ... | 2018-02-17 14:23:10 |
| 2           | 99384     | 0.02  | ... | 2018-02-17 14:23:12 |
| (AUTO INCR) | ...       | ...   | ... | ...                 |
| 70565       | 147       |       |     | 2018-02-18 16:59:00 |
| ...         | ...       | ...   | ... | ...                 |

Итак, после установки FOREIGN KEY я вставил новый сделайте запись в Child с невиданным ранее Child.parent_id, и база данных выдаст ожидаемую жалобу:

"Cannot add or update a child row: a foreign key constraint fails..."

Есть ли для этого известная работа? Я подумываю об изменении процесса транзакции для вставки записи Parent по умолчанию с новой Parent.id перед отправкой данных в таблицу Child, но было бы неплохо, если бы существовала простая БД решение, как опция, которая позволяет хранить значения отключенного внешнего ключа, пока родительский внешний ключ не появится в родительской таблице.

1 Ответ

1 голос
/ 13 марта 2020

Нет «простого» решения.

BEGIN;
INSERT INTO parent ...
    ON DUPLICATE KEY UPDATE
        id = LAST_INSERT_ID(id);
$parent_id = SELECT LAST_INSERT_ID();
INSERT INTO child
    ( ..., parent_id, ... )
    VALUES
    ( ..., $parent_id, ... )
COMMIT;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...