Oracle LOB字段在PHP PDO_OCI下的解决方法
在我们的项目中,使用了Oracle做为数据库,PDO_OCI 作为数据库驱动。
项目中需要使用到CLOB字段来存储大量的数据,什么CLOB?我们先来看看Oracle官方的说明:
Oracle 提供了以下 LOB 类型:
* BLOB,用于存储二进制数据
* CLOB,用于使用数据库字符集编码存储字符数据
* NCLOB,用于使用国家字符集存储 Unicode 字符数据。 注意,您将在本文中使用的 PHP OCI8 扩展当前不支持 NCLOB。
* BFILE,用于引用存在于操作系统的文件系统中的外部文
在PHP中,如果你想把LOB字段当做普通的字段来存取数据,会导致程序出错,甚至包括 httpd.exe 的非法错误。PHP的 OCI8 扩展提供了这一字段的支持,但仅提供了 BLOB、CLOB、BFILE 三种类型字段的支持(使用方法请参考Oracle官方文档),但 PDO_OCI 并没有提供这样的支持,那么我们如何解决这个问题?
通过查询相关文档找到了以下的解决办法,由于项目中使用了 Zend_Framework,那么我就以 Zend_Framework 来解决问题,关于 PHP 中的使用方法请参考PHP手册 PDO Functions - Large Objects (LOBs) 一节:
$stmt->bindColumn('CONTENT', $content, PDO::PARAM_LOB);
$stmt->bindColumn('TITLE', $title, PDO::PARAM_STR);
$stmt->execute();
while ($row = $stmt->fetch(PDO::FETCH_BOUND)) {
echo '<h1>' . $title . '</h1>';
echo stream_get_contents($content) .'<hr />';
}
这里,使用到了 PDOStatement->bindColumn() 的方法,参阅相关资料得知:PDO::PARAM_LOB 可用于大文本对像字段,并使用 PDO::FETCH_BOUND 模式来进行存取,这是关于 PDO::PARAM_LOB 的说明:
PDO::PARAM_LOB (integer)
Represents the SQL large object data type.
这样的方法需要要求我们对所需要存取的字段都进行绑定,因此在例子中还使用了 PDO::PARAM_STR,但是那将会是一件非常烦琐的事。因此在项目中我们使用了 OCI8 的扩展来完成工作,这样工作变得简单很多,这也是Oracle官方给出的使用方法,取出数据时用到了一个 load() 的方法,至于更详细的用法就不在这里啰嗦了,大家可以自己参考一下文档。
相关的 Zend_Framework 代码如下:
$stmt->execute();
while ($row = $stmt->fetch(Zend_Db::FETCH_ASSOC)) {
echo '<h1>' . $row['TITLE'] . '</h1>';
echo $row['CONTENT']->load() . '<hr />';
}
显然,上面的方法要方便很多。
另外,Zend Framework 对 Oracle 的 OCI 驱动的 lastInsertId (sequence) 的BUG还没有修正,如果大家在使用中出现问题,请找到 Zend_Db_Adapter_Oracle 第218行的 $sequenceName .= ‘_seq’; ,修正为 $sequenceName .= ‘_SEQ’; 即可(PS:这里需要大写,也不知道他们到底有没有做过测试,估计是没有的)。

08月 14th, 2007 at 23:09:35
生日快乐啊,没有留言版,上这儿占一楼!
08月 16th, 2007 at 13:17:15
谢谢,不过那是农历的生日~~