返回

GORM学习记录:Raw()和 Exec()的妙用

后端

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 的功能。

常见问题解答

  1. 我应该什么时候使用 Raw() 方法而不是 GORM 的内置方法?

答:如果您需要执行一个复杂的 SQL 语句,这个 SQL 语句不能使用 GORM 的内置方法实现,那么您应该使用 Raw() 方法。

  1. Exec() 方法是否支持事务?

答:不,Exec() 方法不支持事务。如果您需要在事务中执行原生 SQL 语句,您应该使用 Raw() 方法并手动管理事务。

  1. 我可以使用 Raw() 方法更新或删除记录吗?

答:是的,您可以使用 Raw() 方法更新或删除记录。但是,您需要小心地编写您的 SQL 语句以防止 SQL 注入攻击。

  1. Raw() 方法是否比 GORM 的内置方法慢?

答:是的,Raw() 方法通常比 GORM 的内置方法慢,因为 GORM 的内置方法已经过优化以使用 GORM 的缓存和查询构建器。

  1. 我可以在 Raw() 方法中使用占位符吗?

答:是的,您可以在 Raw() 方法中使用占位符,但您需要使用 ? 而不是 GORM 内置方法中的 $n