gpt4 book ai didi

oracle - 奇怪的Oracle XMLType.getClobVal()结果

转载 作者:行者123 更新时间:2023-12-04 05:54:26 25 4
gpt4 key购买 nike

我使用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中写了check:
// ... 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 );

准备两个带有XML的CLOB。首先是空字符,第二个没有空字符。
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>';

检查第一个CLOB中是否为null,第二个CLOB中是否为null:
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:
DBMS_OUTPUT.put_line( DBMS_LOB.INSTR( P3, chr(0) ) );

它表明,数据库内部不存在空值,只要我们在PL/SQL上下文中,就不存在空值。但是,当我尝试在SQL Developer(在Windows上)或Java(在Red Hat EE和Tomcat7上)中使用以下SQL时,在所有返回的CLOB中,位置4000处出现空字符:
select T.P.getClobVal() from T1 T;

BR
JM

最佳答案

它不是Oracle错误(它很好地存储和检索\0。它是客户端/Windows错误(不同的客户端在“NUL”方面的行为与Windows有所不同))

实际上,chr(0)在非blob中不是有效字符(我很好奇,您通常如何首先获得XMLType来接受它,因为通常它不会解析)。

在C中使用\0表示字符串的结尾(NUL终止符),某些GUI会在该点停止处理该字符串。例如:

![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的情况更好,如您所见:

但是如果您将其复制,剪贴板将仅将其复制到nul字符。此复制粘贴错误不是SQL开发人员的错,这是Windows剪贴板不允许NUL正确粘贴的问题。

使用sql developer/windows剪贴板时,您应该只使用 replace(T1.PROJECT.getClobVal(), chr(0), null)即可解决此问题。

关于oracle - 奇怪的Oracle XMLType.getClobVal()结果,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13534264/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com