未处理的拒绝SequelizeDatabaseError:外键约束错误:无法添加外键

时间:2016-10-21 08:49:42

标签: mysql node.js sequelize.js

var state = require('./state')
module.exports = function (sequelize, DataTypes) {
    var city = sequelize.define('city', {
        city_id : {
            type : DataTypes.INTEGER,
            autoIncrement : true,
            primaryKey : true
        },
        city_name : {
            type : DataTypes.STRING,
            allowNull : false,
            unique : true
        },
        city_state_id : {
            type : DataTypes.INTEGER,
            allowNull : false,
            references : {
                model : 'states',
                key : 'state_id'
            }
        }
    }
    return  city;
}

这是我的引用文件。

module.exports = function (sequelize, DataTypes) {
    var state = sequelize.define('state', {
        state_id: {
            type: DataTypes.INTEGER,
            autoIncrement: true,
            primaryKey: true
        },
        state_name: {
            type: DataTypes.STRING,
            allowNull: false,
            unique: true
        },
    })
    return state;
}

我不知道为什么我不能在这里添加外键约束。任何人都可以帮助我吗?我收到这样的错误:

未处理拒绝SequelizeDatabaseError:ER_CANNOT_ADD_FOREIGN:无法添加外键约束 当我尝试在终端上执行migration.js时:node migration.js

migration.js:

 /*jslint node: true */
 'use strict';
 var Sequelize = require('sequelize');
 var fs = require('fs');
 var schema_dir = './schema/';
 var config = require('./config').mysql_conf;
 var connection = new Sequelize(config.database, config.username, config.password, config);
 fs.readdir(schema_dir, function(err, files) {
     if (err) {
         console.log(err);
     } else {
         files = files.sort();
         console.log(files);
         for (var i = 0; i < files.length; i++) {
             var module_name = files[i].slice(0, -3);
             console.log(schema_dir + files[i]);
             //  var schema = require(schema_dir + module_name);
             try {
                 var model = connection['import']('' + schema_dir + module_name);
                 model.sync().then(function() {
                     console.log("table created: " + module_name);
                 });
                 model.sync({force : true})
             } catch (ex) {
                 console.log("error with module_name: " + module_name, ex);
             }
         }
     }

 });

任何人都知道为什么会这样?

1 个答案:

答案 0 :(得分:3)

需要理解/修复一些事项以确保其正常工作。

sync()vs sync({force:true})

sync()将运行CREATE TABLE IF NOT EXISTS,而sync({force: true})将运行DROP TABLE IF EXISTS,然后再次创建表格。因此,此迁移方法适用于本地/ dev以上的环境。此外,如果要创建列,更改数据类型等,不能使用这些方法来应用更改。

使用此选项在本地进行测试,然后通过SHOW CREATE TABLE创建迁移文件,并通过Sequelize migration运行这些文件。

同步的异步性

sync()具有讽刺意味的异步,这意味着同步循环不能保证每个模型按顺序加载。这可以输出不同的错误日志并将您抛弃。您应该使用异步处理模块,如async:

async.eachSeries(files, function(file, callback) {
    var model = require(currentDir + '/' + file);
    model
        .sync({force: true})
        .then(function() {
            console.log('Force-synced %s', file);
            callback();
        })
        .catch(callback);
}, function(err) {
    if(err) throw err;
    console.log('Completed migration in order as such %o', files);
});

迁移文件的顺序

您有city.model.jsstate.model.js等文件名。由于fs.readdir将按字母顺序读取它们,

    city_state_id : {
        type : DataTypes.INTEGER,
        allowNull : false,
        references : {
            model : 'states',
            key : 'state_id'
        }
    }

无法引用表states,因为它尚不存在。

您需要正确订购。一种方法是创建一个这样的订单数组:

var order = [
    'state',
    'city'
];

async.eachSeries(order, function(file, callback) {
    var model = require(currentDir + '/' + file + '.model.js');
    model
        .sync({force: true})
        .then(function() {
            console.log('Force-synced %s', file);
            callback();
        })
        .catch(callback);
}, function(err) {
    if(err) throw err;
    console.log('Completed migration in order as such %o', files);
});

其他人不会等待模型加载

如果您正在运行测试或服务器,他们可能会在加载之前开始尝试访问模型。 sync的异步性质会阻止服务器等待加载模型。

解决方案是使用模型作为查询的方式,而不是改变表结构的方法。这应该用于本地测试并使用Sequelize migration进行更改。