【go秀一秀】sql包

juhaorensheng1898 2013-08-19 10:54:09
包文件
database/sql


func Register(name string, driver driver.Driver)
Register使得数据库驱动可以使用事先定义好的名字使用。如果使用同样的名字注册,或者是注册的的sql驱动是空的,Register会panic。

type DB struct {
// contains filtered or unexported fields
}
DB是一个数据库处理器。它能很安全地被多个goroutines并发调用。
如果对应的数据库驱动有连接和会话状态的概念,sql包就能自动管理创建和释放连接,其中包括管理一个自由连接池。如果有观察会话状态的需求的话,有两种方法。多个goroutine不共用一个 *DB,或者在事物中创建和监控所有的状态。一旦DB.Open被调用,返回的Tx是绑定在一个独立的连接上的。当Tx.Commit或者Tx.Rollback被调用,连接就会返回到DB的闲置连接池。


func Open(driverName, dataSourceName string) (*DB, error)
Open打开一个数据库,这个数据库是由其驱动名称和驱动制定的数据源信息打开的,这个数据源信息通常是由至少一个数据库名字和连接信息组成的。
多数用户通过指定的驱动连接辅助函数来打开一个数据库。打开数据库之后会返回*DB。


func (db *DB) Begin() (*Tx, error)
Begin开始一个事务。事务的隔离级别是由驱动决定的。

func (db *DB) Close() error
Close关闭数据库,释放一些使用中的资源。


func (db *DB) Driver() driver.Driver
Driver返回了数据库的底层驱动。


func (db *DB) Exec(query string, args ...interface{}) (Result, error)
Exec执行query操作,而没有返回任何行。

func (db *DB) Prepare(query string) (*Stmt, error)
Prepare为后面的执行操作事先定义了声明。

func (db *DB) Query(query string, args ...interface{}) (*Rows, error)
Query执行了一个有返回行的查询操作,比如SELECT。

func (db *DB) QueryRow(query string, args ...interface{}) *Row
QueryRow执行一个至多只返回一行记录的查询操作。 QueryRow总是返回一个非空值。Error只会在调用行的Scan方法的时候才返回。


type NullBool struct {
Bool bool
Valid bool // Valid is true if Bool is not NULL // 如果Bool非空,Valid就为true
}
NullBool代表了可空的bool类型。 NullBool实现了Scanner接口,所以它和NullString一样可以被当做scan的目标变量。


func (n *NullBool) Scan(value interface{}) error
Scan实现了Scanner接口。


func (n NullBool) Value() (driver.Value, error)
Value实现了driver的Valuer接口。


type NullFloat64 struct {
Float64 float64
Valid bool // Valid is true if Float64 is not NULL // 如果Float64非空,Valid就为true。
}
NullFloat64代表了可空的float64类型。 NullFloat64实现了Scanner接口,所以它和NullString一样可以被当做scan的目标变量。


func (n *NullFloat64) Scan(value interface{}) error
Scan实现了Scanner接口。


func (n NullFloat64) Value() (driver.Value, error)
Value实现了driver的Valuer接口。



type NullInt64 struct {
Int64 int64
Valid bool // Valid is true if Int64 is not NULL
}
NullInt64代表了可空的int64类型。 NullInt64实现了Scanner接口,所以它和NullString一样可以被当做scan的目标变量。


func (n *NullInt64) Scan(value interface{}) error
Scan实现了Scaner接口。


func (n NullInt64) Value() (driver.Value, error)
Value实现了driver Valuer接口。



type NullString struct {
String string
Valid bool // Valid is true if String is not NULL // 如果String不是空,则Valid为true
}
NullString代表一个可空的string。 NUllString实现了Scanner接口,所以它可以被当做scan的目标变量使用:


func (ns *NullString) Scan(value interface{}) error
Scan实现了Scanner接口。


func (ns NullString) Value() (driver.Value, error)
Value实现了driver Valuer接口。

type RawBytes []byte
RawBytes是一个字节数组,它是由数据库自己维护的一个内存空间。当一个Scan被放入到RawBytes中之后,你下次调用Next,Scan或者Close就可以获取到slice了。


type Result interface {
LastInsertId() (int64, error)
RowsAffected() (int64, error)
}
一个Result结构代表了一个执行过的SQL命令。


type Row struct {
// contains filtered or unexported fields
}
Row是调用QueryRow的结果,代表了查询操作的一行数据。


func (r *Row) Scan(dest ...interface{}) error
Scan将符合的行的对应列拷贝到dest指的对应值中。如果多于一个的行满足查询条件,Scan使用第一行,而忽略其他行。如果没有行满足查询条件,Scan返回ErrNoRows。



type Rows struct {
// contains filtered or unexported fields
}
Rows代表查询的结果。它的指针最初指向结果集的第一行数据,需要使用Next来进一步操作。


rows, err := db.Query("SELECT ...")
...
for rows.Next() {
var id int
var name string
err = rows.Scan(&id, &name)
...
}
err = rows.Err() // get any error encountered during iteration




func (rs *Rows) Close() error
Close关闭Rows,就禁止了进一步的枚举使用。如果遍历过程结束了,Rows就会自动关闭了。关闭是非常重要的。



func (rs *Rows) Columns() ([]string, error)
Columns返回列名字。当rows设置了closed,Columns方法会返回error。


func (rs *Rows) Err() error
Err返回错误。如果有错误的话,就会在循环过程中捕获到。



