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
}
相关推荐
MetaverseMan8 分钟前
Golang单例模式和工厂模式详解
开发语言·golang·适配器模式
danns8889 分钟前
neo4j数据库创建范例(SQL文)
数据库·sql·neo4j
杏花春雨江南22 分钟前
Spring Cloud Gateway 作为一个独立的服务进行部署吗
java·开发语言
GSDjisidi23 分钟前
东京本社招聘 | 财务负责人 & 多个日本IT岗位(Java/C++/Python/AWS 等),IT营业同步招募
java·开发语言·aws
skywalk816324 分钟前
copyparty 是一款使用单个 Python 文件实现的内网文件共享工具,具有跨平台、低资源占用等特点,适合需要本地化文件管理的场景
开发语言·python
BYSJMG29 分钟前
计算机毕设选题:基于Python+MySQL校园美食推荐系统【源码+文档+调试】
大数据·开发语言·python·mysql·django·课程设计·美食
Zz_waiting.33 分钟前
案例开发 - 日程管理 - 第七期
开发语言·前端·javascript·vue.js·html·路由
writeone34 分钟前
9-10关于JS初学产生的问题
开发语言·javascript·ecmascript
索迪迈科技2 小时前
Flink Task线程处理模型:Mailbox
java·大数据·开发语言·数据结构·算法·flink
太阳的后裔3 小时前
随笔一些用C#封装的控件
开发语言·c#