Skip to content
0

Gorm 使用问题大全

仅记录已经遇到的问题,其他问题请参考 Gorm 官方文档

Error 1170 (42000): BLOB/TEXT column 'userId' used in key specification without a key length

背景

使用 gorm 连接 mysql 时,执行 AutoMigrate 方法时出现错误:

Error 1170 (42000): BLOB/TEXT column 'userId' used in key specification without a key length

创建数据库表的SQL如下,添加了 userId 字段作为唯一索引:

sql
CREATE TABLE `user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
  `userId` varchar(253) NOT NULL DEFAULT '' COMMENT '用户 ID',
  `username` varchar(253) NOT NULL DEFAULT '' COMMENT '用户名称',
  `status` tinyint(3) unsigned NOT NULL DEFAULT 1 COMMENT '用户状态,0-禁用;1-启用',
  `nickname` varchar(253) NOT NULL DEFAULT '' COMMENT '用户昵称',
  `password` varchar(64) NOT NULL DEFAULT '' COMMENT '用户加密后的密码',
  `email` varchar(253) NOT NULL DEFAULT '' COMMENT '用户电子邮箱',
  `phone` varchar(16) NOT NULL DEFAULT '' COMMENT '用户手机号',
  `createdAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updatedAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_username` (`username`),
  UNIQUE KEY `idx_user_id` (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户表';

在使用 Go 编码时,我是使用了 gen-gorm-models 来生成 gorm 模型, 生成的 Model 定义如下:

go
// UserM 用户表
type UserM struct {
	ID        int64      `gorm:"column:id;primaryKey;autoIncrement:true;comment:主键 ID" json:"id"`                     // 主键 ID
	UserID    string     `gorm:"column:userId;not null;comment:用户 ID" json:"userId"`                                  // 用户 ID
	Username  string     `gorm:"column:username;not null;comment:用户名称" json:"username"`                               // 用户名称
	Status    *int32     `gorm:"column:status;not null;default:1;comment:用户状态,0-禁用;1-启用" json:"status"`               // 用户状态,0-禁用;1-启用
	Nickname  string     `gorm:"column:nickname;not null;comment:用户昵称" json:"nickname"`                               // 用户昵称
	Password  string     `gorm:"column:password;not null;comment:用户加密后的密码" json:"password"`                           // 用户加密后的密码
	Email     string     `gorm:"column:email;not null;comment:用户电子邮箱" json:"email"`                                   // 用户电子邮箱
	Phone     string     `gorm:"column:phone;not null;comment:用户手机号" json:"phone"`                                    // 用户手机号
	CreatedAt *time.Time `gorm:"column:createdAt;not null;default:current_timestamp;comment:创建时间" json:"createdAt"`   // 创建时间
	UpdatedAt *time.Time `gorm:"column:updatedAt;not null;default:current_timestamp;comment:最后修改时间" json:"updatedAt"` // 最后修改时间
}

可以看到,gorm tag 没有指定 userId 字段的长度(即 varchar(64)),导致 mysql 报错。

解决方法

修改代码生成工具的代码,将 FieldWithTypeTag 由 false 改为 true,重新生成模型即可。

  • FieldWithTypeTag:设置为true,自动从数据库获取字段类型和长度信息。

Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'createdAt' at row 1

错误信息

shell
error: code = 500 reason = UserCreateFailed message = create user failed: Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'createdAt' at row 1 metadata = map[] cause = <nil>

背景

使用 gorm 连接 mysql 时,insert 数据时,createdAt 字段没有设置 value,导致报错。

创建数据库表的 sql 如下,添加了 createdAt 字段的默认值为当前时间。

sql
CREATE TABLE `user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
  `userId` varchar(253) NOT NULL DEFAULT '' COMMENT '用户 ID',
  `username` varchar(253) NOT NULL DEFAULT '' COMMENT '用户名称',
  `status` tinyint(3) unsigned NOT NULL DEFAULT 1 COMMENT '用户状态,0-禁用;1-启用',
  `nickname` varchar(253) NOT NULL DEFAULT '' COMMENT '用户昵称',
  `password` varchar(64) NOT NULL DEFAULT '' COMMENT '用户加密后的密码',
  `email` varchar(253) NOT NULL DEFAULT '' COMMENT '用户电子邮箱',
  `phone` varchar(16) NOT NULL DEFAULT '' COMMENT '用户手机号',
  `createdAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  `updatedAt` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最后修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_username` (`username`),
  UNIQUE KEY `idx_user_id` (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户表';

在使用 Go 编码时,我是使用了 gen-gorm-models 来生成 gorm 模型, 生成的 Model 定义如下:

go
type UserM struct {
	ID        int64     `gorm:"column:id;type:bigint unsigned;primaryKey;autoIncrement:true;comment:主键 ID" json:"id"`              // 主键 ID
	UserID    string    `gorm:"column:userId;type:varchar(253);not null;comment:用户 ID" json:"userId"`                              // 用户 ID
	Username  string    `gorm:"column:username;type:varchar(253);not null;comment:用户名称" json:"username"`                           // 用户名称
	Status    int32     `gorm:"column:status;type:tinyint unsigned;not null;default:1;comment:用户状态,0-禁用;1-启用" json:"status"`       // 用户状态,0-禁用;1-启用
	Nickname  string    `gorm:"column:nickname;type:varchar(253);not null;comment:用户昵称" json:"nickname"`                           // 用户昵称
	Password  string    `gorm:"column:password;type:varchar(64);not null;comment:用户加密后的密码" json:"password"`                        // 用户加密后的密码
	Email     string    `gorm:"column:email;type:varchar(253);not null;comment:用户电子邮箱" json:"email"`                               // 用户电子邮箱
	Phone     string    `gorm:"column:phone;type:varchar(16);not null;comment:用户手机号" json:"phone"`                                 // 用户手机号
	CreatedAt time.Time `gorm:"column:createdAt;type:datetime;not null;default:current_timestamp;comment:创建时间" json:"createdAt"`   // 创建时间
	UpdatedAt time.Time `gorm:"column:updatedAt;type:datetime;not null;default:current_timestamp;comment:最后修改时间" json:"updatedAt"` // 最后修改时间
}

运行代码,调用 CreateUser 方法,报错如下:

shell
error: code = 500 reason = UserCreateFailed message = create user failed: Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'createdAt' at row 1 metadata = map[] cause = <nil>

查看程序日志,发现是在调用 CreateUser 方法时,createdAt 字段的值为 0001-01-01T00:00:00Z,导致 mysql 报错。

shell
Failed to insert object into database   {"object": {"id":1,"userId":"user-droan9","username":"art","status":1,"nickname":"art","password":"$2a$10$KDmXsFSZg6.WQHo/BcYn3ewWxnMCRGuxjbekxrMTfD3FDzHnXiyCW","email":"[email protected]","phone":"13800000000","createdAt":"0001-01-01T00:00:00Z","updatedAt":"2025-11-06T15:30:13.359+08:00"}, "error": "Error 1292 (22007): Incorrect datetime value: '0000-00-00' for column 'createdAt' at row 1"}

那么如何解决这个问题呢?

解决方法

查看官方文档的约定,GORM使用字段 CreatedAt 和 UpdatedAt 来自动跟踪记录的创建和更新时间。

所以创建数据库表时我们不再设置默认值为当前时间,而是在代码中由 gorm 自动设置。

sql
CREATE TABLE `user` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
  `userId` varchar(253) NOT NULL DEFAULT '' COMMENT '用户 ID',
  `username` varchar(253) NOT NULL DEFAULT '' COMMENT '用户名称',
  `status` tinyint(3) unsigned NOT NULL DEFAULT 1 COMMENT '用户状态,0-禁用;1-启用',
  `nickname` varchar(253) NOT NULL DEFAULT '' COMMENT '用户昵称',
  `password` varchar(64) NOT NULL DEFAULT '' COMMENT '用户加密后的密码',
  `email` varchar(253) NOT NULL DEFAULT '' COMMENT '用户电子邮箱',
  `phone` varchar(16) NOT NULL DEFAULT '' COMMENT '用户手机号',
  `createdAt` datetime NOT NULL COMMENT '创建时间',
  `updatedAt` datetime NOT NULL COMMENT '最后修改时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `idx_username` (`username`),
  UNIQUE KEY `idx_user_id` (`userId`)
) ENGINE=InnoDB AUTO_INCREMENT=0 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci COMMENT='用户表';

