Внешний ключ между таблицами MySQL InnoDB не работает ... почему? - PullRequest
0 голосов
/ 22 января 2012

У меня есть следующие таблицы:

Порода (MyIsam)
изображение (InnoDB)
specie_map (InnoDB)

Таблица specie_map должна отображать изображение на вид и поэтому имеет следующие столбцы:

specie_id
image_id

Оба типа int 11, как и столбцы id в таблицах specie и image. Я знаю, что не могу создать внешний ключ между specie_id и specie => id, так как таблица specie является таблицей MyIsam. Однако я ожидаю, что можно будет создать внешний ключ между image_id и image => id.

Я могу создать этот внешний ключ, и он сохранит его, однако связанное с ним действие CASCADE не работает. Когда я удаляю изображение, оно не удаляет запись specie_map, связанную с ним. Я ожидаю, что это сработает, так как этот внешний ключ находится между таблицами InnoDB. Оба столбца проиндексированы и имеют одинаковый тип данных.

Это ограничение MySQL или я что-то не так делаю?

Обновление: в соответствии с настоящим описанием таблиц. Я обрезал неважные столбцы:

-- ----------------------------
-- Table structure for `image`
-- ----------------------------
DROP TABLE IF EXISTS `image`;
CREATE TABLE `image` (
  `id` int(11) NOT NULL auto_increment,
  `guid` char(36) default NULL,
  `title` varchar(255) NOT NULL,
  `description` text,
  `user_id` int(11) NOT NULL,
  `item_id` int(11) default NULL,
  `date_uploaded` timestamp NOT NULL default '0000-00-00 00:00:00',
  `date_created` timestamp NOT NULL default '0000-00-00 00:00:00',
  `date_modified` timestamp NOT NULL default '0000-00-00 00:00:00',
  `status` enum('softdeleted','tobedeleted','active') default 'active',

  PRIMARY KEY  (`id`),
  KEY `image_user` (`user_id`),
  KEY `image_item` (`item_id`),
  KEY `image_mod_by` (`moderated_by`),
  CONSTRAINT `image_mod_by` FOREIGN KEY (`moderated_by`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
  CONSTRAINT `image_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='stores image data (not file data)';


-- ----------------------------
-- Table structure for `specie`
-- ----------------------------
DROP TABLE IF EXISTS `specie`;
CREATE TABLE `specie` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(256) NOT NULL,
  `commonname` varchar(256) NOT NULL,
   PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=22 DEFAULT CHARSET=utf8 ROW_FORMAT=DYNAMIC;


-- ----------------------------
-- Table structure for `specie_map`
-- ----------------------------
DROP TABLE IF EXISTS `specie_map`;
CREATE TABLE `specie_map` (
  `id` int(11) NOT NULL auto_increment,
  `image_id` int(11) NOT NULL,
  `specie_id` int(11) NOT NULL,
  `user_id` int(11) NOT NULL,
  `karma` int(11) NOT NULL,
  `date_created` timestamp NOT NULL default CURRENT_TIMESTAMP on update CURRENT_TIMESTAMP,
  PRIMARY KEY  (`id`),
  KEY `image_id` (`image_id`),
  KEY `specie_id` (`specie_id`),
  CONSTRAINT `specie_map_ibfk_1` FOREIGN KEY (`image_id`) REFERENCES `image` (`id`) ON DELETE CASCADE ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Ответы [ 2 ]

2 голосов
/ 22 января 2012

Я думаю, вам следует опубликовать точные операторы DDL, которые вы использовали, когда пытались создать эти таблицы и внешний ключ. Внешние ключи между таблицами innodb работают нормально, но есть еще несколько вещей, на которые стоит обратить внимание:

0) Обе таблицы должны быть InnoDB. Это уже подчеркивалось другими авторами, и это, вероятно, является непосредственной причиной вашей проблемы.

1) тип данных столбцов-ссылок (те, которые составляют внешний ключ) и соответствующих столбцов-ссылок должны быть одинаковыми. Например, вы не можете создать ограничение внешнего ключа для столбца INT UNSIGNED для простого столбца INT.

2) если внешний ключ создается как часть таблицы DDL, обязательно поместите определение внешнего ключа в раздел ограничений, то есть ниже всех определений столбцов. Например:

CREATE TABLE parent (
    id int unsigned PRIMARY KEY
);

CREATE TABLE child (
    parent_id int unsigned
,   foreign key (parent_id) 
        references parent (id)
);

будет работать, но это:

CREATE TABLE child (
    parent_id int unsigned 
        foreign key references parent (id)
);

не будет. Он молча завершится ошибкой, потому что синтаксический анализатор MySQL игнорирует эти типы определений ограничений даже до того, как InnoDB создаст таблицу (глупо, но это так)

3) Должен быть индекс по всем указанным столбцам. Обычно ссылочные столбцы вместе составляют первичный ключ или уникальное ограничение в любом случае, но ваша задача - определить до определения внешнего ключа.

Последнее слово: если вы думаете, что ваш DDL в порядке, но вы все равно получаете сообщение об ошибке, например, так:

ERROR 1005 (HY000): Can't create table 'test.child' (errno: 150)
Warning (Code 150): Create table 'test/child' with foreign key constraint failed. There is no index in the referenced table where the referenced columns appear as the first columns.

Error (Code 1005): Can't create table 'test.child' (errno: 150)

Тогда эти ошибки могут все еще не раскрывать истинную природу ошибки (опять глупо, но это так). Чтобы пролить больше света на него, запустите эту команду сразу после вашей попытки создать внешний ключ:

SHOW ENGINE INNODB STATUS;

Это даст вам кучу информации о статусе, и один раздел там будет выглядеть так:

------------------------
LATEST FOREIGN KEY ERROR
------------------------
120122 11:38:28 Error in foreign key constraint of table test/child:
foreign key (parent_id) references parent (id) ):
Cannot find an index in the referenced table where the
referenced columns appear as the first columns, or column types
in the table and the referenced table do not match for constraint.
Note that the internal storage type of ENUM and SET changed in
tables created with >= InnoDB-4.1.12, and such columns in old tables
cannot be referenced by such columns in new tables.
See http://dev.mysql.com/doc/refman/5.5/en/innodb-foreign-key-constraints.html
for correct foreign key definition.

Как видите, это дает немного больше информации и выявляет истинную проблему, а именно: "типы столбцов в таблице и в ссылочной таблице не соответствуют ограничениям"

Поэтому, пожалуйста, опубликуйте свой фактический DDL, я уверен, что где-то там есть проблема.

2 голосов
/ 22 января 2012

Внешние ключи работают только с InnoDb в mysql.MyISAM не поддерживает их (операторы игнорируются).

И есть ли причина, по которой вы смешиваете несколько машин БД?

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