# 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)
}
~~~