




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
第golang連接sqlx庫的操作使用指南目錄sqlx庫使用指南sqlx介紹安裝sqlx基本使用連接數(shù)據(jù)庫查詢插入、更新和刪除NamedExecNamedQuery事務(wù)操作sqlx.Insqlx.In的批量插入示例表結(jié)構(gòu)結(jié)構(gòu)體bindvars(綁定變量)自己拼接語句實現(xiàn)批量插入使用sqlx.In實現(xiàn)批量插入使用NamedExec實現(xiàn)批量插入sqlx.In的查詢示例in查詢in查詢和FIND_IN_SET函數(shù)
sqlx庫使用指南
在項目中我們通??赡軙褂胐atabase/sql連接MySQL數(shù)據(jù)庫。本文借助使用sqlx實現(xiàn)批量插入數(shù)據(jù)的例子,介紹了sqlx中可能被你忽視了的sqlx.In和DB.NamedExec方法。
sqlx介紹
在項目中我們通??赡軙褂胐atabase/sql連接MySQL數(shù)據(jù)庫。sqlx可以認為是Go語言內(nèi)置database/sql的超集,它在優(yōu)秀的內(nèi)置database/sql基礎(chǔ)上提供了一組擴展。這些擴展中除了大家常用來查詢的Get(destinterface{},...)error和Select(destinterface{},...)error外還有很多其他強大的功能。
安裝sqlx
goget/jmoiron/sqlx
基本使用
連接數(shù)據(jù)庫
vardb*sqlx.DB
funcinitDB()(errerror){
dsn:="user:password@tcp(:3306)/sql_testcharset=utf8mb4parseTime=True"
//也可以使用MustConnect連接不成功就panic
db,err=sqlx.Connect("mysql",dsn)
iferr!=nil{
fmt.Printf("connectDBfailed,err:%v\n",err)
return
db.SetMaxOpenConns(20)
db.SetMaxIdleConns(10)
return
查詢
查詢單行數(shù)據(jù)示例代碼如下:
//查詢單條數(shù)據(jù)示例
funcqueryRowDemo(){
sqlStr:="selectid,name,agefromuserwhereid="
varuuser
err:=db.Get(u,sqlStr,1)
iferr!=nil{
fmt.Printf("getfailed,err:%v\n",err)
return
fmt.Printf("id:%dname:%sage:%d\n",u.ID,u.Name,u.Age)
查詢多行數(shù)據(jù)示例代碼如下:
//查詢多條數(shù)據(jù)示例
funcqueryMultiRowDemo(){
sqlStr:="selectid,name,agefromuserwhereid"
varusers[]user
err:=db.Select(amp;users,sqlStr,0)
iferr!=nil{
fmt.Printf("queryfailed,err:%v\n",err)
return
fmt.Printf("users:%#v\n",users)
插入、更新和刪除
sqlx中的exec方法與原生sql中的exec使用基本一致:
//插入數(shù)據(jù)
funcinsertRowDemo(){
sqlStr:="insertintouser(name,age)values(,)"
ret,err:=db.Exec(sqlStr,"沙河小王子",19)
iferr!=nil{
fmt.Printf("insertfailed,err:%v\n",err)
return
theID,err:=ret.LastInsertId()//新插入數(shù)據(jù)的id
iferr!=nil{
fmt.Printf("getlastinsertIDfailed,err:%v\n",err)
return
fmt.Printf("insertsuccess,theidis%d.\n",theID)
//更新數(shù)據(jù)
funcupdateRowDemo(){
sqlStr:="updateusersetage=whereid="
ret,err:=db.Exec(sqlStr,39,6)
iferr!=nil{
fmt.Printf("updatefailed,err:%v\n",err)
return
n,err:=ret.RowsAffected()//操作影響的行數(shù)
iferr!=nil{
fmt.Printf("getRowsAffectedfailed,err:%v\n",err)
return
fmt.Printf("updatesuccess,affectedrows:%d\n",n)
//刪除數(shù)據(jù)
funcdeleteRowDemo(){
sqlStr:="deletefromuserwhereid="
ret,err:=db.Exec(sqlStr,6)
iferr!=nil{
fmt.Printf("deletefailed,err:%v\n",err)
return
n,err:=ret.RowsAffected()//操作影響的行數(shù)
iferr!=nil{
fmt.Printf("getRowsAffectedfailed,err:%v\n",err)
return
fmt.Printf("deletesuccess,affectedrows:%d\n",n)
NamedExec
DB.NamedExec方法用來綁定SQL語句與結(jié)構(gòu)體或map中的同名字段。
funcinsertUserDemo()(errerror){
sqlStr:="INSERTINTOuser(name,age)VALUES(:name,:age)"
_,err=db.NamedExec(sqlStr,
map[string]interface{}{
"name":"七米",
"age":28,
return
NamedQuery
與DB.NamedExec同理,這里是支持查詢。
funcnamedQuery(){
sqlStr:="SELECT*FROMuserWHEREname=:name"
//使用map做命名查詢
rows,err:=db.NamedQuery(sqlStr,map[string]interface{}{"name":"七米"})
iferr!=nil{
fmt.Printf("db.NamedQueryfailed,err:%v\n",err)
return
deferrows.Close()
forrows.Next(){
varuuser
err:=rows.StructScan(u)
iferr!=nil{
fmt.Printf("scanfailed,err:%v\n",err)
continue
fmt.Printf("user:%#v\n",u)
u:=user{
Name:"七米",
//使用結(jié)構(gòu)體命名查詢,根據(jù)結(jié)構(gòu)體字段的dbtag進行映射
rows,err=db.NamedQuery(sqlStr,u)
iferr!=nil{
fmt.Printf("db.NamedQueryfailed,err:%v\n",err)
return
deferrows.Close()
forrows.Next(){
varuuser
err:=rows.StructScan(u)
iferr!=nil{
fmt.Printf("scanfailed,err:%v\n",err)
continue
fmt.Printf("user:%#v\n",u)
事務(wù)操作
對于事務(wù)操作,我們可以使用sqlx中提供的db.Beginx()和tx.Exec()方法。示例代碼如下:
functransactionDemo2()(errerror){
tx,err:=db.Beginx()//開啟事務(wù)
iferr!=nil{
fmt.Printf("begintransfailed,err:%v\n",err)
returnerr
deferfunc(){
ifp:=recover();p!=nil{
tx.Rollback()
panic(p)//re-throwpanicafterRollback
}elseiferr!=nil{
fmt.Println("rollback")
tx.Rollback()//errisnon-nil;don'tchangeit
}else{
err=tx.Commit()//errisnil;ifCommitreturnserrorupdateerr
fmt.Println("commit")
sqlStr1:="Updateusersetage=20whereid="
rs,err:=tx.Exec(sqlStr1,1)
iferr!=nil{
returnerr
n,err:=rs.RowsAffected()
iferr!=nil{
returnerr
ifn!=1{
returnerrors.New("execsqlStr1failed")
sqlStr2:="Updateusersetage=50wherei="
rs,err=tx.Exec(sqlStr2,5)
iferr!=nil{
returnerr
n,err=rs.RowsAffected()
iferr!=nil{
returnerr
ifn!=1{
returnerrors.New("execsqlStr1failed")
returnerr
sqlx.In
sqlx.In是sqlx提供的一個非常方便的函數(shù)。
sqlx.In的批量插入示例
表結(jié)構(gòu)
為了方便演示插入數(shù)據(jù)操作,這里創(chuàng)建一個user表,表結(jié)構(gòu)如下:
CREATETABLE`user`(
`id`BIGINT(20)NOTNULLAUTO_INCREMENT,
`name`VARCHAR(20)DEFAULT'',
`age`INT(11)DEFAULT'0',
PRIMARYKEY(`id`)
)ENGINE=InnoDBAUTO_INCREMENT=1DEFAULTCHARSET=utf8mb4;
結(jié)構(gòu)體
定義一個user結(jié)構(gòu)體,字段通過tag與數(shù)據(jù)庫中user表的列一致。
typeUserstruct{
Namestring`db:"name"`
Ageint`db:"age"`
bindvars(綁定變量)
查詢占位符在內(nèi)部稱為bindvars(查詢占位符),它非常重要。你應(yīng)該始終使用它們向數(shù)據(jù)庫發(fā)送值,因為它們可以防止SQL注入攻擊。database/sql不嘗試對查詢文本進行任何驗證;它與編碼的參數(shù)一起按原樣發(fā)送到服務(wù)器。除非驅(qū)動程序?qū)崿F(xiàn)一個特殊的接口,否則在執(zhí)行之前,查詢是在服務(wù)器上準(zhǔn)備的。因此bindvars是特定于數(shù)據(jù)庫的:
MySQL中使用PostgreSQL使用枚舉的$1、$2等bindvar語法SQLite中和$1的語法都支持Oracle中使用:name的語法
bindvars的一個常見誤解是,它們用來在sql語句中插入值。它們其實僅用于參數(shù)化,不允許更改SQL語句的結(jié)構(gòu)。例如,使用bindvars嘗試參數(shù)化列或表名將不起作用:
//?不能用來插入表名(做SQL語句中表名的占位符)
db.Query("SELECT*FROM","mytable")
//?也不能用來插入列名(做SQL語句中列名的占位符)
db.Query("SELECT,FROMpeople","name","location")
自己拼接語句實現(xiàn)批量插入
比較笨,但是很好理解。就是有多少個User就拼接多少個(,)。
//BatchInsertUsers自行構(gòu)造批量插入的語句
funcBatchInsertUsers(users[]*User)error{
//存放(,)的slice
valueStrings:=make([]string,0,len(users))
//存放values的slice
valueArgs:=make([]interface{},0,len(users)*2)
//遍歷users準(zhǔn)備相關(guān)數(shù)據(jù)
for_,u:=rangeusers{
//此處占位符要與插入值的個數(shù)對應(yīng)
valueStrings=append(valueStrings,"(,)")
valueArgs=append(valueArgs,u.Name)
valueArgs=append(valueArgs,u.Age)
//自行拼接要執(zhí)行的具體語句
stmt:=fmt.Sprintf("INSERTINTOuser(name,age)VALUES%s",
strings.Join(valueStrings,","))
_,err:=DB.Exec(stmt,valueArgs...)
returnerr
使用sqlx.In實現(xiàn)批量插入
前提是需要我們的結(jié)構(gòu)體實現(xiàn)driver.Valuer接口:
func(uUser)Value()(driver.Value,error){
return[]interface{}{u.Name,u.Age},nil
使用sqlx.In實現(xiàn)批量插入代碼如下:
//BatchInsertUsers2使用sqlx.In幫我們拼接語句和參數(shù),注意傳入的參數(shù)是[]interface{}
funcBatchInsertUsers2(users[]interface{})error{
query,args,_:=sqlx.In(
"INSERTINTOuser(name,age)VALUES(),(),()",
users...,//如果arg實現(xiàn)了driver.Valuer,sqlx.In會通過調(diào)用Value()來展開它
fmt.Println(query)//查看生成的querystring
fmt.Println(args)//查看生成的args
_,err:=DB.Exec(query,args...)
returnerr
使用NamedExec實現(xiàn)批量插入
注意:該功能需1.3.1版本以上,并且1.3.1版本目前還有點問題,sql語句最后不能有空格和;,詳見issues/690。
使用NamedExec實現(xiàn)批量插入的代碼如下:
//BatchInsertUsers3使用NamedExec實現(xiàn)批量插入
funcBatchInsertUsers3(users[]*User)error{
_,err:=DB.NamedExec("INSERTINTOuser(name,age)VALUES(:name,:age)",users)
returnerr
把上面三種方法綜合起來試一下:
funcmain(){
err:=initDB()
iferr!=nil{
panic(err)
deferDB.Close()
u1:=User{Name:"七米",Age:18}
u2:=User{Name:"q1mi",Age:28}
u3:=User{Name:"小王子",Age:38}
//方法1
users:=[]*User{u1,u2,u3}
err=BatchInsertUsers(users)
iferr!=nil{
fmt.Printf("BatchInsertUsersfailed,err:%v\n",err)
//方法2
users2:=[]interface{}{u1,u2,u3}
err=BatchInsertUsers2(users2)
iferr!=nil{
fmt.Printf("BatchInsertUsers2failed,err:%v\n",err)
//方法3
users3:=[]*User{u1,u2,u3}
err=BatchInsertUsers3(users3)
iferr!=nil{
fmt.Printf("BatchInsertUsers3failed,err:%v\n",err)
sqlx.In的查詢示例
關(guān)于sqlx.In這里再補充一個用法,在sqlx查詢語句中實現(xiàn)In查詢和FIND_IN_SET函數(shù)。
即實現(xiàn)SELECT*FROMuserWHEREidin(3,2,1);
和SELECT*FROMuserWHEREidin(3,2,1)ORDERBYFIND_IN_SET(id,3,2,1。
in查詢
查詢id在給定id集合中的數(shù)據(jù)。
//QueryByIDs根據(jù)給定ID查詢
funcQueryByIDs(ids[]int)(users[]User,errerror){
//動態(tài)填充id
query,args,err:=sqlx.In("SELECTname,ageFROMuser
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 紡織工藝優(yōu)化實踐試題及答案
- 《高效課堂管理》課件
- 采購試題庫及答案
- 酒館轉(zhuǎn)讓合同協(xié)議書
- 企業(yè)衛(wèi)生承包合同協(xié)議書
- 轉(zhuǎn)讓飯店合同協(xié)議書
- 餐飲外賣合同協(xié)議書
- 合同協(xié)議書副本怎么寫
- 民房合同協(xié)議書
- 合同協(xié)議書的間隔
- 工商企業(yè)管理專業(yè)模擬實訓(xùn)報告
- 煙花爆竹事故應(yīng)急處置
- 專利法全套ppt課件(完整版)
- 八年級英語15篇完形填空(附答案)
- 《馬克思主義與社會科學(xué)方法論》課件第四講 社會矛盾研究方法
- 會寶嶺選礦廠集中控制技術(shù)方案
- 第13講巧解弦圖與面積
- 畢業(yè)設(shè)計(論文)-CK6150總體及縱向進給和尾座部件的設(shè)計
- 初中物理新課程標(biāo)準(zhǔn)學(xué)生必做的20個實驗
- 天津市公路工程工地試驗室管理規(guī)定
- 小學(xué)心理健康《欣賞我自己》教學(xué)設(shè)計
評論
0/150
提交評論