Ошибка № 150 mySQL - PullRequest
       9

Ошибка № 150 mySQL

3 голосов
/ 03 июня 2010

Это заставляет меня потеть - я получаю ошибку 150, когда пытаюсь создать таблицу в mySQL. Я обыскивал форумы безрезультатно. В операторе используются ограничения внешнего ключа - обе таблицы InnoDB, все соответствующие столбцы имеют одинаковый тип данных, и обе таблицы имеют одинаковые набор символов и параметры сортировки. Вот CREATE TABLE и исходный оператор CREATE TABLE для таблицы, на которую ссылаются. Есть идеи?

Новая таблица:

CREATE TABLE `approval` (
  `rev_id` int(10) UNSIGNED NOT NULL,
  `rev_page` int(10) UNSIGNED NOT NULL,
  `user_id` int(10) UNSIGNED NOT NULL,
  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY  (`rev_id`,`rev_page`,`user_id`),
  KEY `FK_approval_user` (`user_id`),
  CONSTRAINT `FK_approval_revision` FOREIGN KEY (`rev_id`, `rev_page`) REFERENCES `revision` (`rev_id`, `rev_page`),
  CONSTRAINT `FK_approval_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Ссылочная таблица:

CREATE TABLE `revision` (
  `rev_id` int(10) unsigned NOT NULL auto_increment,
  `rev_page` int(10) unsigned NOT NULL,
  `rev_text_id` int(10) unsigned NOT NULL,
  `rev_comment` tinyblob NOT NULL,
  `rev_user` int(10) unsigned NOT NULL default '0',
  `rev_user_text` varbinary(255) NOT NULL default '',
  `rev_timestamp` binary(14) NOT NULL default '\0\0\0\0\0\0\0\0\0\0\0\0\0\0',
  `rev_minor_edit` tinyint(3) unsigned NOT NULL default '0',
  `rev_deleted` tinyint(3) unsigned NOT NULL default '0',
  `rev_len` int(10) unsigned default NULL,
  `rev_parent_id` int(10) unsigned default NULL,
  PRIMARY KEY  (`rev_id`),
  UNIQUE KEY `rev_page_id` (`rev_page`,`rev_id`),
  KEY `rev_timestamp` (`rev_timestamp`),
  KEY `page_timestamp` (`rev_page`,`rev_timestamp`),
  KEY `user_timestamp` (`rev_user`,`rev_timestamp`),
  KEY `usertext_timestamp` (`rev_user_text`,`rev_timestamp`)
) ENGINE=InnoDB AUTO_INCREMENT=4904 DEFAULT CHARSET=binary MAX_ROWS=10000000 AVG_ROW_LENGTH=1024;

Ответы [ 4 ]

4 голосов
/ 03 июня 2010

Эта ошибка обычно связана с ограничениями внешнего ключа. Выполните show innodb status и найдите раздел LATEST FOREIGN KEY ERROR , чтобы получить более конкретное объяснение.

Вот что я получаю при создании второй таблицы:

Ошибка в ограничении внешнего ключа тестирование / утверждение таблицы: FOREIGN KEY (rev_id, rev_page) ССЫЛКИ revision (rev_id, rev_page),
ОГРАНИЧЕНИЕ FK_approval_user ИНОСТРАННЫЙ КЛЮЧ (user_id) ССЫЛКИ user (user_id)) ENGINE = InnoDB DEFAULT CHARSET = latin1: не удается найти индекс в ссылочной таблице, где указанные столбцы отображаются как первые столбцы или типы столбцов в таблице и ссылочная таблица не совпадает для ограничения.

2 голосов
/ 03 июня 2010

Обновление: я должен был быть слепым:

Причина, по которой ваша таблица не работает, заключается в том, что ваш ключ "rev_page_id" находится в неправильном порядке (innodb требует, чтобы ключ был в том же порядке, что и внешний ключ:

CREATE TABLE `revision` (
  `rev_id` int(10) unsigned NOT NULL auto_increment,
  ....
  `rev_parent_id` int(10) unsigned default NULL,
  PRIMARY KEY  (`rev_id`),
  -- wrong:
  -- UNIQUE KEY `rev_page_id` (`rev_page`,`rev_id`), 
  -- better:
  UNIQUE KEY `rev_page_id` (`rev_id`, `rev_page`),
  ....

Пожалуйста, игнорируйте предложение ниже:


Попробуйте

SHOW ENGINE INNODB STATUS

Ищите что-нибудь. как "LAST INNODB FOREIGN KEY ERROR" К сожалению, сообщение об ошибке в большинстве случаев не очень интуитивно понятно. Поскольку вы сказали, что типы все одинаковые, я думаю, это может быть следующая ошибка:

  • Имя FK уже существует (имена FK должны быть уникальными для всей базы данных). Чтобы быть правдой, они должны быть уникальными для всего экземпляра mysql, но внутренне innodb добавляет имя базы данных к имени внешнего ключа (FK_approval_user внутренне называется yourdbname # FK_approval_user)

Обновление:

Похоже, вам не хватает ключа для "FK_approval_revision"

Должно выглядеть так:

CREATE TABLE `approval` (
  `rev_id` int(10) UNSIGNED NOT NULL,
  `rev_page` int(10) UNSIGNED NOT NULL,
  `user_id` int(10) UNSIGNED NOT NULL,
  `date` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY  (`rev_id`,`rev_page`,`user_id`),
  KEY `FK_approval_user` (`user_id`),
  KEY `FK_approval_revision` (`rev_id`, `rev_page`),
  CONSTRAINT `FK_approval_revision` FOREIGN KEY (`rev_id`, `rev_page`) REFERENCES `revision` (`rev_id`, `rev_page`),
  CONSTRAINT `FK_approval_user` FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;
1 голос
/ 03 июня 2010

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

FOREIGN KEY (`rev_page`,`rev_id`) REFERENCES `revision` (`rev_page`,`rev_id`)

Ваш исходный запрос не работает, потому что порядок полей должен быть таким же, как в уникальном индексе. Однако добавление столбца rev_page в ограничение является излишним (revision.rev_id + revision.rev_page является уникальным на 100% без ограничения уникальности, поскольку revision.rev_id сам по себе уникален). Так что вам не нужен уникальный ключ на (revision.rev_id + revision.rev_page), и было бы намного лучше, если вы измените ограничение на

FOREIGN KEY (`rev_id`) REFERENCES `revision` (`rev_id`)
0 голосов
/ 16 сентября 2011

показать статус innodb

этот cmd очень помогает

...