Я 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, как я могу это сделать?
Вы передаете 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);
}
}
В 12c Oracle увеличил размер VARCHAR2 (примечание не VARCHAR) до 32 767 байт в SQL. Чтобы использовать это увеличение, вам необходимо изменить параметр инициализации MAX_STRING_SIZE
на EXTENDED
. Это одностороннее изменение, которое невозможно отменить и может сильно повлиять на ваше приложение. Это то, что вы хотите проверить первым.
Внутри расширенные столбцы будут сохраняться как LOB в любом случае, поэтому обработка LOB будет выполняться в фоновом режиме Oracle, нравится вам это или нет, и любые ограничения LOB могут (не знаю) все еще применяться. Если не существует подлинной деловой потребности, стоит просто выполнить некоторую обработку больших объектов в PHP.
echo $row['PATCH_AUDIT']->read($row['CHR']);
где CHR - это ceil(dbms_lob.getlength(patch_audit))
В Повар-книге 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, как указано в документе 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 байт.