Golang中GROM多表关联跟原生SQL多表关联区别

文章目录


前言

  • 对比GROM多表关联和原生Sql多表关联

一、GROM多表关联

  1. 适用于返回全部数据
  2. 需要逻辑外键(不会在数据库创建任何约束)
  3. 适合三个表以下的关联
  4. 有几张表就会查询几次
go 复制代码
type Product struct {
	gorm.Model           // 包含ID, CreatedAt, UpdatedAt, DeletedAt
	CateID       uint    `gorm:"not null;index:idx_cate_id" json:"cate_id"`          // 普通索引
	TagID        string  `gorm:"size:255;not null;index:idx_tag_id" json:"tag_id"`   // 多标签字符串存储,如"1,2,3"
	Name         string  `gorm:"size:255;not null;uniqueIndex:idx_name" json:"name"` // 唯一索引
	Sku          string  `gorm:"size:50;not null;uniqueIndex:idx_sku" json:"sku"`    // 唯一索引
	Price        float64 `gorm:"type:decimal(10,2);not null;default:0.00" json:"price"`
	Stock        int     `gorm:"not null;default:0" json:"stock"`
	StockWarning int     `gorm:"not null;default:0" json:"stock_warning"`
	CostPrice    float64 `gorm:"type:decimal(10,2);not null;default:0.00;" json:"cost_price"`
	Status       int8    `gorm:"type:tinyint;not null;default:1;index:idx_status" json:"status"` // 普通索引
	Description  *string `gorm:"type:text" json:"description"`
	ImageUrl     *string `gorm:"size:255" json:"image_url"`
	Unit         string  `gorm:"size:255;not null" json:"unit"`

	// 🔗 关联关系:多对一 (多个商品属于一个分类)
	// 🔗 关联关系:多对一 (多个商品属于一个分类)
	// 逻辑外键 不会同步到数据库中,仅在此模型或项目内使用
	Category OrderCate `gorm:"foreignKey:CateID" json:"category"`
}


//GROM示例
// 查询商品及其分类信息(GORM联查)
func GetProduvtWithCategroy(id uint) (*Product , error){
	var product Product
	// 步骤1. First(&product) 先根据id查询商品表,获取到producr.CateID
	// 步骤2. Preload("Category"),再根据获取到的分类id查询分类表,获取到分类信息后返回到Category字段
	// 合并结果,将分类信息填充到 product.Category字段
	result := DB.Preload("Category").Where("id = ?" , id).First(&product)
	return &product, result.Error
}

二、原生Sql多表关联

  1. 适用于三个表以上关联
  2. 只查询一次
  3. 适用于返回精准字段
go 复制代码
// 商品列表结果结构体(用于API返回)
type ProductListResult struct {
	ID           uint    `json:"id"`
	Name         string  `json:"name"`
	Price        float64 `json:"price"`
	Stock        int     `json:"stock"`
	Status       int8    `json:"status"`
	CateID       uint    `json:"cate_id"`
	CategoryName string  `json:"category_name"`
	ImageUrl     *string `json:"image_url"`
}


// 一方面减少查询次数,一方面精准控制返回字段

// 步骤1. FROM products p; 查询商品表 p为表代号
// 步骤2.  LEFT JOIN products_cate c ON p.cate_id  = c.id;左连接分类表(根据cate_id关联分类表主键id,左连接保证即使分类表中没有对应记录,商品信息也能显示)
// 步骤3. WHERE p.deleted_at IS NULL 过滤已删除的商品
// 步骤4. ORDER BY p.created_at DESC 按创建时间倒序排序
// 步骤5. SELECT  查询指定字段, COALESCE:判断字段是否为空,如果为空则返回默认值
// 步骤6. LIMIT 10 OFFSET 0 分页查询,每页10条,从第0条开始
// 步骤7. Raw() 执行SQL语句,Scan() 将查询结果映射到results切片中



// 左连接: 左连接会保留左表的所有数据,即使右表中没有匹配的数据,也会保留左表的数据。
// 右连接: 右连接会保留右表所有的数据,即使左表中没有匹配的数据,也会保留右表数据。
// 内连接: 内连接只返回两个表中匹配的数据,如果一个表中没有匹配的数据,则不会返回结果。

func GetProductListWithCategory() ([]ProductListResult, error) {
	var results []ProductListResult
	sql := `
		SELECT
			p.id,
			p.name,
			p.price,
			p.stock,
			p.status,
			p.cate_id,
			COALESCE(c.name, '未分类') as category_name,
			p.image_url
		FROM products p
        LEFT JOIN products_cate c ON p.cate_id = c.id
		WHERE p.deleted_at IS NULL
		ORDER BY p.created_at DESC
	`
	err := DB.Raw(sql).Scan(&results).Error
	return results, err
}
相关推荐
GISer_Jing4 小时前
JavaScript 中Object、Array 和 String的常用方法
开发语言·javascript·ecmascript
耳总是一颗苹果6 小时前
C语言---动态内存管理
c语言·开发语言
手眼通天王水水6 小时前
【Linux】3. Shell语言
linux·运维·服务器·开发语言
小蜗牛狂飙记6 小时前
在github上传python项目,然后在另外一台电脑下载下来后如何保障成功运行
开发语言·python·github
小苏兮6 小时前
【C语言】字符串与字符函数详解(上)
c语言·开发语言·算法
程序员JerrySUN7 小时前
Valgrind Memcheck 全解析教程:6个程序说明基础内存错误
android·java·linux·运维·开发语言·学习
apocelipes7 小时前
使用uint64_t批量比较短字符串
c语言·数据结构·c++·算法·性能优化·golang
不愧是你呀7 小时前
Muduo库中单例模式详解
开发语言·c++·单例模式
柠檬味的薄荷心8 小时前
【C#补全计划:类和对象(一)】
开发语言·c#
骁的小小站8 小时前
The Missing Semester of Your CS Education 学习笔记以及一些拓展知识(三)
开发语言·经验分享·笔记·学习·其他·bash·excel