14

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

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

4

3 回答 3

18

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

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

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

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

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

于 2013-05-05T04:59:30.950 回答
15

查看PDO 的官方文档

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

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

于 2013-05-05T04:23:07.660 回答
6

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

在此处输入图像描述

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

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

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

常见的反对意见:

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

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

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

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

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

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

于 2018-08-30T17:43:14.320 回答