如何不使用DryRun模式获取GORM已执行的SQL语句?
不使用DryRun获取GORM执行SQL的实现方法
完全可以不开启DryRun模式获取已执行的SQL,推荐以下两种实现方案,均不影响SQL的正常执行,且可以捕获报错场景的SQL信息:
方案1:自定义GORM日志(推荐)
自定义日志是GORM官方推荐的全局SQL捕获方案,一次配置即可覆盖所有数据库操作
- 实现GORM的
logger.Interface接口,重写Trace方法,该方法会在每次SQL执行完成后被调用,可以直接获取到完整SQL、执行耗时、影响行数、错误信息等全量内容 - 初始化GORM实例时将自定义日志实现注册到配置中即可
示例代码:
import ( "context" "log" "time" "gorm.io/gorm/logger" ) // CustomSQLLogger 自定义GORM日志实现 type CustomSQLLogger struct { logger.Interface } // Trace 重写Trace方法捕获SQL执行信息 func (l *CustomSQLLogger) Trace(ctx context.Context, begin time.Time, fc func() (sql string, rowsAffected int64), err error) { sql, rowsAffected := fc() // 仅当SQL执行报错时记录日志,可根据业务需求调整逻辑 if err != nil { log.Printf("SQL执行失败: 错误信息=%v 执行SQL=%s 影响行数=%d 执行耗时=%v", err, sql, rowsAffected, time.Since(begin)) } // 保留原有GORM日志逻辑,可根据需求决定是否保留 l.Interface.Trace(ctx, begin, fc, err) }
GORM初始化配置示例:
import ( "gorm.io/driver/mysql" "gorm.io/gorm" "gorm.io/gorm/logger" ) dsn := "你的数据库连接串" db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{ // 注册自定义日志,可自行调整基础日志级别 Logger: &CustomSQLLogger{ Interface: logger.Default.LogMode(logger.Info), }, })
方案2:使用GORM回调捕获
如果不需要全局捕获,仅需要针对特定操作场景捕获SQL,可以使用GORM的回调机制,在对应操作执行完成后触发自定义逻辑:
// 给创建操作注册执行后回调,可同理给Update、Query、Delete等操作注册回调 err = db.Callback().Create().After("gorm:after_create").Register("log_error_sql", func(db *gorm.DB) { if db.Error != nil { // Explain方法会自动拼接参数,生成完整可执行的SQL语句 fullSQL := db.Dialector.Explain(db.Statement.SQL.String(), db.Statement.Vars...) log.Printf("创建操作SQL报错: 错误=%v 完整SQL=%s", db.Error, fullSQL) } })
注意事项
- 两种方案均不会开启DryRun模式,SQL会正常提交到数据库执行
- 若需要获取带参数的完整SQL,优先使用
Dialector.Explain方法生成,避免手动拼接参数的安全问题和格式问题
内容的提问来源于stack exchange,提问作者Eduardo Mior
相关产品推荐
相关产品推荐

