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.