勇敢就是向前走

Sequelize插入时主键冲突的解决方案

源起

问题出现:一言爬虫使用Sequelize插入唯一键('content')和先前有重复的数据,会报错。
这里是我的数据库结构,


id是int类型AI自增,content是唯一键并开了索引。

解决尝试——数据库层面

通过模拟并构建SQL命令复现错误,发现问题出在content数据有重复。因为其中只要有一条重复,插入失败,全部都会失败。但id还依然保持自增。

尝试在数据库(mysql)层面解决这一问题,即尝试修改结构使content字段重复不返回失败,并在重复时,不插入新纪录。
查询资料得到如下内容:

  1. 重复时,更新旧记录

重复时仅更新 ON DUPLICATE KEY UPDATE 后面的字段,其它字段都不更新

INSERT INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES 
('lilisss', 100, 'c', '2001-01-02 00:00:00', 2)
ON DUPLICATE KEY UPDATE  name = CONCAT(values(name), '_'), age = values(age) + 20;

重复时用新记录覆盖旧记录

INSERT INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES 
('lili', 19, 'c', '2001-01-02 00:00:00', 2)
ON DUPLICATE KEY UPDATE  name = values(name), age = values(age), sex = values(sex), birthday = values(birthday), class = values (class);
  1. 重复时,不插入新纪录
INSERT IGNORE INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES ('lili', 19, 'm', '2001-01-02 00:00:00', 2);

重复时删除重建,删除原语句,插入新语句

REPLACE INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES 
('lilissssss', 19, 's', '2001-01-02 00:00:00', 2);
  1. 重复时,删除旧记录,插入新记录
REPLACE INTO `test`.`person`(`name`, `age`, `sex`, `birthday`, `class`) VALUES ('lilissssss', 19, 's', '2001-01-02 00:00:00', 2);

但是我总不能使用了Sequelize还使用原生SQL吧,于是开始寻找Sequelize层面的解决方案。

解决尝试——Sequelize层面

因为我是批量新增数据,故使用方法Model.bulkCreate([…object])
例如:

let params = [{"name": "张三", "age": 21},{"name": "小李", "age": 20}];
let data = await model.bulkCreate(params);

以上代码便可以批量在数据库中插入数据,但是默认不会过滤掉重复的内容,比如我这次的数组里已经有张三这个人,下一次我插入数据库中就应该只插入小李而不会再次存入张三。

与此同时,我们应该在定义数据模型的时候在这两个字段加上唯一索引,不然是无效的。
例如:

name: {
    type: DataTypes.STRING(128),
    unique: true, //唯一
    allowNull: false, //将 allowNull 设置为 false 将为该列添加 NOT NULL
},
age: {
    type: DataTypes.INTEGER,
    unique: true, //唯一
    allowNull: false, //将 allowNull 设置为 false 将为该列添加 NOT NULL
},

于是乎:

let params = [{"name": "张三", "age": 21},{"name": "小李", "age": 20}];
let data = await model.bulkCreate(params,{
    updateOnDuplicate:['name','age']
});

这样就可以完美插入数据啦!!!

资料查询清单:

  1. Sequelize 中文文档索引
  2. 使用Sequelize--廖雪峰
  3. mysql 插入重复——小猪快点跑
  4. koa2+sequelize批量新增如何避免重复——莫等闲

添加新评论