2011-05-04 1 views
8

Я создал таблицу скриптом:Ошибка "Не удается создать таблицу ..." при добавлении FOREIGN KEY

SET SQL_MODE="NO_AUTO_VALUE_ON_ZERO"; 

DROP TABLE IF EXISTS `Table1`; 
CREATE TABLE IF NOT EXISTS `Table1` (
    `id` bigint(20) NOT NULL AUTO_INCREMENT, 
    `parentId` bigint(20) DEFAULT NULL, 
    `name` varchar(1024) NOT NULL, 
    `description` varchar(16384) NOT NULL DEFAULT '', 
    `imageId` bigint(20) DEFAULT NULL, 
    PRIMARY KEY (`id`), 
    KEY `name` (`name`(255)), 
    KEY `parentId` (`parentId`), 
    KEY `imageId` (`imageId`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=27 ; 


INSERT INTO `Table1` (`id`, `parentId`, `name`, `description`, `imageId`) VALUES 
(0, NULL, 'name1', '', NULL), 
(12, 0, 'name2', '', NULL); 

Тогда я пытаюсь добавить внешний ключ:

ALTER TABLE `Table1` 
    ADD CONSTRAINT `Table1_ibfk_2` 
    FOREIGN KEY (`parentId`) REFERENCES `Table1` (`id`); 

и получить следующая ошибка:

ERROR 1005 (HY000): Can't create table 'sandbox.#sql-c28_4c' (errno: 150) 

Что не так?

Я бегу

SHOW ENGINE INNODB STATUS; 

Там Последняя FOREIGN KEY ERROR следующим образом:

------------------------ 
LATEST FOREIGN KEY ERROR 
------------------------ 
110504 22:06:55 Error in foreign key constraint of table sandbox/#sql-c28_61: 

    FOREIGN KEY (`parentId`) REFERENCES `Table1` (`id`): 
Cannot resolve table name close to: 
(`id`) 
------------ 

Но это не помогает мне понять, что это не так.

Я использую Windows Vista, MySql 5.5.11

UPDATE:

Проблема возникает при обновлении с MySql 5.0.67.

ответ

4

фон

ERROR 1005 (HY000): Can't create table 'sandbox.#sql-c28_4c' (errno: 150)

Когда команда MySQL для ALTER TABLE он действительно выполняет следующие действия:

  1. копировать данные из существующей таблицы в новую временную таблицу.
  2. Alter структуры новой временной таблицы
  3. удалить старую таблицу
  4. переименовать временную таблицу в old_table_name.

Проблема
Ваш запрос неудачу в шаге 1.
Обратите внимание, что tablenames ссылки на файлы.
На Linux tablenames чувствительны к регистру

В Windows они не чувствительны к регистру.

Ответ
Поскольку вы, очевидно, работает Linux, в случае таблицы вы REFERENCES для нужд быть такой же случай, как в определении этой таблицы, вероятно, нижний регистр.
У вас работает Windows, поэтому чувствительность к регистру не должна быть проблемой, может быть, это инструмент, который вы используете, у меня тоже были эти проблемы, и использование всех строчных букв для табличных имен повсеместно решало мои проблемы.

Правильный ответ
Настройте систему variabele

lower_case_table_names=1 

Чтобы избавиться от этой проблемы.

Примечания, что если у вас есть lower_case_table_names=2 на Windows, ваш Windoze окно превращается в случае чувствительный Linux поля, насколько MySQL обеспокоен!

Ссылка
http://dev.mysql.com/doc/refman/5.5/en/identifier-case-sensitivity.html

+0

Извините, но ваш правильный ответ не подходит :) Я использую lower_case_table_names = 0, более того, я хочу, чтобы исправлено http://bugs.mysql.com/bug.php?id=55222. И более того: все отлично работает с MySql 5.1.56. Будет понижаться. В именах файлов Windows не учитываются регистры, но есть внутренние таблицы mysql, в которых хранятся другие имена таблиц, и их можно обрабатывать с учетом регистра в зависимости от значения lower_case_table_names – sergtk

+1

@sergdev, из документов: имена таблиц и баз данных хранятся на диске, используя буквенный регистр, указанный в инструкции CREATE TABLE или CREATE DATABASE. Сравнение имен чувствительно к регистру. Вы не должны устанавливать эту переменную в 0, если вы используете MySQL в системе с именами без учета регистра (например, Windows или Mac OS X). Если вы вынудите эту переменную к 0 с --lower-case-table-names = 0 в файловой системе без учета регистра и получите доступ к табличным именам MyISAM с использованием разных буквенных букв, может возникнуть повреждение индекса. ** ** выглядит как ваша настройка: ** ' lower_case_table_names = 0' ** - проблема ** – Johan

0

Я думаю, что ваша декларация вашего иностранного ключа может быть неправильной, в зависимости от того, что вы действительно были после. Кажется, это говорит о том, что «parentID» из «Table1» будет ссылаться на поле «id» из «Table1».

ALTER TABLE `Table1` 
    ADD CONSTRAINT `Table1_ibfk_2` 
    FOREIGN KEY (`parentId`) REFERENCES `Table1` (`id`); 

Может попробовать это:

ALTER TABLE `Table1` 
    ADD CONSTRAINT `Table1_ibfk_2` 
    FOREIGN KEY (`id`) REFERENCES Parent(`parentId`); 
+0

ИНОСТРАННЫЙ КЛЮЧ ('parentId') ССЫЛКИ' Таблица1' ('id'); это то, что я хочу. Я хочу, чтобы parentId ссылался на одну и ту же таблицу и имел одно из значений id-column. На самом деле это древовидная структура. – sergtk

+0

Я не был уверен, что это то, ради чего вы шли, я подумал, что это будет самое простое решение. –

+0

Был ли этот код работать до и проблема появилась только после того, как вы обновили версию? –

1

Нашли обходной путь.

Название таблицы должно быть в нижнем регистре после REFERENCES.

ALTER TABLE `Table1` 
    ADD CONSTRAINT `Table1_ibfk_2` 
    FOREIGN KEY (`parentId`) REFERENCES `table1` (`id`); 

Похож на ошибку в MySql 5.5.11.

FI. phpmyadmin не может добавить внешний ключ.

Экспорт также производит имя в нижнем регистре.

MySql 5.1.56 работает должным образом.

+0

Похоже на ошибку: http://bugs.mysql.com/bug.php?id=60229 – Benjamin

+0

Хорошо бы ожидать, что она будет исправлена. Теперь я вернулся к более старой версии. – sergtk

1

В моем случае это было связано с тем, что поле, которое было ссылочное поле было слишком длинное имя, то есть. foreign key (some_other_table_with_long_name_id). Попробуйте коротко. В этом случае сообщение об ошибке немного вводит в заблуждение.

Также определения полей должны быть одинаковыми (обратите внимание на подтип unsigned).

0

У меня было то же самое исключение:

[PDOException]                     
    SQLSTATE[HY000]: General error: 1005 Can't create table 'service.#sql-4851_c07' (errno: 150) 

Проблема у меня было, поле я хотел, чтобы сделать внешний ключ на не было позволено быть NULL :) После того, как я понял, что я должен был сделать это позволило чтобы быть нулевым, все начало работать.

Конечно, в первоначальном вопросе, это не так, я просто хотел, чтобы другие знали о возможном решении.