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表元信息示例說明如何執行數據庫操作。