Ограничение внешнего ключа должно жаловаться, но почему-то это не так - PullRequest
1 голос
/ 11 февраля 2011

У меня есть, помимо прочего, три таблицы: account, address и account_address.Таблица account_address имеет account_id и address_id.Это ваше стандартное отношение «многие ко многим».

У меня сложная ситуация, когда у меня есть запись account_address, которая указывает на account, которого не существует.Поскольку у меня есть внешний ключ на account_address.account_id, указывающий на account, этого не должно произойти, верно?

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

CREATE TABLE `account_address` (    
  `id` bigint(20) NOT NULL AUTO_INCREMENT,    
  `account_id` bigint(20) NOT NULL,    
  `address_id` bigint(20) NOT NULL,   
  `created_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',    
  `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',    
  PRIMARY KEY (`id`),    
  KEY `fk_account_address_account_id` (`account_id`),    
  KEY `fk_account_address_address_id` (`address_id`),   
  KEY `index_account_address_account_id` (`account_id`) USING BTREE,    
  KEY `index_account_address_address_id` (`address_id`) USING BTREE,    
  CONSTRAINT `fk_account_address_account_id` FOREIGN KEY (`account_id`) REFERENCES `account` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,    
  CONSTRAINT `fk_account_address_address_id` FOREIGN KEY (`address_id`) REFERENCES `address` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION    
) ENGINE=InnoDB AUTO_INCREMENT=697173 DEFAULT CHARSET=latin1

Видите?FOREIGN KEY (account_id) REFERENCES account (id).

Теперь вот несколько запросов, которые показывают, что ограничение не выполнено:

select aa.account_id
from account_address aa
where aa.address_id = 15116

Этот запрос дает мне следующий результат:

15116
37033
62325
71857
93774
119066

Так, очевидноадрес 15116 связан с шестью различными учетными записями (одна учетная запись, что интересно, имеет тот же идентификатор, что и адрес).Но проверьте это:

select * from account where id in (15116, 37033, 62325, 71857, 93774, 119066)

НЕТ результатов! Разве моя СУБД не должна была когда-нибудь сказать мне, что у меня сбой ограничения внешнего ключа?!

Я вижу только две возможности:

  1. I 'я неверно истолковываю то, что вижу
  2. Моя СУБД ведет себя некорректно

Я уверен, что надежда № 1 такова, но я не знаю, что я мог неправильно истолковать,Это загадка для меня самого высокого порядка.Любые мысли будут с благодарностью.

Ответы [ 2 ]

1 голос
/ 11 февраля 2011

Ограничение остановит любые действия, чтобы сделать что-то «злое», но не сможет ретроактивно убедиться, что все в порядке. Вы можете, как это делают многие сценарии импорта, в зависимости от порядка, в котором происходит обработка, установить проверку этих ограничений на 0.

Так что если по какой-то причине информация неверна, может возникнуть такая ситуация. Тогда ваша СУБД не будет плохо себя вести, и вы также не будете неправильно ее интерпретировать.

Так что я бы выбрал вариант 3 : некоторые операции импорта или вставки работают неправильно, возможно, с использованием "set foreign_key_checks = 0". Или это старые данные.

(из руководства:

mysql> SET foreign_key_checks = 0;
mysql> SOURCE dump_file_name;
mysql> SET foreign_key_checks = 1;

)

0 голосов
/ 11 февраля 2011

MySQL имеет переменную сервера для отключения проверки внешнего ключа - set foreign_key_checks=0, которая используется в случаях, таких как импорт файла дампа, когда таблица может иметь FK, указывающий на таблицу «позже» в дампе, который не имеет был загружен еще. Обычно это убивает импорт, хотя данные в порядке. Отключение проверок FK позволяет продолжить импорт.

Возможно, ваши отсутствующие записи были удалены в то время, когда проверка ключа была отключена. Чтобы проверить, работают ли ключи сейчас правильно, добавьте пару связанных записей и удалите одну, которая должна завершиться ошибкой из-за настройки «бездействия» на FK. Если это продолжается, то либо вы не подключены к InnoDB (возможно, он отключен и mysql автоматически преобразуется в MyISAM), проверки клавиш отключены (проверьте эту переменную сервера), либо что-то действительно испортило ваш сервер.

...