这些差异可能很微妙,有时很重要,有时实际上根本不存在。
一般来说,准备好的语句 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() 及其类似物,而不是显式使用准备好的语句,因为它会使源代码更加简单。
由于在这种情况下,出于安全原因使用准备好的语句,因此通过其他方式处理安全问题并改用纯文本查询可能是值得的,因为它会提高性能。但是,除非有足够的流量(或预计流量在未来会大幅增长)以减轻服务器上的负载,否则任何收益都可能无关紧要。再次归结为现实世界的用例。
对于任何对准备好的语句和直接纯文本查询之间的区别的一些指标感兴趣的人,有一篇很好的文章 here(它也很好地解释了上述大部分内容)。