我是Sequelize的新手,并且正在通过官方教程网站(http://docs.sequelizejs.com/manual/tutorial/)学习 在尝试本教程中的代码时,我陷入了困境。
我尝试的代码是这样的:
const City = sequelize.define('city', { countryCode: Sequelize.STRING });
const Country = sequelize.define('country', { isoCode: Sequelize.STRING });
Country.hasMany(City, {foreignKey: 'countryCode', sourceKey: 'isoCode'});
City.belongsTo(Country, {foreignKey: 'countryCode', targetKey: 'isoCode'});
sequelize.sync();
运行此代码时,节点控制台会给我一个错误:
“未处理的拒绝SequelizeDatabaseError:无法添加外键约束。在引用表'countries'中缺少约束'cities_ibfk_1'的索引””
有人能告诉我这是什么问题吗?非常感谢您的帮助。谢谢。
上面的代码来自本教程的关联部分(http://docs.sequelizejs.com/manual/tutorial/associations.html) 一对多关联。
我还附上了Sequelize自动生成的代码:
CREATE TABLE IF NOT EXISTS `countries` (
`id` INTEGER NOT NULL auto_increment ,
`isoCode` VARCHAR(255),
`createdAt` DATETIME NOT NULL,
`updatedAt` DATETIME NOT NULL,
PRIMARY KEY (`id`))
ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `cities` (
`id` INTEGER NOT NULL auto_increment ,
`createdAt` DATETIME NOT NULL,
`updatedAt` DATETIME NOT NULL,
`countryCode` VARCHAR(255),
PRIMARY KEY (`id`),
FOREIGN KEY (`countryCode`) REFERENCES `countries` (`isoCode`)
ON DELETE SET NULL ON UPDATE CASCADE)
ENGINE=InnoDB;
乍一看似乎SQL语法在这里不是错误的,但是无论如何这都会导致错误。任何人都可以找出问题所在吗?还是这是Sequelize的问题?
答案 0 :(得分:1)
发生此错误是因为Sequelize教程中的示例代码存在语法错误。
如果我们要为外键制定规则,则它必须引用被引用表的主键。问题在于,在代码中,外键countryCode
试图引用isoCode
模型(在真实的MySQL DB中为Country
表)的countries
。>
const City = sequelize.define('city', { countryCode: Sequelize.STRING });
const Country = sequelize.define('country', { isoCode: Sequelize.STRING });
Country.hasMany(City, {foreignKey: 'countryCode', sourceKey: 'isoCode'});
City.belongsTo(Country, {foreignKey: 'countryCode', targetKey: 'isoCode'});
上面的Sequelize代码将转换为如下的SQL语句:
CREATE TABLE IF NOT EXISTS `countries` (
`id` INTEGER NOT NULL auto_increment ,
`isoCode` VARCHAR(255),
`createdAt` DATETIME NOT NULL,
`updatedAt` DATETIME NOT NULL,
PRIMARY KEY (`id`))
ENGINE=InnoDB;
CREATE TABLE IF NOT EXISTS `cities` (
`id` INTEGER NOT NULL auto_increment ,
`createdAt` DATETIME NOT NULL,
`updatedAt` DATETIME NOT NULL,
`countryCode` VARCHAR(255),
PRIMARY KEY (`id`),
FOREIGN KEY (`countryCode`) REFERENCES `countries` (`isoCode`)
ON DELETE SET NULL ON UPDATE CASCADE)
ENGINE=InnoDB;
要解决此语法错误,我们必须使isoCode
模型中的City
为主键。让我们修复代码:
const City = sequelize.define('city', { countryCode: Sequelize.STRING})
const Country = sequelize.define('country', {
isoCode: {
type: Sequelize.STRING,
primaryKey: true
}
})
// ... the rest of code followed below
修复模型定义后,代码将按预期工作!
但是我想知道的是... 官方教程如何发布此代码,并让初学者在不知道这行不通的情况下尝试一下。当然,有人会说这不是Sequelize的问题,而是理解SQL的问题。但是我仍然认为该教程应该固定以避免这种情况的发生。
此解决方案的局限性在于,没有必要使用选项sourceKey
和targetKey
,因为即使没有它们,Sequelize也会自动找出关系并识别出源密钥是什么表中的目标键。
我仍然不明白这一点……我想现在,我只需要不使用sourceKey和targetkey选项。