数据库连接和驱动#
安装数据库驱动包
go get -u github.com/go-sql-driver/mysql导入数据驱动
import (
"database/sql"
_ "github.com/go-sql-driver/mysql" //引用包内部分函数
)sql.DB 结构体
sql.DB结构是sql/database包封装的一个数据库操作对象,包含了操作数据库的基本方法。
DSN
DSN全称为Data Source Name,表示数据库连来源,用于定义如何连接数据库,不同数据库的DSN格式是不同的,这取决于数据库驱动的实现,
下面是 go-sql-driver/sql 的DSN格式:
//[用户名[:密码]@][协议(数据库服务器地址)]]/数据库名称?参数列表
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]连接数据库#
在 sql/database包中.使用 sql.Open来连接数据库,值得注意的是 sql.Open 这样连接不会验证密码和账户是否正确,数据库是否存在,只会校验 DSN 格式.
drever := "mysql"
//root为数据库用户名,后面为密码,tcp代表tcp协议,test处填写自己的数据库名称
DSN := "root:123123@tcp(127.0.0.1:3306)/godatabase?charset=utf8"
db, err := sql.Open(drever, DSN)
if err != nil { //不会校验用户名密码是否正确,只校验数据源格式
fmt.Printf("sql.Open err: %v", err) //dsn格式不正确时报错
return
}验证账号密码以及要连接的数据库是否正确
使用 sql.Ping() 可以检验账号密码和数据库是否存在
err = db.Ping() //用来测试账号密码
if err != nil {
fmt.Printf("db.Ping err: %v", err)
return
}完整代码:
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt")
type info struct {
id int `db.id`
name string `db.name`
password int `db.password`
}
func main() {
drever := "mysql"
//root为数据库用户名,后面为密码,tcp代表tcp协议,test处填写自己的数据库名称
DSN := "root:123123@tcp(127.0.0.1:3306)/godatabase?charset=utf8"
db, err := sql.Open(drever, DSN)
if err != nil { //不会校验用户名密码是否正确,只校验数据源格式
fmt.Printf("sql.Open err: %v", err) //dsn格式不正确时报错
return
}
err = db.Ping() //用来测试账号密码
if err != nil {
fmt.Printf("db.Ping err: %v", err)
return
}
db.SetMaxOpenConns(5) //设置最大数据库连接数
fmt.Println("连接数据库成功!")
}输出结果:
连接数据库成功!数据库操作#
查询数据库#
使用 sql.Query() 即可查询,和JAVA相同的是 都要传入SQL语句并且返回一个结果集.
而从结果集读出信息需要创建查询数据表对应的结构体,还需要用到读取结果集的语句
sql.Scan() ,值得注意的是,传入的结构体变量要转为指针,
结构体:
type info struct {
id int `db.id`
name string `db.name`
password int `db.password`
}查询方法代码:
func dbQuery(db *sql.DB, tableName string, inFo info) {
SQL := "SELECT * FROM " + tableName //SQL语句
rows, err := db.Query(SQL) //获得结果集
if err != nil { //捕获错误
fmt.Printf("db.Query err: %v", err)
return
}
for rows.Next() {
err := rows.Scan(&inFo.id, &inFo.name, &inFo.password) //从结果集中读取
if err != nil {
fmt.Printf("rows.Scan err: %v", err)
return
}
fmt.Println(inFo) //输出
}
rows.Close()
}完整代码:
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt")
type info struct {
id int `db.id`
name string `db.name`
password int `db.password`
}
func main() {
drever := "mysql"
//root为数据库用户名,后面为密码,tcp代表tcp协议,test处填写自己的数据库名称
DSN := "root:123123@tcp(127.0.0.1:3306)/godatabase?charset=utf8"
db, err := sql.Open(drever, DSN)
if err != nil { //不会校验用户名密码是否正确,只校验数据源格式
fmt.Printf("sql.Open err: %v", err) //dsn格式不正确时报错
return
}
err = db.Ping() //用来测试账号密码
if err != nil {
fmt.Printf("db.Ping err: %v", err)
return
}
db.SetMaxOpenConns(5) //设置最大数据库连接数
fmt.Println("连接数据库成功!")
fmt.Println("查询数据库")
var iNFO info
dbQuery(db, "userinfo", iNFO)
}
func dbQuery(db *sql.DB, tableName string, inFo info) {
SQL := "SELECT * FROM " + tableName
rows, err := db.Query(SQL) //获得结果集
if err != nil {
fmt.Printf("db.Query err: %v", err)
return
}
for rows.Next() {
err := rows.Scan(&inFo.id, &inFo.name, &inFo.password)
if err != nil {
fmt.Printf("rows.Scan err: %v", err)
return
}
fmt.Println(inFo)
}
rows.Close()
}输出结果:
连接数据库成功!
查询数据库
{1 123 123123}
{2 1234 123123}此外还有两两种常用操作:
QueryRow表示只返回一行的查询,作为Query的一个常见特例。Prepare表示准备一个需要多次使用的语句,供后续执行用。(预编译)
增加数据库条目#
增加新条目需要使用 sql.Exec() 方法来实现,当然,也是要传入SQL语句的.
func dbExec(db *sql.DB) {
SQL := "INSERT INTO userinfo(name,password) VALUES (?,?)" //我的数据表ID设置为自增,所以设置了两个值
, err := db.Exec(SQL, 12, 1234) //添加新条目 ,会返回err
if err != nil {
fmt.Printf("db.Exec err: %v", err)
return
}
}输出结果:
连接数据库成功!
查询数据库
{1 123 123123}
{2 1234 123123}
添加新条目
再次查询
{1 123 123123}
{2 1234 123123}
{4 12 1234}更新数据库#
数据库的更新也是和添加数据库条目相同,使用 sql.Exec() + SQL语句即可查询.
func dbUpdate(db *sql.DB) {
SQL := "UPDATE userinfo SET name where id=1"
_, err := db.Exec(SQL, "啊啊", 1)
if err != nil {
fmt.Printf("db Update err: %v", err)
return
}
}输出结果:
连接数据库成功!
查询数据库
{1 123 123123}
{2 1234 123123}
添加新条目
再次查询
{1 123 123123}
{2 1234 123123}
{6 12 1234}
更新后查询
{1 啊啊 123123}
{2 1234 123123}
{6 12 1234}删除数据库条目#
数据库条目的删除也是和添加数据库条目,更新数据库相同,使用 sql.Exec() + SQL语句即可查询.
func dbDelete(db *sql.DB) {
SQL := "DELETE FROM userinfo WHERE id= ? "
_, err := db.Exec(SQL, 7)
if err != nil {
fmt.Printf("db Delete err: %v", err)
return
}
}输出结果:
连接数据库成功!
查询数据库
{1 啊啊 123123}
{2 1234 123123}
{7 1234 1232}
添加新条目
添加后查询
{1 啊啊 123123}
{2 1234 123123}
{7 1234 1232}
{8 12 1234}
更新数据库
更新后查询
{1 啊啊 123123}
{2 1234 123123}
{7 1234 1232}
{8 12 1234}
删除数据库条目
删除后查询
{1 啊啊 123123}
{2 1234 123123}
{8 12 1234}完整代码:
package main
import (
"database/sql"
_ "github.com/go-sql-driver/mysql"
"fmt")
type info struct {
id int `db.id`
name string `db.name`
password int `db.password`
}
func main() {
drever := "mysql"
//root为数据库用户名,后面为密码,tcp代表tcp协议,test处填写自己的数据库名称
DSN := "root:123123@tcp(127.0.0.1:3306)/godatabase?charset=utf8"
db, err := sql.Open(drever, DSN)
if err != nil { //不会校验用户名密码是否正确,只校验数据源格式
fmt.Printf("sql.Open err: %v", err) //dsn格式不正确时报错
return
}
err = db.Ping() //用来测试账号密码
if err != nil {
fmt.Printf("db.Ping err: %v", err)
return
}
db.SetMaxOpenConns(5) //设置最大数据库连接数
fmt.Println("连接数据库成功!")
fmt.Println("查询数据库")
var iNFO info
dbQuery(db, "userinfo", iNFO)
fmt.Println("添加新条目")
dbExec(db)
fmt.Println("添加后查询")
dbQuery(db, "userinfo", iNFO)
fmt.Println("更新数据库")
dbUpdate(db)
fmt.Println("更新后查询")
dbQuery(db, "userinfo", iNFO)
fmt.Println("删除数据库条目")
dbDelete(db)
fmt.Println("删除后查询")
dbQuery(db, "userinfo", iNFO)
}
func dbQuery(db *sql.DB, tableName string, inFo info) {
SQL := "SELECT * FROM " + tableName
rows, err := db.Query(SQL) //获得结果集
if err != nil {
fmt.Printf("db.Query err: %v", err)
return
}
for rows.Next() {
err := rows.Scan(&inFo.id, &inFo.name, &inFo.password)
if err != nil {
fmt.Printf("rows.Scan err: %v", err)
return
}
fmt.Println(inFo)
}
rows.Close()
}
func dbExec(db *sql.DB) {
SQL := "INSERT INTO userinfo(name,password) VALUES (?,?)"
_, err := db.Exec(SQL, 12, 1234)
if err != nil {
fmt.Printf("db.Exec err: %v", err)
return
}
}
func dbUpdate(db *sql.DB) {
SQL := "UPDATE userinfo SET name=? where id=?"
_, err := db.Exec(SQL, "啊啊", 1)
if err != nil {
fmt.Printf("db Update err: %v", err)
return
}
}
func dbDelete(db *sql.DB) {
SQL := "DELETE FROM userinfo WHERE id= ? "
_, err := db.Exec(SQL, 7)
if err != nil {
fmt.Printf("db Delete err: %v", err)
return
}
}其他#
MySQL事务#
不过这这样一条一条的增删改查是非常繁琐的 ,这样高重复的 MySQL ,就构成了一个 事务. 具体的SQL事务,可以看这篇文章: MySQL 事务 | 菜鸟教程 (runoob.com)
这里简单摘抄一句 MySQL事务 :
MySQL 事务主要用于处理操作量大,复杂度高的数据。比如说,在人员管理系统中,你删除一个人员,你既需要删除人员的基本资料,也要删除和该人员相关的信息,如信箱,文章等等,这样,这些数据库操作语句就构成一个事务!
