这是一个基于 6 年前 PHP.net PDO::prepare 手册中非常很容易错过的评论的确认/澄清请求,我没有在其他地方看到过该评论(即使在伟大的 phpdelusions 博客中)。如果这是真的,那么它的可能性就非常大,我觉得它值得更广泛的覆盖范围和搜索突出显示(如果不是,则需要揭穿)。
这是评论(海莉·沃森):
It is possible to prepare in advance several statements against a single connection. As long as that connection remains open the statements can be executed and fetched from as often as you like in any order; their "prepare-execute-fetch" steps can be interleaved in whichever way is best.
So if you're likely to be using several statements often (perhaps within a loop of transactions), you may like to consider preparing all the statements you'll be using up front.
我有一些代码必须像(伪代码)一样运行:
foreach (fetchAll row with PDO) {
process row results
if (condition)
update table with processed results
else
delete row no longer needed
}
根据该评论,我可以在循环之前创建两个准备好的语句,一个用于更新查询,一个用于删除查询,然后(仅)在循环内执行。只要句柄不同并保留,连接就应该缓存两者,我可以互换使用它们,并且不必在循环内进行任何 SQL 语句解析,这将非常低效:
// do statement prepare/execute/fetchAll for main loop, then...
$update_stmt = $PDO->prepare($update_query);
$delete_stmt = $PDO->prepare($delete_query);
foreach (fetchAll row) {
process row results
if (condition)
$update_stmt->execute(some_processed_values);
else
$delete_stmt->execute(some_other_values);
}
由于这里的大多数问题只讨论一次使用一个准备好的语句,如果广泛应用,这对代码效率有很好的影响,有人想确认这确实是这样吗(至少从 PHP7 开始)?如果是这样,我想这种形式的代码的其他简洁应用程序可以在解决方案中共享。
最佳答案
同时使用多个准备好的语句并且乱序执行它们是没有问题的。
您可以使用交织的语句运行如下代码,它会起作用。
$stmt1 = $pdo->prepare('INSERT INTO addplate(Plate) VALUES(?)');
$stmt2 = $pdo->prepare('UPDATE addplate SET Plate=? WHERE Plate=?');
$stmt1->execute(['val1']);
$stmt2->execute(['val2', 'val1']);
$stmt1->execute(['val1']);
$stmt2->execute(['val2', 'val1']);
$stmt1->execute(['val1']);
当由于某种原因您无法避免 N+1 问题时,这可以为您带来一些性能优势。您准备一次内部查询,然后在循环内多次执行它。
但是,如果您想运行 unbuffered query,这可能会成为生成结果的查询的问题。 (很少使用)。 PDO 默认情况下执行缓冲查询,因此您需要将它们关闭才能遇到此问题。
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$stmt1 = $pdo->prepare('SELECT * FROM addplate WHERE Plate=?');
$stmt2 = $pdo->prepare('SELECT * FROM addplate WHERE Plate=?');
$stmt1->execute(['val1']);
var_dump($stmt1->fetch());
$stmt2->execute(['val2']); // <-- Error if stmt1 still has more records
var_dump($stmt2->fetch());
它将产生:
Fatal error: Uncaught PDOException: SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute.
关于php - 一次使用多个 PDO 准备好的语句,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60130072/