-
Notifications
You must be signed in to change notification settings - Fork 9
Replace方法
Tuuz edited this page Nov 6, 2023
·
10 revisions
- Mysql原本就支持Replace方法并且十分灵活,你只需要按照常规流程操作即可
- Oracle版本的使用上与Mysql略有出入,为了实现更加灵活的Replace方法,你可以查看下面提供的几个场景的Demo,十分简单易上手
原版框架的Replace方法因为Oracle不支持的原因,会导致报错,新版(v1.12.6+)在修复故障的同时,使用Merge方法覆写了Replace,使Oracle数据库也可以和Mysql一样使用ReplaceInto方法
- 数据库
- 名称:aaa
- 字段:
- id:NUMBER
- val:VARCHAR2
- val2:VARCHAR2
CREATE TABLE "C##TEST"."aaa" (
"id" NUMBER NOT NULL ENABLE,
"val" VARCHAR2 ( 255 ) DEFAULT '',
"val2" VARCHAR2 ( 255 ),
PRIMARY KEY ( "id" ) USING INDEX PCTFREE 10 INITRANS 2 MAXTRANS 255 COMPUTE STATISTICS STORAGE ( INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) TABLESPACE "USERS" ENABLE
) SEGMENT CREATION IMMEDIATE PCTFREE 10 PCTUSED 40 INITRANS 1 MAXTRANS 255 NOCOMPRESS LOGGING STORAGE ( INITIAL 65536 NEXT 1048576 MINEXTENTS 1 MAXEXTENTS 2147483645 PCTINCREASE 0 FREELISTS 1 FREELIST GROUPS 1 BUFFER_POOL DEFAULT FLASH_CACHE DEFAULT CELL_FLASH_CACHE DEFAULT ) TABLESPACE "USERS"
- 我希望直接把这个方法当成insert来用,性能差点我不在意:
- 你要不要看看你自己在说什么?
- 我希望只检测id,当id=2时,修改val和val2字段的数据,当id=2不存在时插入这一条数据
tuuz.Db()
db := tuuz.Db().Table("aaa")
db.Fields()
db.Where("id")
db.Data(map[string]any{
"id": "2",
"val": "ggg",
"val2": "sss",
})
fmt.Println(db.Replace())
- 我希望检测id=2是否存在的同时,检测val是否也叫"ggg"如果有就更新val2为"sss"如果没有,就插入这一整条数据
tuuz.Db()
db := tuuz.Db().Table("aaa")
db.Fields()
db.Where("id")
db.Where("val")
db.Data(map[string]any{
"id": "2",
"val": "ggg",
"val2": "sss",
})
fmt.Println(db.Replace())
- 我希望全检测,如果三个字段均有重复的就不要插入了,如果没有重复的就插入一条新的数据(当Insert来用)
- 请注意这个方法不健康,因为没有做主键检测,假设你的主键是id,使用这个方法,id重复了,他就不会成功插入,举个例子:
tuuz.Db()
db := tuuz.Db().Table("aaa")
db.Fields()
db.Data(map[string]any{
"id": "2",
"val": "ggg",
"val2": "sss",
})
fmt.Println(db.Replace())
- 例如id为2的那条数据已经存在了(id是主键),err就会立即报错,你将你会看到Oracle的错误信息:
unique constraint (C##TEST.SYS_C008317) violated
- 所以在这个情况下,我强烈建议你使用db.Where(你的主键),来避免此类错误的发生,当然如果你需要的就是重复报错并在前端返回,那么也许这么设计刚好可以解决你的问题
- 所以Replace的设计主要就是为了解决你使用中的灵活性问题,让Oracle也可以用着很方便
- 为什么要用where来承接,为什么不能直接使用db.Where("id",2)这样的方法,不是看起来更方便吗?
- 因为MySQL也是这么用的,举个例子,默认的Mysql Replace into用法
REPLACE INTO aaa (id, val, val2) VALUES (2, 'ccc', 'fff');
- 如果我只想根据id来修改其他字段,语句就会变成这样
INSERT INTO aaa (id, val, val2) VALUES (2, 'ccc', 'fff') ON DUPLICATE KEY UPDATE val = 'ccc', val2 = 'fff';
- 所以在这个基础上,如果不传where,就是上面的用法,传where,就自动变成了下面的模式,当然这只是一个MySQL的Demo用于解释框架是如何更加灵活的解决Oracle中使用Replace的方法
- 环境测试
- 已经通过测试环境测试
- 安全性
- 已使用PrepareStatement来解决注入问题,请不要在Where中输入动态查询参数避免预处理失效(也许来自远程的PostGet参数)
- 操作使用
- 因为Oracle的不同,框架已经做了Oracle关键字处理,你无需自己再处理,例如使用NUMBER关键字作为字段时你无需使用db.Where(""NUMBER"")来处理,你可以直接使用db.Where("NUMBER")即可,其他的内容框架已经做过处理了,当然如果吃的很饱也可以自己处理一遍,框架没有反直觉的设计,你觉得这样行,大概率就是行的,不行你可以再ISSUE或直接PR