虽然 GOLANG 自带 SQL 库 database/sql,但为了简化代码提高编程效率,笔者推荐使用第三方库来处理数据库相关操作。
本文介绍如何使用 SQLX 库连接 MySQL 数据库并执行简单的 SELECT 查询语句。
示例代码来自 nwpc-oper/nmc-typhoon-db-client 项目,从 NMC 台风数据库中检索台风数据,计划用于 CMA-PI 上的业务系统。
安装
连接 MySQL 数据库需要下载数据库驱动 Go-MySQL-Driver。
go get -u github.com/go-sql-driver/mysql
下载 SQLX 库
go get github.com/jmoiron/sqlx
在源码中载入上述两个库
import (
创建数据库连接
SQLX 使用的数据库连接地址字符串与 SQLAlchemy 不同,格式如下所示
user:password@tcp(host:port)/database?param1=value1
为了解析时间字段,增加 parseTime=true
参数
var
执行查询
使用 sqlx.DB
对象的 Queryx()
函数执行 SQL 语句,返回值中的 rows
是一个迭代器。
querySQL
处理结果
在标准库 database/sql 中,对每行对象使用 Scan()
方法获取具体的字段值。
该方法需要为每个字段设置一个变量。例如
var (
如果检索结果中字段很多,就可能会导致代码不够简洁。
SQLX 库提供 StructScan()
方法,可以将所有字段放入一个结构体中。
下面首先定义结构体 Record
代表每行数据,再将检索结果全部转为 Record
。
定义记录结构体
为每个字段都创建对应的成员,可以使用名称为 db
的 struct tag,为字段指定对应的列名。
type
注:上面的代码中使用了自定义的数据类型 DataString
,DataFloat64
,DataInt32
和 NullDateTime
,并定义名为 csv 的 struct tag,这都是为了将结果输出到 CSV 格式文件,后面会介绍。
解析检索数据
使用 StructScan
方法根据每行结果填充 Record
对象,将所有结果放到 records
数组中。
records
输出CSV文件
使用 csvutil 库将 Records
对象输出到 CSV 文件中
自定义类型
因为数据库中的部分字段可以为空,所以不能使用内置的格式,而是使用类似 mysql.NullTime
,sql.NullString
等特殊类型。
csvutil 库在输出 CSV 文件时会调用对象的 MarshalCSV()
方法,上述这些特殊类型都没有定义该方法,所以无法直接使用。
nmc-typhoon-db-client 项目使用自定义类型封装上述类型,并为这些自定义类型创建 MarshalCSV()
方法。这就是上面提到的 DataString
,DataFloat64
,DataInt32
和 NullDateTime
几种类型。
以 DataInt32
为例说明。MarshalCSV()
方法会检测是否为空,只有不为空的情况下才会返回字节数组。
type
另外,这种方式也可以用于自定义日期和时间的序列化。
DateTime
是对 time.Time
的封装,序列化时返回 YYYYMMDDHH
格式的字符串
type
输出
csvutil.Marshal()
函数返回序列化后的字节数组,可以直接写入到文件中。
默认设置下,输出的 CSV 文件使用逗号分隔,并包含表头。
b,
讨论
当前代码还有改进空间,queryColumnsString
字符串由列名字符串数组拼接而成,与 Record
类型的成员变量名称有重复。后续可以考虑使用反射机制,直接从 Record
类型生成 queryColumnsString
字符串。
参考
nwpc-oper/nmc-typhoon-db-client
https://github.com/nwpc-oper/nmc-typhoon-db-client
《SQLAlchemy:执行简单的SQL语句》介绍使用 Python 的 SQLAlchemy 库实现同样的功能。