Golang 获取MySQL表元信息
本文介绍Golang如何操作数据库,并通过获取Mysql表元信息进行实例演示。
 
1. Golang 操作DBMS
Golang 通过标准database/sql包实现了对关系型数据库很好的支持,如MySQL, MS SQL Server, Oracle 和 Postgres,当然NoSql也没有问题,如MongoDB、Redis。
 
使用Golang标准库可以很容易与Mysql交互,其他数据库也一样,可以参加Golang数据库驱动列表。
 
SQL标准库提供通用接口及常用方法用于访问或操作数据库。数据库包包括连接池,正确使用可确保线程安全。数据库包必须和具体数据库驱动包一起使用。
 
2. 连接Mysql
连接Mysql需要使用标准SQL包和Mysql驱动,Mysql驱动包实现标准包方法和接口。一般实现SQl标准包通常通过标准包暴露驱动接口,入口点代码在SQL驱动的Go文件。
 
SQL包是存在于Go标准库中的标准SQL包。因为init()函数是在任何其他函数之前执行的,所以可以肯定的是,只要在代码中包含了MySQL包,则Mysql驱动会被自动注册并通过标准SQL包调用。
 
import (
"database/sql"
"fmt"
_ "github.com/go-sql-driver/mysql"
)
这里下划线_表示载入包但不直接使用,我们通过标准SQL包使用。没有下划线,编译器会提示导入没有使用错误。
加载包的动作即使是静态方式,但包中的init()方法仍会执行,初始化方法会注册Mysql驱动给标准包,从而使用对标准包的方法调用转为对具体Mysql实现的方法调用。
 
为了数据库处理对象可以重用,定义全局数据库处理指针:
 
var db *sql.DB
与数据库交互的第一个函数是sql.Open(),获取数据库对象,用于执行查询和命令。第一个参数指定数据库驱动,这里是mysql。第二个参数是连接字符串。
db, err = sql.Open("mysql", "root:pass123@/sakila?charset=utf8&parseTime=true")
 
sql.Open()函数返回数据库连接处理器,用于对数据库执行查询和命令。同时返回错误对象,没有错误则为nil。
连接字符串包括用户名和密码,这里还指定字符集和解析时间类型,完整内容请参考官网。
 
在init方法中调用Open方法:
 
func init()  {
db, err = sql.Open("mysql", "root:a123@/sakila?charset=utf8&parseTime=true")
checkErr(err)
}
检查错误方法:
func checkErr(err error) {
if err != nil {
panic(err)
}
}
3. 获取Mysql数据库元信息
获取元信息主要包括获取数据库中表信息以及表的字段信息。从INFORMATION_SCHEMA.TABLES表中查询表信息:
 
SELECT table_name name,IFNULL(TABLE_COMMENT,table_name) value
 FROM INFORMATION_SCHEMA.TABLES 
WHERE UPPER(table_type)='BASE TABLE'
AND LOWER(table_schema) = 'sakila' 
ORDER BY table_name asc;
获取表字段信息,从information_schema.columns表查询字段信息:
SELECT COLUMN_NAME fName,column_comment fDesc,DATA_TYPE dataType,
       IS_NULLABLE isNull,IFNULL(CHARACTER_MAXIMUM_LENGTH,0) sLength
FROM information_schema.columns 
WHERE table_schema = 'sakila' AND table_name = 'actor';  
3.1. 查询数据库表信息
使用?作为参数占位符,db.Query()执行查询,参数为SQL字符串和数据库名。
 
func TableInfo(dbName string) map[string]string  {
sqlStr := `SELECT table_name tableName,TABLE_COMMENT tableDesc
FROM INFORMATION_SCHEMA.TABLES 
WHERE UPPER(table_type)='BASE TABLE'
AND LOWER(table_schema) = ? 
ORDER BY table_name asc`
 
var result = make(map[string]string)
 
rows, err := db.Query(sqlStr,dbName)
checkErr(err)
 
for rows.Next() {
var tableName,tableDesc string
err = rows.Scan(&tableName, &tableDesc)
checkErr(err)
 
if len(tableDesc) == 0 {
tableDesc = tableName
}
result[tableName] = tableDesc
}
return result
}
遍历查询结果,数据库名称和注释信息作为键值对存储在Map中。
3.2. 查询表字段信息
定义FieldInfo函数,参数为数据库名和表名,返回Field类型切片,我们首先看Field结构体:
 
type Field struct {
fieldName string
fieldDesc string
dataType  string
isNull    string
length    int
}
查询字段函数FieldInfo():
func FieldInfo(dbName,tableName string) [] Field{
sqlStr := `SELECT COLUMN_NAME fName,column_comment fDesc,DATA_TYPE dataType,
IS_NULLABLE isNull,IFNULL(CHARACTER_MAXIMUM_LENGTH,0) sLength
FROM information_schema.columns 
WHERE table_schema = ? AND table_name = ?`
 
 
var result [] Field
 
rows, err := db.Query(sqlStr,dbName,tableName)
checkErr(err)
 
for rows.Next() {
var f Field
err = rows.Scan(&f.fieldName, &f.fieldDesc, &f.dataType, &f.isNull, &f.length)
checkErr(err)
 
result = append(result, f)
}
return result
}
3.3. 测试
下面在main函数中进行测试:
 
func main() {
defer db.Close()
 
tableInfo := TableInfo("sakila")
fmt.Println(tableInfo)
 
filedInfo := FieldInfo("sakila","actor")
 
for _,item := range filedInfo {
fmt.Println(item)
}
}
defer db.Close()语句确保执行完毕后关闭数据库连接。
4. 总结
本文介绍了标准database/sql包及Mysql驱动,最后通过获取Mysql表元信息示例说明如何执行数据库操作。