这是另一个错误1005,create table thread上的errno 150。我见过很多,但没有人能回答我的问题。
我在mysql workbench中有一个数据库,它是前向工程的,并且充满了数据。然后,我从模型视图创建一个新表。之后,在新表和数据库中的现有表之间添加N: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 Error Number 1005 Can’t create table ‘.\mydb#sql-328_45.frm’ (errno: 150)我尽可能彻底地搜索了,但答案可能仍然存在。在这种情况下,我很抱歉。
可能是因为旧表(tips)中已经包含了数据。同步1:n关系,这会在旧表(tips)中添加一个外键,尽管工作起来很奇怪。如果数据是问题所在,这就行不通了,正如我在这篇文章中发现的那样:How to add foreign key to MySQL table?
另一方面,添加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

最佳答案

TL;博士
我知道您需要同步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_binlatin1_swedish_ci排序规则使用相同的字符集(latin1)。
解释
实验
当我禁用Tips_has_SEntencesCREATE 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 TABLETips表执行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

为什么校勘有区别?
当我进一步阅读character sets and collations on columns时,mysql文档说:
如果指定的字符集x不带排序规则,则使用字符集x及其默认排序规则。
如果指定的collate y没有字符集,则使用与y和collation y关联的字符集。
要查看我运行的默认排序规则和相关字符集:
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将SHOW COLLATION列的排序规则解析为Tips.idTips,因为这是显式设置latin1_swedish_ci字符集的默认排序规则。
排序规则将由字符集解析,而不是从表继承,因为字符集是在列上显式设置的。这正是在文档中指定它的方式,因此这可能是所需的行为。
更进一步
现在我知道latin1列的排序规则是Tips.idTips。因此,与其显式地更改latin1_swedish_ci列的字符集,我还以为可以将排序规则更改为Tips_has_SEntences.Tips_idTips
`Tips_idTips` VARCHAR(45) COLLATE latin1_swedish_ci NOT NULL,

这同样有效。
有趣的是latin1_swedish_ci现在说该列是/应该用这一行创建的:
`Tips_idTips` varchar(45) CHARACTER SET latin1 NOT NULL,

结论
字符集,排序规则和外键一起是地狱。
当我有选择的时候,我更喜欢用整数列作为外键,而不是字符串/文本类型。现在我知道原因了:)
查看您发布的代码,这似乎是数据库中所有“旧”表的问题,因为所有文本列似乎都显式定义了字符集SHOW CREATE TABLE

关于mysql - 在填充的数据库中进行正向工程某些新关系失败(错误号150),我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/26237098/

10-10 17:15
查看更多