sql

Variables

ErrConnDone

在已经提交或回滚的连接上执行的任何操作都会返回 ErrConnDone。

1
var ErrConnDone = errors.New("database/sql: connection is already closed")

ErrNoRows

当 QueryRow 没有返回行时,Scan 返回 ErrNoRows。在这种情况下,QueryRow 会返回一个占位符* Row 值,该值将推迟发生此错误直到扫描。

1
var ErrNoRows = errors.New("sql: no rows in result set")

ErrTxDone

对已经提交或回滚的事务执行的任何操作都会返回 ErrTxDone。

1
var ErrTxDone = errors.New("sql: Transaction has already been committed or rolled back")

func Drivers() []string

1
func Drivers() []string

驱动程序返回已注册驱动程序名称的排序列表。

func Register(name string, driver driver.Driver)

1
func Register(name string, driver driver.Driver)

Register 使用提供的名称提供数据库驱动程序。如果使用相同的名称调用 Register 两次,或者驱动程序为零,则会发生混乱。

type ColumnType

1
func (rs *Rows) ColumnTypes() ([]*ColumnType, error)
1
2
3
type ColumnType struct {
// 包含过滤或未导出的字段
}

ColumnType 包含列的名称和类型。

func (*ColumnType) DatabaseTypeName

1
func (ci *ColumnType) DatabaseTypeName() string

DatabaseTypeName 返回列类型的数据库系统名称。如果返回空字符串,则不支持驱动程序类型名称。请查阅您的驱动程序文档以获取驱动程序数据类型列表 不包括长度说明符。常见类型包括 “VARCHAR”,“TEXT”,“NVARCHAR”,“DECIMAL”,“BOOL”,“INT”,“BIGINT”。

func (*ColumnType) DecimalSize

1
func (ci *ColumnType) DecimalSize() (precision, scale int64, ok bool)

DecimalSize 返回小数类型的比例和精度。如果不适用或者不支持,那么ok 是错误的。

func (*ColumnType) Length

1
func (ci *ColumnType) Length() (length int64, ok bool)

Length 返回可变长度列类型(如文本和二进制字段类型)的列类型长度。如果类型长度没有限制,则数值为 math.MaxInt64(任何数据库限制仍将适用)。如果列类型不是可变长度,例如 int,或者如果驱动程序不支持,那么 ok 是 false。

func (*ColumnType) Name

1
func (ci *ColumnType) Name() string

Name 返回列的名称或别名。

func (*ColumnType) Nullable

1
func (ci *ColumnType) Nullable() (nullable, ok bool)

Nullable 返回列是否可以为 null。如果一个驱动程序不支持这个属性,ok 将会是 false。

func (*ColumnType) ScanType

1
func (ci *ColumnType) ScanType() reflect.Type

ScanType 使用 Rows.Scan 返回适合扫描的 Go 类型。如果驱动程序不支持此属性,ScanType 将返回空接口的类型。

type Conn

1
func (db *DB) Conn(ctx context.Context) (*Conn, error)
1
2
3
type Conn struct {        
// 包含过滤或未导出的字段
}

Conn 代表一个数据库会话而不是一个数据库会话池。除非特别需要连续的单个数据库会话,否则首选运行 DB 查询。

Conn 必须调用 Close 来将连接返回到数据库池,并且可以与正在运行的查询同时进行。

在调用 Close 之后,连接上的所有操作都会因 ErrConnDone 而失败。

func (*Conn) BeginTx

1
func (c *Conn) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error)

BeginTx 开始一个事务。

提供的上下文用于事务提交或回滚之前。如果上下文被取消,sql包将回滚事务。如果提供给 BeginTx 的上下文被取消,则Tx.Commit 将返回错误。

提供的 TxOptions 是可选的,如果应该使用默认值,则可能为零。如果使用驱动程序不支持的非默认隔离级别,则会返回错误。

func (*Conn) Close

1
func (c *Conn) Close() error

Close 将连接返回到连接池。Close 后的所有操作都将返回ErrConnDone。Close 是安全地与其他操作同时进行,并会阻止,直到所有其他操作完成。首先取消使用的上下文,然后直接调用 close 可能会很有用。

func (*Conn) ExecContext

1
func (c *Conn) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error)

ExecContext 执行查询而不返回任何行。这些参数用于查询中的任何占位符参数。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
package main

import (
"context"
"database/sql"
"log"
)

var (
ctx context.Context
db *sql.DB
)

