PDO->query() 和 PDO->exec() 的区别

Posted

技术标签:

【中文标题】PDO->query() 和 PDO->exec() 的区别【英文标题】:Difference between PDO->query() and PDO->exec() 【发布时间】:2013-04-29 04:22:49 【问题描述】:

让对 PDO 的引用等于一个 PDO 对象,而不是 PDO 本身--

我看到here 有PDO->query()PDO->exec()。在链接的页面中,似乎PDO->query(); 仅用于SELECT 语句,PDO->exec() 用于UPDATE,INSERT,DELETE 语句。现在,我是 PDO 的新手,所以我不确定在使用它方面会发生什么相当,所以我希望能解释一下为什么要使用不同的方法,以及为什么有不同的方法。

【问题讨论】:

【参考方案1】:

尽管理论上存在任何差异,但无论如何都不应使用这些函数 - 因此,没有什么可担心的。

使用 PDO 的唯一原因是支持准备好的语句,但这些函数都没有提供它。所以,它们不应该被使用。

请改用prepare()/execute()尤其是用于 UPDATE、INSERT、DELETE 语句。

请注意,虽然准备好的陈述被广泛宣传为一种安全措施,但这只是为了吸引人们的注意力。但它们真正的目的是正确的查询格式。这也为您提供了安全性——因为格式正确的查询也不能被注入——就像副作用一样。但同样 - 格式化是一个主要目标,只是因为如果没有正确格式化,即使是无辜的数据也可能导致查询错误。

编辑: 请注意execute() 仅返回TRUEFALSE 以指示操作成功。对于其他信息,例如受UPDATE 影响的记录数,提供了rowCount() 等方法。请参阅docs。

【讨论】:

没错,我刚刚在我正在阅读的页面中看到了这一点。也感谢您的意见。不应该只在我处理变量(用户输入)时使用准备和执行,而不是当我只是为自己获取一些不依赖于任何输入的任何信息时?再次感谢您的输入。 :) 准备好的语句不适用于“任何类型的输入”。它们用于正确运行查询,无论您是为自己还是为他人运行它们。这是正确的查询格式问题,而不是安全问题。 它被宣传为安全只是为了吸引人们。但真正的目的是正确的查询格式。这也为您提供了安全性 - 因为格式正确的查询也不能被注入,就像副作用一样。 对某个主题发表自己的看法总是有帮助的,尤其是在您熟悉它的情况下,但您应该尊重 OP 并至少回答原始问题。 这太有偏见了(***主义),以至于它甚至没有回答这个问题......在很多情况下,您不需要准备好的语句,并且如前所述,它们会增加开销。 【参考方案2】:

看official docs for PDO:

PDO::exec() - "执行一条 SQL 语句并返回受影响的行数" PDO::query() - “执行一条 SQL 语句,将结果集作为 PDOStatement 对象返回”

两个函数都执行查询,但exec() 只返回受影响的行数。这对于 UPDATE 查询很有用,在该查询中没有返回任何有用的信息,只有知道是否修改了正确的行数才有用。

【讨论】:

【参考方案3】:

我制作了一个流程图,试图帮助您确定在任何特定情况下应该使用哪个:

PDOStatement::prepare() 结合绑定变量会:

防止意外的语法错误 防止 SQL 注入攻击 使具有不同值的重复查询更有效。准备查询仅将查询发送到数据库服务器而不发送值。当您execute() PDOStatement 时,您只发送不带查询的值。使用不同的值执行相同的查询 10 次,使用准备好的语句会更有效率。

在任何情况下,您都不应该将用户输入直接放入查询中。但是,如果您的查询没有值并且您决定使用PDO::query() 而不是PDO::exec(),或者如果您使用PDOStatement::prepare() 而不是其他两个中的任何一个,这不是安全问题,而是更多的效率问题问题。

常见的反对意见:

"但是如果我从数据库中提取变量呢?如果我使用准备好的语句将其放入数据库中,那么在没有准备好的语句的情况下将它们直接放入其他查询中是安全的,对吧?强>"

绝对不是。仅仅因为您在插入数据库时​​使用了准备好的语句并不会为将来的查询清理它。在后续查询中使用这些值时,您将需要再次使用准备好的语句。

"但是如果我只是手动将字符串硬编码到查询中,那么在没有准备好的语句的情况下将它们直接放入其他查询中是安全的,对吧?"

是的,它是安全的……暂时。也许今天我正在对其进行硬编码。明天我从数据库中提取它,然后我允许用户在数据库中编辑该字段。但是我会记得返回并更新查询以使用准备好的语句来保证完整性吗?可能不是。每当您在查询中发送值时,准备好的语句都是一种很好的做法。

"我可以将值直接放入查询中吗?"

我唯一可以将值直接放入查询的情况是,例如,发送布尔值(10)、空字符串或NULL。在任何这些情况下,值都会被硬编码到查询中,而不是作为变量。

【讨论】:

以上是关于PDO->query() 和 PDO->exec() 的区别的主要内容,如果未能解决你的问题,请参考以下文章

PHP PDO 执行失败时事务会回滚吗?

PDO连续query()失败问题

PHP PDO获取结果集

pdo 事务机制

PDO类PDOPDOStatementPDOException

PDO 中没有行时返回值