Внешний ключ Mysql не уникальным ключом - как это возможно? - PullRequest
7 голосов
/ 02 марта 2010

Я переносил базу данных mysql на postgres и наткнулся на следующий блок в DDL (Примечание: это то, что я получил из mysqldump):

CREATE TABLE `catalog_property_value` (
  `id` int(10) unsigned NOT NULL,
  `property_id` int(10) unsigned NOT NULL,
  `sort` int(10) unsigned NOT NULL,
  `value_number` decimal(15,5) DEFAULT NULL,
  `value_string` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`,`sort`),
  KEY `FK_catalog_property_value` (`property_id`),
  KEY `NewIndex1` (`id`),
  CONSTRAINT `FK_catalog_property_value` FOREIGN KEY (`property_id`) REFERENCES `catalog_property` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
SET character_set_client = @saved_cs_client;

CREATE TABLE `catalog_realty_property_value_link` (
  `realty_id` int(10) unsigned NOT NULL,
  `property_id` int(10) unsigned NOT NULL,
  `value_id` int(10) unsigned NOT NULL,
  `dt_is_denormalized` tinyint(1) unsigned NOT NULL,
  PRIMARY KEY (`realty_id`,`property_id`,`value_id`),
  KEY `FK_catalog_realty_property_value_link_property` (`property_id`),
  KEY `FK_catalog_realty_property_value_link_value` (`value_id`),
  CONSTRAINT `FK_catalog_realty_property_value_link_property` FOREIGN KEY (`property_id`) REFERENCES `catalog_property` (`id`) ON DELETE CASCADE,
  CONSTRAINT `FK_catalog_realty_property_value_link_realty` FOREIGN KEY (`realty_id`) REFERENCES `catalog_realty` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
  CONSTRAINT `FK_catalog_realty_property_value_link_value` FOREIGN KEY (`value_id`) REFERENCES `catalog_property_value` (`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Теперь я вижу, что единственным уникальным ключом в первой таблице является комбинация (id, sort):

PRIMARY KEY (`id`,`sort`),

однако, вторая таблица имеет ссылку на первую только по столбцу id, который не является уникальным!

CONSTRAINT `FK_catalog_realty_property_value_link_value` FOREIGN KEY (`value_id`) REFERENCES `catalog_property_value` (`id`) ON DELETE CASCADE

Итак, что я здесь не так понял? Как это возможно?

Ответы [ 4 ]

8 голосов
/ 04 марта 2010

Из руководства:

Отклонение от стандартов SQL : A Ограничение FOREIGN KEY, которое ссылается неуникальный ключ не является стандартным SQL. Это расширение InnoDB к стандарту SQL.

Похоже, что InnoDB допускает неуникальные индексы в качестве кандидатов для ссылок на внешние ключи. В другом месте руководства говорится, что вы можете ссылаться на подмножество столбцов в ссылочном индексе до тех пор, пока ссылочные столбцы перечислены первыми и в том же порядке, что и первичный ключ.

Следовательно, это определение является законным в InnoDB, хотя это не стандартный SQL и оставляет меня, по крайней мере, немного смущенным намерениями первоначального дизайнера.

Страница руководства здесь .

2 голосов
/ 04 марта 2010

Странное поведение FK в innoDB описано в руководстве .

Обработка ссылок на внешние ключи на неуникальные ключи или ключи которые содержат значения NULL не хорошо определено для таких операций, как ОБНОВЛЕНИЕ или УДАЛИТЬ КАСКАД. Вам рекомендуется использовать внешние ключи, которые ссылаются только на УНИКАЛЬНЫЕ и НЕ НУЛЬНЫЕ ключи.

PostgreSQL не принимает эту конструкцию, внешний ключ должен указывать на уникальный ключ.

0 голосов
/ 02 марта 2010

Наиболее вероятным ответом является то, что идентификатор действительно уникален в таблице catalog_propery_value, но автор объявил PK как суперключ (id, sort) по неизвестным причинам, возможно, связанным с индексацией, а не с применением уникальности.

0 голосов
/ 02 марта 2010

Это совершенно законно, согласно Википедии :

Столбцы в справочной таблице должен быть первичным ключом или другим ключ-кандидат в ссылочной таблице.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...