我想知道——如果这段代码:
// example 1
$statement = $pdo->query('SELECT * FROM table'); // MySQL
while ($row = $statement->fetch())
{
// doing something interesting
}
相当于这段代码:
// example 2
$statement = $pdo->query('SELECT * FROM table'); // MySQL
foreach ($statement as $row)
{
// doing something interesting
}
在 MySQL 的无缓冲查询的上下文中? (我知道循环给出相同的结果。)
或者换句话说:
- 我敢肯定,执行第一个示例不会留下任何未读数据(根据 Causes of MySQL error 2014 Cannot execute queries while other unbuffered queries are active 的答案),如果下一个
query
或准备
在循环抛出General error: 2014 Cannot execute queries while other unbuffered queries are active.
- 我不确定第二个示例是否以相同的方式工作:获取所有数据。
我试过类似的东西:
$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$statement = $pdo->query('SELECT * FROM table WHERE x = 1');
while(...) OR foreach(...)
{
// some magic
}
OR
$statement->fetch(); // just fetch(), not fetchAll()
$statement = $pdo->query('SELECT * FROM table WHERE x = 2'); // MySQL
...
和:
- 在
while
或foreach
的情况下,代码运行没有错误。 - 如果只是
fetch()
,我会得到error: 2014
。
看来,我回答了我自己的问题;)但我仍然不确定。我也找不到可以回答我的问题的任何文档或 SO 问题。
最佳答案
PHP 5.5.12, window
我做了更多的测试。我创建了一个包含 100 000 条记录的表,并检查了使用不同方法对表中的所有值求和时占用了多少内存:
+----------+-------------+--------+
| method | memory used | time |
+----------+-------------+--------+
| fetchAll | 69.9157 MB | 7.20 s | // <-- fails if memory_limit < 69 M
| while | 0.2494 MB | 3.24 s |
| foreach | 0.2494 MB | 0.98 s | // <-- here I disagree with Ollie
+----------+-------------+--------+
考虑到我的问题和上面的测试,我得出结论:
- 使用
foreach
和while
在缓冲查询方面是等价的:这两种方法都是逐行读取,并且在执行循环后所有数据都以这种方式获取,下一个查询不会抛出error 2014
-
foreach
不会做类似fetchAll
的事情在遍历PDOStatement
之前获取整个结果集: 如果是这样,测试将在memory_limit < 69M
时失败(恕我直言:这很合逻辑,因为PDOStatement
实现了Traversable
接口(interface))。所以我不能同意 Ollie Jones 的回答(至少在我的计算机和环境中)。
关于php - 在无缓冲查询的上下文中,foreach 是否等同于 while?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32417524/