我使用Oracle 11g(在Red Hat上)。我有XMLType列简单的常规表:奇怪的Oracle XMLType.getClobVal()结果
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的其余部分未被复制。
// ... 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));
阅读器返回完整的XML,但我会抛出异常,因为在4000位置空字符我可以删除此单个字节,但这将是相当:
为了证实这一点,我在java中写检查奇怪的解决方法。
我没有在那里使用VARCHAR2,但也许这个问题与VARCHAR2限制(4000字节)有关?任何其他想法?这是一个Oracle错误还是我错过了什么?
--------------------编辑--------------------
Value使用下面的存储过程中插入:习惯称它为
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 || '' || 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
尝试插入第一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;
检查是否有空。没有空:
DBMS_OUTPUT.put_line(DBMS_LOB.INSTR(P3, chr(0)));
它接缝,有内部数据库中没有空,只要我们在PL/SQL背景下,有没有空。但是,当我尝试使用SQL开发人员(在Windows上)以下SQL或Java中(在Red Hat EE和Tomcat7)我所有返回的CLOB得到空字符在4000位置:
select T.P.getClobVal() from T1 T;
BR, JM
没有错误,你可以把它写使用'utl_file',看看内容如何看起来像一个文件?你还可以尝试从PROJECTS中选择XMLType.getClobVal(PROJECT);'? (虽然没有功能上的差异) – Annjawn
柱状体是如何填充的?你确定问题在于检索 - 如果不同的客户看到相同的事情听起来不太可能。您也可以选择值的子字符串,并查看是否仍然存在空字符。 –
我运行utlfile.sql和prvtfile.plb,但我仍然无法使用utl_file(ORA-06521:PL/SQL:错误映射函数),抱歉。 – Mikosz