通过 DBLink 移动 XML

发布于 2024-11-14 17:18:49 字数 578 浏览 4 评论 0原文

我正在尝试通过 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 列而收到此错误,但我不确定如何解决此问题。

(甲骨文10g)

I am trying to move some data over a dblink and one of the columns is an XMLType column. The code looks like this:

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 returns these errors:

ORA-02055: distributed update operation failed; rollback required
ORA-22804: remote operations not permitted on object tables or user-defined type columns

Some research on ORA-22804 shows that I am probably getting this error because of the XMLType column, but I am not sure how to resolve this.

(Oracle 10g)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

沫雨熙 2024-11-21 17:18:49

我们得到 ORA-22804 是因为 Oracle 数据库中类型的每个实例都有一个 OID,该 OID 在数据库中是唯一的。我们无法将该 OID 传输到另一个数据库;之前在尝试导入具有用户定义类型的模式时,这让我感到悲伤。我没有意识到它也影响了 XMLType,但它是一个对象,所以这并不奇怪。

解决方案很棘手:您必须将 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 中使用它。

We get ORA-22804 because every instance of a Type in our Oracle database has an OID, which is unique within the database. We cannot transfer that OID to another database; this has caused me grief before when trying to import schemas which have User-Defined Types. I hadn't realised that it also affected XMLType, but it is an Object so it is not surprising.

The solution is icky: you will have to unload the XML into text on your local database and then convert it back into XML in the remote database.

I don't have a distributed DB set-up to test this right now, but if you're lucky it may work:

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;

If the asClobVal() method doesn't work you may need to use the SQL function XMLSERIALIZE() instead.

XMLSerialize(DOCUMENT xml_data AS CLOB) 

If you're really unlucky you won't be able to do this in a single SQL statement, and you'll have to solve it using PL/SQL. To a certain extent this will depend on which version of the database you are using; the more recent the version, the more likely you'll be able to it in SQL rather than PL/SQL.

夏天碎花小短裙 2024-11-21 17:18:49

尝试以相反的方式进行此操作。即登录到远程数据库,创建到本地数据库的数据库链接,然后执行如下插入

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;

Try to do this the other way around. That is log into the remote db, create a dblink to the local db, and do an insert like this

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;
我的黑色迷你裙 2024-11-21 17:18:49

而是执行数据拉取。

  1. 在远程数据库中创建数据拉取过程 B.
  2. 创建同义词并向 dblink 用户提供授权。
  3. 从数据库 A(源)调用远程过程 在数据库 A(源)执行提交。

(同时..等待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;

Instead Perform a Data PULL.

  1. create the data pull procedure at Remote database B.
  2. create synonyms and provide grants to the dblink user.
  3. Call the Remote procedure from Database A (Source) Perform a commit at Database A(source).

(Meanwhile .. wait for oracle to find some solution to perform the PUSH of XML over dblink in the future)

Create a procedure at Remote site Database 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;

Call the procedure from Database A

DECLARE
  V_COUNT NUMBER := 0;
BEGIN
  PR_REMOTE(V_COUNT);
  COMMIT;
END;
已下线请稍等 2024-11-21 17:18:49

我在连接到 SQL Server 的异构数据库链接时遇到了同样的问题。

由于数据少于 4000 个字符,最终使用 xmltype.getStringVal() 插入 SQL Server 端的 VARCHAR 列。

如果超过 4000 个字符,还有 xmltype.getClobVal() 但我还没有测试过。

I was facing the same issue with an heterogeneous DB link to SQL server.

Ended up using xmltype.getStringVal() to insert in a VARCHAR column on SQL Server side as the data was under 4000 characters.

There is also xmltype.getClobVal() if over 4000 characters but I haven't tested it.

绝影如岚 2024-11-21 17:18:49

"xml->text->xml" 链可能很复杂,但在某些情况下可能会有所帮助(例如,当不能选择插入而只能更新时)。
您可以尝试使用“n”个 varchar 列(在目标表中或在不同的表中,可能在远程数据库上的不同架构中),其中“n”是:
ceil(max(dbms_lob.getlength(MyXmlColumn)) / 4000)

然后您可以将这些片段传输到远程临时字段:

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

XmlType 可以从片段重新组合,如下所示:

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;

最后使用结果更新任何remothe 模式中的其他表如:

update RemoteSchema.MyTable2 t2 set t2.MyXmlColumn = concat_to_xml(1 /*some Id*/);

The "xml->text->xml" chain might be complicated, but could help in some cases (for example when inserting is not on option but updating only).
You can try with "n" peaces of varchar columns (in the destination table or in a differnet one, perheaps in different schema on the remote DB), where "n" is:
ceil(max(dbms_lob.getlength(MyXmlColumn)) / 4000)

Then you can transfer these fragments to remote temporary fields:

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

XmlType can be re-composed from fragments like this:

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;

Finally use the result to update any other table in the remothe schema like:

update RemoteSchema.MyTable2 t2 set t2.MyXmlColumn = concat_to_xml(1 /*some Id*/);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文