2012-11-23 7 views
8

Oracle 11g (Red Hat)를 사용합니다.이상한 Oracle XMLType.getClobVal() 결과

CREATE TABLE PROJECTS 
(
    PROJECT_ID NUMBER(*, 0) NOT NULL, 
    PROJECT SYS.XMLTYPE, 
); 

(Windows에서) 오라클 SQL Developer를 사용하여 내가 할 : : 그것은 작동

select T1.PROJECT P1 from PROJECTS T1 where PROJECT_ID = '161'; 

나는 XMLType을 열 간단한 일반 테이블이있다. 나는 하나의 세포를 얻는다. 나는 두 번 클릭하고 전체 XML 파일을 다운로드 할 수 있습니다. 그것은 작동

select T1.PROJECT.getClobVal() P1 from PROJECTS T1 where PROJECT_ID = '161'; 

을 :

은 그 때 나는 CLOB로 결과를 얻기 위해 노력했다. 나는 하나의 세포를 얻는다. 나는 두 번 클릭하고 전체 텍스트를보고 그것을 복사 할 수 있습니다. 그러나 문제가 있습니다. 클립 보드에 복사 할 때 처음 4000 자 밖에 얻을 수 없습니다. 위치 4000에 0x00 문자가 있고 나머지 CLOB가 복사되지 않은 것으로 보입니다.

// ... 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에서 null 문자가 있기 때문에 나는이 단일 바이트를 제거 할 수 발생합니다 그러나 이것은 오히려 것 :

이를 확인하기 위해, 나는 자바에서 수표를 썼다 이상한 해결 방법.

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; 

자바 코드 :

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); 

XML로 두 개의 CLOB를 준비하십시오. 첫 번째는 null 문자이고 두 번째 문자는없는 문자입니다.

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>'; 

확인 널 (null)이 아닌 두 번째의 첫 번째 CLOB에있는 경우는 예상대로

DBMS_OUTPUT.put_line(DBMS_LOB.INSTR(P1, chr(0))); 
DBMS_OUTPUT.put_line(DBMS_LOB.INSTR(P2, chr(0))); 

우리는 얻을 것이다 :

14 
0 

봅니다 XMLTYPE에 처음 CLOB를 삽입 할 수 있습니다. 이거 작동 안 할거야. 해당 값을 삽입 할 수 없습니다.

insert into T1 (P) values (XMLTYPE(P1)); 

XMLTYPE에 두 번째 CLOB를 삽입하십시오. 작동합니다 :

insert into T1 (P) values (XMLTYPE(P2)); 

세 번째 CLOB에 삽입 된 XML을 읽으려고합니다.작동 여부 :

select T.P.getClobVal() into P3 from T1 T where rownum = 1; 

null이 있는지 확인하십시오. 그것은 데이터베이스 내부에 널 (null)이없고만큼 우리는 PL/SQL 컨텍스트에있는 한에는 널 (null)이 없다는 것을 솔기

DBMS_OUTPUT.put_line(DBMS_LOB.INSTR(P3, chr(0))); 

: NO 널 (null)이 없습니다. 그러나 나는 (Windows의 경우) SQL Developer에서 다음 SQL을 사용하거나 (레드햇 EE 및 Tomcat7에) 자바에서 나는 모든 반환 CLOB에에 위치 4000에 널 문자를받을 때 :

select T.P.getClobVal() from T1 T; 

BR, JM

+2

같은 오류 당신은 그것을'utl_file' 및 내용 모양을 어떻게 볼을 사용하여 파일에 쓸 수 있습니까? 또한'PROJECT에서 XMLType.getClobVal (PROJECT)를 선택하십시오; (기능적으로 다른 것은 아무것도 없음) – Annjawn

+1

열은 어떻게 채워 졌습니까? 다른 클라이언트가 똑같은 것을 본다면 문제는 검색과 관련이있을 것 같지 않은가요? 값의 서브 문자열을 선택하여 null char가 여전히 거기에 있는지 확인할 수도 있습니다. –

+0

utlfile.sql 및 prvtfile.plb를 실행했지만 여전히 utl_file (ORA-06521 : PL/SQL : 오류 매핑 기능)을 사용할 수 없습니다. 죄송합니다. – Mikosz

답변

6

