问题描述
嗨,
我必须使用DBLink将ALL_VIEWS的数据从一个数据库传输到另一个数据库。两者都是Oracle数据库,版本也相同,即Oracle 18c。很少有视图的文本列长度超过32767,不能使用本机动态sql传输。因此,我使用DBMS_SQL来实现同样的目标。
我正在尝试使用DBMS_SQL.COLUMN_VALUE_LONG从ALL_VIEW @ 中提取长列值,并在CLOB列中插入结果。下面是我正在使用的PLSQL块。(请用工作中的DB链接替换db_link)
尝试使用DBMS_SQL.COLUMN_VALUE_LONG() 获取长列值时,上述块失败,并显示 “ORA-03101: 无效输入数据”。
ORA-03101: invalid ORA-06512: at line 79
ORA-06512: at line 51
ORA-02063: preceding line from REPORTING_SYSTEM
ORA-06512: at "SYS.DBMS_SQL", line 2066
ORA-06512: at line 40
Oracle数据库版本是: Oracle数据库18c企业版版本18.0.0.0.0。但是,此语句在11g环境中可以正常工作。如果我们删除db_link,那么这也可以正常工作。
我必须使用DBLink将ALL_VIEWS的数据从一个数据库传输到另一个数据库。两者都是Oracle数据库,版本也相同,即Oracle 18c。很少有视图的文本列长度超过32767,不能使用本机动态sql传输。因此,我使用DBMS_SQL来实现同样的目标。
我正在尝试使用DBMS_SQL.COLUMN_VALUE_LONG从ALL_VIEW @
CREATE TABLE san_ora03101_test
( resource_name VARCHAR2 (100),
view_owner VARCHAR2(100),
view_name VARCHAR2(100),
text CLOB
);
/
DECLARE
s_sql CLOB:= q'[SELECT *
FROM (
SELECT v.view_name resource_name
, v.owner view_owner
, v.view_name
, v.text text
FROM all_views@REPORTING_SYSTEM v)]';
cur BINARY_INTEGER;
s_res_name VARCHAR2(100);
s_owner VARCHAR2(100);
s_vname VARCHAR2(100);
c_text CLOB;
n_res NUMBER;
BEGIN
cur:=DBMS_SQL.OPEN_CURSOR;
DBMS_SQL.PARSE(cur, s_sql, DBMS_SQL.NATIVE);
DBMS_SQL.DEFINE_COLUMN(cur, 1, s_res_name, 100);
DBMS_SQL.DEFINE_COLUMN(cur, 2, s_owner, 100);
DBMS_SQL.DEFINE_COLUMN(cur, 3, s_vname, 100);
DBMS_SQL.DEFINE_COLUMN_LONG(cur, 4);
n_res:=DBMS_SQL.EXECUTE(cur);
WHILE DBMS_SQL.FETCH_ROWS(cur) > 0 LOOP
DBMS_SQL.COLUMN_VALUE(cur, 1, s_res_name);
DBMS_SQL.COLUMN_VALUE(cur, 2, s_owner);
DBMS_SQL.COLUMN_VALUE(cur, 3, s_vname);
DECLARE
c_tmp CLOB;
n_pos INTEGER:=0;
s_tmp VARCHAR2(32767);
n_tpos INTEGER;
n_piece_len NUMBER:= 32767;
BEGIN
LOOP
dbms_output.put_line(' n_pos: '||n_pos||',s_tmp: '||s_tmp||',n_tpos: '||n_tpos||',cur: '||cur||', s_res_name: '||s_res_name||',s_owner: '||s_owner||',s_vname: '||s_vname);
DBMS_SQL.COLUMN_VALUE_LONG(cur, 4, n_piece_len, n_pos, s_tmp, n_tpos);
c_tmp:=c_tmp||s_tmp;
n_pos:=n_pos+n_piece_len;
EXIT WHEN n_tpos < n_piece_len;
END LOOP;
c_text:=c_tmp;
EXCEPTION
WHEN OTHERS THEN
dbms_output.put_line(' ERR_STACK: '||dbms_utility.format_error_stack||', SQL_TRACE: '||dbms_utility.format_error_backtrace);
RAISE;
END;
-- INSERT RECORDS
INSERT
INTO san_ora03101_test
(
resource_name
, view_owner
, view_name
, text
)
VALUES
(
s_res_name
, s_owner
, s_vname
, c_text
);
END LOOP;
DBMS_SQL.CLOSE_CURSOR(cur);
COMMIT;
EXCEPTION
WHEN OTHERS THEN
IF DBMS_SQL.IS_OPEN(cur) THEN
DBMS_SQL.CLOSE_CURSOR(cur);
END IF;
RAISE;
END;
/
尝试使用DBMS_SQL.COLUMN_VALUE_LONG() 获取长列值时,上述块失败,并显示 “ORA-03101: 无效输入数据”。
ORA-03101: invalid ORA-06512: at line 79
ORA-06512: at line 51
ORA-02063: preceding line from REPORTING_SYSTEM
ORA-06512: at "SYS.DBMS_SQL", line 2066
ORA-06512: at line 40
Oracle数据库版本是: Oracle数据库18c企业版版本18.0.0.0.0。但是,此语句在11g环境中可以正常工作。如果我们删除db_link,那么这也可以正常工作。
专家解答
我有一个希望更容易的提议给你。使用SQLPlus中的COPY命令在本地获取数据,然后您可以透明地将 (本地) 长转换为CLOB。
“remote_db” 是一个tnsnamers.ora条目,而不是数据库链接
SQL> create table local_all_views 2 ( owner varchar2(30), view_name varchar2(128), text_length int, text long); Table created. SQL> SQL> set long 1000000 SQL> copy from scott/tiger@remote_db - > insert local_all_views (owner, view_name, text_length, text ) - > using select owner, view_name, text_length, text from all_views; Array fetch/bind size is 15. (arraysize is 15) Will commit when done. (copycommit is 0) Maximum long size is 1000000. (long is 1000000) 7249 rows selected from scott@remote_db. 7249 rows inserted into LOCAL_ALL_VIEWS. 7249 rows committed into LOCAL_ALL_VIEWS at DEFAULT HOST connection. SQL> SQL> alter table local_all_views modify text clob; Table altered. SQL> desc local_all_views Name Null? Type ----------------------------------------- -------- ---------------------------- OWNER VARCHAR2(30) VIEW_NAME VARCHAR2(128) TEXT_LENGTH NUMBER(38) TEXT CLOB
“remote_db” 是一个tnsnamers.ora条目,而不是数据库链接
文章转载自ASKTOM,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。




