当前位置: 首页 > 面试题库 >

为什么甚至在Golang中使用* DB.exec()或预备语句?

许博易
2023-03-14
问题内容

我在Gogre和Postgresql中使用。

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

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

然后它在这里说:

Go在幕后为您创建准备好的语句。例如,一个简单的db.Query(sql,param1,param2)的工作方式是:准备sql,然后使用参数执行该sql,最后关闭该语句。

如果 query() 在准备好的表述下使用,我为什么还要打扰使用准备好的表述呢?


问题答案:

“为什么还要使用db.Exec()”:

这是真的,你可以用db.Execdb.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 COUNTdb.QueryRowrow.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 connections open。这是因为要丢弃返回的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



 类似资料:
  • 我正在使用golang和Postgresql。 这里说,对于不返回行(插入、删除、更新)的操作,我们应该使用 如果函数名包括Query,则它被设计为询问数据库的问题,并将返回一组行,即使它是空的。不返回行的语句不应使用查询函数;它们应该使用Exec()。 然后它在这里说: Go在封面下为您创建准备好的语句。一个简单的db。例如,查询(sql、参数1、参数2)的工作原理是准备sql,然后用参数执行它

  • 为什么JPA OneToOne(甚至OneToMany)的默认为。 我的意思是,强制对已从关系中移除的实体执行移除操作,并在默认情况下将移除操作级联到这些实体,难道不是更好吗? 如果只使用默认值,当前默认为false的行为不会导致孤儿条目(可能会成为僵尸记录),从而导致数据库表随着时间的推移而膨胀吗?还是我错过了这里的东西? 谢谢 当从关系中移除一对一或一对多关系中的目标实体时,通常希望将移除操作

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

  • 问题内容: 我在程序中尝试了准备好的语句,但是没有用。 注释的部分是“准备报表”部分。当我将其更改为常规语句时,一切都正确。 有人可以告诉我我想念什么吗? 非常感谢。 问题答案: 尝试从查询中删除并在添加参数后使用:

  • 问题内容: 嗨,我需要在我的网站中使用“准备好的声明”。我尝试使用这个 但这不起作用。当我改变并以它的工作。 问题答案: CodeIgniter不支持预备语句。如果查看CI的Database类的源代码,您将看到它们仅通过用传递的数组中的数据替换问号来解析绑定: https://github.com/EllisLab/CodeIgniter/blob/develop/system/database/

  • 我现在能够在运行在Websphere服务器上的Java EE项目中自动进行增量编译。 我整理jRebel是因为我在突然启动服务器时遇到了问题,并且注意到现在Intellij正在自动编译,我也能够“几乎”有效地看到更改(比Eclipse慢) 那么,intellij中甚至需要jRebel吗?我对Websphere的设置可以在下图中看到。注意,我只添加了一个Ear文件,它不是分解版本,仍然这是工作。jr