PHP stream_get_contents()奇怪地从数据库中读取LOB

时间:2016-12-29 21:39:07

标签: php oracle pdo

我在具有类似CLOB数据的表中有2条记录。其中每一个都是从查询中解析出来的,然后通过php在一个循环中读取一个字符串,对着返回的PDO :: FETCH_ASSOC

在查询返回结果后,它看起来像这样:

ID   |   NAME   |   DESCRIPTION   |   LOB_DEFINITION
4409     foo        blah blah         long text that is stored in a lob ~ 5k characters
4410     foobar     blah blah         some other long text stored in a lob ~ 5k characters

我的问题是,一旦我开始循环并从LOB中读取内容,它们就不会“重置”所以,读取的任何和所有对象都将具有与它读取的第一个LOB相同的值:

类似的东西:

foreach($result as $r) {
$lob = stream_get_contents($r['LOB_DEFINITION']);
echo $r['ID'].'-<i>'.$lob.'</i><HR>';
unset($lob);
}

会产生如下输出:

4409- 长文本存储在一个高约5k个字符

4410- 长文本存储在一个高约5k个字符

而不是我期望获得的内容:

4409- 长文本存储在一个高约5k个字符

4410- 一些其他长文本存储在一个高约5k个字符

我也检查了资源ID,它们是不同的资源......

我在这里不知所措......有没有人对这个问题有所了解?

2 个答案:

答案 0 :(得分:1)

几个小时的研究得出以下结论:

从oracle表返回多记录集,其中一列是clob数据类型,将导致检索到的最后一条记录clob成为检索到的所有clob的值。这就是造成上述行为的原因。

我最终要解决的问题是:

选择我计划使用clobs的所有记录(不是clobs本身,只是记录ID)

然后,我循环遍历这些记录ID,并使用单独的数据库调用,使用主键逐个处理CLOB数据以提取记录,以确保回送数据不超过1条记录。所以从本质上说现在正在发生的事情:

从表中检索我想要使用的所有clob的ID后,我就这样解析了它们:

foreach($result as $r) {
  $query = 'select lob_definition from mytable where id = '.$r;
  $lobresult = oracleConnection->query($query)->fetchAll(FETCH_COLUM);
    $lob = stream_get_contents($lobresult);
    echo $r['ID'].'-<i>'.$lob.'</i><HR>';
    unset($lob);
}

这种效果已经解决了我的问题(所有这些都是用各种方法抽象出来的,但基本上就是发生了什么。

答案 1 :(得分:0)

这是由于PDO(OCI):: fetchAll中的长期错误 https://bugs.php.net/bug.php?id=46728

您不必像Jeffs答案那样对每一行进行单独的查询。您只需要避免fetchAll。根据错误说明中建议的解决方法,我正在使用以下函数来获取所有LOB:

function fetchAllLOB(PDOStatement $stmt): array
{
    $result = [];
    while ($row = $stmt->fetch()) {
        foreach ($row as $name => $value) {
            if (is_resource($value)) {
                $row[$name] = stream_get_contents($value);
            }
        }
        $result[] = $row;
    }
    return $result;
}