Форвард-инжиниринг: некоторые новые отношения терпят неудачу в заполненной базе данных (errno 150)
Это еще одна ошибка 1005, ошибка 150 при создании потока таблицы. Я видел много из них, но никто не дает ответа на мой вопрос.
У меня есть база данных в MySQL Workbench, которая разработана и заполнена данными. Затем я создаю из представления модели новую таблицу. После этого я добавляю отношение:m между этой новой таблицей и существующей таблицей в моей базе данных.
Наконец, я пытаюсь синхронизировать свою базу данных. Сгенерированный код для создания двух новых таблиц:
SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0;
SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0;
SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='TRADITIONAL,ALLOW_INVALID_DATES';
CREATE TABLE IF NOT EXISTS `mydb`.`SEntences` (
`idSEntences` INT(11) NOT NULL,
PRIMARY KEY (`idSEntences`))
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1
COLLATE = latin1_bin;
CREATE TABLE IF NOT EXISTS `mydb`.`Tips_has_SEntences` (
`Tips_idTips` VARCHAR(45) NOT NULL,
`SEntences_idSEntences` INT(11) NOT NULL,
PRIMARY KEY (`Tips_idTips`, `SEntences_idSEntences`),
INDEX `fk_Tips_has_SEntences_SEntences1_idx` (`SEntences_idSEntences` ASC),
INDEX `fk_Tips_has_SEntences_Tips1_idx` (`Tips_idTips` ASC),
CONSTRAINT `fk_Tips_has_SEntences_Tips1`
FOREIGN KEY (`Tips_idTips`)
REFERENCES `mydb`.`Tips` (`idTips`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Tips_has_SEntences_SEntences1`
FOREIGN KEY (`SEntences_idSEntences`)
REFERENCES `mydb`.`SEntences` (`idSEntences`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1
COLLATE = latin1_bin;
SET SQL_MODE=@OLD_SQL_MODE;
SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS;
SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS;
Я получаю ошибку, с этим журналом:
Executing SQL script in server
ERROR: Error 1005: Can't create table 'mydb.Tips_has_SEntences' (errno: 150)
CREATE TABLE IF NOT EXISTS `mydb`.`Tips_has_SEntences` (
`Tips_idTips` VARCHAR(45) NOT NULL,
`SEntences_idSEntences` INT(11) NOT NULL,
PRIMARY KEY (`Tips_idTips`, `SEntences_idSEntences`),
INDEX `fk_Tips_has_SEntences_SEntences1_idx` (`SEntences_idSEntences` ASC),
INDEX `fk_Tips_has_SEntences_Tips1_idx` (`Tips_idTips` ASC),
CONSTRAINT `fk_Tips_has_SEntences_Tips1`
FOREIGN KEY (`Tips_idTips`)
REFERENCES `mydb`.`Tips` (`idTips`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Tips_has_SEntences_SEntences1`
FOREIGN KEY (`SEntences_idSEntences`)
REFERENCES `mydb`.`SEntences` (`idSEntences`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1
COLLATE = latin1_bin
SQL script execution finished: statements: 3 succeeded, 1 failed
Fetching back view definitions in final form.
Nothing to fetch
Запустив mysql из терминала, с помощью команды SHOW ENGINE INNODB STATUS\G я получаю следующие выходные данные из самого последнего поля ошибки внешнего ключа:
------------------------
LATEST FOREIGN KEY ERROR
------------------------
141007 14:18:53 Error in foreign key constraint of table mydb/Tips_has_SEntences:
FOREIGN KEY (`Tips_idTips`)
REFERENCES `mydb`.`Tips` (`idTips`)
ON DELETE NO ACTION
ON UPDATE NO ACTION,
CONSTRAINT `fk_Tips_has_SEntences_SEntences1`
FOREIGN KEY (`SEntences_idSEntences`)
REFERENCES `mydb`.`SEntences` (`idSEntences`)
ON DELETE NO ACTION
ON UPDATE NO ACTION)
ENGINE = InnoDB
DEFAULT CHARACTER SET = latin1
COLLATE = latin1_bin:
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.
После исследования моей проблемы, я не могу понять, что не так. Все типы данных одинаковы, внешние ключи находятся на первичных ключах (которые имеют первичные индексы на них) и т. Д. Я исследовал различные ответы на переполнение стека по этой ошибке и просмотрел эту страницу, связанную с одной из них: Ошибка MySQL 1005 Can't создать таблицу '.\mydb#sql-328_45.frm' (errno: 150) Я искал так тщательно, как мог, но ответ все еще мог быть там. В таком случае извините.
Может быть, это связано с тем, что в старой таблице (Tips) уже есть данные. Синхронизация отношения 1:n, который добавляет внешний ключ в старую таблицу (Советы), хотя странно работает. если бы проблема была с данными, это не сработало бы, как я обнаружил в этом посте: Как добавить внешний ключ в таблицу MySQL?
С другой стороны, добавление отношения 1:n, которое потребовало бы добавления внешнего ключа старой таблицы (Tips) к новой, генерирует те же ошибки и журналы (за исключением ссылки на таблицу, подобную этой: '. \ MYDB # SQL-328_45.frm ').
Должен отметить, что эти проблемы возникают для любой моей старой таблицы (таблица уже в базе данных с данными). Кроме того, я уверен, что обновил MySQL Workbench после того, как я заполнил базу данных данными, прежде чем я продолжил заполнять ее и пытался добавить эти новые таблицы. Сейчас это версия 6 и работает в Kubuntu, Linux.
В чем здесь проблема и как ее можно лечить? Идут ли до крайности, такие как экспорт базы данных, удаление и импорт ее единственным способом? Даже в таком случае, что мне делать именно? Имейте в виду, что это база данных с множеством записей, около 100000.
Если вам нужна дополнительная информация, я предоставлю их с этого момента.
Код создания таблицы советов:
SHOW CREATE TABLE mydb.Tips;
CREATE TABLE `Tips` (
`idTips` varchar(45) CHARACTER SET latin1 NOT NULL,
`like_count` int(10) unsigned DEFAULT NULL,
`text` longtext CHARACTER SET latin1,
`created_at` bigint(19) unsigned DEFAULT NULL,
`url` varchar(100) CHARACTER SET latin1 DEFAULT NULL,
`todo_count` bigint(19) unsigned DEFAULT NULL,
`save_count` bigint(19) unsigned DEFAULT NULL,
`Venues_idVenues` varchar(45) CHARACTER SET latin1 NOT NULL,
PRIMARY KEY (`idTips`),
KEY `fk_Tips_Venues1` (`Venues_idVenues`),
CONSTRAINT `fk_Tips_Venues1` FOREIGN KEY (`Venues_idVenues`) REFERENCES `Venues` (`idVenues`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1 COLLATE=latin1_bin
1 ответ
ТЛ; др
imho нужно синхронизировать определение Tips.idTips
столбец и Tips_has_SEntences.Tips_idTips
колонка.
В частности, набор символов и сопоставление столбцов не соответствуют.
разрешение
Итак, в коде выполните одно из следующих действий:
определить набор символов или сопоставление
Tips_has_SEntences.Tips_idTips
столбец явно.`Tips_idTips` VARCHAR(45) CHARACTER SET latin1 NOT NULL,
или же
`Tips_idTips` VARCHAR(45) COLLATE latin1_swedish_ci NOT NULL,
сбросить явное сопоставление по умолчанию на
Tips_has_SEntences
Таблица.COLLATE = latin1_bin -- remove this section
опустить явное определение набора символов на
Tips.idTips
колонка.`idTips` varchar(45) NOT NULL,
указать
latin1_bin
сопоставление наTips.idTips
колонка.`idTips` varchar(45) COLLATE latin1_bin NOT NULL,
Будьте осторожны: последние два варианта могут привести к потере данных, если при использовании ALTER TABLE
запрос, наборы символов "to" и "from" несовместимы.
Вы должны быть в безопасности, так как latin1_bin
а также latin1_swedish_ci
сопоставление использовать тот же набор символов (latin1
).
объяснение
эксперимент
Когда я отключил тревожный внешний ключ в Tips_has_SEntences
CREATE TABLE
заявление:
-- CONSTRAINT `fk_Tips_has_SEntences_Tips1`
-- FOREIGN KEY (`Tips_idTips`)
-- REFERENCES `mydb`.`Tips` (`idTips`)
-- ON DELETE NO ACTION
-- ON UPDATE NO ACTION,
Запустил запросы и сделал SHOW CREATE TABLE
на Tips
а также Tips_has_SEntences
Таблицы, в которых я нашел определение двух столбцов, к которым подключался внешний ключ, немного отличались.
...
`idTips` varchar(45) CHARACTER SET latin1 NOT NULL,
...
`Tips_idTips` varchar(45) COLLATE latin1_bin NOT NULL,
...
На Tips.idTips
столбец набор символов явно установлен и на Tips_has_SEntences.Tips_idTips
В столбце установлено сопоставление по умолчанию для таблицы.
Я предполагаю, что столбцы внешнего ключа нельзя легко сравнивать, и ссылочная целостность не поддерживается, когда параметры сортировки или наборы символов двух задействованных столбцов не совпадают.
Дальнейшее расследование
Затем я побежал SHOW FULL COLUMN
чтобы показать детали столбцов в вопросе.
Field Type Collation Null Key
idTips varchar(45) latin1_swedish_ci NO PRI
...
Tips_idTips varchar(45) latin1_bin NO PRI
Почему разница в сопоставлении?
Когда я читал дальше о наборах символов и сопоставлениях по столбцам, документы MySQL говорили:
- Если CHARACTER SET X указан без COLLATE, используется набор символов X и его сопоставление по умолчанию.
- Если COLLATE Y указан без CHARACTER SET, используется набор символов, связанный с Y и сопоставлением Y.
Для просмотра параметров сортировки по умолчанию и связанных наборов символов я запустил SHOW COLLATION
:
Collation Charset Id Default Compiled Sortlen
...
latin1_german1_ci latin1 5 Yes 1
latin1_swedish_ci latin1 8 Yes Yes 1
latin1_danish_ci latin1 15 Yes 1
latin1_german2_ci latin1 31 Yes 2
latin1_bin latin1 47 Yes 1
latin1_general_ci latin1 48 Yes 1
latin1_general_cs latin1 49 Yes 1
latin1_spanish_ci latin1 94 Yes 1
...
Теперь мы можем видеть, что MySQL разрешает сопоставление Tips.idTips
столбец к latin1_swedish_ci
потому что это сопоставление по умолчанию для явно установленного latin1
набор символов.
Параметры сортировки будут разрешаться набором символов, а не наследоваться из таблицы, поскольку набор символов был явно установлен в столбце. Это именно так, как это было указано в документации, так что это, вероятно, желаемое поведение.
Взять это еще дальше
Теперь я знал, что сопоставление Tips.idTips
колонка была latin1_swedish_ci
, Таким образом, вместо явного изменения набора символов Tips_has_SEntences.Tips_idTips
столбец, я думал, что я мог бы просто изменить сопоставление на latin1_swedish_ci
,
`Tips_idTips` VARCHAR(45) COLLATE latin1_swedish_ci NOT NULL,
Это тоже работает.
что интересно SHOW CREATE TABLE
теперь говорит, что столбец был / должен быть создан с этой строкой:
`Tips_idTips` varchar(45) CHARACTER SET latin1 NOT NULL,
Заключение
Наборы символов, сопоставление и внешние ключи вместе - ад.
Я предпочитаю целочисленные столбцы для внешних ключей вместо строковых / текстовых типов, когда у меня есть выбор. И теперь я знаю почему:)
Глядя на код, который вы разместили, кажется, что это проблема со всеми "старыми" таблицами в вашей базе данных, так как все текстовые столбцы имеют набор символов latin1
определено явно.