当前位置: 首页 > 知识库问答 >
问题:

为什么还要在Golang中使用*DB. exec()或准备好的语句?

都飞跃
2023-03-14

我正在使用golang和Postgresql。

这里说,对于不返回行(插入、删除、更新)的操作,我们应该使用exec()

如果函数名包括Query,则它被设计为询问数据库的问题,并将返回一组行,即使它是空的。不返回行的语句不应使用查询函数;它们应该使用Exec()。

然后它在这里说:

Go在封面下为您创建准备好的语句。一个简单的db。例如,查询(sql、参数1、参数2)的工作原理是准备sql,然后用参数执行它,最后关闭语句。

如果query()?


共有1个答案

周健
2023-03-14

确实可以使用db。执行db。Query可互换地执行相同的sql语句,但是这两种方法返回不同类型的结果。如果由驱动程序实现,则从db返回结果。exec可以告诉您查询影响了多少行,而是db。查询将返回行对象。

例如,假设您想要执行一个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)

有第三种方法可以结合postgres CTE、SELECT COUNTdb.QueryRowrow.Scan来实现这一点,但我认为没有必要用一个例子来说明与db.Exec相比,这种方法有多么不合理。

db.Query上使用db.Exec的另一个原因是,当您不关心返回的结果时,您只需要执行查询并检查是否有错误。在这种情况下,您可以执行以下操作:

if _, err := db.Exec(`<my_sql_query>`); err != nil {
    panic(err)
}

另一方面,你不能(你可以但不应该)这样做:

if _, err := db.Query(`<my_sql_query>`); err != nil {
    panic(err)
}

执行此操作后,过一会儿,您的程序将因一个类似于打开的连接太多的错误而死机。这是因为您放弃了返回的db.Rows值,而没有首先对其进行强制Close调用,因此最终打开的连接数会增加,并最终达到服务器的限制。

我认为你引用的那本书不对。至少在我看来,db.Query调用是否每次都创建一个新的准备语句取决于您使用的驱动程序。

例如,请参见queryDC(由db.Query调用的未报告方法)的这两部分:不带预处理语句和带预处理语句。

无论这本书是否正确,由db.Query创建的db.Stmt将在关闭返回的对象后被丢弃,除非有一些内部缓存正在进行。如果您改为手动调用db.Prepare,然后缓存并重用返回的db.Stmt,则可能会提高需要经常执行的查询的性能。

要了解如何使用准备好的声明来优化性能,您可以查看官方文档:https://www.postgresql.org/docs/current/static/sql-prepare.html

 类似资料:
  • 问题内容: 我在Gogre和Postgresql中使用。 它在这里说,对于不返回行(插入,删除,更新)的操作,我们应该使用 如果函数名称包含Query,则它被设计为询问数据库问题,并且即使它为空,也将返回一组行。不返回行的语句不应使用查询函数;他们应该使用Exec()。 然后它在这里说: Go在幕后为您创建准备好的语句。例如,一个简单的db.Query(sql,param1,param2)的工作方

  • 使用PHP和MySQLi,我有一个简单的表单,其中包含4个HTML 5下拉列表输入。现在想知道我是否仍然必须使用Prepared语句来保护我的数据库?我是否仍有SQL注入问题的风险?或者使用此类输入是否存在任何其他类型的风险。谢谢

  • 问题内容: 我正在重新设计一个使用最小数据库的PHP驱动的网站。原始版本使用“伪准备语句”(执行引号和参数替换的PHP函数)来防止注入攻击并将数据库逻辑与页面逻辑分开。 用一个使用PDO和真正的预备语句的对象替换这些临时功能似乎很自然,但是在对它们进行阅读之后,我不太确定。PDO似乎仍然是一个好主意,但是准备好的语句的主要卖点之一是能够重用它们……我永远不会。这是我的设置: 这些语句都很简单。大多

  • 问题内容: 在mysqli准备好的语句中,NULL变成’‘(对于字符串)或0(对于整数)。我想将其存储为真正的NULL。有什么办法吗? 问题答案: 我知道这是一个旧线程,但是可以将真实的NULL值绑定到准备好的语句(请阅读this)。 实际上,您可以使用mysqli_bind_parameter将NULL值传递给数据库。只需创建一个变量并将NULL值(请参见手册页)存储到该变量并将其绑定即可。无论

  • 问题内容: 对于此查询,有必要使用吗? 任何改进或查询是否还好? 在这种情况下,查询速度很重要。 问题答案: 否,准备好的查询(正确使用时)将确保对数据进行正确的转义以进行安全查询。您有点正确地使用它们,只需要更改一件事。因为您使用的是“?” 占位符,最好通过execute方法传递参数。 请注意,如果要将其输出到页面,数据库清理并不意味着可以在HTML中安全显示,因此也可以在其上运行htmlspe

  • 问题内容: 在下面的代码中,我展示了我认为在golang中嵌入(提升方法的地方)和组合(提升方法的地方)之间的区别。 为什么要在golang中使用组合? 问题答案: 值得阅读有关“嵌入到有效Go中”的部分。 一个常见的示例是具有Mutex的结构/映射。 打字容易得多 而不是必须编写适当的包装器函数(重复的)或遇到困难 当你将永远做互斥领域的唯一事情就是访问方法(和在这种情况下) 当您尝试在嵌入式字