
本文详解如何在 gorm 模型结构体中正确声明跨多个字段的联合唯一索引,涵盖标签语法、迁移注意事项及常见误区,确保数据库约束准确生效。
本文详解如何在 gorm 模型结构体中正确声明跨多个字段的联合唯一索引,涵盖标签语法、迁移注意事项及常见误区,确保数据库约束准确生效。
在 GORM(v2)中,为多个字段创建联合唯一索引(Composite Unique Index),不能通过为每个字段单独添加 unique 标签来实现——那样会生成两个独立的单列唯一索引,而非一个覆盖多列的约束。正确做法是:为所有参与字段指定相同的索引名,并统一声明 unique 属性,GORM 将自动合并它们为一个复合唯一索引。
以下是一个标准示例:
type Something struct {
gorm.Model
First string `gorm:"index:idx_first_second,unique"`
Second string `gorm:"index:idx_first_second,unique"`
Third string `gorm:"column:third_name"` // 可选:自定义列名
}当执行 AutoMigrate 时,GORM 会生成类似如下 SQL(以 PostgreSQL 为例):
CREATE UNIQUE INDEX idx_first_second ON somethings (first, second);
✅ 关键要点:
- 索引名(如 idx_first_second)必须完全一致,且建议使用语义化命名,便于维护;
- 所有参与字段均需包含 index:
,unique,缺一不可; - 字段声明顺序即为索引列顺序,影响查询性能与覆盖范围(例如 (first, second) 不等价于 (second, first));
- 若还需支持前缀索引(如 MySQL 的 varchar(100) 列仅索引前 20 字符),可追加 size 参数:gorm:"index:idx_first_second,unique;size:20"。
⚠️ 注意事项:
- GORM v2 不再支持旧版 sql: 标签(如 sql:"unique_index:..."),该语法已废弃,强行使用将被忽略;
- AutoMigrate 不会自动删除或重命名已有索引;若需修改索引结构(如增删字段),应手动使用 db.Migrator().DropIndex() 配合重新迁移;
- 联合唯一索引允许任一字段为 NULL(取决于数据库方言),但多数场景下建议配合 NOT NULL 约束以避免歧义,可通过 gorm:"not null" 显式声明。
最后,推荐在模型定义后添加注释说明索引意图,提升团队可读性:
// idx_first_second ensures uniqueness across (First, Second) — e.g., no duplicate combinations.
type Something struct {
gorm.Model
First string `gorm:"index:idx_first_second,unique"`
Second string `gorm:"index:idx_first_second,unique"`
}掌握这一模式,即可稳健构建符合业务一致性的多维数据约束。