이 아니 오라클 버그 (그것을 저장하고 \ 0 잘. 자사의 클라이언트/윈도우 버그 (다른 클라이언트와 마찬가지로 창 "NUL"에 관해서는 다르게 동작)

CHR (0) 아닌 를 검색 비 BLOB 내의 유효한 문자 (실제로는 XMLType을 어떻게 받아 들여 XML을 파싱 할 것인가에 대해 궁금합니다.)

\ 0은 C에서 문자열의 끝 (NUL 종결 자)을 나타 내기 위해 사용되며 일부 GUI는 해당 지점에서 문자열 처리를 중단합니다. 예를 들면 : 당신이 그것을 볼 수 있듯이, TOAD

SQL 개발자 요금 더 나은 :

![SQL> select 'IM VISIBLE'||chr(0)||'BUT IM INVISIBLE' 
    2 from dual 
    3/

'IMVISIBLE'||CHR(0)||'BUTIM 
--------------------------- 
IM VISIBLE BUT IM INVISIBLE 

SQL> 

아직 두꺼비는이에 비참하게 실패

SQL Developer

을하지만 당신은 그것의를 복사 할 경우 클립 보드는 문자를 최대로 복사합니다. 이 복사본 붙여 넣기 오류는 SQL 개발자의 잘못이 아니지만 Windows 클립 보드에 문제가있어 NUL이 제대로 붙여 넣을 수 없습니다.

당신은 단지 replace(T1.PROJECT.getClobVal(), chr(0), null)이 라운드를 얻을 때 SQL 개발자/윈도우 클립 보드를 사용해야합니다. CHR(0)이 존재 아닌지 확인하려면 결과 CLOB에 PL/SQL (안 자바)의 INSTR 테스트를 수행 - 그것은 .getClobVal() 전화 또는 아니라면 확인할 수있을만큼 쉬운

+0

응답 해 주셔서 감사합니다. 물론 클립 보드는 Windows의 문제이지만이 문제는 주된 문제가 아니며 테스트하는 방법 일뿐입니다. 왜 null이 있는지 알고 싶습니다 :). 그리고 나는 이것이 클라이언트의 문제가 아니라고 생각합니다. 이 테이블에서 SQL Developer 나 Blob in Java를 사용하여 단일 셀을 다운로드하면 null 문자가 없습니다. PROJECT.getClobVal()을 사용할 때만 나타납니다 (SQL Developer와 Java 모두). 그래서 나에게 그것은 getClobVal()이 결과의 위치 4000에 널 문자를 삽입한다는 것이다. – Mikosz

+2

아니요.이 작업을 수행하지 않아야하며, 그렇지 않은 경우라면 모든 단일 LOB에서 Oracle에 SR을 제출하는 것이 좋습니다. XMLType을 1MB를 넘는 파일에 광범위하게 사용하고 그 곳에서 chr (0)을 삭제하지 않았습니다 (10.2.0.4 + 11.2.0.2). – DazzaL

+0

감사합니다. 11.2.02 (Express Edition)도 사용합니다. 가장 간단한 테스트로 내 게시물을 편집했습니다. PL/SQL 외부로 전송 될 때 모든 getClobVal() 결과에 문제가 발생하는 것 같습니다. – Mikosz

1

.

그렇지 않으면 Oracle 클라이언트 설치시 손가락을 가리킬 것입니다.

+0

감사. PL/SQL에서 null이 없다는 것이 맞습니다. 결과가 외부로 전송 될 때 나타납니다. 두 개의 다른 클라이언트 (Windows의 경우 SQL Developer, Red Hat의 경우 Java)를 사용하기 때문에 이상합니다. – Mikosz

+2

JDBC 버그로 어려움을 겪을 수 있습니다. 귀하의 고객 모두가 Java 기반으로보고 있습니다. – Ben

3

Mikosz (Clob로 XMLType 값을 출력 할 때 4000 번째 문자 주위에 추가 'NUL'문자가 표시됨)에서 설명한 것과 똑같은 문제가 발생했습니다. SQLDeveloper에서 놀면서 흥미로운 해결 방법을 발견했습니다. 내 XMLType의 출력을 보려고했지만 4000 번째 문자로 스크롤하는 것이 싫어서 substr (...)에서 Clob 출력을 래핑하기 시작했습니다. 놀랍게도이 문제는 실제로 사라졌습니다. 이 내용을 자바 응용 프로그램에 통합하여 문제가 더 이상 나타나지 않고 추가 문자없이 Clob을 검색 할 수 있음을 확인했습니다. 나는 이것이 이상적인 해결 방법이 아니라는 것을 안다. 나는 아직도 그것이 작동하는 이유를 잘 모른다. (누군가 내가 그것을 설명 할 수 있다면 좋아할 것이다.) 그러나 나는 현재 일하고있는 것의 축약 된 예를 보여주고있다.

// Gets the xml contents 
String sql = "select substr(x.xml_content.getClobVal(), 0) as xml_content from my_table x"; 
ps = con.prepareStatement(sql); 
if(rs.next()) { 
    Reader reader = new BufferedReader(rs.getCharacterStream("xml_content")); 
    ... 
} 
+0

또한 몇 군데에서 XMLType 열을 사용한다는 점을 언급 할 필요가 있습니다. 스키마 (structured xml)를 등록한 곳에서는이 문제가 보이지 않습니다. 등록 된 스키마를 사용하지 않는 XMLType 열에 대해서는이 문제가 표시됩니다. – Mark

+0

제안 해 주신 데 대해 감사드립니다. 그것은 내 문제도 해결했다. 이것이 내가 적절한 해결책을 찾을 수있는 유일한 곳이었습니다. –

3

버그 : 14781609 XDB : XMLType.getclobval()은 XML이 CLOB에 저장 될 때 임시 LOB를 반환합니다. 패치 세트 11.2.0에서 수정.4

및 BLOB으로 읽는다면 다른 해결책 후

T1.PROJECT.getBlobVal(nls_charset_id('UTF8'))