PHP中exec和execute的区别

16

我正在学习php,但在我的教程中,我看到了类似于以下这些行:

$DatabaseAdd->exec('INSERT INTO db_name......

还有这一个:

$request->execute(array(.....

exec和execute有什么区别?我们能用其中一个来替换另一个吗?


1
为什么不去阅读文档呢?http://php.net/manual/en/pdo.exec.php http://php.net/manual/en/pdostatement.execute.php - Marc B
1
抱歉,我是新手,这是我的第一个问题。我应该自己去做的。无论如何,谢谢... - freij
2个回答

23

简而言之

  • 使用PDO::exec发出一次性的非预处理语句,不返回结果集。
  • 使用PDO::query发出一次性的非预处理语句,返回结果集。

如果语句只执行一次和/或以不支持预处理语句的方式动态构建,则这两种方法都很有用。通常需要额外的工具来正确构建语句(避免SQL注入漏洞)。由于它们的灵活性很少需要,因此通常更喜欢:

  • 无论是否返回结果,都使用PDOStatement::preparePDOStatement::execute准备并执行语句。如果多次执行和/或在热路径中执行非常有用。还不需要额外的工具来处理语句构建。几乎总是建议尽可能使用。

execquery仅限于在连接上下文中操作PDO对象。 exec用于不返回结果集的语句(例如INSERTUPDATEDELETE),而query将返回结果集(例如SELECT语句)。它们只是两个接口,本质上是相同的事情(发出语句)。 SQL语句按原样传递给服务器,因此从客户端的角度来看可能被认为是动态的。
这意味着理论上在每次调用时都可能对它们进行解析、解释/编译并被DBMS优化为查询计划。如果它们被多次执行,则会影响性能成本。

实际上,如果多次执行,它们通常会被缓存并重复使用,但是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 方法是非法的(会产生错误)。

免责声明:只是根据文档进行解释,不再是经常使用者。

类似问题:


3
PDO::exec() 函数可以在单个函数调用中执行 SQL 语句,并返回语句所影响的行数。即使您使用了 "SELECT",也不会返回结果。明白了吗?更多信息请参考:http://php.net/manual/en/pdo.exec.php

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接