生成的 GORM Model 中,CreatedAtUpdatedAt 字段的类型为 time.Time,gorm 会自动将其设置为当前时间。

go
type UserM struct {
	ID        int64     `gorm:"column:id;type:bigint unsigned;primaryKey;autoIncrement:true;comment:主键 ID" json:"id"`        // 主键 ID
	UserID    string    `gorm:"column:userId;type:varchar(253);not null;comment:用户 ID" json:"userId"`                        // 用户 ID
	Username  string    `gorm:"column:username;type:varchar(253);not null;comment:用户名称" json:"username"`                     // 用户名称
	Status    int32     `gorm:"column:status;type:tinyint unsigned;not null;default:1;comment:用户状态,0-禁用;1-启用" json:"status"` // 用户状态,0-禁用;1-启用
	Nickname  string    `gorm:"column:nickname;type:varchar(253);not null;comment:用户昵称" json:"nickname"`                     // 用户昵称
	Password  string    `gorm:"column:password;type:varchar(64);not null;comment:用户加密后的密码" json:"password"`                  // 用户加密后的密码
	Email     string    `gorm:"column:email;type:varchar(253);not null;comment:用户电子邮箱" json:"email"`                         // 用户电子邮箱
	Phone     string    `gorm:"column:phone;type:varchar(16);not null;comment:用户手机号" json:"phone"`                           // 用户手机号
	CreatedAt time.Time `gorm:"column:createdAt;type:datetime;not null;comment:创建时间" json:"createdAt"`                       // 创建时间
	UpdatedAt time.Time `gorm:"column:updatedAt;type:datetime;not null;comment:最后修改时间" json:"updatedAt"`                     // 最后修改时间
}

最后,调用 CreateUser 方法,即可成功创建用户。

更多关于时间的使用姿势

AutoMigrate 和 索引管理

查看官方文档

使用 AutoMigrate 会创建表、缺失的外键、约束、列和索引。 It will change existing column’s type if its size, precision changed, or if it’s changing from non-nullable to nullable.

当手动创建表的索引,并且使用了 gorm gen 包自动生成 Model 代码,那么需要配置 FieldWithIndexTagtrue,否则会出现索引丢失问题。

最近更新