Oracle 11g DB 返回流而不是字符串

Posted

技术标签:

【中文标题】Oracle 11g DB 返回流而不是字符串【英文标题】:Oracle 11g DB returning Streams instead of Strings 【发布时间】:2012-02-06 09:01:27 【问题描述】:

我在这里有一个新数据库,它是从 Oracle 10g 到 Oracle 11g 的升级版本 - 主要问题是 LOB 列,每次任何函数返回 LOB 作为结果时,新数据库都不会返回类似旧的做了:

旧数据库:

["C"]=>
string(23) "3874163,3874197,3874201"

新数据库:

["C"]=>
resource(182) of type (stream)

现在在读取流时,有时会出现引用不存在的流资源的错误,并且一切都失败了。我猜连接在没有读取流的情况下关闭,因此访问丢失。

例如,当更改语句以包含针对 varchar 的强制转换时:

CONVERT(VARCHAR, C, 120)

或者像这样:

SELECT TO_CHAR(FUNC())

该值再次作为字符串返回,但这并不是真正的最佳解决方案,因为每个语句都需要更改。

是否有任何方法/选项可以防止 LOB 作为流传输,而是像 Oracle 10g 中那样作为字符串传输?

编辑: 我们正在使用 oci 函数集进行 db 访问。

【问题讨论】:

数据库元数据是否发生了变化? 11g 有一些新的 LOB 选项,例如 SecureFiles。你能比较一下USER_LOBS在10g和11g之间的区别吗? @jonearles USER_LOBS 是什么?我对USER_JOBS 很熟悉,当我使用USER_LOBS 访问谷歌时,这几乎是我能找到的所有内容。我认为元数据没有改变,但我会检查一下。 您专门使用哪些 oci 函数进行读取?另外,请参阅此处了解 oci 10g/11g 差异和示例docs.oracle.com/cd/B28359_01/appdev.111/b28395/oci07lob.htm 我们这里的代码中大部分都是oci_fetch_row()... 【参考方案1】:

这不是一个真正的答案,但我希望有一些帮助。

貌似10g和11g的LOB的返回方式有点小差别,11g以下有一些说明当LOB超过一定值时从btyes到byteStreams的转换,在JDBC参考手册(我知道这不会影响 OCI 调用,因为它们使用不同的驱动程序集)。

从我在 php 中的 OCI8 函数方面可以看出,获取函数的默认操作是 LOB 作为引用返回,需要使用 ->read() ->load() 等函数访问(参见 @ 987654321@ - 关于模式和默认值)。

现在我不知道您是否使用 OCI 功能来访问您的 oracle 系统,因为您的问题中没有指定它。

如果您可以让我们知道您是否重新编译了 php 或使用较新的客户端版本更新了 oracle 驱动程序,那么有助于解决此问题的其他几个项目。

我知道这不是一个完整的解决方案,但如果您使用 oci_fetch_* 返回行,请在调用 OCI_RETURN_LOBS 时添加第二个参数,这将导致获取返回 LOB 字段的字符串而不是对流的引用,或使用 $variable["C"]->load() 访问此 LOB,这将导致它加载完整的流并像普通字符串一样工作。

希望这会有所帮助。

【讨论】:

似乎(根据文档)只有oci_fetch_array() 支持该参数。该代码主要使用 oci_fetch_row() 不支持的地方:( 如果您可以更改代码,您可以将 oci_fetch_row() 替换为 oci_fetch_array($rs,OCI_NUM+OCI_RETURN_NULLS+OCI_RETURN_LOBS) ,这将为您提供相同的功能,当然这可以让我进行很多更改根据它的使用量,另一个选项是使用 override_function() 命令 (php.net/manual/en/function.override-function.php) 在公共包含文件中重载 oci_fetch_row 函数 函数重载可能是目前最好的答案......我不太喜欢它,因为重载标准功能感觉很脏,但这可能是最安全的方法。 好吧,让我们再等 1-2 天,如果有人想出一个更好的解决方案,也许有一个配置选项,否则我认为你会得到正确的答案和赏金 - 已经有很大帮助了 :) 在做这样的事情之前最好还是谨慎行事:)。【参考方案2】:

如果您使用 PDO,您可能需要将 PDO::PARAM_LOB 更改为 PDO::PARAM_STR。例如结合绑定列:

$statement->bindColumn(1, $as_string, PDO::PARAM_STR, 256);
$statement->bindColumn(1, $as_lob, PDO::PARAM_LOB);

【讨论】:

丑陋的事情是我们仍然需要识别每个语句中的每个 lob(不仅仅是语句本身,而是绑定)并调整它。不过,谢谢您的回答。【参考方案3】:

使用 LOB 时,您必须使用 OCI::read 或 OCI::load 来获取其内容。

[...]
$row = oci_fetch_assoc($result);

$lobContents = $row['LOB_COLUMN']->load(); //fetches the whole LOB
//or
while ($buffer = $row['LOB_COLUMN']->read(4096))  //sequential read
   $lobContents .= $buffer;

【讨论】:

是的,但这意味着对遗留代码进行大量更改。这不是我真正需要的。查看问题。

以上是关于Oracle 11g DB 返回流而不是字符串的主要内容,如果未能解决你的问题,请参考以下文章

在 svm-predict 命令中使用字符串流而不是文件流

oracle 11g管理口令设了很多都无效,怎么办,[INS-32010] 字符串包含无效字符。

安装oracle 11g出现“ORA-00911:无效字符”怎么办?

oracle 11g 没有US7ASCII字符集么?在选择字符集的时候要选择哪一呀?

Oracle 11g修改字符集AL32UTF8为ZHS16GBK

Oracle 11g静默安装后lsnrctl文件0字节