zoukankan      html  css  js  c++  java
  • 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

    回滚事务。

    笃志:“博学而笃志,切问而近思,仁在其中矣。”
    弘毅:“士不可以不弘毅,任重而道远。”
    止于至善:“大学之道,在明明德,在亲民,在止于至善。”
    关注:笃志弘毅,止于至善
  • 相关阅读:
    SharePoint服务器端对象模型 之 访问用户、用户组和权限(Part 2)
    SharePoint服务器端对象模型 之 访问用户、用户组和权限(Part 1)
    SharePoint服务器端对象模型 之 使用LINQ进行数据访问操作(Part 4)
    SharePoint服务器端对象模型 之 使用LINQ进行数据访问操作(Part 3)
    SharePoint 服务器端对象模型 之 使用LINQ进行数据访问操作(Part 2)
    Restful.Data 开源持久层组件项目最新进展和使用说明
    高性能网站架构设计之缓存篇(6)- Redis 集群(中)
    让 asp.net 在 mac 上飞
    高性能网站架构设计之缓存篇(5)- Redis 集群(上)
    高性能网站架构设计之缓存篇(4)- Redis 主从复制
  • 原文地址:https://www.cnblogs.com/dzhy/p/11065300.html
Copyright © 2011-2022 走看看