GORM学习记录:Raw()和 Exec()的妙用
2022-12-05 13:14:09
GORM 中的 Raw() 和 Exec() 方法:何时以及如何使用它们
简介
在 GORM,一个流行的 Go 语言 ORM 库中,有两种方法可以操作原生 SQL 语句:Raw() 和 Exec()。这两种方法提供了不同的功能,了解它们的差异对于有效使用 GORM 至关重要。
Raw() 方法
Raw() 方法允许您执行带有参数的原生 SQL 语句。它的语法如下:
func (db *DB) Raw(sql string, values ...interface{}) *Stmt
其中:
sql
是要执行的原生 SQL 语句values
是 SQL 语句中的参数
Raw() 方法返回一个 *Stmt
类型的对象,您可以使用它来执行 SQL 语句并获取结果。例如:
db.Raw("SELECT * FROM users WHERE name = ?", "John").Scan(&users)
这段代码将执行 SELECT * FROM users WHERE name = "John"
SQL 语句,并将结果存储在 users
变量中。
Exec() 方法
Exec() 方法允许您执行不带参数的原生 SQL 语句。它的语法如下:
func (db *DB) Exec(sql string) (sql.Result, error)
其中:
sql
是要执行的原生 SQL 语句
Exec() 方法返回一个 sql.Result
类型的对象,您可以使用它来获取受影响的行数和最后插入的行的 ID。例如:
result, err := db.Exec("DELETE FROM users WHERE name = ?", "John")
if err != nil {
// Handle error
}
rowsAffected := result.RowsAffected
lastInsertedID := result.LastInsertId
Raw() 和 Exec() 的区别
Raw() 和 Exec() 的主要区别在于:
- Raw() 方法允许您执行带有参数的原生 SQL 语句,而 Exec() 方法只允许您执行不带参数的原生 SQL 语句。
- Raw() 方法返回一个
*Stmt
类型的对象,您可以使用它来执行 SQL 语句并获取结果,而 Exec() 方法返回一个sql.Result
类型的对象,您可以使用它来获取受影响的行数和最后插入的行的 ID。
何时使用 Raw() 和 Exec()
根据您的需要,选择使用 Raw() 或 Exec() 方法:
使用 Raw() 方法的场景:
- 您需要执行一个复杂的 SQL 语句,这个 SQL 语句不能使用 GORM 的内置方法实现。
- 您需要执行一个带有参数的 SQL 语句。
使用 Exec() 方法的场景:
- 您需要执行一个不带参数的 SQL 语句。
- 您需要获取受影响的行数或最后插入的行的 ID。
示例
// 使用 Raw() 方法执行带有参数的 SQL 语句
users := []User{}
db.Raw("SELECT * FROM users WHERE name = ?", "John").Scan(&users)
// 使用 Exec() 方法执行不带参数的 SQL 语句
result, err := db.Exec("DELETE FROM users WHERE name = ?", "John")
if err != nil {
// Handle error
}
rowsAffected := result.RowsAffected
lastInsertedID := result.LastInsertId
结论
Raw() 和 Exec() 方法提供了操作原生 SQL 语句的两种不同方式。通过理解它们的差异,您可以选择适合您需求的方法并充分利用 GORM 的功能。
常见问题解答
- 我应该什么时候使用 Raw() 方法而不是 GORM 的内置方法?
答:如果您需要执行一个复杂的 SQL 语句,这个 SQL 语句不能使用 GORM 的内置方法实现,那么您应该使用 Raw() 方法。
- Exec() 方法是否支持事务?
答:不,Exec() 方法不支持事务。如果您需要在事务中执行原生 SQL 语句,您应该使用 Raw() 方法并手动管理事务。
- 我可以使用 Raw() 方法更新或删除记录吗?
答:是的,您可以使用 Raw() 方法更新或删除记录。但是,您需要小心地编写您的 SQL 语句以防止 SQL 注入攻击。
- Raw() 方法是否比 GORM 的内置方法慢?
答:是的,Raw() 方法通常比 GORM 的内置方法慢,因为 GORM 的内置方法已经过优化以使用 GORM 的缓存和查询构建器。
- 我可以在 Raw() 方法中使用占位符吗?
答:是的,您可以在 Raw() 方法中使用占位符,但您需要使用 ?
而不是 GORM 内置方法中的 $n
。