PDO Небуферизованные запросы

Я пытаюсь войти в детали 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

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

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

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 id, потому что я портирую с другой системы.

Ответы

Ответ 1

Проблема заключается в том, что 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;
}
?>

Ответ 2

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

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

$stmt = $pdo->prepare('UPDATE users SET active = 1');
$stmt->execute();
unset($stmt);

Ответ 3

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

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

$resul->closeCursor();

перед возвратом.

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

Ответ 4

Я просто трачу 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

Во всяком случае, проблема возникла из-за того, что мои оригинальные_байты и new_bytes как в неподписанных bigints, а в том, что если бы у меня когда-либо была работа, где new_bytes, где на самом деле LARGER, чем original_bytes, тогда у меня был бы неприятный MySQL "вне диапазона", ошибка. И это произошло случайно, после того, как я немного поработал над моим сервисом по мини-настройке.

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

Ничего, нижняя строка:

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

Ответ 5

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

Ответ 6

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