我正在学习php,但在我的教程中,我看到了类似于以下这些行:
$DatabaseAdd->exec('INSERT INTO db_name......
还有这一个:
$request->execute(array(.....
exec和execute有什么区别?我们能用其中一个来替换另一个吗?
我正在学习php,但在我的教程中,我看到了类似于以下这些行:
$DatabaseAdd->exec('INSERT INTO db_name......
还有这一个:
$request->execute(array(.....
exec和execute有什么区别?我们能用其中一个来替换另一个吗?
简而言之
PDO::exec
发出一次性的非预处理语句,不返回结果集。PDO::query
发出一次性的非预处理语句,返回结果集。如果语句只执行一次和/或以不支持预处理语句的方式动态构建,则这两种方法都很有用。通常需要额外的工具来正确构建语句(避免SQL注入漏洞)。由于它们的灵活性很少需要,因此通常更喜欢:
PDOStatement::prepare
和PDOStatement::execute
准备并执行语句。如果多次执行和/或在热路径中执行非常有用。还不需要额外的工具来处理语句构建。几乎总是建议尽可能使用。exec
和query
仅限于在连接上下文中操作PDO
对象。 exec
用于不返回结果集的语句(例如INSERT
,UPDATE
,DELETE
),而query
将返回结果集(例如SELECT
语句)。它们只是两个接口,本质上是相同的事情(发出语句)。 SQL语句按原样传递给服务器,因此从客户端的角度来看可能被认为是动态的。实际上,如果多次执行,它们通常会被缓存并重复使用,但是DBMS只能机会主义地这样做,没有任何保证。根据它们的匹配方式,稍微更改查询可能需要DBMS完全重新编译它。有时客户端会动态构建查询(使用原始字符串连接太频繁,有时使用适当的 基于语言 或 基于库 的工具支持),以致于DBMS根本无法缓存查询计划。
更新:对于好奇的人,Pinq 是 PHP 的基于语言的查询构建器的一个示例,而 Doctrine LDBAL 是基于库的示例。请注意,Pinq 仅解析用于谓词的 PHP 表达式(似乎是这样),并且仍然使用流畅的 API处理其余部分(尽管有些人认为流畅的接口可以形成DSLs的类型)。WHERE
子句中有不同的值),如果有一种方法可以将其传达给数据库管理系统,以便它不会肯定丢弃整个查询计划,这不是很好吗?这也可能使它能够执行更加重量级的优化,否则它可能不会这样做,因为它在执行之前有更多时间准备语句(缓慢的初始化阶段)(可能在热路径上执行)。
大多数数据库系统通过准备语句(使用各种机制,我不确定是否标准)提供此功能。PDO通过prepare
方法以统一的方式公开它,该方法返回另一个对象,表示准备好的语句。
您可以重复使用该对象,特别是它的 execute
方法(它向DBMS发出语句以执行先前准备好的语句)。如果语句是参数化的,您甚至可以为每个 execute
调用传递新参数。
这也迫使您使用足够适当的工具来构建和发出语句。正如我之前提到的,基本字符串连接和其他临时技术只能帮您做到一定程度,否则您很可能会因为未能正确 转义 动态部分/参数而自食其果。这是 SQL注入 漏洞的主要来源。
请注意,如果语句返回结果集(例如 SELECT
),您需要使用各种 fetch
变体来检索结果。
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();
$result = $sth->fetchAll();
print_r($result);
(来源)
同时需要注意的是,query
方法返回的结果以 PDOStatement
对象的形式呈现(就像 prepare
方法返回的那些对象一样)。虽然我们可以理解为什么在这里重用了这个接口,但这可能不是最好的设计(至少可以这么说)。例如,虽然(a)它似乎没有明确记录,(b)我也没有测试过,但我会认为在由 query
返回的 PDOStatement
上调用 execute
方法是非法的(会产生错误)。
免责声明:只是根据文档进行解释,不再是经常使用者。
类似问题: