“为什么还要使用db.Exec()”:
这是真的,你可以用
db.Exec和
db.Query互换执行相同的SQL语句,但是这两种方法返回不同类型的结果。如果由驱动程序实现,则返回的结果
db.Exec可以告诉您查询影响了多少行,而
db.Query将返回行对象。
例如,假设您要执行一条
DELETe语句,并且想知道该语句删除了多少行。您可以通过以下适当方式进行操作:
res, err := db.Exec(`DELETE FROM my_table WHERe expires_at = $1`, time.Now())if err != nil { panic(err)}numDeleted, err := res.RowsAffected()if err != nil { panic(err)}print(numDeleted)或者更冗长和客观上更昂贵的方式:
rows, err := db.Query(`DELETE FROM my_table WHERe expires_at = $1 RETURNING *`, time.Now())if err != nil { panic(err)}defer rows.Close()var numDelete intfor rows.Next() { numDeleted += 1}if err := rows.Err(); err != nil { panic(err)}print(numDeleted)有一个第3的方式,你可以用Postgres的热膨胀系数的组合做到这一点
SELECTCOUNT,
db.QueryRow而
row.Scan但我不认为一个例子是要说明如何不合理的做法相比时,这将是
db.Exec。
使用
db.Execover的另一个原因
db.Query是,当您不关心返回的结果时,只需要执行查询并检查是否有错误即可。在这种情况下,您可以执行以下操作:
if _, err := db.Exec(`<my_sql_query>`); err != nil { panic(err)}另一方面,您不能(可以但不能)这样做:
if _, err := db.Query(`<my_sql_query>`); err != nil { panic(err)}这样做后不久,您的程序将因出现类似于的错误而惊慌失措
too many connectionsopen。这是因为要丢弃返回的
db.Rows值而没有先对其进行强制
Close调用,因此最终导致打开的连接数增加,最终达到服务器的限制。
“或用Golang准备的语句?”:
我认为您引用的书不正确。至少在我看来,
db.Query每次调用是否创建一个新的准备好的语句都取决于您使用的驱动程序。
例如,请参见
queryDC(未调用by的方法的
db.Query)这两个部分:不带准备语句和带准备语句。
不管书是否正确,除非关闭返回的对象,否则除非进行一些内部缓存,否则
db.Stmt创建者都是正确的。如果改为手动调用,然后缓存并重用返回的内容,则可能会提高需要经常执行的查询的性能。
db.Query``Rows``db.Prepare``db.Stmt
要了解如何使用准备好的语句来优化性能,可以看一下官方文档:https : //www.postgresql.org/docs/current/static/sql-
prepare.html



