全部学科
NodeJS全栈
nodejs
Python全栈
python
小程序首页
📅 2026-05-21 8 分钟 ✍️ juanwangdev

GORM 原生 SQL 执行

本文介绍 GORM 中执行原生 SQL 的核心方法。

Raw 方法执行查询

基本用法

Go
// 简单查询
db.Raw("SELECT id, name, email FROM users WHERE status = ?", "active").Find(&users)

// 带参数查询
db.Raw("SELECT * FROM orders WHERE user_id = ? AND amount > ?", userID, 100).Find(&orders)

// 多参数查询
db.Raw("SELECT * FROM users WHERE created_at BETWEEN ? AND ?", startDate, endDate).Find(&users)

语法格式:

Go
db.Raw("SQL 语句", 参数1, 参数2...).Find(&结果)

Scan 接收结果

Go
// 扫描到结构体
db.Raw("SELECT id, name FROM users").Scan(&users)

// 扫描到自定义结构体
type UserSummary struct {
    ID    uint
    Name  string
    Email string
}
db.Raw("SELECT id, name, email FROM users").Scan(&summaries)

// 扫描到单个值
var count int64
db.Raw("SELECT COUNT(*) FROM users").Scan(&count)

// 扫描到多个变量
var name string
var age int
db.Raw("SELECT name, age FROM users WHERE id = ?", 1).Row().Scan(&name, &age)

命名参数

Go
// 使用 @ 命名参数
db.Raw(
    "SELECT * FROM users WHERE name = @name AND age = @age",
    sql.Named("name", "张三"),
    sql.Named("age", 25),
).Find(&users)

// 使用 map 参数
db.Raw(
    "SELECT * FROM users WHERE name = @name AND age >= @age",
    map[string]interface{}{"name": "张三", "age": 18},
).Find(&users)

Exec 方法执行写操作

Go
// INSERT
db.Exec("INSERT INTO users (name, email) VALUES (?, ?)", "张三", "zhang@example.com")

// UPDATE
db.Exec("UPDATE users SET status = ? WHERE id = ?", "active", 1)

// DELETE
db.Exec("DELETE FROM orders WHERE status = ? AND created_at < ?", "cancelled", date)

// 获取影响行数
result := db.Exec("UPDATE products SET stock = stock - 1 WHERE id = ?", 1)
result.RowsAffected // 影响行数
result.Error        // 执行错误

复杂查询场景

多表连接查询

Go
db.Raw(`
    SELECT u.name, o.id as order_id, o.amount
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    WHERE o.status = ?
    ORDER BY o.created_at DESC
`, "paid").Scan(&results)

窗口函数

Go
db.Raw(`
    SELECT user_id, amount,
           ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY created_at DESC) as rn
    FROM orders
`).Scan(&results)

CASE WHEN 语句

Go
db.Raw(`
    SELECT id, name,
           CASE status
               WHEN 1 THEN 'active'
               WHEN 2 THEN 'inactive'
               ELSE 'unknown'
           END as status_name
    FROM users
`).Scan(&users)

注意事项

  1. Raw 查询使用 ? 占位符时,参数按位置顺序传入。
  2. 不同数据库的占位符可能不同(PostgreSQL 使用 $1, $2)。
  3. Scan 接收结果时,字段名需与 SQL 返回列名匹配(支持 as 别名)。
  4. Exec 方法返回 RowsAffected 可用于验证写操作是否生效。
  5. 原生 SQL 绕过 GORM 钩子和软删除机制,需手动处理。

要点总结

  • Raw 方法用于执行只读原生 SQL,配合 Find 或 Scan 接收结果。
  • Scan 支持扫描到结构体、单个变量或多个变量。
  • Exec 方法用于执行写操作(INSERT/UPDATE/DELETE),返回影响行数和错误。
  • 命名参数使用 @name 格式,配合 sql.Named 或 map 传入。
  • 原生 SQL 适用于多表连接、窗口函数、数据库特定语法等复杂场景。
  • 原生 SQL 不触发 GORM 钩子和自动软删除,需谨慎使用。

存放路径:D:\git2\jwdev\articles\GORM\进阶\高级查询技术\原生 SQL 执行.md

📝 发现内容有误?点击此处直接编辑

← 上一篇 GORM 分页查询实现
下一篇 → GORM 子查询实现
想查看更多题目和详细解析?
小程序提供完整的题库、模拟考试和详细解析
马上就来

长按或扫描二维码,立即体验

扫码体验小程序
马上就来
使用微信扫描二维码
立即体验完整题库