PDO无缓冲查询

时间:2009-05-08 19:40:15

标签: php 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属性来启用查询缓冲。在第77行的D:\ Servidor \ xampp_1_7_1 \ htdocs \ bitacora \ func_db.php

我尝试修改连接属性,但它不起作用。

这些是我的核心数据库功能:

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];
    }
}

有人可以为此解释一下吗? PD。请不要建议使用自动数字ID,因为我从另一个系统移植。

6 个答案:

答案 0 :(得分:22)

问题是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;
}
?>

答案 1 :(得分:16)

如果您没有执行返回数据的查询(即UPDATE,INSERT等),我认为PDOStatement :: closeCursor()不起作用。

更好的解决方案是在调用PDOStatement :: execute()之后简单地取消设置()PDOStatement对象:

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

答案 2 :(得分:8)

问题似乎是---我对PDO不太熟悉---在你的getValue调用返回后,查询仍然绑定到连接(你只需要第一个值,但是连接返回几个,或者希望这样做。)

也许可以通过添加

来修复getValue
$resul->closeCursor();

返回之前。

否则,如果对getValue的查询将始终返回单个(或足够少)值,则似乎首选使用fetchAll。

答案 3 :(得分:3)

我只花了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 都是unsigned bigints,这意味着如果我有一份工作,其中new_bytes实际上比original_bytes,然后我会有一个令人讨厌的MySQL“超出范围”错误。这只是在运行我的缩小服务一段时间后随机发生的。

为什么我得到这个奇怪的MySQL错误,而不是只是给我一个简单的错误,是超出我的!当我运行原始查询时,它实际上出现在SQLBuddy(轻量级PHPMyAdmin)中。 我有PDO异常,所以它应该给我MySQL错误。

没关系,底线是:

如果您收到此错误,请务必检查您的原始MySQL是否真的正确并且仍在工作!!!

答案 4 :(得分:0)

我的一个朋友在xampp 1.7.1版本中遇到了同样的问题。在通过5.2.9-2 php.net构建替换xampp / php / *并将所有必需的文件复制到xampp / apache / bin之后,它运行正常。

答案 5 :(得分:0)

如果您使用的是XAMPP 1.7.1,则只需升级到1.7.2。