PHP-7:mysqli查询#2返回没有结果,除非查询#1关闭 - 为什么?

时间:2016-05-19 16:41:51

标签: php mysqli

我有一些PHP-7代码(使用“mysqli”),当然,它想要执行多个查询并滚动它们的结果集。但是,我发现除非 close()前一个语句,下一个语句......虽然它似乎运行...但没有产生任何结果。

(也就是说,受影响的行数将返回零。)

我无法解释这种行为。 。 。

(顺便说一下,必要的功能似乎是语句 - 关闭。不处理结果集。)

= = =

认为这与引用的问题重复,因为答案显然是使用 mysqli_multi_query 而我不是。我在三个连续的循环中执行三个不同的,不相关的查询。

如果你建议我“累积多个结果集”并且只是不知道它,但我不相信这是我的用例。我所见过的那些API调用的唯一引用,特别是使用多个查询调用,我使用。但我会很高兴来了解我在这里错了。

代码示例

echo "Test: simple query.\n"; 
$iter = DB::query('select count(*) from address_book'); 
echo "Query returned " . $iter->rowCount() . " results.\n"; 

foreach ($iter as $v) 
    print_r($v); 

$iter = null;  // WITHOUT this, next stmt will produce no results.

echo "Test: simple query again.\n"; 
$iter = DB::query('select count(*) from address_book'); 
echo "Query returned " . $iter->rowCount() . " results.\n"; 

foreach ($iter as $v) 
    print_r($v); 

 $iter = null;  // DITTO ...

以下是迭代器支持函数:

// Retrieve current element
public function current () {
    if ($this->current == null) {
        $this->current = $this->fetch();
    }

    return $this->current;
}

// Retrieve value of next element
public function next () {
    $this->current = $this->fetch();
    $this->position++;

    return $this->current;
}


// Retrieve key of current element
public function key () {
    return $this->position;
}


// Check if current position is valid - used to stop an iterator
public function valid () {
    if ($this->position >= 0 && $this->position < $this->rowCount()) {
        return true;
    }

    return false;
}

// Rewind the iterator to the first element
public function rewind () {
    $this->checkNoResultException();
    $this->position = 0;
    $this->_result->data_seek(0);
}

这是'查询':

public static function query ( $stmt, $params = null ) {
    $objInstance = self::getInstance();

    try {
        if ($params === null) {
            return $objInstance->query($stmt);
        }
        else {
            return $objInstance->prepare($stmt)->execute($params);
        }
    }
    catch(MysqliException $e) {
        error_log("(DB::query) Query failed: " . $e->getMessage());
        die("SQL Query failed -- see log");
    }
}

2 个答案:

答案 0 :(得分:0)

关闭:我结束了“解决”这个问题......有点......通过改变类来对光标做fetch_all(),存储整个结果 - 设置在一个数组中,然后立即关闭句柄本身。因为我知道我总是在宽大的机器上处理合理大小的结果集,这实际上让我有效地规避了几个......“怪异。”

我从来没有得到令人满意的解释,为什么观察到的行为首先发生。 。

答案 1 :(得分:-1)

我将“回答”这个问题,不是因为它真的得到回答,而是......首先,给RiggsFolly一个“大声喊叫”,立刻跳进去帮助18个评论的交流如上所述。 非常,非常感谢他的敏捷和坚持。

问题尚未完全解决,但我在上面显示的测试用例代码中发现了许多有趣的事情:

•如果您如上所示设置$iter = null;,则问题可靠地消失...即使将变量设置为null也会使PHP无法执行垃圾收集立即。 (但是,我确实看到了析构函数被立即调用!)

•如果您调用$iter->close(),我的代码将关闭结果句柄和语句句柄,问题就会消失。

(!)如果您使用不同的变量来执行第二个查询,问题就会消失! (换句话说,将$iter更改为$iter1$iter2

^^^ 这个最后一个要点非常有趣,意外! ^^^

作为预防措施,我还在statement-object上添加了一个显式__destruct方法来显式调用它的close()方法,如果存在,则显式地销毁语句和结果句柄,只要清理确实发生了。这不会影响结果,但我觉得它让我觉得有点温暖和模糊。 。 。

我欢迎任何关于这个问题的进一步见解,因为它肯定会让我感到困惑。 :-D