Golang SQL包中的QueryRow和Exec有什么区别?

5
在 Golang 的 SQL 包中,有 QueryRow 和 Exec 两种执行查询语句的方法。如果我正在事务中执行插入查询语句,从性能角度来看,哪种方法更好?
``` err = tx.QueryRow(query, params).Scan(&id) ```
vs
``` result, err = tx.Exec(query, params) ```
2个回答

12

通常读取一行数据使用 QueryRow()

err := tx.QueryRow(`Select col from t where col=$1`, "val").Scan(&colholder)

如果需要通过 UPDATEDELETEINSERT 等方式操作数据,请使用 Exec

result, err := tx.Exec(`Delete from t where col=$1`, "val")

正如您所看到的,在Exec中没有任何要扫描的内容,因为那是执行而不是查询。
然而,没有人阻止您对Exec操作使用QueryRow,反之亦然,但这并不是预期的目的。您可能会失去每种操作类型的底层优化。 另外,如果您在Exec中使用QueryRow,您将获得sql.ErrNoRows错误,因为在UPDATEINSERTDELETE中没有行可返回。
同样地,如果您在Exec操作中使用查询操作,您将无法从Exec中获取值,因为它返回响应,不可.Scan
然而,有些情况下需要使用QueryRow来执行Exec操作。
err := tx.QueryRow(`Delete from t where col=$1 returning id`, "val").Scan(&deletedID)

如果您想从SQL操作中返回值,请使用QueryRow,否则请使用Exec

在您的情况下,如果您想要插入操作后返回一些数据(例如id),请使用QueryRow,否则Exec就可以胜任了。


3

如果你插入一行数据,请使用QueryRow - 它专门用于最多一个行更新。

如果你正在执行具有多个结果的多行命令更新/查询,请使用Exec。来自Exec的行结果在行迭代完成后需要关闭。

因此,为了使用方便,如果你知道只操作一行,请使用QueryRow


1
Exec 返回 sql.Result 而不是 *sql.Rows,因此无法通过 sql.Result 进行迭代。tx.Query 将返回 *sql.Rows 以进行关闭和迭代。 - topenion
queryRow 如何处理 tx.RollBack() 和 tx.Commit()? - srx lnx

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接