Показать большие текстовые данные, хранящиеся в CLOB

0

Я 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, как я могу это сделать?

  • 0
    с какими версиями oracle, oci, phpare вы работаете? в качестве общего руководства вы можете попробовать пример кода с длиной подстроки <2000. Рассматривали ли вы замену вашего оператора SQL на Anon PLSQL, который предлагает вам больше возможностей для управления содержимым clob?
Теги:
plsql
oci

3 ответа

1
Лучший ответ

Предполагая, что вы используете Oracle 11.2 или ранее

Вы передаете DBMS_LOB.SUBSTR() CLOB, что означает, что тип данных возвращаемого значения является VARCHAR2. Вы вызываете оператор SELECT, что означает, что вы используете возвращаемое значение в SQL.

Максимальный размер VARCHAR2 в SQL составляет 4000 байт. Это заметно отличается от максимального размера VARCHAR2 в PL/SQL, что составляет 32 767 байт.

Вот почему dbms_lob.substr(patch_audit, 4000) работает, но dbms_lob.substr(patch_audit, 4001) не будет.

Это жесткие ограничения, встроенные в базу данных, и вокруг них нет никакого пути. Если вы хотите сделать это в SQL, вам нужно разделить свой CLOB на 4000 байт и SELECT несколько частей данных. Это означает, что выполняется повторение через 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 будет хорошим местом для начала. Там есть несколько блогов, которые дают вам указание; Марк Фостер написал следующее (слегка измененное для вас)

$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 байт в SQL. Чтобы использовать это увеличение, вам необходимо изменить параметр инициализации MAX_STRING_SIZE на EXTENDED. Это одностороннее изменение, которое невозможно отменить и может сильно повлиять на ваше приложение. Это то, что вы хотите проверить первым.

Внутри расширенные столбцы будут сохраняться как LOB в любом случае, поэтому обработка LOB будет выполняться в фоновом режиме Oracle, нравится вам это или нет, и любые ограничения LOB могут (не знаю) все еще применяться. Если не существует подлинной деловой потребности, стоит просто выполнить некоторую обработку больших объектов в PHP.

  • 0
    Спасибо огромное ... Работает отлично. Я использую второй вариант бу таким образом echo $row['PATCH_AUDIT']->read($row['CHR']); где CHR - это ceil(dbms_lob.getlength(patch_audit))
3

В Повар-книге 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";
}
  • 0
    Новый пользователь, пожалуйста, используйте лучшее форматирование и попробуйте и лучше объясните «почему» при ответе, чтобы избежать пометки вашего вклада!
2

Причина, по которой значение, возвращаемое dbms_lob.substr равно null, состоит в том, что вы передаете число, превышающее 32767, как указано в документе documenatation

(32767 - максимальный размер переменной varchar2 в pl/sql, а поскольку версия CLOB dbms_lob.substr возвращает значение varchar2, это самый большой объем данных, которые могут быть возвращены и сохранены в переменной varchar2.)

Трудно сказать, как вы должны проходить этот CLOB, потому что вы не предоставили спецификацию для htf.escape_sc - если это может принять CLOB, тогда просто передайте clob как один. В противном случае вам придется разбить свой CLOB и каким-то образом их объединить.

ETA: Что касается исходной ошибки, это более чем вероятно из-за того, что в htf.escape_sc не может обрабатываться строка из 9999 байт или тот факт, что предел для varchar2 в выражении SQL составляет 4000 байт.

  • 0
    Операция приводит к ошибке при извлечении подстроки длиной 9999 <32767.
  • 0
    Я в порядке с первыми 32767 персонажами ...
Показать ещё 2 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню