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 }

 

posted @ 2020-03-02 15:40  萌萌~  阅读(3223)  评论(0编辑  收藏  举报