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
}
相关推荐
小苏兮17 小时前
【C++】stack与queue的使用与模拟实现
开发语言·c++
2351618 小时前
【MySQL】MVCC:从核心原理到幻读解决方案
java·数据库·后端·sql·mysql·缓存
高山有多高18 小时前
栈:“后进先出” 的艺术,撑起程序世界的底层骨架
c语言·开发语言·数据结构·c++·算法
蔗理苦18 小时前
2025-10-07 Python不基础 19——私有对象
开发语言·python·私有对象
greentea_201319 小时前
Codeforces Round 65 C. Round Table Knights(71)
c语言·开发语言·算法
小秋学嵌入式-不读研版19 小时前
C61-结构体数组
c语言·开发语言·数据结构·笔记·算法
Evand J19 小时前
组合导航的MATLAB例程,二维平面上的CKF滤波,融合IMU和GNSS数据,仿真,观测为X和Y轴的坐标,附代码下载链接
开发语言·matlab·平面·imu·组合导航
蔗理苦20 小时前
2025-10-07 Python不基础 20——全局变量与自由变量
开发语言·python
IT 小阿姨(数据库)20 小时前
PostgreSQL通过pg_basebackup物理备份搭建流复制备库(Streaming Replication Standby)
运维·服务器·数据库·sql·postgresql·centos
-森屿安年-20 小时前
C++ 类与对象
开发语言·c++