顺晟科技
2021-06-16 10:27:26
476
在项目中,我们通常会使用数据库/sql来连接MySQL数据库。以sqlx批量插入数据为例,介绍了sqlx的方法。输入和输出。在SQLX中可能被您忽略的名称索引。
在项目中,我们通常会使用数据库/sql来连接MySQL数据库。Sqlx可以看作是Go语言内置数据库/sql的超集,它在的内置数据库/sql的基础上提供了一套扩展。除了Get(dest接口{},)错误并选择(目标接口{},)错误,它们通常用于查询,在这些扩展中还有许多其他强大的功能。
以sqlx批量插入数据为例,介绍了sqlx的方法。输入和输出。在SQLX中可能被您忽略的名称索引。
前提
连接到数据库
var DB *sqlx。分贝
func initDB() (err错误){
DSN :=' username : password @ TCP(127 . 0 . 0 . 1:3306)/sqlx _ demo '
//你死机了也用MustConnect连接不成功。
DB,err=sqlx。Connect('mysql ',dsn)
如果出错!=零{
fmt。Printf('连接数据库失败,错误:%v\n ',错误)
返回
}
fmt。Println('连接到MySQL . ')
返回
}
表结构
创建表格`用户` (
` id` BIGINT(20)非空自动增量,
` name` VARCHAR(20) DEFAULT ',
` age` INT(11) DEFAULT '0 ',
主键(` id `)
)ENGINE=Innodb AUTO _ INDEX=1 DEFAULT CHARSET=utf 8 MB 4;
结构体
用户类型结构{
名称字符串` db: '名称' '
Age int `db:'age ' '
}
Bindvars(绑定变量)
查询占位符?内部叫bindvars,很重要。您应该始终使用它们向数据库发送值,因为它们可以防止SQL注入攻击。数据库/sq不尝试验证查询文本;它与编码参数一起被发送到服务器。除非驱动程序实现了一个特殊的接口,否则查询是在执行之前在服务器上准备好的。因此,bindvars是特定于数据库的:
用在MySQL中?
PostgreSQL使用$1、$2等枚举bindvar语法。
在SQLite?并且支持$1的语法
甲骨文中使用:name的语法
其他数据库可能不同。您可以使用sqlx。重新绑定(字符串)字符串函数和?获取适合在当前数据库类型上执行的查询语句。
bindvars的一个常见误解是,它们用于将值插入语句。它们只用于参数化,不允许改变SQL语句的结构。例如,试图用bindvars参数化列或表名没有效果:
//?它不能用于插入表名(作为SQL语句中表名的占位符)
db。查询('选择*从?',' mytable ')
//?它也不能用于插入列名(作为SQL语句中列名的占位符)
db。查询(' SELECT?FROM people ',' name ',' location ')
如何实现批量插入?
实现批量插入的自拼接语句
很蠢,但是很好理解。是拼接尽可能多的用户(?)。
//批处理插入用户自己构造用于批处理插入的语句
func BatchInsertUsers(用户[]*用户)错误{
//商店(?切片)
value strings :=make([]string,0,len(users))
//保存值的切片
value args :=make([]interface { },0,len(user)* 2)
//遍历用户准备相关数据
对于_,u :=范围用户{
//此处的占位符应对应于插入值的数量
value strings=append(value strings,'(?)')
valueArgs=追加(valueArgs,u.Name)
valueArgs=append(valueArgs,u年龄)
}
//拼接自己要执行的特定语句
stmt :=fmt。Sprintf('插入到用户(姓名,年龄)值%s ',
弦乐。Join(valueStrings,','))
_,err :=DB。Exec(stmt,valueArgs.)
返回错误
}
使用sqlx。为了实现批量插入
前提是我们的结构需要实现驱动。估值器接口:
用户值()(驱动程序。值,错误){
返回[]接口{}{u.Name,u.Age},零
}
使用sqlx。为了实现批量插入,代码如下:
//batchinsertuser2使用sqlx。为了帮助我们拼接语句和参数,请注意传入的参数是[]接口{}
func Batchinsertusers 2(user[]接口{})错误{
query,args,_ :=sqlx。在(
插入用户(姓名、年龄)值(?), (?), (?)',
用户.//如果arg实现驱动。赋值器,sqlx。在中,将通过调用Value()来展开它
)
fmt .Println(查询)//查看生成的参数
fmt .Println(args) //查看生成的一个参数名
_,err :=DB .Exec(查询,参数.)
返回错误
}
使用NamedExec实现批量插入
注意:该功能目前有人已经推了#285 PR,但是作者还没有发释放,所以想要使用下面的方法实现批量插入需要暂时使用掌握分支的代码:
在项目目录下执行以下命令下载并使用掌握分支代码:
去找github.com/jmoiron/sqlx@master
使用NamedExec实现批量插入的代码如下:
//batchinsertsusers 3使用NamedExec实现批量插入
func BatchInsertUsers3(用户[*]用户)错误{
_,err :=DB .名称索引('插入用户(姓名,年龄)值(:姓名,年龄),'用户)
返回错误
}
把上面三种方法综合起来试一下:
func main() {
err :=initDB()
如果出错!=零{
恐慌(错误)
}
延迟数据库。关闭()
u1 :=用户{姓名: '七米,年龄: 18 }
u2 :=用户{姓名: 'q1mi ',年龄: 28}
u3 :=用户{姓名: '小王子,年龄: 38 }
//方法一
用户:=[]*用户{u1,u2,u3}
err=BatchInsertUsers(用户)
如果出错!=零{
fmt .printf(' batchinsertus失败,错误' :%v\n ',错误)
}
//方法2
用户2 :=[]界面{ } { u1,u2,u3}
err=Batchinsertusers 2(用户2)
如果出错!=零{
fmt .printf(' batchinsertsusers2失败,错误' :%v\n ',错误)
}
//方法3
用户3 :=[]*用户{u1,u2,u3}
err=Batchinsertusers 3(用户3)
如果出错!=零{
fmt .printf(' batchinsertsusers 3失败,错误' :%v\n ',错误)
}
}
sqlx .在…里的查询示例
关于sqlx .在…里这里再补充一个用法,在sqlx查询语句中实现在…里查询和查找_输入_设置函数。即实现在(3,2,1)中选择*出发地用户WHERE id和从用户中选择*在(3,2,1)中标识为"按查找_输入_设置排序"(标识为"3,2,1");
在查询
查询编号在给定编号集合中的数据。
//查询byid根据给定身份查询
函数查询BYIDs(ids[]int)(用户[]用户,错误){
//动态填充编号
query,args,err :=sqlx .在('从用户中选择姓名、年龄,其中编号在(?)’,ids)
如果出错!=零{
返回
}
//sqlx .在…里返回带`?` bindvar的查询语句,我们使用Rebind()重新绑定它
查询=数据库。重新绑定(查询)
错误=数据库。选择(用户、查询、参数.)
返回
}
在查询和查找_输入_设置函数
查询编号在给定编号集合的数据并维持给定编号集合的顺序。
//QueryAndOrderByIDs按照指定编号查询并维护顺序
func QueryAndOrderByIDs(ids[]int)(User[]User,err error){
//动态填充编号
strIDs :=make([]string,0,len(ids))
对于_,id :=范围ids {
strIDs=append(strIDs,fmt .Sprintf('%d ',id))
}
query,args,err :=sqlx .在('从用户中选择姓名、年龄,其中编号在(?)按查找_输入_设置排序(id,)’、id、字符串. Join(strIDs,','))
如果出错!=零{
返回
}
//sqlx .在…里返回带`?` bindvar的查询语句,我们使用Rebind()重新绑定它
查询=数据库。重新绑定(查询)
错误=数据库。选择(用户、查询、参数.)
返回
}
当然,在这个例子里面你也可以先使用在…里查询,然后通过代码按给定的本能冲动对查询结果进行排序。
28
1990-12
02
2022-09
12
2022-05
29
2021-08
29
2021-08
28
2021-08