php 对一个请求执行无缓冲查询

a5g8bdjr  于 2023-01-16  发布在  PHP
关注(0)|答案(5)|浏览(169)

我希望只对某些请求执行无缓冲查询。
在MySQL中我是这样做的:

$req = mysql_unbuffered_query('SELECT * FROM forum_topics
ORDER BY (topic_id/topic_stick) DESC, topic_last_post DESC');
while($data = mysql_fetch_assoc($req)) {
   // display results...
}

我看了PHP文档,根据pdo中的文档,我们必须按照这种方式进行无缓冲查询:

$pdo = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass');
$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

$uresult = $pdo->query("SELECT Name FROM City");

if ($uresult) {
   while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) {
       echo $row['Name'] . PHP_EOL;
   }
}

但是,是否可以只对“forum_topics”表结果执行无缓冲操作,而不将所有pdo示例设置为无缓冲?

0sgqnhkj

0sgqnhkj1#

回复,这不工作,我获得一个错误,而使用您的方法:

    • 数据库状态[IM001]:驱动程序不支持此功能:此驱动程序不支持设置属性**

怎么啦?

    • 编辑:**我在www.example.com文档中找到了解决方案。php.net doc.

如果您使用此选项:

$sth->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

它不工作。
但如果在prepare()中将其设置为数组,则可以正常工作。

$sth = $pdo->prepare('SELECT * FROM my_table',
array(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY => false));

我希望这能帮助那些还没有找到解决这个问题的方法的人。

1l5u6lss

1l5u6lss2#

您可以设置PDO连接的属性:

$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

然后运行这个特定的查询哪个结果需要被取消缓冲,

$uresult = $pdo->query("SELECT Name FROM City");
while ($row = $uresult->fetch(PDO::FETCH_ASSOC)) {
    echo $row['Name'] . PHP_EOL;
}

然后将属性设置回

$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
au9on6nz

au9on6nz3#

这里的答案都是试图在statment * 上使用MYSQL_ATTR_USE_BUFFERED_QUERY *。而且MYSQL_ATTR_USE_BUFFERED_QUERY只在整个连接上操作,正如您似乎已经发现的那样。
MYSQL_ATTR_USE_BUFFERED_QUERY也只在使用mysqlnd库时才能工作--如果使用的是PHP 7或更高版本,这种可能性很大。
您最初将连接设置为无缓冲的方法是正确的,也是唯一一个 * 实际上 * 有效的方法。

$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, false);

但是,是否可以只对"forum_topics"表结果执行无缓冲操作,而不将所有pdo示例设置为无缓冲?
不是所有的"示例"都被设置为unbuffered,只有那个连接的"示例"才是。你可以简单地立即将缓冲重新设置为ala:

$pdo->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);

问题在于,在非缓冲模式下,每个连接只能迭代一个查询,因此在检索完第一个集合中的所有数据之前,无法运行第二个查询。
通常,您只想对非常大的数据集使用无缓冲查询。我建议您对数据库使用第二个PDO连接,专门用于 * 仅 * 在需要运行无缓冲查询时打开的无缓冲查询,即:

$pdo2 = new PDO("mysql:host=localhost;dbname=world", 'my_user', 'my_pass');
$pdo2->setAttribute(PDO::MYSQL_ATTR_USE_BUFFERED_QUERY, true);
c2e8gylq

c2e8gylq4#

MySQL不实现语句级属性设置。

资料来源:

下面是您的错误消息:

  • https://github.com/php/php-src/blob/master/ext/pdo/pdo_stmt.c#L1630
pdo_raise_impl_error(stmt->dbh, stmt, "IM001", "This driver doesn't support setting attributes");

在上述stmt->methods->set_attribute上检查上述条件。
上面定义了stmt->methods,并且在以下位置声明了类型:

  • https://github.com/php/php-src/blob/5d6e923d46a89fe9cd8fb6c3a6da675aa67197b4/ext/pdo/php_pdo_driver.h#L417
struct pdo_stmt_methods

set_attribute参数是第10个结构项。
下面是MySQL PDO的实现,语句方法定义如下:

  • https://github.com/php/php-src/blob/2ba4fb126391c578d20d859c841c4d31cd14adef/ext/pdo_mysql/mysql_statement.c#L935
NULL, /* set_attr */

这表明MySQL PDO模块确实实现了该特性。

讨论:

我已经查看了其他扩展。而且只有Firebird PDO数据库模块支持该特性。

cmssoen2

cmssoen25#

作为一种变通方法,如果我的查询是SELECT,我不调用fetchAll函数。

$query = 'SELECT ...... ';
                $arr = explode(' ', $query);
                $query_type = strtolower($arr[0]);
                if ($query_type == 'select') {
                    $query_response = $query_prepare->fetchAll(PDO::FETCH_ASSOC);
                } else {
                    $query_response = '';
                }

另外,当你在查询的开头不小心放了一个空格时,你必须处理这个异常。希望这对你有帮助。

相关问题