You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Gorm AutoMigrate导入CSV时如何避免重复邮箱数据插入?

实现方案

1. 调整模型结构,添加带条件的唯一索引

给Emails字段添加带过滤条件的唯一索引,仅对非空邮箱做唯一性约束,空字符串不受唯一规则限制:

type User struct {
    // 注意:gorm.Model已自带uint类型的ID、CreatedAt等字段,和你自定义的int64 ID会产生冲突,建议二选一保留
    gorm.Model
    // ID                           int64  `csv:"_" db:"id"`
    FirstName                    string `csv:"First name" db:"first_name"`
    LastName                     string `csv:"Last name" db:"last_name"`
    // 仅非空邮箱走唯一约束
    Emails                       string `csv:"Emails" db:"emails" gorm:"uniqueIndex:idx_unique_email,where:emails != ''"`
}

执行AutoMigrate时会自动创建该条件索引,无需手动操作数据库。

2. 插入数据时添加冲突处理逻辑

引入Gorm的冲突处理从句,遇到非空邮箱重复时直接跳过插入,不会抛出异常:

// 首先导入依赖包
import "gorm.io/gorm/clause"

func main() {
    // 补充原有代码缺失的error判断
    file, err := os.Open(os.Args[1])
    if err != nil {
        panic(err)
    }
    defer file.Close()
    users := []User{}
    err = gocsv.Unmarshal(file, &users)
    if err != nil {
        panic(err)
    }
    db, err := gorm.Open(postgres.Open("host=xxx.xx.x.x user=database password=password dbname=database port=5432 sslmode=disable"))
    if err != nil {
        panic(err)
    }

    err = db.AutoMigrate(&User{})
    if err != nil {
        panic(err)
    }

    // 插入时添加冲突跳过逻辑
    result := db.Clauses(clause.OnConflict{
        Columns: []clause.Column{{Name: "emails"}},
        // 仅非空邮箱触发冲突校验
        Where: clause.Where{
            Exprs: []clause.Expression{clause.Neq{Column: "emails", Value: ""}},
        },
        DoNothing: true,
    }).Create(&users)
    if result.Error != nil {
        panic(result.Error)
    }
    // 可通过RowsAffected查看实际成功插入的行数
    fmt.Printf("成功插入%d条数据\n", result.RowsAffected)
}

注意事项

  • 如果数据库中已经存在users表且有重复的非空邮箱数据,执行AutoMigrate时会因为索引创建失败报错,需要先清理历史重复数据再执行迁移
  • 空邮箱字段不受唯一约束限制,可正常插入多条记录,完全匹配你的需求

内容的提问来源于stack exchange,提问作者Benk I

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.02 22:54:02