이상한 Oracle XMLType.getClobVal() 결과가 발생했습니다.
저는 (Red Hat에서) Oracle 11g을 사용합니다.XMLType 열이 있는 간단한 정규 테이블이 있습니다.
CREATE TABLE PROJECTS
(
PROJECT_ID NUMBER(*, 0) NOT NULL,
PROJECT SYS.XMLTYPE,
);
Windows에서 Oracle SQL Developer를 사용하면 다음 작업을 수행할 수 있습니다.
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에 check in 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에 null 문자가 있기 때문에 예외가 발생합니다.저는 이 바이트 하나를 제거할 수는 있지만 이것은 오히려 이상한 해결책이 될 것입니다.
거기서 VARCHAR2를 사용하지 않지만 이 문제가 어떻게든 VARCHAR2 제한(4000바이트)과 관련이 있는 것은 아닐까요?다른 생각 있나요?오라클 버그인가요, 아니면 제가 뭔가를 놓치고 있는 건가요?
-------------------- 편집 ----------------------------------
다음 저장 프로시저를 사용하여 값을 삽입했습니다.
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 문자, 두 번째는 null 문자입니다.
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에 있고 두 번째 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;
Null이 있는지 확인합니다.null이 없습니다.
DBMS_OUTPUT.put_line( DBMS_LOB.INSTR( P3, chr(0) ) );
데이터베이스 내부에 null이 없는 것으로 보이며 PL/SQL 컨텍스트에 있는 한 null은 없습니다.그러나 SQL 개발자에서 다음 SQL을 사용하려고 할 때(Windows에서) 또는 Java에서(Red Hat EE 및 Tomcat7에서) 반환되는 모든 CLOB에서 위치 4000에 null 문자가 표시됩니다.
select T.P.getClobVal() from T1 T;
BR, JM
오라클 버그가 아닙니다. \0을 저장하고 검색합니다.클라이언트/윈도우 버그입니다. ("NUL"에 대해서는 윈도우와 다르게 클라이언트가 동작함)
chr(0)은 실제로 비블롭에서 유효한 문자가 아닙니다. 일반적으로 구문 분석하지 않는 것처럼 처음부터 XMLType이 이를 받아들이도록 하는 방법이 궁금합니다.
\0은 C에서 문자열의 끝(NUL 터미네이터)을 나타내기 위해 사용되며, 일부 GUI는 해당 시점에서 문자열 처리를 중지합니다.예를 들어,

보다시피 sql 개발자의 요금이 더 좋습니다.

복사하면 클립보드가 null 문자로만 복사합니다.이 복사 붙여넣기 오류는 SQL developers fault는 아니지만 NUL을 제대로 붙여넣지 못하는 윈도우 클립보드의 문제입니다.
ㅇreplace(T1.PROJECT.getClobVal(), chr(0), null)sql developer/합니다를 할 때 이합니다.
Mikosz에서 설명한 것과 동일한 문제를 겪고 있었습니다(클롭으로 XMLType 값을 출력할 때 4000번째 문자 주변에 'NUL' 문자가 추가로 표시됨).SQL 개발자에서 놀다가 재미있는 해결책을 발견했습니다.XMLType의 출력을 보려고 했지만 4000번째 문자로 스크롤하는 것에 지쳐서 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"));
...
}
Bug:14781609 XDB: XMLType.getclobval()은 패치 세트 11.2.0.4의 CLOB.fix에 XML이 저장될 때 임시 LOB를 반환합니다.
그리고 또 다른 해결책을 blob으로 읽는다면, 다음과 같은 오류는 없습니다.
T1.PROJECT.getBlobVal(nls_charset_id('UTF8'))
그것이 그것인지 확인할 수 있을 만큼 충분히 쉽습니다..getClobVal() -부 -부INSTR(Java닌) /SQL이 CLOB를다하는지 에서 테스트합니다.CHR(0)존재 여부.
만약 그렇지 않다면, 당신의 Oracle 클라이언트 설치를 지목하겠습니다.
언급URL : https://stackoverflow.com/questions/13534264/strange-oracle-xmltype-getclobval-result
'programing' 카테고리의 다른 글
| 변수가 여러 문자열 값과 같지 않은지 확인하는 더 간단한 방법은? (0) | 2023.10.11 |
|---|---|
| AV 오디오 녹음기에서 오류가 발생함 (0) | 2023.10.11 |
| #정의 블록을 클랜 형식으로 정렬할 수 있습니까? (0) | 2023.10.11 |
| 실행된 SQL이 값을 반환하더라도 최대 절전 모드가 null 목록을 반환합니다. (0) | 2023.10.11 |
| ORA-01031 보기를 생성하는 동안 권한이 부족합니까? (0) | 2023.10.06 |