NodeJS序列化自动生成模型并运行迁移SQL语法错误

时间:2019-05-09 14:01:09

标签: mysql node.js model migration sequelize.js

我正在用MySQL构建一个新的NodeJS应用程序。我需要使用现有的数据库架构。我有一个mysql dump文件,该文件已加载到数据库中(在docker容器中)。我正在尝试自动生成模型和迁移,然后成功运行迁移。我能够生成模型和迁移,但是运行生成的迁移时会出现SQL语法错误。

以下是相关版本:

Node10-高山

"mysql": "^2.17.1",
"mysql2": "^1.6.5",
"sequelize": "^5.8.5",
"sequelize-auto": "^0.4.29",
"sequelize-auto-migrations": "^1.0.3"

我使用了sequelize-auto模块来自动生成模型。可行。

sequelize-auto -o "./models" -d sequelize_auto_test -h localhost -u username -p 5432 -x password -e mysql

然后我尝试使用sequelize-auto-migrations模块生成Migration,然后自动运行它们。

生成初始迁移文件有效。

node ./node_modules/sequelize-auto-migrations/bin/makemigration --name <initial_migration_name>

但是,在运行实际迁移时,会出现语法错误。

node ./node_modules/sequelize-auto-migrations/bin/runmigration

这适用于许多表,但随后遇到语法错误。

     code: 'ER_PARSE_ERROR',
     errno: 1064,
     sqlState: '42000',
     sqlMessage:
      'You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near \') ENGINE=InnoDB\' at line 1',
     sql: 'CREATE TABLE IF NOT EXISTS `osw` () ENGINE=InnoDB;' },
  sql: 'CREATE TABLE IF NOT EXISTS `osw` () ENGINE=InnoDB;' }

以下是相关模型osw.js(由sequelize-auto模块生成):

/* jshint indent: 2 */

module.exports = function(sequelize, DataTypes) {
  return sequelize.define('osw', {
    OSWID: {
      type: DataTypes.INTEGER(10).UNSIGNED,
      allowNull: false,
      primaryKey: true
    },
    IdentificationID: {
      type: DataTypes.INTEGER(10).UNSIGNED,
      allowNull: true,
      references: {
        model: 'itemidentification',
        key: 'IdentificationID'
      }
    },
    ProposedHours: {
      type: DataTypes.DECIMAL,
      allowNull: true
    },
    WorkStartDate: {
      type: DataTypes.DATEONLY,
      allowNull: true
    },
    WorkEndDate: {
      type: DataTypes.DATEONLY,
      allowNull: true
    },
    FormatID: {
      type: DataTypes.INTEGER(10).UNSIGNED,
      allowNull: true,
      references: {
        model: 'formats',
        key: 'FormatID'
      }
    },
    WorkLocationID: {
      type: DataTypes.INTEGER(10).UNSIGNED,
      allowNull: true
    }
  }, {
    tableName: 'osw'
  });
};

这是mysql转储文件的相关部分:

