我正在学习php,但是在我使用的教程中,我可以看到类似以下内容的内容:
$DatabaseAdd->exec('INSERT INTO db_name......
和这个 :
$request->execute(array(.....
exec和execute之间有什么区别吗?我们可以用一个替代另一个吗?
tl; dr
PDO::exec
到的问题一次性非预处理语句不返回结果集。PDO::query
到的问题一次性非预处理语句返回结果集。如果仅一次执行该语句和/或如果它们以准备好的语句不支持的方式动态构造,则这两个都是有用的。通常需要其他工具来正确构造语句(并避免出现诸如SQL注入漏洞之类的东西)。再加上很少需要灵活性的事实,这通常意味着:
PDOStatement::prepare
和PDOStatement::execute
准备语句并执行它们,无论它们是否返回结果。如果多次执行和/或在热路径中执行,则很有用。也不需要其他工具来处理语句构造。几乎总是建议尽可能。exec
并且query
作用于PDO
对象,因此仅在连接的上下文中起作用。exec
用于那些不返回结果集的语句(例如INSERT
,UPDATE
,DELETE
),同时query
将返回结果集(例如,从SELECT
语句)。它们只是两个基本上执行相同操作(发出语句)的相似接口。SQL语句按原样传递给服务器,因此从客户端的角度来看,可以将其视为动态的。
这意味着从理论上讲,在执行之前,它们可能总是(在每次调用时)由DBMS解析,解释/编译和优化为查询计划。如果多次执行它们,则在性能方面会付出高昂的代价。
实际上,如果多次执行它们,通常会对其进行缓存和重用,但是DBMS只能在没有任何保证的情况下机会性地这样做。根据它们的匹配方式,稍微更改查询可能需要DBMS完全重新编译它。有时,客户端会动态地构建查询(通常使用原始字符串连接,有时会使用适当的基于语言或基于库的工具支持),这样DBMS根本不可能缓存查询计划。
更新:出于好奇,Pinq是PHP的基于语言的查询构建器的示例,而Doctrine LDBAL是基于库的示例。请注意,Pinq仅解析PHP表达式以查找谓词(似乎),而其余部分仍使用fluent API(尽管有些人认为fluent接口可以形成DSL类型)。
使用适当的工具和/或仅在一次(或很少次数)执行语句时,这样做很好,有时是必要的。
对于您知道您将多次发出同一条语句(可能仅具有不同的参数(例如,谓词/WHERE
子句中的值不同))的情况,如果有一种方法可以将其与DBMS通讯,那不是很好。不能肯定会丢弃整个查询计划吗?它也可能允许它执行更多的重量级优化,而其他情况下可能不会这样做,因为它有更多的时间在执行之前(可能是在热路径中)准备语句(缓慢的初始化阶段)。
大多数数据库系统以预准备语句的形式(使用各种机制,非标准AFAIK)提供此功能。PDO通过该prepare
方法以统一的方式公开它,该方法返回另一个代表准备好的语句的对象。
然后,您可以重用该对象,尤其是其execute
方法(向DBMS发出一条语句以执行先前准备的语句)。如果该语句已参数化,则您甚至可以为每个execute
调用传递新参数。
这也迫使您使用足够适当的工具来构造和发布语句。就像我之前提到的那样,基本的字符串连接和其他特殊技术只能在您踏入脚下之前走到最远,很可能是因为未能正确地避开动态部分/参数。这是SQL注入漏洞的#1来源。
请注意,如果该语句返回结果集(例如SELECT
),则需要使用各种fetch
变体来检索结果。
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();
$result = $sth->fetchAll();
print_r($result);
(来源)
另外请注意,query
它本身很混乱,它以PDOStatement
对象的形式返回结果(就像由返回的一样prepare
)。尽管可能会理解为什么在此重用此接口,但它可能不是最好的设计(至少可以这样说)。例如,尽管(a)似乎没有明确记录,并且(b)我尚未对其进行测试,但我认为调用execute
a的PDOStatement
返回query
是非法的(产生错误)。
免责声明:仅解释文档,不再是经常使用的用户。
类似问题:
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句