PDO 无缓冲查询

发布于 2024-07-20 02:52:44 字数 1921 浏览 4 评论 0原文

我正在尝试了解 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];
    }
}

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

I'm trying to get into PDO details. So I coded this:

$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);

my getValue function works fine, and I get the next sequence for the table. But when I get into execWithParameters, i get this exception:

PDOException: SQLSTATE[HY000]: General error: 2014 Cannot execute queries while other unbuffered queries are active. Consider using PDOStatement::fetchAll(). Alternatively, if your code is only ever going to run against mysql, you may enable query buffering by setting the PDO::MYSQL_ATTR_USE_BUFFERED_QUERY attribute. in D:\Servidor\xampp_1_7_1\htdocs\bitacora\func_db.php on line 77

I tried to modify the connection attributes but it doesn't work.

These are my core db functions:

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

Somebody who can shed a light for this? PD. Please do not suggest doing autonumeric id, cause i am porting from another system.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

浪菊怪哟 2024-07-27 02:52:44

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

The issue is that mysql only allows for one outstanding cursor at a given time. By using the fetch() method and not consuming all the pending data, you are leaving a cursor open.

The recommended approach is to consume all the data using the fetchAll() method.
An alternative is to use the closeCursor() method.

If you change this function, I think you will be happier:

<?php
function getValue($cn, $comando) {
    $resul = $cn->query($comando);
    if (!$resul) return null;
    foreach ($resul->fetchAll() as $res) {
            $retorno = $res[0];
            break;
    }
    return $retorno;
}
?>
老街孤人 2024-07-27 02:52:44

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

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

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

I don't think PDOStatement::closeCursor() would work if you're not doing a query that returns data (i.e. an UPDATE, INSERT, etc).

A better solution is to simply unset() your PDOStatement object after calling PDOStatement::execute():

$stmt = $pdo->prepare('UPDATE users SET active = 1');
$stmt->execute();
unset($stmt);
无戏配角 2024-07-27 02:52:44

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

添加来修复

$resul->closeCursor();

也许 getValue 可以通过在返回之前

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

The problem seems to be---I'm not too familiar with PDO--- that after your getValue call returns, the query is still bound to the connection (You only ever ask for the first value, yet the connection returns several, or expects to do so).

Perhaps getValue can be fixed by adding

$resul->closeCursor();

before the return.

Otherwise, if queries to getValue will always return a single (or few enough) value, it seems that using fetchAll will be preferred.

人生百味 2024-07-27 02:52:44

我只花了 15 分钟在互联网上谷歌搜索,并查看了至少 5 个不同的 Stackoverflow 问题,其中一些人声称我的 bug 显然是由错误版本的 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都是无符号的bigints,这意味着如果我曾经有一份工作,new_bytes实际上比original_bytes大,那么我会遇到令人讨厌的 MySQL“超出范围”错误。 这只是在运行我的缩小服务一段时间后随机发生的。

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

没关系,底线是:

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

I just spend 15 minutes googling all around the internet, and viewed at least 5 different Stackoverflow questions, some who claimed my bug apparently arose from the wrong version of PHP, wrong version of MySQL library or any other magical black-box stuff...

I changed all my code into using "fetchAll" and I even called closeCursor() and unset() on the query object after each and every query. I was honestly getting desperate! I also tried the MYSQL_ATTR_USE_BUFFERED_QUERY flag, but it did not work.

FINALLY I threw everything out the window and looked at the PHP error, and tracked the line of code where it happened.

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

Anyway, the problem happened because my original_bytes and new_bytes both where unsigned bigints, and that meant that if I ever had a job where the new_bytes where actually LARGER than the original_bytes, then I would have a nasty MySQL "out of range" error. And that just happened randomly after running my minification service for a little while.

Why the hell I got this weird MySQL error instead of just giving me the plain error, is beyond me! It actually showed up in SQLBuddy (lightweight PHPMyAdmin) when I ran the raw query.
I had PDO exceptions on, so it should have just given me the MySQL error.

Never mind, the bottom line is:

If you ever get this error, be sure to check that your raw MySQL is actually correct and STILL working!!!

想挽留 2024-07-27 02:52:44

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

A friend of mine had very much the same problem with the xampp 1.7.1 build. After replacing xampp/php/* by the 5.2.9-2 php.net build and copying all necessary files to xampp/apache/bin it worked fine.

窝囊感情。 2024-07-27 02:52:44

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

If you're using XAMPP 1.7.1, you just need to upgrade to 1.7.2.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文