当前位置: 首页 > 知识库问答 >
问题:

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

臧威
2023-03-14

我正在使用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 -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(由续集自动模块生成):

/* 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;

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

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

            },
            {}
        ]
    }
];

共有1个答案

佟翰林
2023-03-14
  • 是的,SQL错误是因为括号之间应该有一个列列表。
  • 是的,迁移文件应该包含列而不是空括号,正如此答案下方的正确文件所示。
  • 错误迁移的原因似乎与您package.json.中指定的最近的Sequelze版本有关。本答案的其余部分解释了该过程。

您的续集自动输出看起来正常,所以我尝试通过以下方式重现迁移步骤:

  1. 在新目录中运行序列化init(未显式安装,NPM显示4.44)并将osw.js粘贴到。/模型。
  2. 安装匹配版本的mysql2和序列化自动迁移,这是调用节点所需的最低限度。/node_modules/序列化自动迁移/bin/m>
  3. 这产生了迁移/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
};

这解决了眼前的问题,但无法解释。我清理了目录,初始化了包,安装了所有依赖项,然后再次尝试生成迁移。这产生了一个空的<code>migrationCommands</code>变量,如上面所示。尝试卸载和重新安装各种软件包都没有效果——我生成了十几次空包。卸载续集导致了一个错误,所以我从一个空目录和<code>npm I-s mysql2续集自动迁移重新开始;续集初始化。从osw生成。js再次工作。

npm显示序列化自动迁移再次使用序列化4.44。npm i序列化安装了5.8.7,生成立即开始失败。因此,序列化自动迁移只能在依赖早期版本的序列化时为您的模型生成。不知道根本原因是什么。

 类似资料:
  • 我有一套序列模型。我想使用迁移,而不是数据库同步。 根据这篇文章,Sequelize CLI似乎能够做到这一点:“当您使用CLI生成模型时,您还可以免费获得迁移脚本。” 如何使用Sequelize CLI从现有的Sequelize模型中自动生成迁移?

  • 我有一个play框架2.2.2 scala应用程序并使用play-flyway 1.0.3。 以下迁移应通过flyway运行: 因此,我将一列添加到表中,然后使用更新语句以编程方式填充它。 第一行执行良好,但update statemens失败 然而,当我使用迁移SQL代码并使用phpmyadmin运行它时,它工作得很好(虽然运行需要2-5秒,但表相当大)。 我的mysql。日志看起来像 flyw

  • 问题内容: 我正在使用Alembic处理Flask的迁移。理论上,应该基于数据库中的更改自动生成迁移。但是,Alembic仅使用上述命令即可生成空白迁移。 有一个与此问题非常相似的问题,即问题是没有导入正确的模型。但是,我已经从我的Flask应用程序导入了模型,如下所示: 以及中导入的数据库元数据env.py(“ start”是我的Flask应用程序主文件的名称): 运行,alembic revi

  • The migration CLI automatically migrates your v1 website to a v2 website. info Manual work is still required after using the migration CLI, as we can't automate a full migration The migration CLI migr

  • 问题内容: 我正在尝试使用任何语法,但无法考虑如何正确编写此代码: 也尝试过 和双引号等。运行迁移时,总是得到以下信息: 语法错误或访问冲突:1064您的SQL语法有错误。检查 与您的MariaDB服务器版本相对应的手册以获取正确的语法,以在第1行的“用户”修改“年龄” DATETIME附近使用 是的,我已经检查过,MariaDB使用MySQL的语法(至少在这种情况下)。 问题答案: 使用反引号而

  • 我使用Prisma 2作为我的ORM。用于迁移和查询。 我有一个助手,它通过以下方式初始化Prisma: 创建新模式 通过运行(简而言之,它运行我的项目目录中的所有迁移)。 在每个测试中,我创建一个新的TestContext,以确保不会有任何副作用。但问题是,由于我的所有测试都是并行运行的,因此在这次迁移中,所有测试都同时在数据库上运行: 这会触发以下错误: