当前位置: 首页 > 知识库问答 >
问题:

奇怪的Oracle XMLType.getClobval()结果

阎辰钊
2023-03-14

我使用Oracle11g(在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) );

值是使用以下存储过程插入的:

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

用XMLS准备两个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>';
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 ) );
select T.P.getClobVal() into P3 from T1 T where rownum = 1;
DBMS_OUTPUT.put_line( DBMS_LOB.INSTR( P3, chr(0) ) );
select T.P.getClobVal() from T1 T;

共有1个答案

公孙国兴
2023-03-14

它不是Oracle的bug(它存储和检索\0很好。它是客户机/windows的bug(不同的客户机在“NUL”方面的行为和windows一样不同)

chr(0)在非blob中实际上不是一个有效的字符(我很好奇XMLType一开始是如何接受它的,因为它通常不会解析)。

\0在C中用于表示字符串的结尾(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>

但是如果你复制它,剪贴板将只复制到nul字符。这个复制粘贴错误不是SQL开发人员的错误,这是windows剪贴板不允许NUL正确粘贴的问题。

在使用sql Developer/Windows剪贴板时,只需替换(T1.project.getClobval(),chr(0),null)就可以解决这个问题。

 类似资料:
  • 当试图从Hitbox API获取数据时,我得到了一个奇怪的结果。对于一个API的命令,这种情况每次都会发生,而对于另一个API的命令,这种情况只是有时发生。结果差不多是这样(这是我得到的最后一个结果): \U001F\B\0\0\0\0\0\U0003W8SμMU~S N T&N G6C$Z%9IGF[(\U0005\U000F(:6\U000F\B P C\U0015\N\U007F V\U00

  • 我有一个程序可以读取两个文件(“incompleta.txt”和“completa.txt”),并比较两个文件中是否有相同的名称。其工作原理如下: 它将“completa.txt”中的所有名称存储在ArrayList中 问题是我的“lista.txt”看起来像这样:Image 第二条线完全是混乱和扭曲的。 我的Java代码:

  • 问题内容: 我现在对Java左移操作有些困惑, 但 看起来像是更多的偏移值,该值的模数为32。 感谢大家对JLS的答复和报价。 我只想知道更多。是否知道以这种方式进行设计的原因?还是只是一些约定?显然C没有这个怪癖? 感谢@paxdiablo。看起来C声明了未定义的行为。 我在这里有一些个人假设: ARM体系结构参考手册A7.1.38 语法LSL Rd,Rm,#immed_5 哪里: Rd 是存储

  • 问题内容: 我有这样的事情: 我希望它会在文本区域中显示“ hello 0”,等待1秒,然后显示“ hello 1”,然后等待1秒,依此类推。 但是发生的情况有所不同,它等待5秒钟,然后显示“ hello 4”。 任何想法? 问题答案: 是的-您基本上是在阻止UI线程,因此永远不会回避实际更新。 在UI线程中休眠是一个非常糟糕的主意。 如果您想执行类似的操作,则应使用。(我假设您正在使用Swing

  • 我正在使用Weka Gui-Explorer,我想根据类{男性,女性}对我的数据进行分类。我使用MultiBoostAB分类器,以REPTree分类器为基础。我正在尝试使用训练集(557个实例)评估我的分类器的准确性 然后是一个具有大约300个属性的测试集(200个实例)。准确率83,5% - 167从200个实例中正确分类,kappa统计量为0,67。我保存了这个模型,并用它来预测 其他未知数据

  • 我使用的是mongodb(v2.6.7)和mongo(2.6.7)shell客户端。 我正在尝试使用insert和update命令返回的WriteResult对象。 根据mongodocs,如果出现错误,它将返回一个writeResult对象,其中包含writeError子文档。但我无法在shell或mongo的javascript文件中访问此子文档。 下面是我的问题的说明。 我插入一个对象,并获