Прежде всего, я не очень разбираюсь в дизайне базы данных. У меня есть таблица хэшей и идентификаторов. Когда добавляется группа новых хешей, каждая строка в группе получает одинаковый идентификатор. Если какой-либо хэш в новой группе уже существует в базе данных, все хэш в новой группе и существующая группа (ы) получить новый, общий идентификатор (фактически объединение идентификаторов, когда хэш повторяются):Игнорировать каскад при обновлении внешнего ключа?
INSERT INTO hashes
(id, hash)
VALUES
($new_id, ...), ($new_id, ...)
ON DUPLICATE KEY UPDATE
repeat_count = repeat_count + 1;
INSERT INTO hashes_lookup SELECT DISTINCT id FROM hashes WHERE hash IN (...);
UPDATE hashes JOIN hashes_lookup USING (id) SET id = '$new_id';
TRUNCATE TABLE hashes_lookup;
Других столы ссылайтесь на эти идентификаторы, так что, если идентификатор изменяется, ограничения внешнего ключа заботятся об обновлении идентификаторов между таблицами. Проблема здесь, однако, заключается в том, что я не могу обеспечить уникальность в любой из дочерних таблиц. Если я делаю, мои запросы не с:
ограничение внешнего ключа для таблицы «...„ запись“...» приведет к дубликата записи в таблице «...»
Эта ошибка имеет смысл, учитывая следующее испытание случай, когда id
и value
являются составной уникальный ключ:
id | value
---+-------
a | 1
b | 2
c | 1
Затем a
получает изменено на c
:
id | value
---+-------
c | 1
b | 2
c | 1
Но c,1
уже существует.
Было бы идеально, если бы была опция ON UPDATE IGNORE CASCADE
, поэтому, если существует повторяющаяся строка, любые дублирующие вставки игнорируются. Тем не менее, я уверен, что реальная проблема здесь - это мой дизайн базы данных, поэтому я открыт для любых предложений. Мое текущее решение заключается в том, чтобы не применять уникальность в дочерних таблицах, что приводит к множеству избыточных строк.
Edit:
CREATE TABLE `hashes` (
`hash` char(64) NOT NULL,
`id` varchar(128) NOT NULL,
`repeat_count` int(11) NOT NULL DEFAULT '0',
`insert_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
`update_timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
UNIQUE KEY `hash` (`hash`) USING BTREE,
KEY `id` (`id`) USING BTREE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
CREATE TABLE `emails` (
`id` varchar(128) NOT NULL,
`group_id` char(5) NOT NULL,
`email` varchar(500) NOT NULL,
KEY `index` (`id`) USING BTREE,
UNIQUE KEY `id` (`id`,`group_id`,`email`(255)) USING BTREE,
CONSTRAINT `emails_ibfk_1` FOREIGN KEY (`id`) REFERENCES `hashes` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=latin1
Пожалуйста, покажите определение таблиц. – Renzo
Я бы выбрал каскад обновления и вручную выполнил эту часть. Для меня эта концепция всегда играет с огнем. – Drew
@Renzo Обновлен с таблицей хешей пример дочерней таблицы, в данном случае таблицы, содержащей электронные письма. – Charlie