Używam Oracle 11g (w Red Hat). Mam proste regularne tabelę z kolumny XMLType:Dziwne Oracle XMLType.getClobVal() wynik
CREATE TABLE PROJECTS
(
PROJECT_ID NUMBER(*, 0) NOT NULL,
PROJECT SYS.XMLTYPE,
);
Używanie Oracle SQL Developer (Windows) robię:
select T1.PROJECT P1 from PROJECTS T1 where PROJECT_ID = '161';
to działa. Dostaję jedną komórkę. Mogę dwukrotnie kliknąć i pobrać cały plik XML.
Potem starał się prowadzić jak CLOB:
select T1.PROJECT.getClobVal() P1 from PROJECTS T1 where PROJECT_ID = '161';
to działa. Dostaję jedną komórkę. Potrafię podwójnie kliknąć i zobaczyć cały tekst i skopiować go. Ale jest problem. Po skopiowaniu do schowka otrzymuję tylko pierwsze 4000 znaków. Wydaje się, że na pozycji 4000 znajduje się znak 0x00, a reszta elementu CLOB nie jest kopiowana.
Aby to potwierdzić, napisałem czek w 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));
czytnik powraca pełną XML ale mój jest wyjątek, ponieważ nie jest null postać w pozycji 4000. mogę usunąć ten jeden bajt, ale to byłoby raczej dziwne obejście.
Nie używam VARCHAR2, ale może ten problem jest w jakiś sposób związany z ograniczeniem VARCHAR2 (4000 bajtów)? Jakieś inne pomysły? Czy to jest błąd Oracle, czy też czegoś mi brakuje?
-------------------- Edycja --------------------
Wartość wstawiono używając następującą procedurę przechowywaną:
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;
kodu Java zwykli nazywać ją:
try (CallableStatement cs = connection.prepareCall("{call addProject(?,?)}"))
{
cs.setInt("projectId", projectId);
cs.setCharacterStream("projectXml", new StringReader(xmlStr) , xmlStr.length());
cs.execute();
}
-------------------- Edycja. PROSTY TEST --------------------
Wykorzystam wszystko, czego nauczyłem się z twoich odpowiedzi. Utwórz najprostszy tabelę:
create table T1 (P XMLTYPE);
Przygotuj dwa obiekty CLOB z plikami XML. Najpierw z charakterem zerowym, drugi bez.
declare
P1 clob;
P2 clob;
P3 clob;
begin
P1 := '<a>';
P2 := '<a>';
FOR i IN 1..1000 LOOP
P1 := P1 || '' || chr(0);
P2 := P2 || '';
END LOOP;
P1 := P1 || '</a>';
P2 := P2 || '</a>';
Sprawdź, czy null jest w pierwszej CLOB, a nie w drugim:
DBMS_OUTPUT.put_line(DBMS_LOB.INSTR(P1, chr(0)));
DBMS_OUTPUT.put_line(DBMS_LOB.INSTR(P2, chr(0)));
Będziemy się zgodnie z oczekiwaniami:
14
0
próby wstawienia pierwszego CLOB do XMLType. To nie zadziała. Nie można wstawić takiej wartości:
insert into T1 (P) values (XMLTYPE(P1));
Spróbuj wstawić drugi obiekt CLOB do XMLTYPE. to będzie działać:
insert into T1 (P) values (XMLTYPE(P2));
spróbować odczytać wprowadzone dane XML do trzeciego CLOB.Będzie działać:
select T.P.getClobVal() into P3 from T1 T where rownum = 1;
Sprawdź, czy jest pusty. NIE ma wartość null:
DBMS_OUTPUT.put_line(DBMS_LOB.INSTR(P3, chr(0)));
szwy, że nie ma zerowy wewnątrz bazy danych i jak długo jesteśmy w kontekście PL/SQL, nie ma wartość null. Ale gdy próbuję użyć następujących SQL w SQL Developer (w systemie Windows) lub w Java (Red Hat EE i Tomcat7) otrzymuję znak null w pozycji 4000 we wszystkich zwróconych CLOB:
select T.P.getClobVal() from T1 T;
Br JM
można zapisywać do pliku przy użyciu 'utl_file' i zobaczyć, jak zawartość wygląda? Czy możesz również spróbować 'select XMLType.getClobVal (PROJECT) from PROJECTS;'? (Nic funkcjonalnie innego) – Annjawn
Jak było wypełnione columm? Czy na pewno problem polega na pobieraniu - brzmi to nieprawdopodobnie, jeśli różni klienci widzą to samo. Możesz także wybrać podzwanie wartości i sprawdzić, czy znak null nadal tam jest. –
Uruchomiłem utlfile.sql i prvtfile.plb, ale nadal nie mogę użyć pliku utl_file (ORA-06521: PL/SQL: funkcja mapowania błędów), przepraszam. – Mikosz