func main() {
// A *DB is a pool of connections. Call Conn to reserve a connection for
// exclusive use.
conn, err := db.Conn(ctx)
if err != nil {
log.Fatal(err)
}
defer conn.Close() // Return the connection to the pool.
id := 41
result, err := conn.ExecContext(ctx, `UPDATE balances SET balance = balance + 10 WHERE user_id = ?;`, id)
if err != nil {
log.Fatal(err)
}
rows, err := result.RowsAffected()
if err != nil {
log.Fatal(err)
}
if rows != 1 {
log.Fatalf("expected single row affected, got %d rows affected", rows)
}
}

func (*Conn) PingContext

1
func (c *Conn) PingContext(ctx context.Context) error

PingContext 验证到数据库的连接是否仍然存在。

func (*Conn) PrepareContext

1
func (c *Conn) PrepareContext(ctx context.Context, query string) (*Stmt, error)

PrepareContext 为以后的查询或执行创建一个准备好的语句。可以从返回的语句中同时运行多个查询或执行。当语句不再需要时,调用者必须调用语句的 Close 方法。

提供的上下文用于编写声明,而不用于执行声明。

func (*Conn) QueryContext

1
func (c *Conn) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)

QueryContext 执行一个返回行的查询,通常是一个 SELECT。该参数适用于查询中的任何占位符参数。

func (*Conn) QueryRowContext

1
func (c *Conn) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row

QueryRowContext 执行一个预计最多只返回一行的查询。QueryRowContext 总是返回一个非零值。错误被推迟到行的扫描方法被调用。如果查询未选择行,则*Row 的扫描将返回错误号。否则,*Row 的扫描将扫描第一个选定的行并丢弃其余行。

func (*Conn) Raw

1
func (c *Conn) Raw(f func(driverConn interface{}) error) (err error)

Raw executes f exposing the underlying driver connection for the duration of f. The driverConn must not be used outside of f.

Once f returns and err is nil, the Conn will continue to be usable until Conn.Close is called.

Raw执行f暴露底层驱动连接的持续时间。driverConn不能在f之外使用。一旦f返回并且err为nil, Conn将继续可用,直到Conn. close被调用。

type DB ★★★★★

1
2
3
type DB struct {
// contains filtered or unexported fields
}

DB是一个数据库句柄,表示一个包含零个或多个底层连接的池。多个 goroutine 并发使用是安全的。

sql 包自动创建并释放连接;它也保持空闲连接的空闲池。如果数据库具有每个连接状态的概念,则只能在事务内可靠地观察到这种状态。一旦 DB.Begin 被调用,返回的 Tx 就绑定到单个连接。在事务上调用 Commit 或 Rollback 后,该事务的连接将返回到数据库的空闲连接池。池的大小可以通过 SetMaxIdleConns 进行控制。

func Open

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

Open 打开一个由其数据库驱动程序名称和驱动程序特定的数据源名称指定的数据库,通常由至少一个数据库名称和连接信息组成。

大多数用户将通过驱动程序特定的连接帮助程序函数打开数据库,该函数返回一个 *DB。Go标准库中不包含数据库驱动程序。有关第三方驱动程序的列表,请参阅https://golang.org/s/sqldrivers。

Open 可能只是验证其参数而不创建与数据库的连接。要验证数据源名称是否有效,请调用 Ping。

返回的数据库对于多个 goroutine 的并发使用是安全的,并保持其自己的空闲连接池。因此,Open 函数应该只调用一次。很少有必要关闭数据库。

func (*DB) Begin

1
2
3
func (db *DB) Begin() (*Tx, error) {
return db.BeginTx(context.Background(), nil)
}

Begin 开始一个事务。默认隔离级别取决于驱动程序。

func (*DB) BeginTx

1
func (db *DB) BeginTx(ctx context.Context, opts *TxOptions) (*Tx, error)

BeginTx 开始一个事务。

提供的上下文用于事务提交或回滚之前。如果上下文被取消,sql包将回滚事务。如果提供给 BeginTx 的上下文被取消,则Tx.Commit 将返回错误。

提供的 TxOptions 是可选的,如果应该使用默认值,则可能为零。如果使用驱动程序不支持的非默认隔离级别,则会返回错误。

func (*DB) Close

1
func (db *DB) Close() error

func (db *DB) Conn

1
func (db *DB) Conn(ctx context.Context) (*Conn, error)

返回单个连接。

func (db *DB) Driver

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

Driver 返回数据库的底层驱动程序。

func (db *DB) Exec

1
2
3
func (db *DB) Exec(query string, args ...interface{}) (Result, error) {
return db.ExecContext(context.Background(), query, args...)
}

Exec 执行写语句,不返回任何rows。该参数适用于查询中的任何占位符参数。

func (db *DB) ExecContext

