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 返回流而不是字符串的主要内容,如果未能解决你的问题,请参考以下文章
oracle 11g管理口令设了很多都无效,怎么办,[INS-32010] 字符串包含无效字符。
安装oracle 11g出现“ORA-00911:无效字符”怎么办?
oracle 11g 没有US7ASCII字符集么?在选择字符集的时候要选择哪一呀?