Versions Compared
Key
- This line was added.
- This line was removed.
- Formatting was changed.
常用方法
Insert
/InsertIgnore/Replace/Save
这几个链式操作方法用于数据的写入,并且支持自动的单条或者批量的数据写入,区别如下:
Insert
使用
INSERT INTO
语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,返回失败,否则写入一条新数据;InsertIgnore
使用
INSERT IGNORE INTO
语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,忽略错误继续执行写入;语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,返回失败,否则写入一条新数据。Replace
使用
REPLACE INTO
语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,会删除原有的记录,必定会写入一条新记录;语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,会删除原有的记录,必定会写入一条新记录。Save
使用
INSERT INTO
语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,更新原有数据,否则写入一条新数据;语句进行数据库写入,如果写入的数据中存在主键或者唯一索引时,更新原有数据,否则写入一条新数据。对于部分数据库,例如PgSQL, SQL server, Oracle
可以使用OnConflict
方法指定冲突键。Code Block language go db.Model(table).Data(g.Map{ "id": 1, "passport": "p1", "password": "pw1", }).OnConflict("id").Save()
在部分数据库类型中,并不支持
Replace/Save
方法,具体请参考数据库类型介绍章节。方法,具体请参考链式操作介绍章节。
这三个方法往往需要结合这几个方法需要结合Data
方法使用,该方法用于传递数据参数,用于数据写入/更新等写操作,支持的参数为string/map/slice/struct/*struct
。例如,在进行Insert
操作时,开发者可以传递任意的map
类型,如: map[string]string
/map[string]interface{}
/map[interface{}]interface{}
等等,也可以传递任意的struct/*struct/[]struct/[]*struct
类型。此外,这三个方法也支持直接的data
参数输入,该参数Data
方法参数一致。
示例1,基本使用
更新等写操作。
InsertIgnore
用于写入数据时如果写入的数据中存在主键或者唯一索引时,忽略错误继续执行写入。该方法定义如下:
Code Block | ||
---|---|---|
| ||
func (m *Model) InsertIgnore(data ...interface{}) (result sql.Result, err error) |
InsertAndGetId
用于写入数据时并直接返回自增字段的ID
。该方法定义如下:
Code Block | ||
---|---|---|
| ||
func (m *Model) InsertAndGetId(data ...interface{}) (lastInsertId int64, err error) |
OnDuplicate/OnDuplicateEx
OnDuplicate/OnDuplicateEx
方法需要结合Save
方法一起使用,用于指定Save
方法的更新/不更新字段,参数为字符串、字符串数组、Map
。例如:
Code Block | ||
---|---|---|
| ||
OnDuplicate("nickname, age")
OnDuplicate("nickname", "age")
OnDuplicate(g.Map{
"nickname": gdb.Raw("CONCAT('name_', VALUES(`nickname`))"),
})
OnDuplicate(g.Map{
"nickname": "passport",
}) |
其中OnDuplicateEx
用于排除指定忽略更新的字段,排除的字段需要在写入的数据集合中。
使用示例
示例1,基本使用
数据写入/保存方法需要结合Data
方法使用,方法的参数类型可以为Map/Struct/Slice
:
Code Block | ||
---|---|---|
|
Data
方法使用:// INSERT INTO `user`(`name`) VALUES('john')
|
g.Model("user").Data(g.Map{"name": "john"}).Insert() // INSERT IGNORE INTO `user`(`uid`,`name`) VALUES(10000,'john') |
g.Model("user").Data(g.Map{"uid": 10000, "name": "john"}).InsertIgnore() // REPLACE INTO `user`(`uid`,`name`) VALUES(10000,'john') |
g.Model("user").Data(g.Map{"uid": 10000, "name": "john"}).Replace() // INSERT INTO `user`(`uid`,`name`) VALUES(10001,'john') ON DUPLICATE KEY UPDATE `uid`=VALUES(`uid`),`name`=VALUES(`name`) |
g.Model("user").Data(g.Map{"uid": 10001, "name": "john"}).Save() |
也可以不使用Data
方法,而给写入/保存方法直接传递数据参数:
Code Block | ||
---|---|---|
| ||
g.Model("user").Insert(g.Map{"name": "john"}) |
g.Model("user").Replace(g.Map{"uid": 10000, "name": "john"}) |
g.Model("user").Save(g.Map{"uid": 10001, "name": "john"}) |
数据参数也常用 struct
类型,例如当表字段为 uid/name/site
时:
Code Block | ||
---|---|---|
| ||
type User struct {
Uid int `orm:"uid"`
Name string `orm:"name"`
Site string `orm:"site"`
}
user := &User{
Uid: 1,
Name: "john",
Site: "https://goframe.org",
}
// INSERT INTO `user`(`uid`,`name`,`site`) VALUES(1,'john','https://goframe.org')
|
g. |
Model( |
"user").Data(user).Insert() |
示例2,数据批量写入
通过给Data
方法输入Slice
数组类型的参数,用以实现批量写入。数组元素需要为Map
或者Struct
类型,以便于数据库组件自动获取字段信息并生成批量操作SQL
。
Code Block | ||
---|---|---|
| ||
// INSERT INTO `user`(`name`) VALUES('john_1'),('john_2'),('john_3')
|
g.Model("user").Data(g.List{ {"name": "john_1"}, {"name": "john_2"}, {"name": "john_3"}, }).Insert() |
可以通过Batch
方法指定批量操作中分批写入条数数量(默认是10
),以下示例将会被拆分为两条写入请求:
Code Block | ||
---|---|---|
| ||
// INSERT INTO `user`(`name`) VALUES('john_1'),('john_2')
// INSERT INTO `user`(`name`) VALUES('john_3')
|
g.Model("user").Data(g.List{ {"name": "john_1"}, {"name": "john_2"}, {"name": "john_3"}, }).Batch(2).Insert() |
示例3,数据批量保存
批量保存操作与单条保存操作原理是一样的,当写入的数据中存在主键或者唯一索引时将会更新原有记录值,否则新写入一条记录。
oracle, dm, mssql
不支持批量保存。
Code Block | ||
---|---|---|
| ||
// INSERT INTO `user`(`uid`,`name`) VALUES(10000,'john_1'),(10001,'john_2'),(10002,'john_3')
// ON DUPLICATE KEY UPDATE `uid`=VALUES(`uid`),`name`=VALUES(`name`)
|
g.Model("user").Data(g.List{ {"uid":10000, "name": "john_1"}, {"uid":10001, "name": "john_2"}, {"uid":10002, "name": "john_3"}, }).Save() |
RawSQL
语句嵌入
gdb.Raw
是字符串类型,该类型的参数将会直接作为SQL
片段嵌入到提交到底层的SQL
语句中,不会被自动转换为字符串参数类型、也不会被当做预处理参数。更详细的介绍请参考章节:ORM高级特性-RawSQL。例如:
Code Block | ||
---|---|---|
| ||
// INSERT INTO `user`(`id`,`passport`,`password`,`nickname`,`create_time`) VALUES('id+2','john','123456','now()') g.Model("user").Data(g.Map{ "id": "id+2", "passport": "john", "password": "123456", "nickname": "JohnGuo", "create_time": "now()", }).Insert() // 执行报错:Error Code: 1136. Column count doesn't match value count at row 1 |
使用gdb.Raw
改造后:
Code Block | ||
---|---|---|
| ||
// INSERT INTO `user`(`id`,`passport`,`password`,`nickname`,`create_time`) VALUES(id+2,'john','123456',now())
g.Model("user").Data(g.Map{
"id": gdb.Raw("id+2"),
"passport": "john",
"password": "123456",
"nickname": "JohnGuo",
"create_time": gdb.Raw("now()"),
}).Insert() |
Panel | ||
---|---|---|
| ||
|