【问题标题】:When returning data on an insert or update, do I still need to use `Exec`?在插入或更新时返回数据时,我还需要使用 Exec 吗?
【发布时间】:2019-08-04 00:17:39
【问题描述】:

根据Go Database SQL,它说使用Exec 来修改数据,而Query 不好,因为底层连接一直保持打开状态,直到调用Rows.Close()。但是,我可以想到两种情况,询问正确的模式是什么。

1) 使用sql.Tx 进行多次更新,这将保持连接直到Tx.RollbackTx.Commit。在这种情况下会重要吗?

2) 在更新、插入或删除时返回数据(尤其是在使用非基于整数的行 ID,如 UUID 时)。在这种情况下,QueryRow 似乎是合适的,特别是因为它返回的Row 没有Close,只有Scan。但是,可以打开 Tx 进行写入,然后立即读取,但这通常是很多额外的工作。

这两种情况我是否遗漏了什么?

我正在使用 Postgres,但从我所阅读的有关 Go 的 DB 集成的内容来看,在大多数情况下,数据库实现应该无关紧要。

【问题讨论】:

  • 我读过这个问题,但它并没有真正回答我的问题或解决我的问题:stackoverflow.com/questions/50664648/…
  • 不是一个 Go 程序员,但看起来文档只是说查询返回一个对象,您需要使用(关闭)做某事并且永远不要忽略......没有具体说明为什么要在查询实际上很糟糕。

标签: sql go


【解决方案1】:

TLDR:将db.Querydb.QueryRowINSERTUPDATEDELETE 一起使用没有任何问题。如果您的 SQL 命令包含 RETURNING 子句,它实际上是适合这项工作的工具。


2) 在某种程度上已经在链接的教程中通过实际排除您提出的场景来回答,因为它正在明确地表达 em> 关于您不关心返回的行并因此选择将返回的值分配给空白标识符的情况。

如果你不关心结果怎么办?如果你只想关心怎么办? 执行一条语句并检查是否有任何错误,但忽略 结果?下面两个语句不是做同样的事情吗?

_, err := db.Exec("DELETE FROM users")  // OK
_, err := db.Query("DELETE FROM users") // BAD

答案是否定的。他们做同样的事情,你不应该 像这样使用Query()Query() 将返回一个 sql.Rows,它 保留数据库连接,直到 sql.Rows 关闭。

语句“...你不应该像这样使用 Query() ...” 并不是指 db.QueryDELETEUPDATE 或 @987654337 一起使用@,相反,它声明并且正确地表明,您永远不应该调用 Query 并将其结果分配给 _,即,无论 sql 命令是什么,您都不应该执行 _, err := db.Query("...

请注意,这同样适用于QueryRow,即您永远不应丢弃返回的sql.Row 值或以任何其他方式省略调用其Scan 方法。这是因为sql.Row 只是sql.Rows 的简单包装器,其Scan 方法在返回之前关闭底层sql.Rows (link)。

1) 据我了解,即使对于交易,以上所有内容仍然适用。如果您有一个由sql.Tx 创建的sql.Rows 实例,并且该sql.Rows 实例尚未关闭,则sql.Tx 本身将被阻止关闭(link)。也就是说,确保在使用 tx.Query 时关闭返回的行,并在使用 tx.QueryRow 时调用返回行的 Scan 方法。

【讨论】:

  • "... 在某种程度上,已经在链接教程中通过实际排除您提出的方案来回答...",它可以这样解释,但关于开发,我不'不要经常依靠缺乏信息作为默认接受。 :咧嘴:
  • 忽略返回的Rows 变量的示例代码很好地突出显示。我没有注意到这一点。对正在开放的交易也有很好的评论。我也没有意识到这一点,很高兴我也提到了这个案例。
猜你喜欢
  • 1970-01-01
  • 2017-08-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多