golang——database/sql包學習


1、database/sql包

sql包提供了保證SQL或類SQL數據庫的泛用接口。

使用sql包時必須注入(至少)一個數據庫驅動。

(1)獲取mysql driver:go get -v github.com/go-sql-driver/mysql

(2)代碼示例:

package main

import (
	"database/sql"
	"fmt"
	"log"
	"time"

	_ "github.com/go-sql-driver/mysql"
)

// 檢查錯誤
func checkErr(err error) {
	if err != nil {
		log.Fatalln(err)
	}
}

// 事務錯誤
func checkTxErr(err error, tx *sql.Tx) {
	if err != nil {
		log.Println(err)
		err = tx.Rollback()
		checkErr(err)
	}
}

// 數據庫實體
type User struct {
	ID      int
	Name    string
	Age     int
	Sex     int
	AddDate time.Time
}

func main() {
	//1、獲取數據庫連接
	db, err := sql.Open("mysql", "root:123456@tcp(127.0.0.1:3306)/test?parseTime=true")
	checkErr(err)
	defer db.Close()
	fmt.Println("數據庫連接成功")
	//2、判斷連接是否有效
	err = db.Ping()
	checkErr(err)
	fmt.Println("數據庫連接有效")
	//3、創建表
	sql := `
		CREATE TABLE IF NOT EXISTS users(
			id INT NOT NULL AUTO_INCREMENT,
			name VARCHAR(100) NOT NULL,
			age INT NOT NULL,
			sex TINYINT,
			add_date DATETIME,
			PRIMARY KEY(id) 
		)
	`
	_, err = db.Exec(sql)
	checkErr(err)

	//4、添加數據
	// sql = "INSERT INTO users (name,age,sex,add_date) VALUES (?,?,?,?)"
	// res, err := db.Exec(sql, "張三", 18, 1, time.Now())
	// checkErr(err)
	// fmt.Println(res.LastInsertId())

	//5、查詢數據
	sql = "SELECT id,name,age,sex,add_date FROM users"
	rows, err := db.Query(sql)
	checkErr(err)
	defer rows.Close()
	user := User{}
	for rows.Next() {
		err = rows.Scan(&user.ID, &user.Name, &user.Age, &user.Sex, &user.AddDate)
		checkErr(err)
		fmt.Println(user, user.AddDate.Format("2006/01/02 15:04:05"))
	}
	err = rows.Err()
	checkErr(err)

	//6、查詢一行
	sql = "SELECT id,name,age,sex,add_date FROM users"
	row := db.QueryRow(sql)
	err = row.Scan(&user.ID, &user.Name, &user.Age, &user.Sex, &user.AddDate)
	checkErr(err)
	fmt.Println(user)

	//7、命令
	sql = "UPDATE users SET name=? WHERE id=?;"
	stmt, err := db.Prepare(sql)
	checkErr(err)
	defer stmt.Close()
	result, err := stmt.Exec("李四", 1)
	checkErr(err)
	fmt.Println(result.RowsAffected())

	//8、查詢
	sql = "SELECT id,name,age,sex,add_date FROM users WHERE id=?"
	stmt2, err := db.Prepare(sql)
	checkErr(err)
	defer stmt2.Close()
	row = stmt2.QueryRow(1)
	err = row.Scan(&user.ID, &user.Name, &user.Age, &user.Sex, &user.AddDate)
	checkErr(err)
	fmt.Println(user)

	//9、事務
	tx, err := db.Begin()
	checkErr(err)
	_, err = tx.Exec("UPDATE users SET age=? WHERE id=?", 20, 1)
	checkTxErr(err, tx)
	_, err = tx.Exec("UPDATE users SET sex=? WHERE id=?", 1, 1)
	checkTxErr(err, tx)
	err = tx.Commit()
	checkTxErr(err, tx)

	//10、查詢一行
	sql = "SELECT id,name,age,sex,add_date FROM users"
	row = db.QueryRow(sql)
	err = row.Scan(&user.ID, &user.Name, &user.Age, &user.Sex, &user.AddDate)
	checkErr(err)
	fmt.Println(user)

}

2、數據庫

2.1、type DB struct{}

DB是一個數據庫句柄,代表一個具有零到多個底層連接的連接池。

它可以安全的被多個go程同時使用。

連接池的大小可以用SetMaxIdleConns方法控制。

2.2、常用方法

(1)func Open(driverName, dataSourceName string) (*DB, error)

打開數據庫,返回數據庫句柄,DB可以安全的被多個go程同時使用,並會維護自身的閑置連接池。

Open函數只需調用一次,很少需要關閉DB。

(2)func (db *DB) Driver() driver.Driver

返回數據庫下層驅動。

(3)func (db *DB) Ping() error

檢查與數據庫的連接是否仍有效,如果需要會創建連接。

(4)func (db *DB) Close() error

關閉數據庫,釋放任何打開的資源。

一般不會關閉DB,因為DB句柄通常被多個go程共享,並長期活躍。

(5)func (db *DB) SetMaxOpenConns(n int)

設置與數據庫建立連接的最大數目。

如果n大於0且小於最大閑置連接數,會將最大閑置連接數減小到匹配最大開啟連接數的限制。

如果n <= 0,不會限制最大開啟連接數,默認為0(無限制)。

(6)func (db *DB) SetMaxIdleConns(n int)

