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


Display Large Text Data Stored in CLOB

我正在将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显示它,我该怎么做?

Oracle+PHP食谱涵盖了这一点。你不必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";
}

dbms_lob.substr返回的值为null的原因是您传入的数字大于32767,如文档中所述

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

很难说你应该如何传递CLOB,因为你还没有提供htf.escape_sc的规范——如果它可以接受CLOB,那么就把CLOB作为一个整体传递进来。否则,您将不得不将CLOB组合起来,然后以某种方式将它们组合起来。

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

假设您使用的是Oracle 11.2或更早版本

您正在向DBMS_LOB.SUBSTR()传递CLOB,这意味着返回值的数据类型是VARCHAR2。您正在调用SELECT语句,这意味着您正在使用SQL中的返回值。

SQL中VARCHAR2的最大大小为4000字节。这与PL/SQL中VARCHAR2的最大大小32767字节形成了鲜明对比。

这就是为什么dbms_lob.substr(patch_audit, 4000)有效,而dbms_lob.substr(patch_audit, 4001)无效。

这些都是数据库中内置的硬限制,并且没有绕过它们的方法。如果您想在SQL中做到这一点,您必须将CLOB拆分为4000字节,并选择数据的多个部分。这意味着要遍历数据库中的CLOB。例如,您可以执行以下操作,计算CLOB中的数据量,并返回N行,每行有4000字节。

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写了以下内容(为您稍作修改)

$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将SQL中的VARCHAR2(注意不是VARCHAR)的大小增加到32767字节。为了使用此增量,您必须将MAX_STRING_SIZE初始化参数更改为EXTENDED。这是一个单向更改,无法撤消,可能会对您的应用程序产生巨大影响这是您想先测试的东西

在内部,扩展列无论如何都将存储为LOB,因此无论您喜欢与否,LOB处理都将由Oracle在后台完成,并且任何LOB限制可能(不知道)仍然适用。除非有真正的业务需求,否则只需要在PHP中进行一些LOB处理是值得的。