Golang中database/sql包
驱动
请求一个连接的函数有好几种,执行完毕处理连接的方式稍有差别,大致如下:
db.Ping() 调用完毕后会马上把连接返回给连接池。
db.Exec() 调用完毕后会马上把连接返回给连接池,但是它返回的Result对象还保留这连接的引用,当后面的代码需要处理结果集的时候连接将会被重用。
db.Query() 调用完毕后会将连接传递给sql.Rows类型,当然后者迭代完毕或者显示的调用.Clonse()方法后,连接将会被释放回到连接池。
db.QueryRow()调用完毕后会将连接传递给sql.Row类型,当.Scan()方法调用之后把连接释放回到连接池。
db.Begin() 调用完毕后将连接传递给sql.Tx类型对象,当.Commit()或.Rollback()方法调用后释放连接。
连接DB
sql.Open
的第一个参数是driver名称,第二个参数是driver连接数据库的信息,各个driver可能不同。DB不是连接,并且只有当需要使用时才会创建连接,如果想立即验证连接,需要用Ping()
方法,如下:err = db.Ping()if err != nil {
// do something here
}sql.DB的设计就是用来作为长连接使用的。不要频繁Open, Close。比较好的做法是,为每个不同的datastore建一个DB对象,保持这些对象Open。如果需要短连接,那么把DB作为参数传入function,而不要在function中Open, Close。
读取DB
如果方法包含
Query
,那么这个方法是用于查询并返回rows的。其他情况应该用Exec()
。var (
id int
name string
)
rows, err := db.Query("select id, name from users where id = ?", 1)if err != nil {
log.Fatal(err)
}
defer rows.Close()for rows.Next() {
err := rows.Scan(&id, &name)
if err != nil {
log.Fatal(err)
}
log.Println(id, name)
}
err = rows.Err()if err != nil {
log.Fatal(err)
}上面代码的过程为:
db.Query()
表示向数据库发送一个query,defer rows.Close()
非常重要,遍历rows使用rows.Next()
, 把遍历到的数据存入变量使用rows.Scan()
, 遍历完成后检查error。有几点需要注意:检查遍历是否有error
结果集(rows)未关闭前,底层的连接处于繁忙状态。当遍历读到最后一条记录时,会发生一个内部EOF错误,自动调用
rows.Close()
,但是如果提前退出循环,rows不会关闭,连接不会回到连接池中,连接也不会关闭。所以手动关闭非常重要。rows.Close()
可以多次调用,是无害操作。
单行Query
err在
Scan
后才产生,所以可以如下写:var name stringerr = db.QueryRow("select name from users where id = ?", 1).Scan(&name)if err != nil {
log.Fatal(err)
}
fmt.Println(name)修改数据,事务
一般用Prepare()和
Exec()
完成INSERT
,UPDATE
,DELETE
操作。事务
db.Begin()
开始事务,Commit()
或Rollback()
关闭事务。Tx
从连接池中取出一个连接,在关闭之前都是使用这个连接。Tx不能和DB层的BEGIN
,COMMIT
混合使用。如果你需要通过多条语句修改连接状态,你必须使用Tx,例如:
创建仅对单个连接可见的临时表
设置变量,例如
SET @var := somevalue
改变连接选项,例如字符集,超时
处理Error
循环Rows的Error
如果循环中发生错误会自动运行
rows.Close()
,用rows.Err()
接收这个错误,Close方法可以多次调用。循环之后判断error是非常必要的。关闭Resultsets时的error
如果你在rows遍历结束之前退出循环,必须手动关闭
关于连接池
当需要连接,且连接池中没有可用连接时,新的连接就会被创建。
默认没有连接上限,这可能会导致数据库产生错误“too many connections”
db.SetMaxIdleConns(N)
设置最大空闲连接数db.SetMaxOpenConns(N)
设置最大打开连接数长时间保持空闲连接可能会导致db timeout
补充:
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
回滚事务。
最新文章
- Entity Framework 教程——概述
- Delphi项目构成之项目文件DPR
- 【noiOJ】p1481
- scrollWidth的巧妙运用
- progressBar 自定义
- RichtextBox去除闪烁光标
- VC2010编写Dll文件(转)
- CodeForces 816B Karen and Coffee(前缀和,大量查询)
- CSS float 属性
- linux静态ip的设置
- python AES加密 ECB PKCS5
- Python 每日随笔
- 20165323 预备作业3 Linux安装及学习
- 吴裕雄 python深度学习与实践(3)
- springmvc处理日期格式
- 开源的PaaS方案:在OpenStack上部署CloudFoundry (一)简介
- builtroot make menuconfig流程
- Elasticsearch: 权威指南(官方教程)
- 巧用CSS属性visibility与opacity代替鼠标经过的jQuery事件
- [SCOI2007]修车 费用流 BZOJ 1070