1
func (db *DB) ExecContext(ctx context.Context, query string, args ...interface{}) (Result, error)

func (db *DB) Ping

1
2
3
func (db *DB) Ping() error {
return db.PingContext(context.Background())
}

Ping 验证与数据库的连接仍然存在,并在必要时建立连接。

func (db *DB) PingContext

1
func (db *DB) PingContext(ctx context.Context) error

func (db *DB) Prepare

1
2
3
func (db *DB) Prepare(query string) (*Stmt, error) {
return db.PrepareContext(context.Background(), query)
}

Prepare 方法实现预处理操作:先将sql语句发送给MySQL服务端,返回一个准备好的状态用于之后的查询和命令。返回值可以同时执行多个查询和命令。

读操作 预处理示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 预处理查询示例
func prepareQueryDemo() {
sqlStr := "select id, name, age from user where id > ?"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("prepare failed, err:%v\n", err)
return
}
defer stmt.Close()
rows, err := stmt.Query(0)
if err != nil {
fmt.Printf("query failed, err:%v\n", err)
return
}
defer rows.Close()
// 循环读取结果集中的数据
for rows.Next() {
var u user
err := rows.Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("scan failed, err:%v\n", err)
return
}
fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
}
}

写操作 预处理也时分类似,示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 预处理插入示例
func prepareInsertDemo() {
sqlStr := "insert into user(name, age) values (?,?)"
stmt, err := db.Prepare(sqlStr)
if err != nil {
fmt.Printf("prepare failed, err:%v\n", err)
return
}
defer stmt.Close()
_, err = stmt.Exec("小王子", 18)
if err != nil {
fmt.Printf("insert failed, err:%v\n", err)
return
}
_, err = stmt.Exec("沙河娜扎", 18)
if err != nil {
fmt.Printf("insert failed, err:%v\n", err)
return
}
fmt.Println("insert success.")
}

func (db *DB) PrepareContext

1
func (db *DB) PrepareContext(ctx context.Context, query string) (*Stmt, error)

func (db *DB) Query

1
2
3
func (db *DB) Query(query string, args ...interface{}) (*Rows, error) {
return db.QueryContext(context.Background(), query, args...)
}

多行查询:执行一次查询,返回多行结果(即Rows),一般用于执行select命令。参数args表示query中的占位参数。

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
// 查询多条数据示例
func queryMultiRowDemo() {
sqlStr := "select id, name, age from user where id > ?"
rows, err := db.Query(sqlStr, 0)
if err != nil {
fmt.Printf("query failed, err:%v\n", err)
return
}
// 非常重要:关闭rows释放持有的数据库链接
defer rows.Close()

// 循环读取结果集中的数据
for rows.Next() {
var u user
err := rows.Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("scan failed, err:%v\n", err)
return
}
fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
}
}

func (db *DB) QueryContext

1
func (db *DB) QueryContext(ctx context.Context, query string, args ...interface{}) (*Rows, error)

func (db *DB) QueryRow

1
2
3
4
func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row {
rows, err := db.QueryContext(ctx, query, args...)
return &Row{rows: rows, err: err}
}

单行查询:执行一次查询,并期望返回最多一行结果(即Row)。QueryRow总是返回非nil的值,直到返回值的Scan方法被调用时,才会返回被延迟的错误。(如:未找到结果)

示例:

1
2
3
4
5
6
7
8
9
10
11
12
// 查询单条数据示例
func queryRowDemo() {
sqlStr := "select id, name, age from user where id=?"
var u user
// 非常重要:确保QueryRow之后调用Scan方法,否则持有的数据库链接不会被释放
err := db.QueryRow(sqlStr, 1).Scan(&u.id, &u.name, &u.age)
if err != nil {
fmt.Printf("scan failed, err:%v\n", err)
return
}
fmt.Printf("id:%d name:%s age:%d\n", u.id, u.name, u.age)
}

func (db *DB) QueryRowContext

1
func (db *DB) QueryRowContext(ctx context.Context, query string, args ...interface{}) *Row

func (db *DB) SetConnMaxIdleTime

1
func (db *DB) SetConnMaxIdleTime(d time.Duration)

设置连接空闲的最大时间。过期的连接在复用之前可能会被延迟关闭。如果d <= 0,则连接不会因为空闲时间而关闭。

func (db *DB) SetConnMaxLifetime

1
func (db *DB) SetConnMaxLifetime(d time.Duration)

设置连接的存活时间。过期的连接在复用之前可能会被延迟关闭。如果d <= 0,则连接不会因为连接的年龄而关闭。

func (db *DB) SetMaxIdleConns

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

