Я использую Oracle 11g (на Red Hat). У меня есть простая обычная таблица со столбцом XMLType:
CREATE TABLE PROJECTS
(
PROJECT_ID NUMBER(*, 0) NOT NULL,
PROJECT SYS.XMLTYPE,
);
Используя Oracle SQL Developer (в Windows), я делаю:
select T1.PROJECT P1 from PROJECTS T1 where PROJECT_ID = '161';
Оно работает. Я получаю одну ячейку. Я могу дважды щелкнуть и загрузить весь XML-файл.
Затем я попытался получить результат в виде CLOB:
select T1.PROJECT.getClobVal() P1 from PROJECTS T1 where PROJECT_ID = '161';
Оно работает. Я получаю одну ячейку. Я могу дважды щелкнуть, увидеть весь текст и скопировать его. Но есть проблема. Когда я копирую его в буфер обмена, я получаю только первые 4000 символов. Кажется, что в позиции 4000 есть символ 0x00, а остальная часть CLOB не копируется.
Чтобы подтвердить это, я написал проверку в java:
// ... create projectsStatement
Reader reader = projectsStatement.getResultSet().getCharacterStream( "P1" );
BufferedReader bf = new BufferedReader( reader );
char buffer[] = new char[ 1024 ];
int count = 0;
int globalPos = 0;
while ( ( count = bf.read( buffer, 0, buffer.length ) ) > 0 )
for ( int i = 0; i < count; i++, globalPos++ )
if ( buffer[ i ] == 0 )
throw new Exception( "ZERO at " + Integer.toString(globalPos) );
Reader возвращает полный XML, но мое исключение выбрасывается, потому что в позиции 4000 есть нулевой символ. Я мог бы удалить этот единственный байт, но это было бы довольно странным обходным путем.
Я там не использую VARCHAR2, но, может быть, эта проблема как-то связана с ограничением VARCHAR2 (4000 байт)? Есть другие идеи? Это ошибка Oracle или мне что-то не хватает?
-------------------- Редактировать --------------------
Значение было вставлено с помощью следующей хранимой процедуры:
create or replace
procedure addProject( projectId number, projectXml clob ) is
sqlstr varchar2(2000);
begin
sqlstr := 'insert into projects ( PROJECT_ID, PROJECT ) VALUES ( :projectId, :projectData )';
execute immediate sqlstr using projectId, XMLTYPE(projectXml);
end;
Код Java для его вызова:
try ( CallableStatement cs = connection.prepareCall("{call addProject(?,?)}") )
{
cs.setInt( "projectId", projectId );
cs.setCharacterStream( "projectXml", new StringReader(xmlStr) , xmlStr.length() );
cs.execute();
}
-------------------- Редактировать. ПРОСТОЙ ТЕСТ --------------------
Я буду использовать все, что узнал из ваших ответов. Создайте простейшую таблицу:
create table T1 ( P XMLTYPE );
Подготовьте два CLOB с XML. Первый с нулевым символом, второй без.
declare
P1 clob;
P2 clob;
P3 clob;
begin
P1 := '<a>';
P2 := '<a>';
FOR i IN 1..1000 LOOP
P1 := P1 || '0123456789' || chr(0);
P2 := P2 || '0123456789';
END LOOP;
P1 := P1 || '</a>';
P2 := P2 || '</a>';
Проверьте, находится ли null в первом CLOB, а не во втором:
DBMS_OUTPUT.put_line( DBMS_LOB.INSTR( P1, chr(0) ) );
DBMS_OUTPUT.put_line( DBMS_LOB.INSTR( P2, chr(0) ) );
Получим ожидаемо:
14
0
Попробуйте вставить первый CLOB в XMLTYPE. Он не будет работать. Невозможно вставить такое значение:
insert into T1 ( P ) values ( XMLTYPE( P1 ) );
Попробуйте вставить второй CLOB в XMLTYPE. Это будет работать:
insert into T1 ( P ) values ( XMLTYPE( P2 ) );
Попробуйте прочитать вставленный XML в третий CLOB. Это будет работать:
select T.P.getClobVal() into P3 from T1 T where rownum = 1;
Проверьте, есть ли нуль. НЕТ НУЛЯ:
DBMS_OUTPUT.put_line( DBMS_LOB.INSTR( P3, chr(0) ) );
Кажется, что внутри базы данных нет нуля, и пока мы находимся в контексте PL / SQL, нет нуля. Но когда я пытаюсь использовать следующий SQL в SQL Developer (в Windows) или в Java (в Red Hat EE и Tomcat7), я получаю нулевой символ в позиции 4000 во всех возвращаемых CLOB:
select T.P.getClobVal() from T1 T;
BR, JM
utl_file
и посмотреть, как выглядит содержимое? Вы тоже можете попробоватьselect XMLType.getClobVal(PROJECT) from PROJECTS;
? (Хотя ничего функционально отличного) - person AnBisw   schedule 24.11.2012