问题描述
嗨,
我必须使用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进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。