当我尝试从表中获取的XMLTYPE转换为nclob时,出现错误:
ORA-03001:未实现的功能
当我尝试动态创建的XMLTYPE时,一切正常。
我的Oracle版本是: 12.1.0.2.0 。
代码示例:
这正常工作:
DECLARE
v_xml XMLTYPE;
v_clob CLOB;
v_nclob nCLOB;
BEGIN
SELECT XMLTYPE('<a>test</a>') INTO v_xml FROM dual;
v_clob := v_xml.getClobVal();
v_nclob := to_nclob(v_clob);
END
;
这会产生错误:
CREATE TABLE TEST_XMLTYPE_TO_NCLOB
(
XML_MSG SYS.XMLTYPE
)
;
INSERT INTO TEST_XMLTYPE_TO_NCLOB (XML_MSG) VALUES (XMLTYPE('<a>test</a>'))
;
SET SERVEROUTPUT ON;
DECLARE
v_xml XMLTYPE;
v_clob CLOB;
v_nclob nCLOB;
BEGIN
SELECT XML_MSG INTO v_xml FROM TEST_XMLTYPE_TO_NCLOB WHERE rownum = 1;
v_clob := v_xml.getClobVal();
v_nclob := to_nclob(v_clob);
END
;
我想知道这是我的错误还是oracle错误?
如何以一种有效的方式对从表中获取的数据进行从XMLTYPE到NCLOB的转换。
顺便说一句-为什么我不能在“其他人”中捕获此异常?
答案 0 :(得分:2)
我认为这与表存储using SecureFile storage有关,该存储不支持NCLOB或与之交互。在查询过程中创建的XMLType不使用SecureFile(或任何)存储,因此不受影响。
编译器似乎发现您将使用SecureFile存储的值-大概会导致XMLType的不同风格(我没有看到此文档,但是看来您可能使用了不同的内部类型与日期一样,通常不必担心;尽管dump()
都说它们都是58型。
为什么它使用从中提取的CLOB值来抱怨您,这是一个谜。也许编译器正在以某种方式重写代码,这意味着它认为XMLType被更直接地使用。或者,更有可能是CLOB的味道略有不同。 (基于@BobJarvis的观察,我认为这似乎很有可能。)
尝试操作PL / SQL变量时,是编译器抛出错误-这是编译时错误,而不是运行时异常,这就是为什么您无法捕获它。
您可以通过以下方法解决该问题:将CLOB转换回XMLType(现在可能是另一个变体,大概是??),然后再转换回CLOB(不同的变体?):
DECLARE
v_xml XMLTYPE;
v_clob CLOB;
v_nclob nCLOB;
BEGIN
SELECT XML_MSG INTO v_xml FROM TEST_XMLTYPE_TO_NCLOB WHERE rownum = 1;
v_clob := v_xml.getClobVal();
v_xml := xmltype(v_xml.getClobVal());
v_clob := v_xml.getClobVal();
v_nclob := to_nclob(replace(v_clob, chr(10), null));
END
;
/
PL/SQL procedure successfully completed.
为什么行得通,为什么有必要,这也是一个谜。但建议以某种方式涉及不同类型的数据类型,或者至少这就是我的解释方式。
对于您的实际情况也可能不切实际。您也可以将其作为查询的一部分:
DECLARE
v_xml XMLTYPE;
v_clob CLOB;
v_nclob nCLOB;
BEGIN
SELECT XMLTYPE(t.XML_MSG.getClobVal()) INTO v_xml
FROM TEST_XMLTYPE_TO_NCLOB t WHERE rownum = 1;
v_clob := v_xml.getClobVal();
v_nclob := to_nclob(replace(v_clob, chr(10), null));
END
;
/
PL/SQL procedure successfully completed.
这不是更好,但您也许可以隐藏更多。或者,您也可以通过明确地使XMLType存储为CLOB或二进制来避免这种情况,但这也不是一种选择或理想选择。
这可能会引起有关Oracle支持的服务请求。这可能是一个已知的错误,但可能被视为预期的行为(另请参见与文档ID 1546992.1稍相关的文档)。
答案 1 :(得分:2)
关于正在发生的事情:
看来,当读回写入XMLTYPE列的数据并将其转换为CLOB时,将在最后添加两个行尾序列(LF / LF)。通过在v_clob := v_xml.getClobVal();
之后添加以下内容,尝试打印出转换后的CLOB:
DBMS_OUTPUT.PUT_LINE('DBMS_OUTPUT.PUT_LINE('v_clob=' || v_clob);
当对从数据库中获取的XMLTYPE转换的CLOB数据执行以上操作时,
<a>test</a>
,其后有两个换行符。在从嵌入式XMLTYPE转换的CLOB上运行DBMS_OUTPUT.PUT_LINE时,会得到
<a>test</a>
之后没有换行符。
现在,要解决的事情是-如果您尝试将从数据库中的XMLTYPE 转换为的CLOB传递给TRIM
函数,则会得到ORA-03001: unimplemented feature
。如果将从内联XMLTYPE转换的CLOB传递给TRIM
函数,它将正常工作。因此,该问题与TO_NCLOB
无关-似乎在您尝试使用从数据库中XMLTYPE值转换而来的CLOB时都会发生。我不知道该如何解决或解决此问题。
在WHEN OTHERS
中捕获-30001异常-它在11.2g中对我来说很好用。
好运。