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;
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;
3条答案
按热度按时间8cdiaqws1#
首先你需要临时表:
第二次使用“从选定位置插入”时:
kjthegm62#
我发布了一个Github项目,它通过dblink查询CLOB和BLOB。https://github.com/HowdPrescott/Lob_Over_DBLink
下面是一个独立函数中的CLOB部分:
我认为这个例子是相当不言自明的,但这里有一点描述。
该函数依赖于这样一个事实,即您可以通过dblink调用远程DB上的函数/过程-在本例中为 dbms_lob.substr()。
首先,它通过使用对象ID(编码到 rowid 中)找到远程表名,这样就不必将远程表名作为另一个参数传入。
还要注意,p_rid参数是一个 urowid,因为它是来自远程DB的 rowid。这就是为什么需要转换它。
然后提取CLOB,并以4000字节的块(这是PL/SQL中的最大varchar 2大小)重新构建。这些块是varchar 2的块,可以通过dblink传递。
在读取了最后一个CLOB之后,*if length(v_chunk)〈c_chunk_size... * 子句得到满足(那么“块”缓冲区将不会被填充)。
当CLOB的长度是4000的倍数时,需要 ORA-06502 的异常捕获,那么即使没有更多的数据,“if”子句也不满足。您可以只依赖此捕获并完全删除“if”子句。但是我做了一些性能测试,发现在大多数情况下,最好将其保留在其中。
pbossiut3#
Howd可能在4年前就有了正确的方法,但是我需要将他的更新为类似下面的内容才能让它工作(我为了自己的使用而简化了他的,所以下面的内容可能无法编译或工作,但是你应该明白,在12.1.0.2.0中不再需要第一个查询):