func (rs *Rows) Next() bool
Next获取下一行的数据以便给Scan调用。在成功的时候返回true,在没有下一行数据的时候返回false。每次调用来Scan获取数据,甚至是第一行数据,都需要调用Next来处理。



func (rs *Rows) Scan(dest ...interface{}) error
Scan将当前行的列输出到dest指向的目标值中。
如果有个参数是*[]byte的类型,Scan在这个参数里面存放的是相关数据的拷贝。这个拷贝是调用函数的人所拥有的,并且可以随时被修改和存取。这个拷贝能避免使用*RawBytes;关于这个类型的使用限制请参考文档。
如果有个参数是*interface{}类型,Scan会将底层驱动提供的这个值不做任何转换直接拷贝返回。如果值是[]byte类型,Scan就会返回一份拷贝,并且调用者获得返回结果。



type Scanner interface {
// Scan从数据库驱动中设置一个值。
//
// src值可以是下面限定的集中类型之一:
//
// int64
// float64
// bool
// []byte
// string
// time.Time
// nil - for NULL values
//
// 如果数据只有通过丢失信息才能存储下来,这个方法就会返回error。
Scan(src interface{}) error
}
Scanner是被Scan使用的接口。




type Stmt struct {
// contains filtered or unexported fields
}
Stmt是定义好的声明。多个goroutine并发使用Stmt是安全的。

func (s *Stmt) Close() error
关闭声明。


func (s *Stmt) Exec(args ...interface{}) (Result, error)
Exec根据给出的参数执行定义好的声明,并返回Result来显示执行的结果。

func (s *Stmt) Query(args ...interface{}) (*Rows, error)
Query根据传递的参数执行一个声明的查询操作,然后以*Rows的结果返回查询结果。


func (s *Stmt) QueryRow(args ...interface{}) *Row
QueryRow根据传递的参数执行一个声明的查询操作。如果在执行声明过程中发生了错误,这个error就会在Scan返回的*Row的时候返回,而这个*Row永远不会是nil。如果查询没有任何行数据,*Row的Scan操作就会返回ErrNoRows。否则,*Rows的Scan操作就会返回第一行数据,并且忽略其他行。

Example usage:
var name string
err := nameByUseridStmt.QueryRow(id).Scan(&name)


type Tx struct {
// contains filtered or unexported fields
}
Tx代表运行中的数据库事务。
必须调用Commit或者Rollback来结束事务。
在调用Commit或者Rollback之后,所有后续对事务的操作就会返回ErrTxDone。



func (tx *Tx) Commit() error
Commit提交事务。


func (tx *Tx) Exec(query string, args ...interface{}) (Result, error)
Exec执行不返回任何行的操作。例如:INSERT和UPDATE操作。


func (tx *Tx) Prepare(query string) (*Stmt, error)
Prepare在一个事务中定义了一个操作的声明。
这里定义的声明操作一旦事务被调用了commited或者rollback之后就不能使用了。
关于如何使用定义好的操作声明,请参考Tx.Stmt。



func (tx *Tx) Query(query string, args ...interface{}) (*Rows, error)
Query执行哪些返回行的查询操作,比如SELECT。


func (tx *Tx) QueryRow(query string, args ...interface{}) *Row
QueryRow执行的查询至多返回一行数据。 QueryRow总是返回非空值。只有当执行行的Scan方法的时候,才会返回Error。



func (tx *Tx) Rollback() error
Rollback回滚事务。



func (tx *Tx) Stmt(stmt *Stmt) *Stmt
Stmt从一个已有的声明中返回指定事务的声明。



下面来个 例子连接mysql,首先记得运行 go get github.com/go-sql-driver/mysql:

package main

import (
"database/sql" //这包一定要引用
"fmt" //这个前面一章讲过
_ "mysql"
"strconv" //这个是为了把int转换为string
)

func main() { //main函数

db, err := sql.Open("mysql", "root:123@tcp(localhost:3306)/happyacc?charset=utf8")
//数据库连接字符串,端口一定要写/
if err != nil { //连接成功 err一定是nil否则就是报错
panic(err.Error()) //抛出异常
fmt.Println(err.Error())//仅仅是显示异常
}
defer db.Close() //只有在前面用了 panic 这时defer才能起作用
rows, err := db.Query("select id,news_title from news") //从新闻表取出两个字段
if err != nil {
panic(err.Error())
fmt.Println(err.Error())
return
}
defer rows.Close()
var id int //定义一个id
var newstitle string //定义新闻标题
//golang的rows 好比数据库的游标,需要用scan函数把对应的值扫进去.当然也可以自己循环它的属性索引
不过不建议这么做。程序可读性太差
for rows.Next() { //开始循环、像游标吗?必须rows.Next()哦
rerr := rows.Scan(&id, &newstitle) //扫每一行,并把字段的值赋到id和newstitle
里面去
if rerr == nil {
fmt.Println(strconv.Itoa(id) + newstitle) //输出来而已,看看
}

}
db.Close() //关闭数据库 别告诉我 你不想关
}
...全文
676 2 打赏 收藏 转发到动态 举报
写回复
用AI写文章
2 条回复
切换为时间正序
请发表友善的回复…
发表回复
十一文 2013-08-19
  • 打赏
  • 举报
回复
感谢 楼主 支持

2,190

社区成员

发帖
与我相关
我的任务
社区描述
go语言学习与交流版
社区管理员
  • go语言社区
  • Freeman Z
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