sql - Golang、数据库/sql、Postgres - 在您需要结果时使用 QueryRow 和 INSERT 不良做法?

标签 sql postgresql go

Go 数据库/sql Postgres 适配器不支持 LastInsertIdFrom the docs :

pq does not support the LastInsertId() method of the Result type in database/sql. To return the identifier of an INSERT (or UPDATE or DELETE), use the Postgres RETURNING clause with a standard Query or QueryRow call.

但是 Go database/sql docs建议不要使用 Query 修改数据库,因为它:

reserves a database connection until the sql.Rows is closed. Since there might be unread data (e.g. more data rows), the connection can not be used. In the example above, the connection will never be released again.

文档还说“你永远不应该像这样使用 Query()。”

如果您需要结果行,大多数人建议使用 QueryRow 对 Postgres 执行 INSERT。我不完全理解文档给出的技术推理,但它似乎与我读过的内容冲突。使用 QueryRow 执行 INSERT 是否安全且被视为良好做法?

最佳答案

该指南,顺便说一下,它不是database/sql 文档,它没有错,但是您错过了引用段落上方片段中的重要部分,请注意//BAD评论:

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

特别注意_。这在 Go 中称为“空白标识符”,它允许您丢弃不关心的值。

当调用 Query 时,你会得到一个 *sql.Rows 实例作为第一个返回值,这个值需要在你完成后关闭,如果你丢弃它你不能关闭它,如果你不关闭它你会泄漏连接。 *sql.Rows 通过调用 Close 方法关闭。

当调用 QueryRow 时,你会得到一个 *sql.Row 值,这个值需要在你用完之后关闭,如果你丢弃它,你可以'关闭它,如果你不关闭它,你会泄漏连接。 *sql.Row 通过调用 Scan 方法关闭。


"Is it safe and considered good practice to use QueryRow to do an INSERT?"

是的,是的,只要你正确处理返回值。

做这样的事情绝对没问题:

var id int
row := db.QueryRow("insert ... returning id", params...)
if err := row.Scan(&id); err != nil { // scan will release the connection
    return err
}
fmt.Println(id)

或者:

rows, err := db.Query("insert ... values (...), (...) returning id", params...)
if err != nil {
    return err
}
defer rows.Close() // make sure that the connection is released once the function returns/panics

var ids []int
for rows.Next() {
    var id int
    if err := rows.Scan(&id); err != nil {
        return err
    }
    ids = append(ids, id)
}
if err := rows.Err(); err != nil {
    return err
}
fmt.Println(ids)

关于sql - Golang、数据库/sql、Postgres - 在您需要结果时使用 QueryRow 和 INSERT 不良做法?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61858042/

相关文章:

sql - 将其他表中的数据插入到仅包含主键的表中

sql - Postgres 截断 CASE 语句列

sql - PostgreSQL:查找以最大订单销售的每种产品的总行总数?

if-statement - 如何在HTML属性中插入if语句?

go - 如何为所有用户安装 golang 二进制文件

SQL 左外连接不提供完整表

java - Hibernate native 查询显示异常

sql - 存储库 - 在 native 查询中排序不起作用

multithreading - 为什么我的 goroutines 在完成时互相等待而不是完成?

sql - 如何深度复制一组数据,并将 FK 引用更改为指向所有副本?