代码之家  ›  专栏  ›  技术社区  ›  CommonSenseCode

为什么还要在golang中使用*db.exec()或prepared语句?

  •  5
  • CommonSenseCode  · 技术社区  · 7 年前

    我在用高朗和PostgreSQL。

    上面写着 here 对于不返回行的操作(插入、删除、更新),我们应该使用 exec()

    如果一个函数名包含查询,它被设计成询问数据库的问题,并返回一组行,即使它是空的。不返回行的语句不应使用查询函数;它们应使用exec()。

    然后它说 here :

    Go在封面下为您创建准备好的报表。例如,一个简单的db.query(sql,param1,param2)通过准备sql,然后用参数执行它,最后关闭语句来工作。

    如果 query() 在封面下使用准备好的声明 为什么我还要费心使用准备好的陈述呢?

    1 回复  |  直到 7 年前
        1
  •  17
  •   mkopriva    7 年前

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

    你真的可以用 db.Exec db.Query 可交换地执行相同的sql语句,但是这两个方法返回不同类型的结果。如果由驱动程序实现,则从 数据库执行器 可以告诉您查询影响了多少行,而 数据库查询 将返回rows对象。

    例如,假设要执行 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 COUNT , db.QueryRow row.Scan 但我不认为有必要用一个例子来说明与 数据库执行器 .

    使用的另一个原因 数据库执行器 结束 数据库查询 当您不关心返回的结果时,当您只需要执行查询并检查是否有错误时。在这种情况下,您可以这样做:

    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 调用它,那么最终打开的连接数会增加,并最终达到服务器的限制。


    “或是准备在高朗发表声明?”:

    我认为你引用的那本书不对。至少在我看来 数据库查询 每次调用都会根据您使用的驱动程序创建一个新的准备好的语句。

    例如,请参见 queryDC (由 数据库查询 ): without prepared statement with prepared statement .

    不管这本书是否正确 db.Stmt 创建人 数据库查询 如果没有内部缓存,在关闭返回的 Rows 反对。如果您改为手动调用 db.Prepare 然后缓存并重用返回的 预算 您可以潜在地提高需要经常执行的查询的性能。

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