我正在学习php,但在我使用的教程中,我可以看到类似这些行:
$DatabaseAdd->exec('INSERT INTO db_name......
Run Code Online (Sandbox Code Playgroud)
还有这个 :
$request->execute(array(.....
Run Code Online (Sandbox Code Playgroud)
exec和execute之间有什么区别吗?我们可以用一个替换另一个吗?
tne*_*tne 17
TL;博士
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表达式的谓词(似乎),并且仍然使用流畅的API(尽管有些人认为流畅的接口可以形成DSL类型).
通过适当的工具和/或当声明仅执行一次(或非常少次)时,这很好并且有时是必要的.
对于你知道你将多次发出相同语句的情况,只有可能使用不同的参数(例如谓词/ WHERE
子句中的不同值),如果有一种方法可以将它传递给DBMS,那么这不是很好吗它肯定不会丢弃整个查询计划?它也可能允许它进行更多的重量级优化,否则它可能不会这样做,因为它有更多的时间来准备语句(缓慢的初始化阶段),然后才能执行它(可能在热路径中).
大多数数据库系统以预准备语句的形式提供此功能(使用各种机制,非标准AFAIK).PDO通过该prepare
方法以统一的方式公开它,该方法返回另一个表示预准备语句的对象.
然后,您可以重用该对象,特别是其execute
方法(向DBMS发出语句以执行先前准备的语句).如果声明参数化,您甚至可以为每个execute
调用传递新参数.
这也迫使您使用足够合适的工具来构建语句并发布它们.正如我前面提到的那样,基本的字符串连接和其他特殊技术只会让你在脚射击之前到目前为止,很可能是因为未能正确地逃避动态部件/参数.这是SQL注入漏洞的第一来源.
请注意,如果语句返回结果集(例如SELECT
),则需要使用各种fetch
变量来检索结果.
$sth = $dbh->prepare("SELECT name, colour FROM fruit");
$sth->execute();
$result = $sth->fetchAll();
print_r($result);
Run Code Online (Sandbox Code Playgroud)
(来源)
还要注意,非常令人困惑的是,query
它本身以PDOStatement
对象的形式返回结果(就像返回的那样prepare
).虽然有人可能理解为什么在这里重用这个接口,但它可能不是最好的设计(至少可以说).例如,虽然(a)它似乎没有明确记录和(b)我没有测试过,但我认为调用execute
a PDOStatement
返回的query
是非法的(产生错误).
免责声明:仅解释文档,而不是常用用户.
类似的问题: