Делать небуферизованные запросы для одного запроса с PDO
Я ищу делать небуферизованные запросы только по некоторым запросам.
В MySQL я делал это:
$req = mysql_unbuffered_query('SELECT * FROM forum_topics
ORDER BY (topic_id/topic_stick) DESC, topic_last_post DESC');
while($data = mysql_fetch_assoc($req)) {
// display results...
}
Я посмотрел на PHP документ, и в соответствии с этим в pdo
мы должны действовать следующим образом, чтобы выполнять запросы без буферизации:
$pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass');
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
$uresult = $pdo->query("SELECT Name FROM City");
if ($uresult) {
while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) {
echo $row['Name'] . PHP_EOL;
}
}
Но возможно ли сделать это без буферизации только для результатов таблицы "forum_topics", не устанавливая для всех экземпляров pdo небуферизованные?
2 ответа
Если вы используете подготовленный оператор (вы можете использовать его для простого выбора), например:
$uresult = $pdo->prepare("SELECT Name FROM City");
тогда вы можете установить атрибут на uresult:
$uresult->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
Затем вы выполняете подготовленный оператор:
$uresult->execute();
if ($uresult) {
while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) {
echo $row['Name'] . PHP_EOL;
}
}
тогда атрибут unbuffered должен применяться только к вашему выражению, а не ко всему объекту pdo
Re, это не работает, я получаю ошибку при использовании вашего метода:
SQLSTATE [IM001]: драйвер не поддерживает эту функцию: этот драйвер не поддерживает настройку атрибутов
В чем дело?
Изменить: я нашел решение на php.net док.
Если вы используете это:
$sth->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
Не работает
Но если вы установите его в массиве prepare(), он будет работать нормально.
$sth = $pdo->prepare('SELECT * FROM my_table',
array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false));
Я надеюсь, что это поможет людям, которые не нашли способ решить эту проблему.
Все ответы здесь пытаются использовать MYSQL_ATTR_USE_BUFFERED_QUERY
на статусе. а такжеMYSQL_ATTR_USE_BUFFERED_QUERY
работает только со всем соединением, как вы, кажется, догадались.
MYSQL_ATTR_USE_BUFFERED_QUERY
также работает, только если вы используете mysqlnd
библиотека - какие у вас хорошие шансы, если вы используете PHP 7 или выше.
Ваш оригинальный метод установления соединения, как небуферизованы был правильный, и только на самом деле функциональным методом.
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);
Но можно ли сделать это без буферизации только для результатов таблицы "forum_topics", не устанавливая все экземпляры pdo в небуферизованные?
Не все экземпляры настроены как небуферизованные, только этот "экземпляр" этого соединения. Вы можете просто немедленно включить буферизацию на ala:
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
Проблема в том, что вы можете выполнять итерацию только одного запроса для каждого соединения в небуферизованном режиме, поэтому вы не можете выполнить второй запрос, пока не получите все данные из первого набора.
Обычно вы хотите использовать небуферизованные запросы только для очень больших наборов данных. Я бы рекомендовал использовать второе соединение PDO с базой данных специально для небуферизованных запросов, которые вы открываете только тогда, когда вам нужно выполнить небуферизованный запрос, иначе:
$pdo2 = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass');
$pdo2->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
MySQL does not implement statement-level attribute setting.
Source:
Here is your error message:
https://github.com/php/php-src/blob/master/ext/pdo/pdo_stmt.c
pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "This driver doesn't support setting attributes");
And the condition above is checked on the stmt->methods->set_attribute
above.
The stmt->methods
is defined above and the type is declared at:
struct pdo_stmt_methods
The set_attribute
parameter is the 10th struct entry.
Here is the MySQL PDO implementation. And the statements methods are defined here:
NULL, /* set_attr */
This shows that the MySQL PDO module does implement that feature.
Discussion:
I have reviewed other extensions. And only the Firebird PDO database module supports that feature.
В качестве обходного пути, если мой запрос SELECT, я не вызываю функцию fetchAll.
$query = 'SELECT ...... ';
$arr = explode(' ', $query);
$query_type = strtolower($arr[0]);
if ($query_type == 'select') {
$query_response = $query_prepare->fetchAll(PDO::FETCH_ASSOC);
} else {
$query_response = '';
}
Также вы должны обработать исключение, когда вы случайно поставили пробел в начале запроса. Надеюсь, это полезно.