mysql - Node/Express/Sequelize : Datatype VIRTUAL gives SQL syntax error in db:migration

标签 mysql node.js express sequelize.js sequelize-cli

数据类型为 Virtual 的模型字段和直接从 Sequelize 手册复制的 get 方法在使用 sequelize-cli 运行 db:migration 时会出现 SQL 语法错误。通过反复试验排除了文件中任何其他可能的错误。
MySQL 5.7.31 和 Sequelize ^6.3.5 与 Express 4.17.1 和 mysql2 2.1.0。
我的迁移文件:

'use strict'
const { DataTypes } = require('sequelize')

module.exports = {
  up: async (queryInterface, Sequelize) => {
    await queryInterface.createTable('users', {
      id: {
        type: DataTypes.UUID,
        defaultValue: Sequelize.UUIDV4,
        primaryKey: true,
        allowNull: false, // constraint on mysql
        unique: true,// constraint on mysql
        validate: {
          isUUID: {
            args: 4,
            msg: 'User ID must be a UUID4 string.'
          }
        }
      },
      firstName: {
        type: DataTypes.STRING,
        required: true,
        allowNull: false,
        notEmpty: true,
        validate: {
          len: {
            args: [2, 90],
            msg: 'The first name must contain between 2 and 90 characters.'
          }
        }
      },
      lastName: {
        type: DataTypes.STRING,
        required: true,
        allowNull: false,
        notEmpty: true,
        validate: {
          len: {
            args: [2, 90],
            msg: 'The last name must contain between 2 and 90 characters.'
          }
        }
      },
     // Code that breaks the migration process:
      fullName: {
        type: DataTypes.VIRTUAL,
        get() {
          return `${this.firstName} ${this.lastName}`;
        }
      },
     // End code that breaks migration process
      email: {
        type: DataTypes.STRING,
        unique: true,
        required: true,
        allowNull: false,
        validate: {
          isEmail: {
            args: [true],
            msg: 'Incorrect email format'
          },
          isLowercase: {
            args: [true],
            msg: 'Email address must be lowercase'
          }, 
          len: {
            args: [2, 50],
            msg: 'The email address must have between 2 and 50 characters',
          },
          notEmpty: {
            args: [true], 
            msg: 'The email field can\'t be empty.'
          },
        }
      },
      password: {
        type: DataTypes.STRING,
        required: true,
        allowNull: false,
        validate: {
          len: {
            args: [8, 99],
            msg: 'Your password must contain at least 8 characters.',
          },
          notEmpty: {
            args: [true],
            msg: 'The password field cannot be empty.'
          }
        }
      },
      resetPasswordToken: {
        type: DataTypes.STRING
      },
      resetPasswordExpire: {
        type: DataTypes.INTEGER
      },
      createdAt: {
        type: DataTypes.DATE,
        required: true,
        allowNull: false
      },
      updatedAt: {
        type: DataTypes.DATE,
        required: true,
        allowNull: false
      },
      deletedAt: {
        type: DataTypes.DATE
      }
    },
    {
      paranoid: true,
      tableName: 'users'
    })
  },
  down: async (queryInterface, Sequelize) => {
    await queryInterface.dropTable('users');
  }
};
sequelize-cli db:migrate 后的控制台输出:
ERROR: 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 'VIRTUAL, `email` VARCHAR(255) 
NOT NULL UNIQUE, `password` VARCHAR(255) NOT NULL,' at line 1

npm ERR! code ELIFECYCLE
npm ERR! errno 1
etc.
如果 fullName 字段从模型中删除,则迁移运行成功。
fullName 字段中的 get() 方法与手册中的示例 ( https://sequelize.org/master/manual/getters-setters-virtuals.html#virtual-fields ) 相同。
它变得更加有趣,因为 Sequelize 手册指出不会将虚拟数据类型添加到数据库中——这是此功能的全部要点:
The VIRTUAL field does not cause a column in the table to exist. 
In other words, the model above will not have a fullName column. 
However, it will appear to have it!
环境:
  • Sequelize 版本:^6.3.5
  • Node.js 版本:12.18.3
  • 操作系统:MacOS/Docker 19.03.13 build 4484c46d9d
  • MySQL 5.7.31
  • Express 4.17.1
  • NPM 包 mysql2 版本 2.1.0(适配器)
  • Sequelize CLI 6.2.0

  • 谢谢你的热心帮助。

    最佳答案

    Virtuals 的存在是为了帮助您查询模型(例如,在您的 API Controller 中获取用户的全名)。由于它们不存在于数据库中,因此不应将它们作为迁移文件的一部分包含在内。
    简而言之,您应该在模型定义中使用 VIRTUAL,而不是在使用 queryInterface.createTable 方法的迁移文件中。
    希望这能回答你的问题。

    关于mysql - Node/Express/Sequelize : Datatype VIRTUAL gives SQL syntax error in db:migration,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64202752/

    相关文章:

    mysql - SQL SELECT 不同查询

    MYSQL组合 View 具有不同条目记录数的两个表

    mysql - 没有为具有复合键的表创建实体类型

    node.js - foreman 在 Node.js 中启动时出现错误

    node.js - 我可以将参数传递给 Mongoose 中的 findbyid() 函数吗

    php - 使用mysql从两个不同的表中获取结果

    node.js - 预检响应中的 Access-Control-Allow-Headers 不允许请求 header 字段内容类型

    javascript - Zapier CLI 中触发器的过滤器响应

    node.js - 如何链接到本地​​ Rust 库? (类似于 npm 链接)

    node.js - FacebookToken错误: This authorization code has been used passport-js