golang sql driver的准备声明

jtu*_*uki 17 mysql go

关于golang的sql驱动程序,下面两个语句有什么区别?

// store.DB is *sql.DB type
rows, err := store.DB.Query(SQL, args ...)
// err != nil
defer rows.Close()
Run Code Online (Sandbox Code Playgroud)

// store.DB is *sql.DB type
stmt, err := store.DB.Prepare(SQL)
// err != nil
defer stmt.Close()

rows, err := stmt.Query(args ...)
// err != nil
defer rows.Close()
Run Code Online (Sandbox Code Playgroud)

看来他们是一样的?有什么微妙的区别吗?

更新:

我们不需要执行很多stmt.Execstmt.Query之后db.Prepare,只需要执行一次execquery在每次之后执行prepare.当我们使用db.Queryor时db.Exec,我们将参数传递给方法而不是使用原始SQL字符串(出于安全考虑).

我找到了一个参考链接:http://go-database-sql.org/prepared.html
似乎两种方式都使用预处理语句,有什么区别?

Sno*_*man 27

差异可能是微妙的,有时是重要的,有时甚至是不存在的.

通常,准备好的语句1.准备好服务器(SQL解析,生成执行计划等),2.使用附加参数执行,然后3.关闭.它允许您重复使用每次传递的不同参数的相同SQL,它可以帮助防止SQL注入,可以提供一些性能增强(驱动程序/协议特定,YMMV)并防止重复步骤,如在执行计划生成和SQL解析中上面的准备步骤.

对于编写源代码的人来说,准备好的语句可能比连接字符串并将其发送到数据库服务器更方便.

DB.Query()方法将SQL作为字符串,以及零个或多个参数(如同Exec(),或QueryRow()).没有其他参数的SQL字符串将准确查询您编写的内容.但是,提供了带有占位符和附加参数的SQL字符串,正在为您完成准备好的语句.

DB.Prepare()方法显式执行一个预准备语句,然后将参数传递给,如:stmt.Exec(...args).

就两者之间的差异以及为何使用其中一个而言,有一些值得思考的事情.

您可以DB.Query()不使用参数.这可以非常有效,因为它可以绕过准备语句必须经过的prepare - > execute - > close序列.

您还可以将其与其他参数和占位符一起用于查询字符串中,并且如上所述,它将在封面下执行预准备语句.这里潜在的问题是,当你进行大量的查询时,每个查询都会产生一个底层准备好的语句.由于涉及额外的步骤,因此每次执行该查询时重新准备,执行和关闭都会相当低效.

使用明确的预准备语句,您可以避免这种低效率,因为您尝试重用您之前准备的SQL,并且可能使用不同的参数.

但是这并不总是如你所料......由于db/sql管理的底层连接池,你的"数据库连接"是非常虚拟的.该DB.Prepare()方法将针对特定连接准备语句,然后在执行时尝试获取相同的连接,但如果该连接不可用,它将只获取一个可用的并重新准备并执行该连接.如果你一遍又一遍地使用同样的预备陈述,那么你可能会在不知不觉中一遍又一遍地准备它.当你处理繁忙的交通时,这显然会被曝光.

很明显,您在什么情况下使用取决于您的具体用例,但我希望上面的详细信息可以帮助您明确说明您可以在每种情况下做出最佳决策.

更新

鉴于OP中的更新,当查询仅需要执行一次时基本上没有区别,因为带有参数的查询在幕后完成为准备好的语句.

使用直接方法(例如DB.Query()及其类似物)与明确使用预准备语句,因为它将导致更简单的源代码.

由于出于安全原因正在使用预准备语句,因此可能值得通过其他方式处理安全问题并使用明文查询,因为它将提高性能.但是,任何收益都可能无关紧要,除非有足够的流量(或预计未来的流量会大幅增长),从而需要减轻服务器上的负担.再次归结为现实世界的用例.

有兴趣的人在准备好的发言和直接明文查询之间的差额部分指标,有一个很好的文章在这里(这也很好地解释很多上述的一个出色的工作).