注册 登录

清河洛

go语言中的数据库操作

qingheluo2021-10-23清河洛427
在go语言中,标准库"database/sql"提供了保证SQL或类SQL数据库的泛用接口,使用前需要注入对应的数据库驱动,go标准库中没有提供任何一个数据库驱动,需要我们通过其他方式安装驱动常用的支持"database/sql"通用接口的数据库驱动包地址: sqlite3:github.com/mattn/go-sqlite3(注册的数据库驱动名称"sqlite3") mysql:github.com/go-sql-driver/mysql(注册的数据库驱动名称"mysql") postgresDB:github.com/lib/pq(注册的数据库驱动名称"pos...

在go语言中,标准库"database/sql"提供了保证SQL或类SQL数据库的泛用接口,使用前需要注入对应的数据库驱动,go标准库中没有提供任何一个数据库驱动,需要我们通过其他方式安装驱动

常用的支持"database/sql"通用接口的数据库驱动包地址:

    sqlite3:github.com/mattn/go-sqlite3(注册的数据库驱动名称"sqlite3")
    mysql:github.com/go-sql-driver/mysql(注册的数据库驱动名称"mysql")
    postgresDB:github.com/lib/pq(注册的数据库驱动名称"postgres")
    
    import (
        "database/sql"
        _ "github.com/mattn/go-sqlite3"
    )

标准库"database/sql"的使用

type Result interface {
    LastInsertId() (int64, error)
    // 返回一个数据库生成的回应命令的整数
    // 当插入新行时,一般来自一个"自增"列
    // 不是所有的数据库都支持该功能,该状态的语法也各有不同。
    RowsAffected() (int64, error)
    // 返回被update、insert或delete命令影响的行数
    // 不是所有的数据库都支持该功能。
}

Register(name string, driver driver.Driver)
    注册并命名一个数据库,可以在Open函数中使用该命名启用该驱动
    当我们引入数据库驱动时都会通过init方法注册,无需我们再去注册

type DB struct {}
    DB是一个数据库(操作)句柄,代表一个具有零到多个底层连接的连接池。
    可以安全的被多个go程同时使用,sql包会自动创建和释放连接;
    它也会维护一个闲置连接的连接池。
    如果数据库具有单连接状态的概念,该状态只有在事务中被观察时才可信。
    一旦调用了BD.Begin,返回的Tx会绑定到单个连接。
    当调用事务Tx的Commit或Rollback后,该事务使用的连接会归还到DB的闲置连接池中。
    连接池的大小可以用SetMaxIdleConns方法控制。

Open(driverName, dataSourceName string) (*DB, error)
    打开一个dirverName指定的数据库
    dataSourceName指定数据源,指定数据库名和连接信息
    该函数可能只是验证其参数,而不创建与数据库的连接
    调用返回值的Ping方法检查数据源的名称是否合法
    返回的DB可以安全的被多个go程同时使用,并会维护自身的闲置连接池。
    sqlite3只需传入数据库文件即可
        db,err := sql.Open("sqlite3","/path/db_file.db")
    mysql:
        db,err := sql.Open("mysql","username:password@tcp(ip:port)/database?charset=utf8")
        常用的可用参数:点击查看
    pgsql:
        db,err := sql.Open("postgres","user=username password=pwd host=localhost ...")
            每项设置为key=val的格式,多个设置项之间使用空格隔开
        db,err := sql.Open("postgres","postgres://user:password@host:port/dbname?key1=val&key2=val2...")
            以类似url的形式传入参数
        常用的可用参数:点击查看

Open函数返回的*DB的方法

    Driver() driver.Driver:返回数据库下层驱动
    Ping() error:检查与数据库的连接是否仍有效,如果需要会创建连接
    Close() error:关闭数据库,释放任何打开的资源
    SetMaxOpenConns(n int):设置与数据库建立连接的最大数目
        如果n <= 0,不会限制最大开启连接数,默认为0
    SetMaxIdleConns(n int):设置连接池中的最大闲置连接数
        如果n大于最大连接数,则最大闲置连接数会设置为最大连接数
        如果n <= 0,不会保留闲置连接
    Exec(query string, args ...interface{}) (Result, error)
        执行一次命令,args表示query中的占位参数
    Query(query string, args ...interface{}) (*Rows, error)
        执行一次查询,返回所有结果(Rows),args表示query中的占位参数
    QueryRow(query string, args ...interface{}) *Row
        执行一次查询,并仅返回一行结果(即Row)
        总是返回非nil的值,直到返回值的Scan方法被调用时,才会返回可能的错误
    占位符(字符串占位符不能使用单引号包含)
        ?:后面参数按照问号的顺序依次提供
        $n:第一个为$1,第二个为$2,以此类推
    Prepare(query string) (*Stmt, error)
        创建一个准备好的状态用于之后的查询和命令
        stmt,err := db.Prepare("insert into info (name,age) values (?,?)")
    Begin() (*Tx, error):Begin开始一个事务。隔离水平由数据库驱动决定

type Row struct {}:表示单行查询结果

    Scan(dest ...interface{}) error
        将该行查询结果各列分别保存进dest参数指定的值中
        如果没有匹配查询的行,会返回ErrNoRows

type Rows struct {}:表示多行查询结果集

    它的游标默认指向结果集的第零行
    
    Columns() ([]string, error):返回所有列的名称
    Scan(dest ...interface{}) error:将当前游标所在行各列结果填充进dest指定的各个值中
    Next() bool:将当前游标向下移动一行。如果没有下一行或者出现错误会返回false
    Close() error:Close关闭Rows,如果Next方法返回假,Rows会自动关闭
    Err() error:返回可能的、在迭代时出现的错误
    使用示例:
    req,err := db.Query("select id,name,age from info")
    for req.Next(){
         var id int
         var name string
         var age int
         err = req.Scan(&id,&name,&age)
         checkErr(err)
         fmt.Println(id,name,age)

type Stmt struct {}:表示准备好的状态,可以安全的被多个go程同时使用

    Exec(args ...interface{}) (Result, error)
    Query(args ...interface{}) (*Rows, error)
    QueryRow(args ...interface{}) *Row
    Close() error:关闭状态
    使用示例:
    stmt,err := db.Prepare("insert into info (name,age) values (?,?)")
        name为字符串,age为数字,但是创建Stmt时的sql语句value中name不需要添加单引号
    req,err := stmt.Exec("三千",30)
        按照创建Stmt时的问号顺序依次传入值即可

type Tx struct {}:代表一个进行中的数据库事务

    一次事务必须以对Commit或Rollback的调用结束。
    调用Commit或Rollback后,所有对事务的操作都会失败并返回错误值ErrTxDone
    
    Exec(query string, args ...interface{}) (Result, error)
    Query(query string, args ...interface{}) (*Rows, error)
    QueryRow(query string, args ...interface{}) *Row
    Prepare(query string) (*Stmt, error)
        准备一个专用于该事务的状态
        返回的该事务专属状态操作在Tx递交会回滚后不能再使用
    Stmt(stmt *Stmt) *Stmt
        使用已存在的状态生成一个该事务特定的状态
    Commit() error:递交事务
    Rollback() error:放弃并回滚事务

使用Open()打开mysql数据库时的可用参数

一般情况下我们使用"username:password@tcp(ip:port)/database"格式

我们可以传入一些参数来配置数据库连接的各种选项

通过在上面字符串最后添加问号(?)分割,以key=val的格式,多个配置项之间使用 & 符号连接,就和网址中get方式传参一样

当传入的字符串值中有空格时,需要使用单引号包含

当传入的值中存在单引号(')或斜杠(/)时需要进行转义

单引号转义为%27,斜杠转义为%2F

常用的参数及其意义

charset: string,设置默认字符集
    可以使用逗号隔开传入多个值,用于兼容
    如charset=utf8mb4,utf8表示优先使用utf8mb4,如果不支持则向后继续取值

checkConnLiveness=true,每次操作之前检测连接的活跃性
    在支持的平台上,每次数据库操作之前会检查从连接池中获取的连接的活跃性
    如果检测活跃性失败,则标记该连接为坏连接,并重新从连接池中获取新连接
    然后检测活跃性,如此循环,知道检测通过后进行下一步操作
    设置为false禁用连接的活跃度检查

collation=utf8mb4_general_ci
    设置用于连接时客户端-服务器交互的排序规则
    如果指定的排序规则在目标服务器上不可用,则连接将失败

clientFoundRows=false:默认update语句返回的是实际更改的行数,设置为true后返回的是匹配的行数

columnsWithAlias=false
    默认返回的列明不含表名
    为true时,对sql.Rows.Columns()的调用将返回表别名和列名,并以点分隔

interpolateParams=true: 为true时允许使用占位符 ? 来避免SQL注入

loc=UTC: 设置时区
    当设置parseTime=true时,默认值为Local,否则默认值为UTC
    如:loc=Asia%2FShanghai

maxAllowedPacket=64*1024*1024
    允许的最大数据包大小(字节),默认值64MiB
    设置为 0 时在每次连接时自动从服务器获取max_allowed_packet变量

multiStatements=false  :是否允许使用分号分割的select语句,即一次性执行多个查询语句
    使用Rows.NextResultSet()获取下一个查询语句的结果
    此时, ? 参数只能在第一个语句中生效

parseTime=false: 为true时会自动将DATE和DATETIME类型转换为Go的time.Time类型

timeout: 设置连接超时时间,需要添加单位,如:readTimeout=1m30s

readTimeout: 设置读操作的超时时间

writeTimeout: 设置写入操作的超时时间

serverPubKey:指定连接数据库服务器的公钥文件

tls=false  :是否启用TLS / SSL加密连接到服务器
    可使用true或false来开启或关闭该功能,还可以传入特殊值
    preferred 表示仅在服务器明确告知要使用TLS时才使用TSL
    skip-verify 表示跳过SSL证书验证,或提供证书文件的路径来验证SSL连接

**其他自定义参数**
    任何其他参数都被解释为系统变量,用于对mysql进行更精细的设置
    如autocommit=1

使用Open()打开pgsql数据库时的可用参数

dbname      要连接到的数据库的名称
user        登录身份的用户
password    用户的密码
host        要连接到的主机。以 / 开头的值适用于 unix 域套接字。(默认为 localhost)
port        要绑定到的端口。(默认值为 5432)
sslmode     是否使用 SSL(默认为 require)
    disable     禁用 SSL
    require     始终 SSL(跳过验证)
    verify-ca   始终 SSL(验证是否由受信任的CA签名)
    verify-full 始终 SSL(验证是否由受信任的CA和主机名签名与证书中的证书是否匹配)
fallback_application_name - 如果未提供,则要回退到的application_name
connect_timeout 连接的最长等待时间(以秒为单位)。零或 未指定表示无限期等待。
sslcert     证书文件位置。该文件必须包含 PEM 编码的数据。
sslkey      密钥文件位置。该文件必须包含 PEM 编码的数据。
sslrootcert 根证书文件的位置。文件 必须包含 PEM 编码数据。


网址导航