我正在学习php,但在我使用的教程中,我可以看到类似这些行:
$DatabaseAdd->exec('INSERT INTO db_name......
和这一个:
$request->execute(array(.....
exec和execute之间有什么区别吗?我们可以用一个替换另一个吗?
答案 0 :(得分:13)
<强> TL;博士强>
PDO::exec
发出不会返回结果集的一次性非准备语句。PDO::query
发出返回结果集的一次性非准备语句。如果语句只执行一次和/或它们是以预准备语句不支持的方式动态构造的,那么这两个语句都很有用。通常需要额外的工具来正确构造语句(并避免像SQL注入漏洞这样的事情)。这与他们的灵活性很少需要的事实相结合意味着它通常更喜欢:
PDOStatement::prepare
和PDOStatement::execute
准备语句并执行它们,无论它们是否返回结果。如果多次执行和/或在热路径中有用。也不需要额外的工具来处理语句构造。几乎总是建议尽可能。 exec
和query
对PDO
个对象起作用,因此仅在连接的上下文中起作用。 exec
用于不返回结果集的语句(例如INSERT
,UPDATE
,DELETE
),而query
将返回结果集(例如,来自SELECT
陈述。它们只是两个类似的接口,基本上做同样的事情(发表声明)。 SQL语句按原样传递给服务器,因此从客户端的角度来看可以认为是动态的。
这意味着理论上他们可能总是(即每次调用)在执行之前被DBMS解析,解释/编译并优化为查询计划。如果多次执行,这在性能方面成本很高。
在实践中,如果多次执行,它们通常会被缓存和重用,但DBMS只能机会性地执行此操作而无需任何保证。根据它们的匹配方式,稍微更改查询可能需要DBMS完全重新编译它。有时,客户端将动态构造查询(通常使用原始字符串连接,有时使用正确的language-based或library-based工具支持),这样DBMS就无法缓存查询计划
更新:对于好奇,Pinq是PHP的基于语言的查询构建器的示例,Doctrine LDBAL是基于库的示例。请注意,Pinq仅解析PHP表达式的谓词(似乎),并且仍然使用fluent API(尽管有些人认为流畅的接口可以形成DSLs的类型)。
使用适当的工具和/或当声明只执行一次(或非常少次)时,这很好,有时是必要的。
对于知道的情况,您将多次发出相同的语句,但可能只有不同的参数(例如谓词/ WHERE
子句中的不同值),不会#39如果有一种方法可以将它传达给DBMS,那么它是不是很好,这样它就不会丢弃整个查询计划?它也可能允许它进行更多的重量级优化,否则它可能不会这样做,因为它有更多的时间来准备语句(缓慢的初始化阶段),然后才能执行它(可能在热路径中)。
大多数数据库系统以prepared statements的形式提供此功能(使用各种机制,非标准AFAIK)。 PDO通过prepare
方法以统一的方式公开它,该方法返回表示预准备语句的another object。
然后,您可以重用该对象,尤其是其execute
方法(向DBMS发出语句以执行先前准备的语句)。如果语句已参数化,您甚至可以为每个execute
调用传递新参数。
这也会迫使您使用足够合适的工具来构建语句并发布它们。正如我前面提到的那样,基本的字符串连接和其他特殊技术只会让你在脚射击之前到目前为止,很可能是因为未能正确地escape动态部件/参数。这是SQL injection漏洞的第一来源。
请注意,如果语句返回结果集(例如SELECT
),则需要使用各种fetch
变体来检索结果。
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();
$result = $sth->fetchAll();
print_r($result);
(Source)
另请注意,query
本身非常令人困惑,它会以PDOStatement
对象的形式返回其结果(就像prepare
返回的那样)。虽然有人可能会理解为什么在这里重用这个界面,但它可能不是最好的设计(至少可以说)。例如,虽然(a)它似乎没有明确记录,(b)我还没有测试过,我会假设在execute
上调用PDOStatement
query
是非法的(产生错误)。
免责声明:仅解释文档,而不是常用用户。
类似的问题:
答案 1 :(得分:3)
PDO :: exec()在单个函数调用中执行SQL语句,返回受该语句影响的行数。
所以即使你使用了“SELECT”,你也不会得到结果。有意义吗?