数据类型为 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!
环境:mysql2
版本 2.1.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/