簡體   English   中英

如何將 CLOB 數據從一個數據庫傳輸到另一個具有 DBLinks 的遠程 ORACLE 數據庫

[英]how to transfer CLOB data from one database to another remote ORACLE database having DBLinks

問題是,如何將 CLOB 數據從一個源數據庫傳輸到另一個具有 DBLinks 的 Oracle 數據庫。

Oracle 無法使用 DBLinks 傳輸 CLOB 數據,所以我們可以有什么樣的解決方案:將 Oracle 中的字段擴展為 Varchar2 32.767 個字符(Oracle 12 的新特性)。

首先你需要臨時表:

create global temporary table TBL_TMP_CLOB
(
  c_clob CLOB
)

第二次使用“從選擇插入”:

INSERT INTO schema.remote_table@dblink(rem_clob) SELECT * FROM TBL_TMP_CLOB; 

我發布了一個通過 dblink 查詢 CLOB 和 BLOB 的 Github 項目。 https://github.com/HowdPrescott/Lob_Over_DBLink

這是獨立函數中的 CLOB 部分:

create or replace function dblink_clob(
    p_dblink    in varchar2
  , p_clob_col  in varchar2
  , p_rid       in urowid
)
return clob is
    /**  A function to fetch a CLOB column over a dblink  **/
    /**  Laurence Prescott 25-Aug-17  **/
    /**  select dblink_clob('some_dblink', 'some_clob_column', rowid)
           from some_table@some_dblink;
         Note: Does not work on tables that have a virtual column (eg. xmltype).
    **/

    c_chunk_size    constant pls_integer := 4000;
    v_chunk         varchar2(4000);
    v_remote_table  varchar2(128);
    v_clob          clob;
    v_pos           pls_integer := 1;
begin
    dbms_lob.createtemporary(v_clob, true, dbms_lob.call);
    execute immediate 'select object_name from user_objects@' ||p_dblink
                   || ' where data_object_id = dbms_rowid.rowid_object(:bv_rid) '
    into v_remote_table using cast (p_rid as rowid);
    loop
        execute immediate 
            'select dbms_lob.substr@' ||p_dblink|| '(' ||p_clob_col|| ', ' ||c_chunk_size
         || ', ' ||v_pos|| ') from ' ||v_remote_table|| '@' ||p_dblink|| ' where rowid = :rid '
        into v_chunk using p_rid;
        begin dbms_lob.append(v_clob, v_chunk);
        exception when others then
            if sqlcode = -6502 then exit; else raise; end if;
        end;
        if length(v_chunk) < c_chunk_size then exit; end if;
        v_pos := v_pos + c_chunk_size;
    end loop;
    return v_clob;
end dblink_clob;

我認為這個例子是相當不言自明的,但這里有一些描述。
該函數依賴於這樣一個事實,即您可以通過 dblink 在遠程數據庫上調用函數/過程 - 在本例中為 dbms_lob.substr()
首先,它使用對象 id(編碼到rowid中)找到遠程表名。 這樣就不必將遠程表名作為另一個參數傳入。
另請注意, p_rid 參數是urowid ,因為它是來自遠程數據庫的rowid 這就是為什么它需要被鑄造。
然后將 CLOB 提取並重建為 4000 字節的塊,這是 PL/SQL 中的最大 varchar2 大小。 這些塊是 varchar2 的,可以通過 dblink 傳遞。
if length(v_chunk) < c_chunk_size ...子句在讀取完最后一個 CLOB 后得到滿足(那么“塊”緩沖區將不會被填充)。
當 CLOB 的長度是 4000 的倍數時,需要ORA-06502的異常捕獲,即使沒有更多數據,“if”子句也不滿足。 您可以僅依靠此捕獲並完全刪除“if”子句。 但是我做了一些性能測試,發現在大多數情況下最好還是保留它。

Howd 在 4 年前可能有正確的方法,但我需要將他的更新為以下內容以使其正常工作(我簡化了他以供我自己使用,因此以下內容可能無法編譯或工作,但你得到了這個想法,在 12.1.0.2.0 中不再需要第一個查詢):

create or replace function dblink_clob(
    p_dblink    in varchar2
  , v_remote_table in varchar2
  , p_clob_col  in varchar2
  , p_rid       in urowid
)
return clob is
    /**  A function to fetch a CLOB column over a dblink  **/
    /**  Laurence Prescott 25-Aug-17  **/
    /**  select dblink_clob('some_dblink', 'some_clob_column', rowid)
           from some_table@some_dblink;
         Note: Does not work on tables that have a virtual column (eg. xmltype).
    **/

    c_chunk_size    constant pls_integer := 4000;
    v_chunk         varchar2(4000);
    v_clob          clob;
    v_pos           pls_integer := 1;
begin
    dbms_lob.createtemporary(v_clob, true, dbms_lob.call);
    loop
        execute immediate 
            'select dbms_lob.substr@' ||p_dblink|| '(' ||p_clob_col|| ', ' ||c_chunk_size
         || ', ' ||v_pos|| ') from ' ||v_remote_table|| '@' ||p_dblink|| ' where rowid = :rid '
        into v_chunk using p_rid;
        begin dbms_lob.append(v_clob, v_chunk);
        exception when others then
            if sqlcode = -6502 then exit; else raise; end if;
        end;
        if length(v_chunk) < c_chunk_size then exit; end if;
        v_pos := v_pos + c_chunk_size;
    end loop;
    return v_clob;
end dblink_clob;

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM