方法操作

方法操作用于原生SQL执行,相对链式操作更偏底层操作一些,在ORM链式操作执行不了太过于复杂的SQL操作时,可以交给方法操作来处理。

接口文档: https://pkg.go.dev/github.com/gogf/gf/v2/database/gdb

常用方法:

本文档的方法列表可能滞后于于代码,详细的方法列表请查看接口文档,以下方法仅供参考。

// SQL操作方法,返回原生的标准库sql对象
Query(ctx context.Context, query string, args ...interface{}) (*sql.Rows, error)
Exec(ctx context.Context, query string, args ...interface{}) (sql.Result, error)
Prepare(ctx context.Context, query string) (*sql.Stmt, error)

// 数据表记录查询:
// 查询单条记录、查询多条记录、获取记录对象、查询单个字段值(链式操作同理) 
GetAll(ctx context.Context, sql string, args ...interface{}) (Result, error)
GetOne(ctx context.Context, sql string, args ...interface{}) (Record, error)
GetValue(ctx context.Context, sql string, args ...interface{}) (Value, error)
GetArray(ctx context.Context, sql string, args ...interface{}) ([]Value, error)
GetCount(ctx context.Context, sql string, args ...interface{}) (int, error)
GetScan(ctx context.Context, objPointer interface{}, sql string, args ...interface{}) error

// 数据单条操作
Insert(ctx context.Context, table string, data interface{}, batch...int) (sql.Result, error)
Replace(ctx context.Context, table string, data interface{}, batch...int) (sql.Result, error)
Save(ctx context.Context, table string, data interface{}, batch...int) (sql.Result, error)

// 数据修改/删除
Update(ctx context.Context, table string, data interface{}, condition interface{}, args ...interface{}) (sql.Result, error)
Delete(ctx context.Context, table string, condition interface{}, args ...interface{}) (sql.Result, error)

简要说明:

  1. Query是原始的数据查询方法,返回的是原生的标准库的结果集对象,需要自行解析。推荐使用Get*方法,会对结果自动做解析。
  2. Exec方法用于写入/更新的SQL的操作。
  3.  在执行数据查询时推荐使用Get*系列查询方法。
  4. Insert/Replace/Save方法中的data参数支持的数据类型为:string/map/slice/struct/*struct,当传递为slice类型时,自动识别为批量操作,此时batch参数有效。

操作示例

1. ORM对象

// 获取默认配置的数据库对象(配置名称为"default")
db := g.DB()

// 获取配置分组名称为"user-center"的数据库对象
db := g.DB("user-center")

// 使用原生单例管理方法获取数据库对象单例
db, err := gdb.Instance()
db, err := gdb.Instance("user-center")

// 注意不用的时候不需要使用Close方法关闭数据库连接(并且gdb也没有提供Close方法),
// 数据库引擎底层采用了链接池设计,当链接不再使用时会自动关闭

2. 数据写入

r, err := db.Insert(ctx, "user", gdb.Map {
    "name": "john",
})

3. 数据查询(列表)

list, err := db.GetAll(ctx, "select * from user limit 2")
list, err := db.GetAll(ctx, "select * from user where age > ? and name like ?", g.Slice{18, "%john%"})
list, err := db.GetAll(ctx, "select * from user where status=?", g.Slice{1})

4. 数据查询(单条)

one, err := db.GetOne(ctx, "select * from user limit 2")
one, err := db.GetOne(ctx, "select * from user where uid=1000")
one, err := db.GetOne(ctx, "select * from user where uid=?", 1000)
one, err := db.GetOne(ctx, "select * from user where uid=?", g.Slice{1000})

5. 数据保存

r, err := db.Save(ctx, "user", gdb.Map {
    "uid"  :  1,
    "name" : "john",
})

6. 批量操作

其中batch参数用于指定批量操作中分批写入条数数量(默认是10)。

_, err := db.Insert(ctx, "user", gdb.List {
    {"name": "john_1"},
    {"name": "john_2"},
    {"name": "john_3"},
    {"name": "john_4"},
}, 10)

7. 数据更新/删除

// db.Update/db.Delete 同理
// UPDATE `user` SET `name`='john' WHERE `uid`=10000
r, err := db.Update(ctx, "user", gdb.Map {"name": "john"}, "uid=?", 10000)
// UPDATE `user` SET `name`='john' WHERE `uid`=10000
r, err := db.Update(ctx, "user", "name='john'", "uid=10000")
// UPDATE `user` SET `name`='john' WHERE `uid`=10000
r, err := db.Update(ctx, "user", "name=?", "uid=?", "john", 10000)

注意,参数域支持并建议使用预处理模式(使用?占位符)进行输入,避免SQL注入风险。




Content Menu

  • No labels

5 Comments

  1. batch参数 有具体点的含义吗?看了文档好像没找到

    1. 表示批量写入数据时的每批次数量,这个数值跟你数据库服务器配置的SQL BufferSize数值有关系。

  2. db.Query("select * from table1") 为什么是 {} 呢?用db.GetAll(..就正常

  3. 建议实现预定义的错误码定义,方便调用时判断是否时不存在,给出友好提示。

    // ------------------------------ 写法1 ----------------------------
    func (s *peerService) GetOne(peerName string) (*model.BlcPeer, error) {
    	var peer model.BlcPeer
    
    	whereSet := fmt.Sprintf("peer_id='%s'", peerName)
    	err := dao.BlcPeer.Where(whereSet).Struct(&peer)
    	if err != nil {
    		return nil, err
    	}
    
    	// 建议实现这种错误定义,方便判断
    	if err == gerror.Error.NotFound {
    		return nil, fmt.Errorf("记录不存在")
    	}
    
    	return &peer, nil
    }
    
    // --------------------------------- 写法2 -------------------------
    func (s *peerService) GetOne(peerName string) (*model.BlcPeer, error) {
    	var peer model.BlcPeer
    
    	whereSet := fmt.Sprintf("peer_id='%s'", peerName)
    	//err := dao.BlcPeer.Where(whereSet).Struct(&peer)
    	pModel := dao.BlcPeer.Where(whereSet)
    	if pModel == nil {
    		return nil, fmt.Errorf("记录不存在")
    	}
    	err := pModel.Struct(&peer)
    	if err != nil {
    		return nil, err
    	}
    
    	return &peer, nil
    }
      
  4. 差评,这样的SQL语句阁下应该如何应对?

    select id from xxx where xxx = ?;

    请问如何将结果解析到一个int64数组?