设置空闲连接池中的最大连接数。如果MaxOpenConns大于0但小于新的MaxIdleConns,那么新的MaxIdleConns将被减少以匹配MaxOpenConns限制。

如果n <= 0,则不保留空闲连接。

缺省的最大空闲连接数是2。这可能会在未来的版本中改变。

func (db *DB) SetMaxOpenConns

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

设置到数据库的最大打开连接数。

如果MaxIdleConns大于0并且新的MaxOpenConns小于MaxIdleConns,那么MaxIdleConns将被减少以匹配新的MaxOpenConns限制。

如果n <= 0,则没有打开连接的数量限制。默认值是0(无限)。

func (db *DB) Stats() DBStats

1
func (db *DB) Stats() DBStats

Stats 返回数据库统计信息

关于 Conn 和 DB

Conn是一个连接,而DB是一个连接池,一般情况下使用DB就行,例如 db.Begin() ,查看源码实现可知:等同于 conn.BeginTx(Context.Background(), nil) ,后者需要手动调用conn.Close(),前者会自动调用conn.Close()

type DBStats

1
func (db *DB) Stats() DBStats
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type DBStats struct {
MaxOpenConnections int // Maximum number of open connections to the database.

// Pool Status
OpenConnections int // The number of established connections both in use and idle.
InUse int // The number of connections currently in use.
Idle int // The number of idle connections.

// Counters
WaitCount int64 // The total number of connections waited for.
WaitDuration time.Duration // The total time blocked waiting for a new connection.
MaxIdleClosed int64 // The total number of connections closed due to SetMaxIdleConns.
MaxIdleTimeClosed int64 // The total number of connections closed due to SetConnMaxIdleTime.
MaxLifetimeClosed int64 // The total number of connections closed due to SetConnMaxLifetime.
}

DBStats 包含数据库统计信息。

type IsolationLevel

1
2
3
4
5
6
7
8
9
10
11
12
type IsolationLevel int

const (
LevelDefault IsolationLevel = iota
LevelReadUncommitted
LevelReadCommitted
LevelWriteCommitted
LevelRepeatableRead
LevelSnapshot
LevelSerializable
LevelLinearizable
)

IsolationLevel 是 TxOptions 中使用的事务隔离级别。

BeginTx 中驱动程序可能支持的各种隔离级别。如果驱动程序不支持给定的隔离级别,则可能会返回错误。

https://en.wikipedia.org/wiki/Isolation_(database_systems)#Isolation_levels.

func (i IsolationLevel) String() string

1
func (i IsolationLevel) String() string

返回事务隔离级别的名称。

type NamedArg

1
2
3
4
type NamedArg struct {
Name string
Value interface{}
}

NamedArg 是一个命名参数。NamedArg 值可以用作 Query 或Exec 的参数,并绑定到 SQL 语句中的相应命名参数。

func Named

1
func Named(name string, value interface{}) NamedArg

Named 提供了一种更简洁的方式来创建 NamedArg 值。

示例:

1
2
3
4
5
6
7
8
db.ExecContext(ctx, `
delete from Invoice
where
TimeCreated < @end
and TimeCreated >= @start;`,
sql.Named("start", startTime),
sql.Named("end", endTime),
)

type NullBool

1
2
3
4
type NullBool struct {
Bool bool
Valid bool // Valid is true if Bool is not NULL
}

func (n *NullBool) Scan(value interface{}) error

func (n NullBool) Value() (driver.Value, error)

type NullByte

func (n *NullByte) Scan(value interface{}) error

func (n NullByte) Value() (driver.Value, error)

type NullFloat64

func (n *NullFloat64) Scan(value interface{}) error

func (n NullFloat64) Value() (driver.Value, error)

type NullInt16

func (n *NullInt16) Scan(value interface{}) error

func (n NullInt16) Value() (driver.Value, error)

type NullInt32

func (n *NullInt32) Scan(value interface{}) error

func (n NullInt32) Value() (driver.Value, error)

type NullInt64

func (n *NullInt64) Scan(value interface{}) error

func (n NullInt64) Value() (driver.Value, error)

type NullString

func (ns *NullString) Scan(value interface{}) error

func (ns NullString) Value() (driver.Value, error)

type NullTime

func (n *NullTime) Scan(value interface{}) error

func (n NullTime) Value() (driver.Value, error)

type Out

1
2
3
4
5
6
7
8
9
10
11
12
type Out struct {

// Dest is a pointer to the value that will be set to the result of the
// stored procedure's OUTPUT parameter.
Dest interface{}

// In is whether the parameter is an INOUT parameter. If so, the input value to the stored
// procedure is the dereferenced value of Dest's pointer, which is then replaced with
// the output value.
In bool
// contains filtered or unexported fields
}

