【GORM】高级查询方案
【GORM】高级查询方案
- 1.Struct & Map查询为空的情况
- 2.FirstOrInit
- 3.FirstOrCreate
- 4.高级查询
1.Struct & Map查询为空的情况
当通过结构体进行查询时,GORM将会只通过非零值字段查询,这意味着如果你的字段值为0,‘’,false或者其他零值时,将不会被用于构建查询条件,例如:
db.Where(&User{Name: "jinzhu", Age: 0}).Find(&users)
// SELECT * FROM users WHERE name = "jinzhu";
可以使用指针或实现 Scanner/Valuer
接口来避免这个问题:
// 使用指针
type User struct {gorm.ModelName stringAge *int
}// 使用 Scanner/Valuer
type User struct {gorm.ModelName stringAge sql.NullInt64 // sql.NullInt64 实现了 Scanner/Valuer 接口
}
2.FirstOrInit
如果记录未找到,将使用参数初始化 struct:
var user User
// 未找到
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrInit(&user)
// db.Where(User{Name: "non_existing"}).Attrs("age", 20).FirstOrInit(&user)
fmt.Println(user) // {{0 0001-01-01 00:00:00 +0000 UTC 0001-01-01 00:00:00 +0000 UTC {0001-01-01 00:00:00 +0000 UTC false}} non_existing 20}
var user User
// 找到
db.Where(User{Name: "xiaoqian"}).Attrs(User{Age: 20}).FirstOrInit(&user)
fmt.Println(user) // {{2 2023-03-09 21:21:06 +0800 CST 2023-03-09 21:21:06 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} xiaoqian 22}
不管记录是否找到,都将参数赋值给 struct:
// 未找到
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrInit(&user)
user -> User{Name: "non_existing", Age: 20}// 找到
db.Where(User{Name: "Jinzhu"}).Assign(User{Age: 30}).FirstOrInit(&user)
SELECT * FROM USERS WHERE name = jinzhu';
user -> User{Id: 111, Name: "Jinzhu", Age: 30}
3.FirstOrCreate
获取匹配的第一条记录, 否则根据给定的条件创建一个新的记录 (仅支持 struct 和 map 条件)
// 未找到
db.FirstOrCreate(&user, User{Name: "non_existing"})
// INSERT INTO "users" (name) VALUES ("non_existing");
// 找到
db.FirstOrCreate(&user, User{Name: "xiaoqian"})
fmt.Println(user)
// {{2 2023-03-09 21:21:06 +0800 CST 2023-03-09 21:21:06 +0800 CST {0001-01-01 00:00:00 +0000 UTC false}} xiaoqian 22}
如果记录未找到,将使用参数创建 struct 和记录:
// 未找到
db.Where(User{Name: "non_existing"}).Attrs(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'non_existing';
// INSERT INTO "users" (name, age) VALUES ("non_existing", 20);// 找到
db.Where(User{Name: "jinzhu"}).Attrs(User{Age: 30}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'jinzhu';
不管记录是否找到,都将参数赋值给 struct 并保存至数据库:
// 未找到
db.Where(User{Name: "non_existing"}).Assign(User{Age: 20}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'non_existing';
// INSERT INTO "users" (name, age) VALUES ("non_existing", 20);// 找到
db.Where(User{Name: "jinzhu"}).Assign(User{Age: 30}).FirstOrCreate(&user)
// SELECT * FROM users WHERE name = 'jinzhu';
// UPDATE users SET age=30 WHERE id = 111;
4.高级查询
子查询:
基于 *gorm.expr
的子查询
db.Where("amount > ?", db.Table("orders").Select("AVG(amount)").Where("state = ?", "paid").SubQuery()).Find(&orders)
// SELECT * FROM "orders" WHERE "orders"."deleted_at" IS NULL AND (amount > (SELECT AVG(amount) FROM "orders" WHERE (state = 'paid')));
选择字段:
Select,指定你想从数据库中检索出的字段,默认会选择全部字段
db.Select("name, age").Find(&users)
// SELECT name, age FROM users;db.Select([]string{"name", "age"}).Find(&users)
// SELECT name, age FROM users;db.Table("users").Select("COALESCE(age,?)", 42).Rows()
// SELECT COALESCE(age,'42') FROM users;
排序:
db.Order("age desc, name").Find(&users)
// SELECT * FROM users ORDER BY age desc, name;db.Order("age desc").Order("name").Find(&users)
// SELECT * FROM users ORDER BY age desc, name;
数量:
Limit,指定从数据库检索出的最大记录数
db.Limit(3).Find(&users)
// SELECT * FROM users LIMIT 3;
偏移:
Offset,指定开始返回记录前要跳过的记录数
db.Offset(3).Find(&users)
总数:
Count,该 model 能获取的记录总数
db.Where("name = ?", "jinzhu").Or("name = ?", "jinzhu 2").Find(&users).Count(&count)
// SELECT * from USERS WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (users)
// SELECT count(*) FROM users WHERE name = 'jinzhu' OR name = 'jinzhu 2'; (count)db.Model(&User{}).Where("name = ?", "jinzhu").Count(&count)
// SELECT count(*) FROM users WHERE name = 'jinzhu'; (count)db.Table("deleted_users").Count(&count)
// SELECT count(*) FROM deleted_users;db.Table("deleted_users").Select("count(distinct(name))").Count(&count)
// SELECT count( distinct(name) ) FROM deleted_users; (count)
Count
必须是链式查询的最后一个操作 ,因为它会覆盖前面的SELECT
,但如果里面使用了count
时不会覆盖👛
Group & Having:
rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Rows()
for rows.Next() {...
}// 使用Scan将多条结果扫描进事先准备好的结构体切片中
type Result struct {Date time.TimeTotal int
}
var rets []Result
db.Table("users").Select("date(created_at) as date, sum(age) as total").Group("date(created_at)").Scan(&rets)rows, err := db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Rows()
for rows.Next() {...
}type Result struct {Date time.TimeTotal int64
}
db.Table("orders").Select("date(created_at) as date, sum(amount) as total").Group("date(created_at)").Having("sum(amount) > ?", 100).Scan(&results)
连接:
Joins,指定连接条件
rows, err := db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Rows()
for rows.Next() {...
}db.Table("users").Select("users.name, emails.email").Joins("left join emails on emails.user_id = users.id").Scan(&results)// 多连接及参数
db.Joins("JOIN emails ON emails.user_id = users.id AND emails.email = ?", "jinzhu@example.org").Joins("JOIN credit_cards ON credit_cards.user_id = users.id").Where("credit_cards.number = ?", "411111111111").Find(&user)
Pluck:
Pluck,查询 model 中的一个列作为切片,如果您想要查询多个列,您应该使用 Scan
var ages []int64
db.Find(&users).Pluck("age", &ages)var names []string
db.Model(&User{}).Pluck("name", &names)db.Table("deleted_users").Pluck("name", &names)
扫描:
Scan,扫描结果至一个 struct
type Result struct {Name stringAge int
}var result Result
db.Table("users").Select("name, age").Where("name = ?", "Antonio").Scan(&result)var results []Result
db.Table("users").Select("name, age").Where("id > ?", 0).Scan(&results)// 原生 SQL
db.Raw("SELECT name, age FROM users WHERE name = ?", "Antonio").Scan(&result)
相关文章:
【GORM】高级查询方案
【GORM】高级查询方案1.Struct & Map查询为空的情况2.FirstOrInit3.FirstOrCreate4.高级查询1.Struct & Map查询为空的情况 当通过结构体进行查询时,GORM将会只通过非零值字段查询,这意味着如果你的字段值为0,‘’,false…...
MFC 简单使用事件
功能三个按钮,一个静态框,默认值是0,增加减少按钮和退出按钮.增加减少按钮显示在静态框中.退出按钮退出软件.实验事件思路新建三个事件,add事件sub事件quit事件,一个按钮触发一个事件,静态框新建一个线程接受事件做出对应的改变.UI添加的代码就不具体说,具体说下事件的代码,这才…...
华为OD机试题 - 端口合并(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:端口合并题目输入输出示例一输入输出说明示例二输入输出说明示例…...
ECharts数据可视化--常用图表类型
目录 一.柱状图 1.基本柱状图 1.1最简单的柱状图 编辑 1.2多系列柱状图 1.3柱状图的样式 (1)柱条样式 (2)柱条的宽度和高度 (3)柱条间距 (4)为柱条添加背景颜色 编辑 2.堆…...
Flutter面试题解析-GridView详解与应用
一、前言Flutter 作为时下最流行的技术之一,凭借其出色的性能以及抹平多端的差异优势,早已引起大批技术爱好者的关注,甚至一些 闲鱼 , 美团 , 腾讯 等大公司均已投入生产使用。虽然目前其生态还没有完全成熟࿰…...
最全的论文写作技巧(建议收藏)
近10年来,笔者有幸多次参与教学论文的评审工作,在此,特将教学论文写作的步骤及相关问题整理汇总如下: 一、选定论题 (一)论题在文中的地位与作用 严格地讲,论文写作是从选定论题开始的。选题…...
面向对象设计模式:设计模式分类(创建型、行为型、结构型)
1. 创建型设计模式 单例模式:https://blog.csdn.net/qq_44992559/article/details/129348686工厂模式:https://blog.csdn.net/qq_44992559/article/details/115222311抽象工厂模式:https://blog.csdn.net/qq_44992559/article/details/12934…...
MySQL数据库迁移
考试系统的数据库一直是在我自己的服务器上面的, 但是最近,自己的服务器马上要过期了,里面的MySQL数据需要迁移出来,放在另外一个服务器上面。百度了几篇教程,也没研究太多,选了一种比较简单的方式进行迁移…...
Docker:关于 Dockerfile 编写优化的一些笔记整理
写在前面 分享一些 Dickerfile 构建镜像优化方式的笔记理解不足小伙伴帮忙指正 对每个人而言,真正的职责只有一个:找到自我。然后在心中坚守其一生,全心全意,永不停息。所有其它的路都是不完整的,是人的逃避方式&#…...
个性化营销:您需要知道的信息
个性化营销在现代企业中风靡一时。我们将剖析您需要了解的有关个性化营销的信息,一起来了解一下吧。 什么是个性化营销? 个性化营销是一种一对一营销形式,它使用实时用户数据和分析来传递品牌信息并针对特定潜在客户。 它与传统营销不同&…...
栈和队列的相互实现
文章目录一、用栈实现队列入队:出队:Java代码实现:二、用队列实现栈入栈:出栈:Java代码实现:附:C版代码1、用栈实现队列2、用队列实现栈栈(stack):先进后出&a…...
iTab新标签页重磅更新 |这些功能绝对有你想要的新体验!
01 写在前面 csdn的朋友们,你好哦,我是iTab 插件的独立开发者,今天给大家安利一下我做的这款桌面插件。 首先要告诉大家一个好消息: 最近iTab新标签页被Edge 浏览器商店官方热门🔥推荐啦。 在此,特别感谢…...
【改机教程】iOS系统去除小黑条,改拍照声、拨号音、键盘音,不用越狱,支持所有机型
大家好,上次给大家分享了几个iOS系统免越狱改机教程 今天带来最新的教程,这次修改利用的是同一个漏洞,由外网大神 tamago 开发,国内大神冷风 进行汉化和优化 可以修改的地方包括 去除底部小黑条 dock栏透明 桌面文件夹透明 桌面…...
Android10开机向导中复用设置中的Wifi界面
很多时候我们需要定制开机向导,在开机向导界面我们一般会实现联网和设置时间等功能,考虑复用与稳定性问题,我们最好复用设置中的WiFi设置和日期设置。但是设置中的wifi设置界面默认是没有下一步按钮的,这会让用户感觉很奇怪。在以…...
川农机械专业小伙转行Java开发,年薪20w
本期学员就业故事,知了姐邀请到一位“特别”的同学,一位从知了堂就业成功近两年的学员再度接受我们的采访。 来自四川农业大学的曾同学,一个本来学机械开挖掘机的粗犷男人,因为不断地努力学习编程,最终成为一个性格闷…...
华为OD机试题 - 打印文件(JavaScript)| 机考必刷
更多题库,搜索引擎搜 梦想橡皮擦华为OD 👑👑👑 更多华为OD题库,搜 梦想橡皮擦 华为OD 👑👑👑 更多华为机考题库,搜 梦想橡皮擦华为OD 👑👑👑 华为OD机试题 最近更新的博客使用说明本篇题解:打印文件题目输入输出示例一输入输出示例二输入输出Code代码解析…...
免费常用API大全,程序员必备
淘宝接口 淘宝开放平台 http://open.taobao.com/?spma219a.7395905.1.1.YdFDV6 APISpace 生活常用 今天吃什么:随机返回一顿美味食物,解决你今天吃什么的难题。 星座查询:根据日期或星座名称,查询星座详细信息,包…...
MySQL主从复制,读写分离
目录 一、MySQL主从复制介绍 MySQL复制过程分成三步 二、主库配置master 1、步骤1 2、第二步:重启Mysql服务 3、第三步:登录Mysql数据库,执行下面SQL 4、第四步:登录Mysql数据库,执行下面SQL,记录下结果中File和…...
什么是UEFI签名认证?UEFI签名有什么好处?
为了防御恶意软件攻击,目前市面上所有电脑设备启动时默认开启安全启动(Secure Boot)模式。安全启动(Secure Boot)是UEFI扩展协议定义的安全标准,可以确保设备只使用OEM厂商信任的软件启动。UEFI签名认证就是对运行在 UEFI 系统下的 efi 驱动和通过 UEFI …...
案例14-课程推送页面逻辑整理--vue
目录一级目录二级目录三级目录一、背景介绍二、问题分析问题1:逻辑边界不清晰,封装意识缺乏问题问题2:展示效果上的问题三、解决过程问题一 代码结构混乱问题解决问题二 代码结构混乱问题解决问题三 展示效果上的细微问题四、总结一级目录 二…...
5大GPU厂商共建 | openKylin社区GPU SIG首次例会召开!
3月8日,openKylin社区GPU SIG首次例会以线上形式召开。此次会议由长沙景美集成电路设计有限公司、摩尔线程智能科技(北京)有限责任公司、格兰菲智能科技有限公司、象帝先计算技术(重庆)有限公司等GPU厂商的多位SIG Mai…...
SpringBoot读取配置文件
目录一、简介1、SpringBoot 中常用读取配置方法2、 ConfigurationProperties和Value的区别二、使用 ConfigurationProperties 读取配置三、使用 Value 读取配置一、简介 在日常开发使用 SpringBoot 框架时,经常有一些配置信息需要放置到配置文件中,我们…...
51驱动NRF24L01通信,NRF24L01与TTL转NRF24L01模块通信
51驱动NRF24L01通信,NRF24L01与TTL转NRF24L01模块通信NRF24L01一、简介二、引脚功能描述程序设计一、对 24L01 的程序编程的基本思路如下:二、Tx 与 Rx 的配置过程1、Tx 模式初始化过程:2、Rx 模式初始化过程:三、基本程序函数通信…...
C++友元
欢迎来观看温柔了岁月.c的博客 目前 设有C学习专栏 C语言项目专栏 数据结构与算法专栏 目前主要更新C学习专栏,C语言项目专栏不定时更新 待C专栏完毕,会陆续更新C项目专栏和数据结构与算法专栏 一周主要三更,星期三,星期五&#x…...
MySQL内置函数
文章目录日期函数字符串函数数学函数其他函数日期函数 获取年月日: mysql> select current_date(); ---------------- | current_date() | ---------------- | 2023-02-01 | ---------------- 1 row in set (0.00 sec)获得时分秒: mysql> se…...
mysql数据库之innodb存储引擎架构之内存架构
一、逻辑存储结构 mysql5.5版本开始,默认使用innodb存储引擎,它擅长事务处理,具有崩溃恢复特性,在日常开发中使用非常广泛。 架构图(左侧为内存架构,右侧为磁盘架构) 二、 内存架构。 1、缓冲…...
Vue:(三十五)路由vue-router
今天,我们开始学习vue中一个很关键的知识点,路由。理解vue的一个插件库,专门用来实现SPA应用单页web应用整个应用只有一个完整的页面点击页面中的导航连接不会刷新页面,只会做页面的局部更新数据需要通过ajax请求获取下来…...
Dynabook笔记本电脑无法开机怎么重装新系统?
Dynabook笔记本电脑无法开机怎么重装新系统?有用户使用Dynabook笔记本电脑出现了无法正常开机的情况。遇到这样的问题是我们的电脑系统出现了损坏,可以尝试进行系统修复。如果无法修复的话,就需要进行系统重装了。以下为大家带来Dynabook笔记…...
React Native基础知识点
1、组件 与react编写web应用不同,不是使用div、span等标签。而是使用RN官方提供的组件,如View、Text等组件来搭建页面 2、宽高 React Native 中的尺寸都是无单位的,表示的是与设备像素密度无关的逻辑像素点。默认值为auto <View style{{…...
nginx 平滑升级
背景介绍 因为一些原因,比如说 Nginx 发现漏洞、应用一些新的模块等等,想对 Nginx 的版本进行更新,最简单的做法就是停止当前的 Nginx 服务,然后开启新的 Nginx 服务。但是这样会导致在一段时间内,用户是无法访问服务…...
做怎样的网站能赚钱/济南seo排名搜索
现在大家用的智能手机是越来越强大,看到的手机界面也是越来越漂亮, 经常可以看到的是屏幕切换的时候有动画效果,或者是原有屏幕逐渐变小然后出现新的屏幕, 又或者是原有屏幕向左边飞出而新的屏幕从右边飞入.做BlackBerry开发的时候自然也希望在BlackBerry上实现这样的效果, 也不…...
国人在线做网站/营销软文范例大全100字
打开网址:https://www.google.com.hk/preferences勾选 “结果打开方式”...
网站建设公司的职责/关键词汇总
S3C2410与指纹传感器MBF200的SPI通信引 言随着网络技术和通信技术的发展,传统的身份认证技术对于信息安全表现得越来越有些力不从心了。由于人的身体特征具有唯一性和稳定性,人们开始把目光转向了生物识别技术,如指纹、虹膜、DNA、掌形识别等…...
找人做网站维护多少钱/潮州seo建站
Epson简单实例1.Epson软件方面编程2.网络配置方面3.vs编码方面软件配置:Epson机械手软件,vs2012网络配置:Tcp通信,IP地址及端口设置硬件配置:Pc机,机械手,机械手供电器一.环境准备①pc,机械手,供电器上电。…...
上海官方网站建/磁力多多
通过消息回退机制和mandatory参数,可以处理交换机投递失败的消息。 消息回退到生产者后,有时候并不知道该如何处理这些无法路由的消息,最多就是打个日志,存到缓存定时投递,超出投递失败次数进行报警,…...
贵州网站建设模板/网络营销的推广方法有哪些
我们都知道,空调有2个功能,一个是制冷,一个是供暖。但是当我们采用空调24小时或者12小时制冷或者供暖时,将耗费大量的电,导致企业和用户的经济成本急剧飙升。在这种情况下,一些企业及研发人员通过不断创新&…...