这是真的,你可以用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 int
for rows.Next() {
numDeleted += 1
}
if err := rows.Err(); err != nil {
panic(err)
}
print(numDeleted)
有一个第3的方式,你可以用Postgres的热膨胀系数的组合做到这一点SELECT COUNT
,db.QueryRow
而row.Scan
但我不认为一个例子是要说明如何不合理的做法相比时,这将是db.Exec
。
使用db.Exec
over的另一个原因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 connections open
。这是因为您要丢弃返回的db.Rows
值而没有先对其进行强制Close
调用,因此最终导致打开的连接数增加,最终达到服务器的限制。
我认为您引用的书不正确。至少在我看来,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
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句