【问题标题】:(Added SQL) Sequelize hasMany association with option(添加 SQL)Sequelize hasMany 与选项的关联
【发布时间】:2019-05-30 13:04:58
【问题描述】:

我是 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' 的索引”

谁能告诉我这有什么问题?我真的很感谢你的帮助。谢谢。

以上代码来自教程的Assotiation部分 (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的问题?

【问题讨论】:

    标签: javascript mysql sql database sequelize.js


    【解决方案1】:

    出现此错误是因为 Sequelize 教程中的示例代码存在语法错误。

    如果我们想为外键制定规则,它必须引用被引用表的主键。问题是在代码中,外键countryCode试图引用Country模型的isoCode(在真实的MySQL数据库中是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;
    

    要修复此语法错误,我们必须将 isoCodeCity 模型作为主键。让我们修复代码:

    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理解的问题。但我仍然认为应该修复教程以避免这种情况发生。


    这个解决方案的局限在于,使用sourceKeytargetKey这两个选项是没有意义的,因为即使没有它们,Sequelize 也会自动找出关系并识别它们之间的源键和目标键是什么表格。

    我还是不明白...我想现在,我只需要不使用 sourceKey 和 targetkey 选项。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多