Golang 獲取MySQL表元信息

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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章