golang
有若干常用orm
库, 如gorm, sqlx等, 在这里总结一下在生产中遇到的问题:
sqlx:
- 1)对于一些经过中间件处理的mysql数据库,即直接访问的实体不是
mysql
本身, 对于这类数据库实体, 有可能不支持prepare
命令类型。
PREPARE stmt FROM `SELECT * FROM xxx WHERE report_time>=? AND report_time<?`;
ERROR 1149 (42000): 1.1-7: syntax error, unexpected NAME
而sqlx
往往会在大部分接口处实现prepare
命令, 导致在orm发出的普通query查询等语句中, 往往会先运行prepare
命令, 如下数据库支持prepare
,其日志:
| 2019-09-11 15:51:42.080353 | root[root] @ [172.24.73.128] | 1473 | 0 | Prepare | SELECT * FROM task_config WHERE task_id = ? |
| 2019-09-11 15:51:42.080373 | root[root] @ [172.24.73.128] | 1473 | 0 | Execute | SELECT * FROM task_config WHERE task_id = 202 |
因此,对于不支持prepare
的mysql
实体,必须使用此链接办法,才能避免出现数据库查询报错, 报错类型多为针对prepare
的?
, 如:
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? ......
- 2)
sqlx
支持unsafa
, 其用于用户只希望将部分结果存于结构体中:
udb := db.Unsafe()
err = udb.Get(&p, "SELECT * FROM person, place LIMIT 1;")
但unsafe
只作用于以上将查询结果对象作为参数传入的情况, 对于Query
等不支持, 这时候需要用Queryx
, 以下示例用于总结1
,2
两点:
query := fmt.Sprintf("SELECT * FROM xxx WHERE xxx BETWEEN %v AND %v", start, end)
udb := db.Unsafe()
rows, err := udb.Queryx(query)
switch {
case err == sql.ErrNoRows:
return nil, nil
case err != nil:
return nil, err
}
var ms []Ms
if rows != nil {
err = sqlx.StructScan(rows, &ms)
rows.Close()
}