Показать большие текстовые данные, хранящиеся в 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 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 байт и выбрать несколько частей данных. Это означает итерацию 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, Это одностороннее изменение, которое не может быть отменено и может оказать большое влияние на ваше приложение. Это то, что вы хотите проверить первый.

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

1

Другие решения

Поваренная книга 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";
}
3

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

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

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

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

2
По вопросам рекламы [email protected]