原生查询

大多数时候,你都不应该使用原生查询。只有在无可奈何的情况下才应该考虑原生查询。使用原生查询可以:

  • 无需使用 ORM 表定义
  • 多数据库,都可直接使用占位符号 ?,自动转换
  • 查询时的参数,支持使用 Model Struct 和 Slice, Array

例如:

  1. o := orm.NewOrm()
  2. ids := []int{1, 2, 3}
  3. var r RawSter
  4. r = o.Raw("SELECT name FROM user WHERE id IN (?, ?, ?)", ids)

这里得到一个RawSeter的实例,它包含极多的方法。

Exec

执行 sql 语句,返回 sql.Result 对象。

  1. res, err := o.Raw("UPDATE user SET name = ?", "your").Exec()
  2. if err == nil {
  3. num, _ := res.RowsAffected()
  4. fmt.Println("mysql row affected nums: ", num)
  5. }

一般来说,使用该方法的应该是非 SELECT 语句。

QueryRow 和 QueryRows

这两个方法的定义是:

  1. QueryRow(containers ...interface{}) error
  2. QueryRows(containers ...interface{}) (int64, error)

这两个方法会把返回的数据赋值给container

例如:

  1. var name string
  2. var id int
  3. // id==2 name=="slene"
  4. dORM.Raw("SELECT 'id','name' FROM `user`").QueryRow(&id,&name)

在这个例子里面,QueryRow会查询得到两列,并且只有一行。在这种情况下,两列的值分别被赋值给idname

使用QueryRows的例子:

  1. var ids []int
  2. var names []int
  3. query = "SELECT 'id','name' FROM `user`"
  4. // ids=>{1,2},names=>{"nobody","slene"}
  5. num, err = dORM.Raw(query).QueryRows(&ids,&names)

同样地,QueryRows也是按照列来返回,因此可以注意到在例子里面我们声明了两个切片,分别对应于idname两个列。

SetArgs

该方法用于设置参数。注意的是,参数个数必须和占位符?的数量保持一致。其定义:

  1. SetArgs(...interface{}) RawSeter

例如:

  1. var name string
  2. var id int
  3. query := "SELECT 'id','name' FROM `user` WHERE `id`=?"
  4. // id==2 name=="slene"
  5. // 等效于"SELECT 'id','name' FROM `user` WHERE `id`=1"
  6. dORM.Raw(query).SetArgs(1).QueryRow(&id,&name)

也可以用于单条 sql 语句,重复利用,替换参数然后执行。

  1. res, err := r.SetArgs("arg1", "arg2").Exec()
  2. res, err := r.SetArgs("arg1", "arg2").Exec()

Values / ValuesList / ValuesFlat

  1. Values(container *[]Params, cols ...string) (int64, error)
  2. ValuesList(container *[]ParamsList, cols ...string) (int64, error)
  3. ValuesFlat(container *ParamsList, cols ...string) (int64, error)

参考QuerySeter中的:

RowsToMap

  1. RowsToMap(result *Params, keyCol, valueCol string) (int64, error)

SQL 查询结果是这样:

name value
total 100
found 200

查询结果匹配到 map 里

  1. res := make(orm.Params)
  2. nums, err := o.Raw("SELECT name, value FROM options_table").RowsToMap(&res, "name", "value")
  3. // res is a map[string]interface{}{
  4. // "total": 100,
  5. // "found": 200,
  6. // }

RowsToStruct

  1. RowsToStruct(ptrStruct interface{}, keyCol, valueCol string) (int64, error)

SQL 查询结果是这样

name value
total 100
found 200

查询结果匹配到 struct 里

  1. type Options struct {
  2. Total int
  3. Found int
  4. }
  5. res := new(Options)
  6. nums, err := o.Raw("SELECT name, value FROM options_table").RowsToStruct(res, "name", "value")
  7. fmt.Println(res.Total) // 100
  8. fmt.Println(res.Found) // 200

匹配支持的名称转换为 snake -> camel, eg: SELECT user_name … 需要你的 struct 中定义有 UserName

Prepare

  1. Prepare() (RawPreparer, error)

用于一次 prepare 多次 exec,以提高批量执行的速度。

  1. p, err := o.Raw("UPDATE user SET name = ? WHERE name = ?").Prepare()
  2. res, err := p.Exec("testing", "slene")
  3. res, err = p.Exec("testing", "astaxie")
  4. // ...
  5. p.Close() // 别忘记关闭 statement