显示CLOB中存储的大型文本数据

时间:2015-02-11 15:35:15

标签: php sql oracle plsql oci

我正在查询我的clob

$patch_log= oci_parse($conn_prs, "select htf.escape_sc(DBMS_LOB.substr(patch_audit, 9999)) as patch_log
from patch_files where bug_id = 12345"); 
...
echo $row['PATCH_LOG'];

我收到错误ORA-06502: PL/SQL: numeric or value error: character string buffer too small

因此,当我将其更改为htf.escape_sc(DBMS_LOB.substr(patch_audit, 4000 ))时,查询运行正常,但首先返回4000.

该列列中的字符数在一种情况下为49979个字符,有时甚至更多。

我需要用php显示它,我该怎么办?

3 个答案:

答案 0 :(得分:3)

Oracle + PHP Cookbook涵盖了这一点。你不得substr吊球。然后在php中调用->load()来获取整个内容。

来自:http://www.oracle.com/technetwork/articles/fuecks-lobs-095315.html

$sql = "SELECT * FROM mylobs ORDER BY Id";

$stmt = oci_parse($conn, $sql);

oci_execute($stmt) or die ("Unable to execute query\n");

while ( $row = oci_fetch_assoc($stmt) ) {
    print "ID: {$row['ID']}, ";

    // Call the load() method to get the contents of the LOB
    print $row['MYLOB']->load()."\n";
}

答案 1 :(得分:2)

dbms_lob.substr返回的值为null的原因是因为您传递的数字大于32767,如the documenatation

(32767是pl / sql中varchar2变量的最大大小,并且由于dbms版本的dbms_lob.substr返回varchar2值,这是可以返回并存储在一个varchar2中的最大数据量。 varchar2变量。)

很难说你应该如何通过CLOB,因为你还没有提供htf.escape_sc的规范 - 如果它可以接受CLOB,那么只需要传递clob作为一个。否则,你将不得不将你的CLOB组合起来,然后以某种方式将它们组合起来。

ETA:至于原始错误,它很可能是由于htf.escape_sc中的某些内容无法处理9999字节的字符串,或者是因为varchar2的限制SQL语句是4000个字节。

答案 2 :(得分:1)

假设您正在使用Oracle 11.2或更早版本

您正在通过DBMS_LOB.SUBSTR() CLOB,这意味着the data type of the returned value是VARCHAR2。您正在调用SELECT语句,这意味着您正在使用SQL中返回的值。

maximum size of a VARCHAR2 in SQL是4,000个字节。这与maximum size of a VARCHAR2 in PL/SQL形成鲜明对比,后者为32,767字节。

这就是为什么dbms_lob.substr(patch_audit, 4000)有效,但dbms_lob.substr(patch_audit, 4001)不会。

这些是内置于数据库中的硬限制,并且有没有方式。如果要在SQL中执行此操作,则必须在4,000字节上拆分CLOB并选择数据的多个部分。这意味着遍历数据库中的CLOB。例如,您可以执行以下操作,它可以计算CLOB中的数据量并返回N行,每行包含4,000个字节。

with my_clob as (
 select patch_audit 
   from patch_files 
  where bug_id = 12345 
        )
 select dbms_lob.substr(patch_audit, 4000, (level - 1) * 4000 + 1)
   from my_clob
connect by level <= ceil(dbms_lob.getlength(patch_audit) / 4000)

不要一次在多个CLOB上执行此操作,否则您将返回大量数据,并且创建层次结构后,CONNECT BY将评估WHERE子句所以子选择必要

,您可以选择CLOB并在PHP中解析它。我不知道任何PHP,但OCI-Lob::read似乎是一个很好的起点。那里有一些博客可以给你一个指示; Mark Foster wrote以下内容(稍作修改)

$result = oci_execute($patch_log);
    if($result !== false){
        while($row = oci_fetch_assoc($patch_log)){
            echo $row['PATCH_LOG']->read(2000);
        }
    }

假设您正在使用Oracle 12.1或更高版本

在12c中,Oracle将VARCHAR2(注意不是VARCHAR)的大小增加到32,767 bytes in SQL。要使用此增量,您必须将MAX_STRING_SIZE初始化参数更改为EXTENDED。这是单向更改,无法撤消,可能会对您的应用程序产生巨大影响。 您要先测试

Internally the extended columns will be stored as LOBs anyway,所以LOB处理将由Oracle在后台完成,无论你喜不喜欢 - 并且任何LOB限制可能(不知道)仍然适用。除非有真正的业务需要,否则值得在PHP中进行一些LOB处理。