Go語言之操作數據庫CRUD


  1 package main
  2 
  3 import (
  4     "database/sql"
  5     "fmt"
  6     _ "github.com/go-sql-driver/mysql"
  7 )
  8 
  9 // 定義一個全局對象db
 10 var db *sql.DB
 11 //定義結構體
 12 type User struct {
 13     Id   int
 14     Name string
 15     Age  int
 16 }
 17 
 18 //初始化數據庫
 19 func InitDB() (err error) {
 20     //連接數據庫
 21     dsn := "root:root@tcp(127.0.0.1:3306)/db3"
 22     db, err = sql.Open("mysql", dsn)
 23     //錯誤處理
 24     if err != nil {
 25         return err
 26     }
 27     //檢驗dsn是否正確
 28     err = db.Ping()
 29     if err != nil {
 30         return err
 31     }
 32     return nil
 33 }
 34 
 35 //數據庫單行查詢
 36 func queryRowDemo() {
 37     //創建User對象
 38     var u User
 39     //sql語句
 40     sqlStr := "select * from user where id=?"
 41     //調用QueryRow方法返回查詢的一行,后邊調用的scan方法是將查詢出來的行放入指定的參數中
 42     err := db.QueryRow(sqlStr, 1).Scan(&u.Id, &u.Name, &u.Age)
 43     if err != nil {
 44         fmt.Println(err)
 45         return
 46     }
 47     fmt.Println(u.Id, u.Name, u.Age)
 48 }
 49 
 50 //查詢多行
 51 /*
 52 查詢多行和查詢單行的不同之處是調用方法query並返回多行
 53 然后通過for循環調用scan方法吧每一行循環遍歷出來
 54 */
 55 func queryDemo() {
 56     //sql語句
 57     sqlStr := "select * from user"
 58     //調用方法
 59     rows, err := db.Query(sqlStr)
 60     //錯誤處理
 61     if err != nil {
 62         fmt.Println(err)
 63     }
 64     //關閉rows釋放持有的數據庫鏈接
 65     defer rows.Close()
 66     //使用for循環進行結果的讀取
 67     for rows.Next() {
 68         var u User
 69         err := rows.Scan(&u.Id, &u.Name, &u.Age)
 70         if err != nil {
 71             fmt.Println(err)
 72         }
 73         fmt.Printf("id:%d name:%s age:%d\n", u.Id, u.Name, u.Age)
 74     }
 75 }
 76 
 77 //插入數據
 78 func InsertDemo() {
 79     //sql語句
 80     sqlStr := "insert into user(name,age) value(?,?)"
 81     //Exec執行一次命令(包括查詢、刪除、更新、插入等),返回的Result是對已執行的SQL命令的總結。參數args表示query中的占位參數
 82     ret, err := db.Exec(sqlStr, "趙六", 30)
 83     if err != nil {
 84         fmt.Println(err)
 85         return
 86     }
 87     fmt.Println(ret)
 88     // 新插入數據的id是theID
 89     theID, err := ret.LastInsertId()
 90     if err != nil {
 91         fmt.Printf("get lastinsert ID failed, err:%v\n", err)
 92         return
 93     }
 94     fmt.Printf("insert success, the id is %d.\n", theID)
 95 }
 96 
 97 //更新數據
 98 func UpdateDemo() {
 99     sqlStr := "update user set age=? where id =?"
100     ret, err := db.Exec(sqlStr, 39, 3)
101     if err != nil {
102         fmt.Printf("update failed, err:%v\n", err)
103         return
104     }
105     n, err := ret.RowsAffected() // 操作影響的行數
106     if err != nil {
107         fmt.Printf("get RowsAffected failed, err:%v\n", err)
108         return
109     }
110     fmt.Printf("update success, affected rows:%d\n", n)
111 }
112 
113 //刪除數據
114 func DeleteDemo() {
115     sqlStr := "delete from user where id=?"
116     ret, err := db.Exec(sqlStr, 4)
117     if err != nil {
118         fmt.Println(err)
119         return
120     }
121     n, err := ret.RowsAffected()
122     if err != nil {
123         fmt.Printf("get RowsAffected failed, err:%v\n", err)
124         return
125     }
126     fmt.Printf("delete success, affected rows:%d\n", n)
127 
128 }
129 func main() {
130     //調用初始化函數
131     err := InitDB()
132     if err != nil {
133         fmt.Println(err)
134     }
135     //調用函數
136     //queryRowDemo()
137     //queryDemo()
138     //InsertDemo()
139     //UpdateDemo()
140     //DeleteDemo()
141 }

 sql預處理:

優化MySQL服務器重復執行SQL的方法,可以提升服務器性能,提前讓服務器編譯,一次編譯多次執行,節省后續編譯的成本。

避免SQL注入問題。

查詢的sql預處理代碼:

 1 //預處理
 2 func prepareSql() {
 3     var u User
 4     sqlStr := "select * from user"
 5     stmt, err := db.Prepare(sqlStr)
 6     if err != nil {
 7         fmt.Println(err)
 8         return
 9     }
10     defer stmt.Close()
11     rows, err := stmt.Query()
12     if err != nil {
13         fmt.Println(err)
14         return
15     }
16     defer rows.Close()
17     for rows.Next() {
18         err := rows.Scan(&u.Id, &u.Name, &u.Age)
19         if err != nil {
20             fmt.Println(err)
21             return
22         }
23         fmt.Println(u.Id, u.Name, u.Age)
24     }
25 }

事務:

  比如,我們去銀行轉賬,操作可以分為下面兩個環節:(1)從第一個賬戶划出款項。  (2)將款項存入第二個賬戶。  
  在這個過程中,兩個環節是關聯的。第一個賬戶划出款項必須保證正確的存入第二個賬戶,如果第二個環節沒有完成,整個的過程都應該取消,否則就會發生丟失款項的問題。整個交易過程,可以看作是一個事物,成功則全部成功,失敗則需要全部撤消,這樣可以避免當操作的中間環節出現問題時,產生數據不一致的問題。
事務的特性:
原子性 一個事務(transaction)中的所有操作,要么全部完成,要么全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
一致性 在事務開始之前和事務結束以后,數據庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、串聯性以及后續數據庫可以自發性地完成預定的工作。
隔離性 數據庫允許多個並發事務同時對其數據進行讀寫和修改的能力,隔離性可以防止多個事務並發執行時由於交叉執行而導致數據的不一致。事務隔離分為不同級別,包括讀未提交(Read uncommitted)、讀提交(read committed)、可重復讀(repeatable read)和串行化(Serializable)。
持久性 事務處理結束后,對數據的修改就是永久的,即便系統故障也不會丟失。
舉例:
 1 func transactionDemo() {
 2     //事務分為 開始事務 提交事務和回滾事務
 3     //開始事務 當開始一個事務后需要用事務進行操作
 4     tx, err := db.Begin()
 5     //出錯了 如果有錯誤就需要進行事務的回滾
 6     if err != nil {
 7         if tx != nil {
 8             tx.Rollback()
 9         }
10         return
11     }
12 
13     sqlStr := "update user set age=100 where id=?"
14     _, err = tx.Exec(sqlStr, 1)
15     if err != nil {
16         fmt.Println(err)
17         tx.Rollback()
18         return
19     }
20 
21     sqlStr1 := "update user set age=101 where id=?"
22     _, err = tx.Exec(sqlStr1, 2)
23     if err != nil {
24         fmt.Println(err)
25         tx.Rollback()
26         return
27     }
28     //事務提交
29     err=tx.Commit()
30     if err!=nil{
31         tx.Rollback()
32         return
33     }
34 
35 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM