PDO Небуферизованные запросы - PullRequest
14 голосов
/ 08 мая 2009

Я пытаюсь вникнуть в детали PDO. Итак, я закодировал это:

$cn = getConnection();

// get table sequence
$comando = "call p_generate_seq('bitacora')";
$id = getValue($cn, $comando);

//$comando = 'INSERT INTO dsa_bitacora (id, estado, fch_creacion) VALUES (?, ?, ?)';
$comando = 'INSERT INTO dsa_bitacora (id, estado, fch_creacion) VALUES (:id, :estado, :fch_creacion)';
$parametros = array (
    ':id'=> (int)$id,
    ':estado'=>1,
    ':fch_creacion'=>date('Y-m-d H:i:s')
);
execWithParameters($cn, $comando, $parametros);

моя функция getValue работает нормально, и я получаю следующую последовательность для таблицы. Но когда я вхожу в execWithParameters, я получаю это исключение:

PDOException: SQLSTATE [HY000]: общая ошибка: 2014 Невозможно выполнить запросы, когда другие небуферизованные запросы активны. Рассмотрите возможность использования PDOStatement :: fetchAll (). В качестве альтернативы, если ваш код работает только с mysql, вы можете включить буферизацию запросов, установив атрибут PDO :: MYSQL_ATTR_USE_BUFFERED_QUERY. в D: \ Servidor \ xampp_1_7_1 \ htdocs \ bitacora \ func_db.php в строке 77

Я пытался изменить атрибуты соединения, но это не работает.

Это мои основные функции БД:

function getConnection() {
    try {
        $cn = new PDO("mysql:host=$host;dbname=$bd", $usuario, $clave, array(
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
            ));

        $cn->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
        return $cn;
    } catch (PDOException $e) {
        print "Error!: " . $e->getMessage() . "<br/>";
        die();
    }
}
function getValue($cn, $comando) {
    $resul = $cn->query($comando);
        if (!$resul) return null;
        while($res = $resul->fetch()) {
            $retorno = $res[0][0];
            break;
        }
        return $retorno;
}
function execWithParameters($cn, $comando, $parametros) {
    $q = $cn->prepare($comando);
    $q->execute($parametros);
    if ($q->errorInfo() != null) {
        $e = $q->errorInfo();
        echo $e[0].':'.$e[1].':'.$e[2];
    }
}

Кто-нибудь, кто может пролить свет на это? Оплаченный Пожалуйста, не предлагайте делать идентификаторы autonumeric, потому что я портирую из другой системы.

Ответы [ 6 ]

22 голосов
/ 13 августа 2009

Проблема заключается в том, что mysql допускает только один ожидающий курсор в данный момент времени. Используя метод fetch () и не используя все ожидающие данные, вы оставляете курсор открытым.

Рекомендуемый подход - использовать все данные, используя метод fetchAll (). Альтернативой является использование метода closeCursor ().

Если вы измените эту функцию, я думаю, вы будете счастливее:

<?php
function getValue($cn, $comando) {
    $resul = $cn->query($comando);
    if (!$resul) return null;
    foreach ($resul->fetchAll() as $res) {
            $retorno = $res[0];
            break;
    }
    return $retorno;
}
?>
16 голосов
/ 03 мая 2011

Я не думаю, что PDOStatement :: closeCursor () будет работать, если вы не выполняете запрос, который возвращает данные (например, UPDATE, INSERT и т. Д.).

Лучшее решение - просто снять () ваш объект PDOStatement после вызова PDOStatement :: execute ():

$stmt = $pdo->prepare('UPDATE users SET active = 1');
$stmt->execute();
unset($stmt);
8 голосов
/ 08 мая 2009

Проблема, по-видимому, в том, что я не слишком знаком с PDO, что после возврата вашего вызова getValue запрос все еще привязан к соединению (вы запрашиваете только первое значение, но соединение возвращает несколько или ожидает сделать это).

Возможно, getValue можно исправить, добавив

$resul->closeCursor();

до возврата.

В противном случае, если запросы getValue всегда будут возвращать одно (или несколько) значение, кажется, что использование fetchAll будет предпочтительным.

3 голосов
/ 30 июня 2014

Я просто потратил 15 минут на поиски в интернете и просмотрел по крайней мере 5 различных вопросов Stackoverflow, некоторые из которых утверждали, что моя ошибка, по-видимому, возникла из-за неправильной версии PHP, неправильной версии библиотеки MySQL или каких-либо других магических черных ящиков. ...

Я изменил весь свой код на использование «fetchAll» и даже вызывал closeCursor () и unset () для объекта запроса после каждого запроса. Я был в отчаянии! Я также пробовал флаг MYSQL_ATTR_USE_BUFFERED_QUERY, но он не работал.

НАКОНЕЦ Я выбросил все в окно, посмотрел на ошибку PHP и отследил строку кода, где это произошло.

SELECT AVG((original_bytes-new_bytes)/original_bytes) as saving 
    FROM (SELECT original_bytes, new_bytes FROM jobs ORDER BY id DESC LIMIT 100) AS t1

Во всяком случае, проблема возникла из-за того, что мои original_bytes и new_bytes оба были в местах без знака bigints, и это означало, что если бы у меня когда-нибудь была работа, где new_bytes на самом деле БОЛЬШЕ, чем original_bytes, тогда у меня была бы неприятная ошибка "вне диапазона" MySQL. И это произошло случайно после небольшого запуска моей службы минификации.

Почему, черт возьми, я получил эту странную ошибку MySQL вместо того, чтобы просто дать мне простую ошибку, мне не под силу! На самом деле он обнаружился в SQLBuddy (облегченный PHPMyAdmin), когда я запустил необработанный запрос. У меня были исключения PDO, поэтому он должен был дать мне ошибку MySQL.

Неважно, суть:

Если вы когда-нибудь получите эту ошибку, убедитесь, что ваш сырой MySQL действительно корректен и все еще работает !!!

0 голосов
/ 25 октября 2009

Если вы используете XAMPP 1.7.1, вам просто нужно перейти на 1.7.2.

0 голосов
/ 19 мая 2009

У моего друга была такая же проблема со сборкой xampp 1.7.1. После замены xampp / php / * сборкой php.net 5.2.9-2 и копирования всех необходимых файлов в xampp / apache / bin все заработало.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...