GORM 数据库错误处理
数据库层面错误如唯一约束冲突、外键约束违反等需特殊处理,本文介绍识别方法与处理策略。
数据库错误类型
数据库错误由底层驱动返回,需通过错误码或类型判断:
Go
import (
"errors"
"gorm.io/gorm"
"gorm.io/driver/mysql"
)
// MySQL 错误码
const (
ErrDupEntry = 1062 // 唯一约束冲突
ErrNoReferencedRow = 1452 // 外键约束违反
ErrRowIsReferenced = 1451 // 被引用无法删除
)
唯一约束冲突处理
Go
import "github.com/go-sql-driver/mysql"
err := db.Create(&User{Email: "test@example.com"}).Error
if err != nil {
var mysqlErr *mysql.MySQLError
if errors.As(err, &mysqlErr) && mysqlErr.Number == ErrDupEntry {
return fmt.Errorf("邮箱已存在")
}
}
外键约束违反处理
Go
// 删除被外键引用的记录
err := db.Delete(&user).Error
if err != nil {
var mysqlErr *mysql.MySQLError
if errors.As(err, &mysqlErr) && mysqlErr.Number == ErrRowIsReferenced {
return fmt.Errorf("该用户有关联订单,无法删除")
}
}
// 插入引用不存在的外键记录
err := db.Create(&Order{UserID: 999}).Error
if errors.As(err, &mysqlErr) && mysqlErr.Number == ErrNoReferencedRow {
return fmt.Errorf("用户不存在")
}
错误处理策略
| 错误类型 | 处理策略 |
|---|---|
| 唯一约束冲突 | 返回友好提示,或改为更新操作 |
| 外键违反 | 检查关联数据是否存在 |
| 数据类型错误 | 检查字段类型与长度 |
| 连接错误 | 重试或切换数据源 |
Go
// 策略1: 冲突时改为更新
err := db.Create(&user).Error
if isDuplicateError(err) {
db.Where("email = ?", user.Email).Updates(user)
}
// 策略2: 使用事务回滚
tx := db.Begin()
defer func() {
if r := recover(); r != nil {
tx.Rollback()
}
}()
不同数据库错误码不同,PostgreSQL 使用 pq 错误码,SQLite 使用 sqlite.ErrConstraint。
要点总结
- 数据库错误通过
errors.As解析具体错误类型 - 唯一约束冲突返回 1062 错误码
- 外键约束违反分 1451(被引用)和 1452(引用不存在)
- 根据错误类型采取重试、回滚或提示策略
文章存放路径:D:\git2\jwdev\articles\GORM\进阶\错误处理与日志\数据库错误处理.md
📝 发现内容有误?点击此处直接编辑