設置連接池中的最大閑置連接數。

如果n大於最大開啟連接數,則新的最大閑置連接數會減小到匹配最大開啟連接數的限制。

如果n <= 0,不會保留閑置連接。

(7)func (db *DB) Exec(query string, args ...interface{}) (Result, error)

執行一次命令(包括查詢、刪除、更新、插入等),不返回任何執行結果。

參數args表示query中的占位參數。

(8)func (db *DB) Query(query string, args ...interface{}) (*Rows, error)

執行一次查詢,返回多行結果(即Rows),一般用於執行select命令。

(9)func (db *DB) QueryRow(query string, args ...interface{}) *Row

執行一次查詢,並期望返回最多一行結果(即Row)。

總是返回非nil的值,直到返回值的Scan方法被調用時,才會返回被延遲的錯誤。

(10)func (db *DB) Prepare(query string) (*Stmt, error)

創建一個准備好的狀態用於之后的查詢和命令。

返回值可以同時執行多個查詢和命令。

(11)func (db *DB) Begin() (*Tx, error)

開始一個事務。

隔離水平由數據庫驅動決定。

3、數據表

3.1、type Rows{}

Rows是查詢的結果。

它的游標指向結果集的第零行,使用Next方法來遍歷各行結果。

3.2、常用方法

(1)func (rs *Rows) Columns() ([]string, error)

返回列名。

如果Rows已經關閉會返回錯誤。

(2)func (rs *Rows) Scan(dest ...interface{}) error

Scan將當前行各列結果填充進dest指定的各個值中。

如果某個參數的類型為*[]byte,Scan會保存對應數據的拷貝,該拷貝為調用者所有,可以安全的,修改或無限期的保存。

如果參數類型為*RawBytes可以避免拷貝;參見RawBytes的文檔獲取其使用的約束。

如果某個參數的類型為*interface{},Scan會不做轉換的拷貝底層驅動提供的值。

如果值的類型為[]byte,會進行數據的拷貝,調用者可以安全使用該值。

(3)func (rs *Rows) Next() bool

Next准備用於Scan方法的下一行結果。

如果成功會返回真,如果沒有下一行或者出現錯誤會返回假。

每一次調用Scan方法,甚至包括第一次調用該方法,都必須在前面先調用Next方法。

(4)func (rs *Rows) Close() error

關閉Rows,阻止對其更多的列舉。

如果Next方法返回假,Rows會自動關閉。

檢查Err方法結果的條件。

Close方法是冪等的(多次調用無效的成功),不影響Err方法的結果。

(5)func (rs *Rows) Err() error

Err返回可能的、在迭代時出現的錯誤。

Err需在顯式或隱式調用Close方法后調用。

4、數據行

4.1、type Row{}

QueryRow方法返回Row,代表單行查詢結果。

4.2、常用方法

(1)func (r *Row) Scan(dest ...interface{}) error

Scan將該行查詢結果各列分別保存進dest參數指定的值中。

如果該查詢匹配多行,Scan會使用第一行結果並丟棄其余各行。

如果沒有匹配查詢的行,Scan會返回ErrNoRows。

5、SQL命令狀態

5.1、type Stmt struct{}

Stmt是准備好的狀態。

Stmt可以安全的被多個go程同時使用。

5.2、常用方法

(1)func (s *Stmt) Exec(args ...interface{}) (Result, error)

使用提供的參數執行准備好的命令狀態,返回Result類型的該狀態執行結果的總結。

(2)func (s *Stmt) Query(args ...interface{}) (*Rows, error)

使用提供的參數執行准備好的查詢狀態,返回Rows類型查詢結果。

(3)func (s *Stmt) QueryRow(args ...interface{}) *Row

使用提供的參數執行准備好的查詢狀態。

如果在執行時遇到了錯誤,該錯誤會被延遲,直到返回值的Scan方法被調用時才釋放。

返回值總是非nil的。

如果沒有查詢到結果,*Row類型返回值的Scan方法會返回ErrNoRows;否則,Scan方法會掃描結果第一行並丟棄其余行。

(4)func (s *Stmt) Close() error

關閉狀態。

6、事務

6.1、type Tx struct{}

Tx代表一個進行中的數據庫事務。

一次事務必須以對Commit或Rollback的調用結束。

調用Commit或Rollback后,所有對事務的操作都會失敗並返回錯誤值ErrTxDone。

6.2、常用方法

(1)func (tx *Tx) Exec(query string, args ...interface{}) (Result, error)

執行命令,但不返回結果。例如執行insert和update。

(2)func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error)

執行查詢並返回零到多行結果(Rows),一般執行select命令。

(3)func (tx *Tx) QueryRow(query string, args ...interface{}) *Row

執行查詢並期望返回最多一行結果(Row)。

總是返回非nil的結果,查詢失敗的錯誤會延遲到在調用該結果的Scan方法時釋放。

(4)func (tx *Tx) Prepare(query string) (*Stmt, error)

准備一個專用於該事務的狀態。

返回的該事務專屬狀態操作在Tx遞交會回滾后不能再使用。

(5)func (tx *Tx) Stmt(stmt *Stmt) *Stmt

使用已存在的狀態生成一個該事務特定的狀態。

(6)func (tx *Tx) Commit() error

提交事務。

(7)func (tx *Tx) Rollback() error

回滾事務。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM