14

我正在尝试了解 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,因为我是从另一个系统移植的。

4

6 回答 6

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;
}
?>
于 2009-08-13T02:54:44.900 回答
16

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

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

$stmt = $pdo->prepare('UPDATE users SET active = 1');
$stmt->execute();
unset($stmt);
于 2011-05-03T03:25:59.130 回答
8

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

也许 getValue 可以通过添加来修复

$resul->closeCursor();

在返回之前。

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

于 2009-05-08T19:58:19.167 回答
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_bytesnew_bytes都在 unsigned bigints 的位置,这意味着如果我曾经有一份工作,其中 new_bytes 实际上比 original_bytes 大,那么我会遇到一个令人讨厌的 MySQL“超出范围”错误。这只是在运行我的缩小服务一段时间后随机发生的。

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

没关系,底线是:

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

于 2014-06-30T18:00:03.923 回答
0

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

于 2009-05-19T08:11:59.850 回答
0

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

于 2009-10-25T14:35:29.843 回答