NodeJS sequelize自动生成模型并运行迁移SQL语法错误。

7
我正在使用MySQL构建一个新的NodeJS应用程序。 我需要使用现有的数据库模式。 我有一个mysql转储文件,它被加载到数据库中(在docker容器中)。 我试图自动生成模型和迁移,然后成功运行迁移。 我能够生成模型和迁移,但是在运行生成的迁移时会出现SQL语法错误。
以下是相关版本: 节点10-阿尔卑斯山
"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 模块生成迁移,并自动运行它们。生成初始迁移文件成功。
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个回答

6
  • 是的,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-auto-migrations 只能在依赖于早期版本 sequelize 时为您的模型生成。不知道根本原因是什么。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接