目前我将准备好的语句保存到私有变量中,因为我忽略了它们在深度方面的实际工作方式,并且只是为了以防万一。
所以问题很简单,如果我迭代相同的$PDO->prepare()
,它会再次准备相同的查询吗?
foreach( $arr as $docid ) {
if( $this->dbLink === null ) { // PDO resource, saved in the object.
throw new Exception( 'Must first connect to DB' );
}
if( $this->queryCheckAccess === null ) {
$query = 'SELECT * from something where id = :id';
$this->queryCheckAccess = $this->dbLink->prepare($query);
}
else {
$result = $this->queryCheckAccess->execute(array(':id'=>$docid));
}
}
重要吗?或者DB Engine / PHP足够聪明,知道它是相同的预处理语句吗?
非常感谢。
-----------------编辑--------------
我想我被误解了。
我问的是如果我这样做会发生什么:
$query = 'SELECT * from something where id = :id';
$this->queryCheckAccess = $this->dbLink->prepare($query);
$query = 'SELECT * from something where id = :id';
$this->queryCheckAccess = $this->dbLink->prepare($query);
$query = 'SELECT * from something where id = :id';
$this->queryCheckAccess = $this->dbLink->prepare($query);
$query = 'SELECT * from something where id = :id';
$this->queryCheckAccess = $this->dbLink->prepare($query);
如果我这样做会发生什么:
if( $this->queryCheckAccess === null ) {
$query = 'SELECT * from something where id = :id';
$this->queryCheckAccess = $this->dbLink->prepare($query);
}
引擎会在第一个示例中准备查询4次吗?或者会注意到它是相同的查询,只是"跳跃"是什么?
答案 0 :(得分:2)
您的代码只准备一次查询,因为在第一次循环迭代之后,它不是NULL,因此条件块将不会运行。但每次循环检查条件都是浪费时间。
但是要回答你的问题,如果你准备()相同的查询,它确实做了多余的工作,即使查询与你之前准备的查询相同。所以你应该避免这种情况。
但你根本不需要在循环内准备。在开始循环之前准备一次,并将变量绑定到参数。您不需要在循环中每次绑定,只需更改该变量的值。
if( $this->dbLink === null ) { // PDO resource, saved in the object.
throw new Exception( 'Must first connect to DB' );
}
$query = 'SELECT * from something where id = :id';
$this->queryCheckAccess = $this->dbLink->prepare($query);
$this->queryCheckAccess->bindParam(':id' => $docidparam);
foreach( $arr as $docid ) {
$docidparam = $docid;
$result = $this->queryCheckAccess->execute();
}
我不确定您是否可以绑定变量并将其用作循环变量,可能存在范围冲突。
此查询的另一个建议是:为什么不运行一个查询来搜索值列表?
$list = implode(",", array_fill(1, count($arr), "?"));
$query = "SELECT * FROM something WHERE id IN ( $list )";
$this->queryCheckAccess = $this->dbLink->prepare($query);
$this->queryCheckAccess->execute($arr);
PS:你也应该检查错误。如果启用PDO错误模式EXCEPTION,则错误将自动引发异常。如果未启用该模式,则需要检查prepare()和execute()的返回值,如果出现错误,则返回 false 。
答案 1 :(得分:0)
我只是运行类似于您的示例的代码,并启用MySQL Query LOG我发现所有准备请求都发送到MySQL服务器
Prepare SELECT * FROM test_table WHERE username = ?
Close stmt
Prepare SELECT * FROM test_table WHERE username = ?
Close stmt
Prepare SELECT * FROM test_table WHERE username = ?
Close stmt
Prepare SELECT * FROM test_table WHERE username = ?
Close stmt
测试代码:
$sth = $dbh->prepare($sql);
$sth = $dbh->prepare($sql);
$sth = $dbh->prepare($sql);
$sth = $dbh->prepare($sql);
$sth = $dbh->prepare($sql);
$sth->bindParam(1, $user);
$sth->execute();
然后,最好的方法是准备一次,并绑定不同的值,然后执行。
$sth = $dbh->prepare($sql);
$user = "test";
$sth->bindParam(1, $user);
$sth->execute();
$user = "test2";
$sth->bindParam(1, $user);
$sth->execute();
$user = "test";
$sth->bindParam(1, $user);
$sth->execute();
答案 2 :(得分:-1)
不,这是准备好的陈述的主要特征之一。如果您要多次运行相同的查询但使用不同的变量,那么准备查询将为您提高速度。特别是如果你使用交易(需要InnoDB存储引擎)。
答案 3 :(得分:-1)
要回答标题中的问题(与正文中的问题完全不同),避免多次准备相同语句的最佳方法,显然是避免运行多个类似的查询 。
要回答问题正文中的问题 - 不,数据库引擎/ PHP不够“智能”,足以知道它是同一个查询再次准备好了。每次新的prepare()调用都会创建另一个语句。我会首先讨厌这种“聪明”的行为。你的工具“更聪明”,你得到的结果越不可预测。
要回答代码中的真正的问题,智能开发人员会使用正确的工具为自己省去麻烦。
使用safeMysql整个混乱将减少到一个查询和一行代码
$data = $this->dbLink->getAll('SELECT * from somth where id IN (?a)', $arr);
S0 - 没有多重查询,没有多重准备,没有多重问题。
顺便说一下,你的代码丢失了第一个id。 然而,如果您不使用结果,那么您将失去所有这些但是最后一个。