我正在尝试通过dblink移动一些数据,其中一列是XMLType列。代码如下所示:
begin
delete from some_schema.some_remote_tab@src_2_trg_dblink;
INSERT INTO some_schema.some_remote_tab@src_2_trg_dblink(id, code, gen_date, xml_data)
SELECT id, code, gen_date, xml_data
FROM local_table;
end;
Oracle会返回以下错误:
ORA-02055: distributed update operation failed; rollback required ORA-22804: remote operations not permitted on object tables or user-defined type columns
对ORA-22804的一些研究表明,由于XMLType列,我可能会收到此错误,但我不知道如何解决此问题。
(Oracle 10g)
答案 0 :(得分:2)
我们得到ORA-22804,因为我们Oracle数据库中每个Type的实例都有一个OID,它在数据库中是唯一的。我们无法将该OID转移到另一个数据库;在尝试导入具有用户定义类型的模式之前,这让我感到悲痛。我没有意识到它也影响了XMLType,但它是一个Object,所以这并不奇怪。
解决方案很糟糕:您必须将XML卸载到本地数据库中的文本中,然后将其转换回远程数据库中的XML。
我目前没有分布式数据库设置来测试,但如果你很幸运,它可能会有效:
INSERT INTO some_schema.some_remote_tab@src_2_trg_dblink(id, code, gen_date, xml_data)
SELECT id, code, gen_date, xmltype ( xml_data.asClobVal() )
FROM local_table;
如果asClobVal()
方法不起作用,则可能需要使用SQL函数XMLSERIALIZE()。
XMLSerialize(DOCUMENT xml_data AS CLOB)
如果你真的不走运,你将无法在单个SQL语句中执行此操作,并且您必须使用PL / SQL解决它。在某种程度上,这取决于您使用的数据库版本;版本越新,你就越有可能在SQL而不是PL / SQL中使用它。
答案 1 :(得分:1)
尝试以相反的方式做到这一点。这是登录到远程数据库,创建到本地数据库的dblink,并执行这样的插入
INSERT INTO remote_schema.some_remote_tab(id, code, gen_date, xml_data)
SELECT id, code, gen_date, xml_data
FROM local_table@dblink_to_local_db;
答案 2 :(得分:0)
而是执行数据拉取。
(同时..等待oracle找到一些解决方案,以便将来在dblink上执行XML的PUSH)
在远程站点数据库B
创建过程CREATE OR REPLACE PROCEDURE PR_REMOTE(OP_TOTAL_COUNT OUT NUMBER) IS
BEGIN
INSERT /*+ DRIVING_SITE(src) */
INTO REMOTE_TABLE TGT_B
(XMLDATA_COL)
SELECT SRC.XMLDATA FROM LOCAL_TABLE@TGT2SRC_DBLINK SRC;
OP_TOTAL_COUNT := SQL%ROWCOUNT;
END;
从数据库A
调用该过程DECLARE
V_COUNT NUMBER := 0;
BEGIN
PR_REMOTE(V_COUNT);
COMMIT;
END;
答案 3 :(得分:0)
我遇到了与SQL服务器的异构数据库链接相同的问题。
使用xmltype.getStringVal()
结束插入SQL Server端的VARCHAR列,因为数据不到4000个字符。
如果超过4000个字符,还有xmltype.getClobVal()
,但我还没有对其进行测试。
答案 4 :(得分:0)
“xml-> text-> xml”链可能很复杂,但在某些情况下可能会有所帮助(例如,当插入不是选项但仅更新时)。 您可以尝试使用varchar列的“n”和平(在目标表或不同的列中,远程数据库上的不同模式中的perheaps),其中“n”是: ceil(max(dbms_lob.getlength(MyXmlColumn))/ 4000)
然后您可以将这些片段传输到远程临时字段:
public class OuterClass {
int i;
public void method1() {
System.out.println("Inside Method 1");
}
class InnerClass {
int j;
public void method2() {
System.out.println("Inside Method 2");
}
}
public static void main(String[] args) {
// To instantiate an inner class, you must first instantiate the outer class
OuterClass outerObject = new OuterClass();
outerObject.method1();
// Then, create the inner object within the outer object
OuterClass.InnerClass innerObject = outerObject.new InnerClass();
innerObject.method2();
}
}
XmlType可以从这样的片段重新组成:
insert into RemoteSchema.MyTable(Id, XmlPart1, XmlPart2,...)
(select 1 /*some Id*/,
dbma_lob.substr(MyXmlColumn.getclobval(), 4000, 1),
dbma_lob.substr(MyXmlColumn.getclobval(), 4000, 4001),
...
from LocalSchema.MyTable
最后使用结果更新remothe架构中的任何其他表,如:
create or replace function concat_to_xml(p_id number)
return xmltype
is
xml_lob clob;
xml xmltype;
begin
dbms_lob.createtemporary(xml_lob, true);
for r in (select XmlPart1, XmlPart2, ... from RemoteSchema.MyTable where Id = p_id)
loop
if r.XmlPart1 is not null then
dbms_lob.writeappend(xml_lob, length(r.XmlPart1), r.XmlPart1);
end if;
if r.XmlPart2 is not null then
dbms_lob.writeappend(xml_lob, length(r.XmlPart2), r.XmlPart2);
end if;
...
end loop;
xml := xmltype(xml_lob);
dbms_lob.freetemporary(xml_lob);
return xml;
end;