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)
注意事项
- Raw 查询使用
?占位符时,参数按位置顺序传入。- 不同数据库的占位符可能不同(PostgreSQL 使用
$1, $2)。- Scan 接收结果时,字段名需与 SQL 返回列名匹配(支持
as别名)。- Exec 方法返回
RowsAffected可用于验证写操作是否生效。- 原生 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
📝 发现内容有误?点击此处直接编辑