CREATE TABLE `OSW` (
  `OSWID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `IdentificationID` int(10) unsigned DEFAULT NULL,
  `ProposedHours` decimal(10,2) DEFAULT NULL,
  `WorkStartDate` date DEFAULT NULL,
  `WorkEndDate` date DEFAULT NULL,
  `FormatID` int(10) unsigned DEFAULT NULL,
  `WorkLocationID` int(10) unsigned DEFAULT NULL,
  PRIMARY KEY (`OSWID`),
  KEY `OSW_FKIndex1` (`IdentificationID`),
  KEY `OSW_Format` (`FormatID`),
  CONSTRAINT `OSW_Format` FOREIGN KEY (`FormatID`) REFERENCES `formats` (`formatid`) ON DELETE SET NULL,
  CONSTRAINT `OSW_Ident` FOREIGN KEY (`IdentificationID`) REFERENCES `itemidentification` (`identificationid`) ON DELETE CASCADE
) ENGINE=InnoDB AUTO_INCREMENT=1147 DEFAULT CHARSET=utf8 PACK_KEYS=0;

更新:我认为该问题可能与自动生成的迁移有关。迁移文件似乎缺少列和字段类型定义,因此这可能就是SQL CREATE table命令缺少列名称的原因。这是针对osw表生成的迁移文件的相关部分:

var migrationCommands = [{
    {
        fn: "createTable",
        params: [
            "osw",
            {

            },
            {}
        ]
    }
];

1 个答案:

答案 0 :(得分:1)

  • 是的,SQL错误是因为括号之间应该有一个列列表。
  • 是的,迁移文件应包含列而不是空括号,这将在此答案下面的正确文件中显示。
  • 迁移不良的原因似乎与您的package.json中指定的最新Sequelize版本有关。该答案的其余部分说明了该过程。

您的sequelize-auto输出看起来很正常,所以我尝试通过以下方式仅复制迁移步骤:

  1. 在新目录中运行sequelize init(未明确安装,NPM显示4.44),并将osw.js粘贴到./models中。
  2. 安装匹配版本的mysql2和sequelize-auto-migrations,这是调用node ./node_modules/sequelize-auto-migrations/bin/makemigration --name osw所需的最低要求
  3. 这产生了migrations / 1-osw.js:
'use strict';

var Sequelize = require('sequelize');

/**
 * Actions summary:
 *
 * createTable "osw", deps: [itemidentification, formats]
 *
 **/

var info = {
    "revision": 1,
    "name": "osw",
    "created": "2019-05-30T03:54:19.054Z",
    "comment": ""
};

var migrationCommands = [{
    fn: "createTable",
    params: [
        "osw",
        {
            "OSWID": {
                "type": Sequelize.INTEGER(10).UNSIGNED,
                "field": "OSWID",
                "primaryKey": true,
                "allowNull": false
            },
            "IdentificationID": {
                "type": Sequelize.INTEGER(10).UNSIGNED,
                "field": "IdentificationID",
                "references": {
                    "model": "itemidentification",
                    "key": "IdentificationID"
                },
                "allowNull": true
            },
            "ProposedHours": {
                "type": Sequelize.DECIMAL,
                "field": "ProposedHours",
                "allowNull": true
            },
            "WorkStartDate": {
                "type": Sequelize.DATEONLY,
                "field": "WorkStartDate",
                "allowNull": true
            },
            "WorkEndDate": {
                "type": Sequelize.DATEONLY,
                "field": "WorkEndDate",
                "allowNull": true
            },
            "FormatID": {
                "type": Sequelize.INTEGER(10).UNSIGNED,
                "field": "FormatID",
                "references": {
                    "model": "formats",
                    "key": "FormatID"
                },
                "allowNull": true
            },
            "WorkLocationID": {
                "type": Sequelize.INTEGER(10).UNSIGNED,
                "field": "WorkLocationID",
                "allowNull": true
            },
            "createdAt": {
                "type": Sequelize.DATE,
                "field": "createdAt",
                "allowNull": false
            },
            "updatedAt": {
                "type": Sequelize.DATE,
                "field": "updatedAt",
                "allowNull": false
            }
        },
        {}
    ]
}];

module.exports = {
    pos: 0,
    up: function(queryInterface, Sequelize)
    {
        var index = this.pos;
        return new Promise(function(resolve, reject) {
            function next() {
                if (index < migrationCommands.length)
                {
                    let command = migrationCommands[index];
                    console.log("[#"+index+"] execute: " + command.fn);
                    index++;
                    queryInterface[command.fn].apply(queryInterface, command.params).then(next, reject);
                }
                else
                    resolve();
            }
            next();
        });
    },
    info: info
};

这解决了眼前的问题,但没有解释。我清理了目录,初始化了程序包,安装了所有依赖项,然后尝试再次生成迁移。如上所示,这产生了一个空的migrationCommands变量。尝试卸载并重新安装各种软件包没有任何效果-我生成了十几次。卸载sequelize会导致错误,因此我以空目录和npm i -s mysql2 sequelize-auto-migrations; sequelize init重新开始。 osw.js的生成再次起作用。

npm显示sequelize-auto-migrations再次使用sequelize 4.44。 npm i sequelize安装了5.8.7,并且生成立即开始失败。因此,仅当依赖于sequelize的早期版本时,sequelize-auto-migrations才能为您的模型生成。不知道根本原因是什么。