Sequelize迁移中为已存在sku、barcode字段添加unique约束方案
Sequelize 给已有字段加唯一约束解决方案
之前尝试的方法报错原因
addColumn报重复字段错误:该方法作用是新增不存在的字段,sku、barcode字段已存在于表中,自然触发重复报错。addIndex报Cannot create property 'fields'错误:参数格式错误,第二个参数要求传入字段名数组,不能直接传字符串字段名。changeColumn报校验错误:一方面迁移是直接操作数据库结构,validate是Sequelize模型层的校验逻辑,数据库不识别该配置;另一方面如果表中已存在重复的sku或barcode数据,加唯一约束时会直接触发校验失败。addConstraint执行异常:基本都是参数格式传错,或者没提前清理表中重复的脏数据导致。
正确操作步骤
1. 提前清理脏数据
执行迁移前必须先处理表中重复的sku、barcode数据,否则唯一约束会创建失败,可以先执行以下SQL排查重复数据(因为模型开启了paranoid软删,需要过滤已删除数据):
-- 排查重复sku SELECT sku, COUNT(*) as count FROM Products WHERE deletedAt IS NULL GROUP BY sku HAVING count > 1; -- 排查重复barcode SELECT barcode, COUNT(*) as count FROM Products WHERE deletedAt IS NULL GROUP BY barcode HAVING count > 1;
把查询到的重复条目全部处理(修改重复值、删除无效条目均可),保证两个字段无重复值后再执行后续操作。
2. 编写正确的迁移文件
推荐使用addConstraint方法创建唯一约束,跨数据库兼容性最好,代码如下:
"use strict"; module.exports = { async up(queryInterface, Sequelize) { // 为sku字段添加唯一约束 await queryInterface.addConstraint("Products", { fields: ["sku"], type: "unique", name: "unique_products_sku" }); // 为barcode字段添加唯一约束 await queryInterface.addConstraint("Products", { fields: ["barcode"], type: "unique", name: "unique_products_barcode" }); }, async down(queryInterface, Sequelize) { // 回滚时删除对应约束 await queryInterface.removeConstraint("Products", "unique_products_sku"); await queryInterface.removeConstraint("Products", "unique_products_barcode"); } };
如果偏好使用addIndex方法,正确参数写法如下(注意第二个参数必须传数组):
async up(queryInterface, Sequelize) { await queryInterface.addIndex("Products", ["sku"], { unique: true, name: "unique_products_sku" }); await queryInterface.addIndex("Products", ["barcode"], { unique: true, name: "unique_products_barcode" }); }
不推荐使用
changeColumn添加唯一约束,不同数据库对该方法的实现兼容性差,容易出现不可预期的问题。
3. 同步更新模型配置
修改Product模型文件,给sku、barcode字段补充unique: true配置,保证模型层和数据库结构一致:
// sku字段配置修改为 sku: { type: DataTypes.STRING, allowNull: false, unique: true, // 新增该行 validate: { notNull: { msg: "Product SKU cannot be empty", }, notEmpty: { msg: "Product SKU cannot be empty", }, }, }, // barcode字段配置修改为 barcode: { type: DataTypes.STRING, allowNull: false, unique: true, // 新增该行 validate: { notNull: { msg: "Product barcode cannot be empty", }, notEmpty: { msg: "Product barcode cannot be empty", }, }, },
写完后执行迁移命令即可完成唯一约束添加。
内容的提问来源于stack exchange,提问作者Muhammad Haekal
相关产品推荐
相关产品推荐

