为了账号安全,请及时绑定邮箱和手机立即绑定

如何从 GORM 结构模型生成 SQL 代码?

如何从 GORM 结构模型生成 SQL 代码?

Go
慕勒3428872 2022-08-09 20:16:09
我正在使用 goose 来管理我的数据库迁移,但我需要直接在迁移文件中写入 SQL 句子。有一种方法可以直接从GORM模型生成SQL?
查看完整描述

3 回答

?
达令说

TA贡献1821条经验 获得超6个赞

遗憾的是,使用该选项不会使迁移 SQL 语句对调用方可用,就像使用普通查询一样。gorm.Session{DryRun: true}


我现在能看到的唯一方法是在通过重新实现接口来记录迁移时捕获迁移运行的SQL。具体来说就是方法。gorm.io/gorm/logger.InterfaceTrace


type Interface interface {

    LogMode(LogLevel) Interface

    Info(context.Context, string, ...interface{})

    Warn(context.Context, string, ...interface{})

    Error(context.Context, string, ...interface{})

    Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error)

}

在内部,您可以调用该函数参数来获取 SQL 和 ,您可以执行任何操作。TracefcRowsAffected


例如:


import (

    "time"

    "context"

    "gorm.io/gorm/logger"

)


type RecorderLogger struct {

    logger.Interface

    Statements []string

}


func (r *RecorderLogger) Trace(ctx context.Context, begin time.Time, fc func() (string, int64), err error) {

    sql, _ := fc()

    r.Statements = append(r.Statements, sql)

}

现在将其用作:


recorder := RecorderLogger{logger.Default.LogMode(logger.Info)}

session := db.Session(&gorm.Session{

    Logger: &recorder

})

session.AutoMigrate(&Model{}, ...)

// or 

session.Migrator().CreateTable(&Model{}, ...) // or any method therein

// now recorder.Statements contains the statements run during migration

这是非常棘手的,你可能会遇到问题,因为修改数据库的当前状态并将其迁移到模型所需的状态(最多一点),为此,当前数据库必须反映生产数据库(或您希望迁移的任何数据库)的当前状态。因此,如果您小心,您可以构建该工具来帮助您启动迁移脚本,但是要正确获得迁移系统的优势,例如您需要亲自动手使用SQL:)AutoMigrategoose


查看完整回答
反对 回复 2022-08-09
?
红颜莎娜

TA贡献1842条经验 获得超12个赞

我个人会使用Gorm内部可用的迁移功能,但对于您的情况,我们可以执行以下操作。


首先,Gorm中有一个名为“Dry Run”的功能,您可以使用它来查看在执行查询时执行的SQL语句。不幸的是,我看不出在使用迁移时这是可能的。所以我建议使用github.com/DATA-DOG/go-sqlmock


我通常会将其用于测试目的,但您可以暂时使用它来获取单独迁移所需的SQL。


package main


import (

    "database/sql"

    "time"


    "github.com/DATA-DOG/go-sqlmock"

    "gorm.io/driver/mysql"

    "gorm.io/gorm"

)


type Model struct {

    ID          uint64 `gorm:"primaryKey"`

    Name        string `gorm:"index"`

    Description string

    CreatedAt   time.Time

    LastLogin   sql.NullTime

}


func main() {

    sqlDB, _, err := sqlmock.New()

    if err != nil {

        panic(err)

    }


    gormDB, err := gorm.Open(mysql.New(mysql.Config{

        Conn:                      sqlDB,

        SkipInitializeWithVersion: true,

    }), &gorm.Config{})

    if err != nil {

        panic(err)

    }


    defer sqlDB.Close()


    gormDB.AutoMigrate(&Model{})

}


这将给你一个这样的结果


all expectations were already fulfilled, call to ExecQuery 'CREATE TABLE `models` (`id` bigint unsigned AUTO_INCREMENT,`name` varchar(191),`description` longtext,`created_at` datetime(3) NULL,`last_login` datetime(3) NULL,PRIMARY KEY (`id`),INDEX idx_models_name (`name`))' with args [] was not expected

[0.003ms] [rows:0] CREATE TABLE `models` (`id` bigint unsigned AUTO_INCREMENT,`name` varchar(191),`description` longtext,`created_at` datetime(3) NULL,`last_login` datetime(3) NULL,PRIMARY KEY (`id`),INDEX idx_models_name (`name`))

其中包含所需的 SQL 语句。这感觉非常笨拙,但会给你你需要的结果


查看完整回答
反对 回复 2022-08-09
?
当年话下

TA贡献1890条经验 获得超9个赞

你可以使用这个库:https://github.com/sunary/sqlize

它允许您从模型创建sql,还支持模型和现有sql之间的差异迁移。


查看完整回答
反对 回复 2022-08-09
  • 3 回答
  • 0 关注
  • 708 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信