Делать небуферизованные запросы для одного запроса с 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:

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:

The set_attribute parameter is the 10th struct entry.

Here is the MySQL PDO implementation. And the statements methods are defined here:

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 = '';
                }

Также вы должны обработать исключение, когда вы случайно поставили пробел в начале запроса. Надеюсь, это полезно.

Другие вопросы по тегам