# MYSQL
* * * * *
--: 作者:jsh
时间:2018年8月15日
* * * * *
GO提供database/sql包用于对sql数据库的访问,作为操作数据库的入口对象sql.DB主要为我们提供两个功能
* sql.DB 通过数据库驱动为我们提供管理底层数据库连接的打开和关闭操作.
* sql.DB 为我们管理数据库连接池
sql.DB结构是一个数据库句柄,它代表的是一个包含零个或任意多个数据库链接的链接池,这个链接池由sql包管理。
**需要引入的包**
* database/sql
* github.com/go-sql-driver/mysql 使用数据库之前必须安装mysql驱动 如果未安装驱动或者没有引入驱动会报以下错误:panic: sql: unknown driver "mysql" (forgotten import?)
* 安装驱动:go get github.com/go-sql-driver/mysql
#### 链接mysql
链接数据库的方式为
~~~
username:password@protocol(address)/dbname?param=value
db, err := sql.Open("mysql","root:root@tcp(127.0.0.1:3306)/answer") // sql.Open("数据库驱动名","链接信息")
Notice:Open函数在执行时并不会真正地与数据库进行链接,它甚至不会检查用户给定的参数:Open函数真正的作用是设置好连接数据库所属的各个结构,并以惰性的方式,等到真正需要时才建立相应的数据库链接。
~~~
#### 查询
~~~
rows, err = db.Query("select id,answer from m_answer limit 10") // DB中执行SQL通过Exec和Query方法,查询操作是通过Query完成,它会返回一个sql.Rows的结果集,包含一个游标用来遍历查询结果
Notice:写查询字段是不要写*,推荐写指定的查询字段名称。如果写*对查询结果进行遍历全部是0
for rows.Next() { // 利用游标对结果级进行遍历
var id int
var answer string
rows.Scan(&id,&answer)
fmt.Println(id,answer)
}
rows.Close() // 关闭查询句柄
Notice:rows.Scan() 参数的顺序很重要, 需要和查询的结果的column对应,不然会造成数据读取错位
------单行查询------
var answer string
err := db.QueryRow("select answer from m_answer where id = 2").Scan(&answer)
check(err)
fmt.Println(answer)
------获取多个记录--------
rows, err := db.Query("select * from m_answer limit 10")
check(err)
columns, err := rows.Columns() // 返回切片
check(err)
//fmt.Println(columns) // 获取所有的字段名称
values := make([]sql.RawBytes, len(columns)) // 创建一个切片
scanArgs := make([]interface{}, len(values)) // 创建一个切片
for i := range values {
scanArgs[i] = &values[i] // 将每个字段的地址放入到一个新切片中
}
for rows.Next() {
err = rows.Scan(scanArgs...) // 将字段的地址传入
check(err)
var value string
for i, val := range values {
value = string(val)
fmt.Println(columns[i], ": ", value)
}
fmt.Println("-----------------------------------")
}
~~~
~~~
// 将查询结构赋值给结构体
type Data stuct{ // 结构体字段
Id int
Answer string
}
rows, err := db.Query("select id,answer from m_answer limit 10") // sql查询结构
check(err)
data := []Post{} // 定义空切片
for rows.Next() {
posts := Post{}
rows.Scan(&posts.Id,&posts.Answer)
data = append(data,posts)
}
fmt.Println(data)
~~~
#### 添加
~~~
func insert_sql(db *sql.DB) {
result, err := db.Exec("insert into `m_user`(`user_name`,`user_pwd`,`user_info`,`user_role`,`real_name`,`add_time`) values('m3','123456','很帅',1,'jsh',1519287123)") // 执行插入sql 返回值是一个资源
check(err)
id, err := result.LastInsertId() // 获取自增长ID
num, err :=result.RowsAffected() // 获取受影响行数
check(err)
fmt.Println(id,num,result)
}
~~~
#### 修改
~~~
func update_sql(db *sql.DB) {
result, err := db.Exec("update `m_user` set `user_name`= 'm4',`user_pwd`='456789' where id in(110,111)")
check(err)
num, err := result.RowsAffected()// 返回受影响行数
check(err)
fmt.Println(num)
}
~~~
#### 删除
~~~
func delect_sql(db *sql.DB) {
result, err := db.Exec("delete from `m_user` where id in(110,111)")
check(err)
num, err := result.RowsAffected() // 返回删除成功的行数
check(err)
fmt.Println(num)
}
~~~
#### 预处理
* 预处理语句可以实现自定义查询
* 预处理语句要比手动拼接字符串sql语句高效
* 预处理语句可以放置sql注入
~~~
---------------查询---------------------
func pre_sql(db *sql.DB,limit int) {
var rows *sql.Rows
rows, err := db.Query("select id,answer from m_answer limit ?",limit) // 预处理参数绑定
check(err)
for rows.Next() {
var id int
var answer string
rows.Scan(&id, &answer)
fmt.Println(id, answer)
}
}
---------------添加--------------------
func pre_insersql(db *sql.DB) {
stmt , err := db.Prepare(`insert into m_user(user_name,user_pwd) values(?,?)`) // 预处理参数绑定
defer stmt.Close()
check(err)
ret ,err := stmt.Exec("jsh","123456") // 执行预处理语句
id ,err := ret.LastInsertId() // 获取自增长ID
fmt.Println(id)
}
---------------删除--------------------
func pre_delectsql(db *sql.DB,id int) {
stmt , err := db.Prepare(`delete from m_user where id = ?`) // 预处理参数绑定
defer stmt.Close()
check(err)
ret ,err := stmt.Exec(id) // 执行删除
row_num ,_ := ret.RowsAffected() // 受影响行数
fmt.Println(row_num)
}
---------------修改--------------------
func pre_updatesql(db *sql.DB,id int) {
stmt , err := db.Prepare(`update m_user set user_name= 'mmp',user_pwd='456789' where id= ?`) // 预处理参数绑定
defer stmt.Close()
check(err)
ret ,err := stmt.Exec(id) // 执行修改语句
num, err := ret.RowsAffected()
check(err)
fmt.Println(num)
}
~~~