sqlx操作MySQL实战及其原理( 二 )


除了使用struct数组或切片,也可以使用map数组或切片,这里就不贴出来了,有兴趣的可以去看文末给出的Demo链接 。
删除
删除也可以使用通用占位符和命名参数的方式,并且会返回本次执行受影响的行数,某些情况下可以使用这个数字判断SQL实际有没有执行成功 。
deleteResult := db.MustExec("Delete from Person where Id=?", 1)log.Println(deleteResult.RowsAffected())deleteMapResult, err := db.NamedExec("Delete from Person where Id=:Id",map[string]interface{}{"Id": 1})if err != nil {log.Println(err)return}log.Println(deleteMapResult.RowsAffected())修改
Sqlx对修改的支持和删除差不多:
updateResult := db.MustExec("Update Person set City=?, UpdateTime=? where Id=?", "Shanghai", time.Now(), 1)log.Println(updateResult.RowsAffected())updateMapResult, err := db.NamedExec("Update Person set City=:City, UpdateTime=:UpdateTime where Id=:Id",map[string]interface{}{"City": "Chong Qing", "UpdateTime": time.Now(), "Id": 1})if err != nil {log.Println(err)}log.Println(updateMapResult.RowsAffected())查询
Sqlx对查询的支持比较多 。
使用Get方法查询一条:
getPerson := &Person{}db.Get(getPerson, "select * from Person where Name=?", "Zhang San")使用Select方法查询多条:
selectPersons := []Person{}db.Select(&selectPersons, "select * from Person where Name=?", "Zhang San")只查询部分字段:
getId := new(int64)db.Get(getId, "select Id from Person where Name=?", "Zhang San")selectTowFieldSlice := []Person{}db.Select(&selectTowFieldSlice, "select Id,Name from Person where Name=?", "Zhang San")selectNameSlice := []string{}db.Select(&selectNameSlice, "select Name from Person where Name=?", "Zhang San")从上可以看出如果只查询部分字段,还可以继续使用struct;特别的只查询一个字段时,使用基本数据类型就可以了 。
除了这些高层次的抽象方法,Sqlx也对更低层次的查询方法进行了扩展:
查询单行:
row = db.QueryRowx("select * from Person where Name=?", "Zhang San")if row.Err() == sql.ErrNoRows {log.Println("Not found Zhang San")} else {queryPerson := &Person{}err = row.StructScan(queryPerson)if err != nil {log.Println(err)return}log.Println("QueryRowx-StructScan:", queryPerson.City)}查询多行:
rows, err := db.Queryx("select * from Person where Name=?", "Zhang San")if err != nil {log.Println(err)return}for rows.Next() {rowSlice, err := rows.SliceScan()if err != nil {log.Println(err)return}log.Println("Queryx-SliceScan:", string(rowSlice[2].([]byte)))}命名参数Query:
rows, err = db.NamedQuery("select * from Person where Name=:n", map[string]interface{}{"n": "Zhang San"})查询出数据行后,这里有多种映射方法:StructScan、SliceScan和MapScan,分别对应映射后的不同数据结构 。
预处理语句对于重复使用的SQL语句,可以采用预处理的方式,减少SQL解析的次数,减少网络通信量,从而提高SQL操作的吞吐量 。
下面的代码展示了sqlx中如何使用stmt查询数据,分别采用了命名参数和通用占位符两种传参方式 。
bosima := Person{}bossma := Person{}nstmt, err := db.PrepareNamed("SELECT * FROM Person WHERE Name = :n")if err != nil {log.Println(err)return}err = nstmt.Get(&bossma, map[string]interface{}{"n": "BOSSMA"})if err != nil {log.Println(err)return}log.Println("NamedStmt-Get1:", bossma.City)err = nstmt.Get(&bosima, map[string]interface{}{"n": "BOSIMA"})if err != nil {log.Println(err)return}log.Println("NamedStmt-Get2:", bosima.City)stmt, err := db.Preparex("SELECT * FROM Person WHERE Name=?")if err != nil {log.Println(err)return}err = stmt.Get(&bosima, "BOSIMA")if err != nil {log.Println(err)return}log.Println("Stmt-Get1:", bosima.City)err = stmt.Get(&bossma, "BOSSMA")if err != nil {log.Println(err)return}log.Println("Stmt-Get2:", bossma.City)对于上文增删改查的方法,sqlx都有相应的扩展方法 。与上文不同的是,需要先使用SQL模版创建一个stmt实例,然后执行相关SQL操作时,不再需要传递SQL语句 。
数据库事务为了在事务中执行sqlx扩展的增删改查方法,sqlx必然也对数据库事务做一些必要的扩展支持 。
tx, err = db.Beginx()if err != nil {log.Println(err)return}tx.MustExec("INSERT INTO Person (Name, City, AddTime, UpdateTime) VALUES (?, ?, ?, ?)", "Zhang San", "Beijing", time.Now(), time.Now())tx.MustExec("INSERT INTO Person (Name, City, AddTime, UpdateTime) VALUES (?, ?, ?, ?)", "Li Si Hai", "Dong Bei", time.Now(), time.Now())err = tx.Commit()if err != nil {log.Println(err)return}log.Println("tx-Beginx is successful")


推荐阅读