Out 可用于从存储过程中检索 OUTPUT 值参数。

并非所有驱动程序和数据库都支持 OUTPUT 值参数。

示例:

1
2
var outArg string
_, err := db.ExecContext(ctx, "ProcName", sql.Named("Arg1", sql.Out{Dest: &outArg}))

type RawBytes

1
type RawBytes []byte

RawBytes 保存对数据库本身拥有的内存的引用。在扫描到RawBytes后,该切片只有在下一次调用next、Scan或Close时才有效。

type Result

1
2
3
4
5
6
7
8
9
10
11
12
13
type Result interface {
// LastInsertId returns the integer generated by the database
// in response to a command. Typically this will be from an
// "auto increment" column when inserting a new row. Not all
// databases support this feature, and the syntax of such
// statements varies.
LastInsertId() (int64, error)

// RowsAffected returns the number of rows affected by an
// update, insert, or delete. Not every database or database
// driver may support this.
RowsAffected() (int64, error)
}

Result 汇总了已执行的SQL语句。

type Row

1
2
3
4
5
type Row struct {
// One of these two will be non-nil:
err error // deferred error for easy chaining
rows *Rows
}

单行查询db.QueryRow()执行一次查询,并期望返回最多一行结果(即Row)。QueryRow总是返回非nil的值,直到返回值的Scan方法被调用时,才会返回被延迟的错误。(如:未找到结果)

func (r *Row) Err() error

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

type Rows

1
2
3
type Rows struct {
// 包含过滤或未导出的字段
}

多行查询db.Query()执行一次查询,返回多行结果(即Rows),一般用于执行select命令。参数args表示query中的占位参数。

Rows is the result of a query. It’s cursor starts before the first row of the result set. Use Next to advance from row to row.

func (rs *Rows) Close() error

func (rs *Rows) ColumnTypes() ([]*ColumnType, error)

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

func (rs *Rows) Err() error

func (rs *Rows) Next() bool

func (rs *Rows) NextResultSet() bool

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

type Scanner

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
type Scanner interface {
// Scan方法从数据库驱动获取一个值。
//
// 参数src的类型保证为如下类型之一:
// int64
// float64
// bool
// []byte
// string
// time.Time
// nil - 表示NULL值
//
// 如果不能不丢失信息的保存一个值,应返回错误。
Scan(src interface{}) error
}

Scanner接口会被Rows或Row等的Scan方法使用。

任何实现了Scanner接口的类型,都可以通过定义自己的Scan函数来处理空值问题,比如:

  • Rows或Row的Scan方法其实就是实现从数据库驱动中获取一个值(该值会转换成src的类型),并将其存储到src,src满足driver.Value类型
  • 而NullString、NullBool等的Scan方法则是将输入的值转换成对应的NullString、NullBool类型并存储下来

type Stmt ★★★

1
2
3
type Stmt struct {
// contains filtered or unexported fields
}

stmt = statement,声明,Stmt是一个准备好的声明。Stmt 对于多个 goroutines 并发使用是安全的。

func (s *Stmt) Close() error

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

func (s *Stmt) ExecContext(ctx context.Context, args …interface{}) (Result, error)

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

func (s *Stmt) QueryContext(ctx context.Context, args …interface{}) (*Rows, error)

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

func (s *Stmt) QueryRowContext(ctx context.Context, args …interface{}) *Row

type Tx ★★★★★

1
2
3
type Tx struct {
// contains filtered or unexported fields
}

Tx 是正在进行的数据库事务。

Transaction 必须以对 Commit 或 Rollback 的调用结束。

在调用 Commit 或 Rollback 之后,事务上的所有操作都会因ErrTxDone而失败。

func (tx *Tx) Commit() error

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

func (tx *Tx) ExecContext(ctx context.Context, query string, args …interface{}) (Result, error)

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

func (tx *Tx) PrepareContext(ctx context.Context, query string) (*Stmt, error)

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

func (tx *Tx) QueryContext(ctx context.Context, query string, args …interface{}) (*Rows, error)

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

func (tx *Tx) QueryRowContext(ctx context.Context, query string, args …interface{}) *Row

func (tx *Tx) Rollback() error

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

func (tx *Tx) StmtContext(ctx context.Context, stmt *Stmt) *Stmt

type TxOptions

1
2
3
4
5
6
type TxOptions struct {
// Isolation is the transaction isolation level.
// If zero, the driver or database's default level is used.
Isolation IsolationLevel
ReadOnly bool
}

TxOptions保存要在DB.BeginTx中使用的事务选项。