您的位置:首页 > 其它

dblink远程库表结构修改导致本地库调用此表的存储过程出错问题解决方法

2015-06-23 16:57 1051 查看
最近遇到一个问题是这样子的:有两个数据库A 和 B 有两个结构相似的表但是列的次序却不一样。以下是我测试用的两个表:

在A库上:

create table student_test
(
student_name  VARCHAR2(100),
student_id    NUMBER(10),
student_gender VARCHAR2(10)
);

desc  student_test;
Name                           Null     Type
------------------------------ -------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
STUDENT_NAME                            VARCHAR2(100)
STUDENT_ID                              NUMBER(10)
STUDENT_GENDER                          VARCHAR2(10)

3 rows selected


在B库上:

create table student_test
(
student_name  VARCHAR2(100),
student_gender VARCHAR2(10)
);

alter table student_test add  student_id    NUMBER(10);

desc  student_test;
Name                           Null     Type
------------------------------ -------- ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
STUDENT_NAME                            VARCHAR2(100)
STUDENT_GENDER                          VARCHAR2(10)
STUDENT_ID                              NUMBER(10)

3 rows selected


由此可以看出A库和B库上的student_id 和student_gender的顺序发生了变化。

在A库上建立到B库上的dblink

create database link cwuk_test
connect  to cwuk_yy IDENTIFIED BY arbor123 using 'B';


然后我们再B库上插入一下数据,commit;

INSERT INTO student_test VALUES ('Yang Yan','woman','6038');


在sqlplus登录A库然后执行以下语句:

SQL>  declare type student_test_type IS TABLE OF student_test%ROWTYPE INDEX BY PLS_INTEGER;
2    stu_test_tab student_test_type;
3    BEGIN
SELECT * BULK collect  INTO stu_test_tab FROM student_test@yy_cwuk_test;
4    5    IF stu_test_tab.COUNT > 0 THEN
6     FOR dblink_inx IN 1..stu_test_tab.COUNT
7    loop
8    DBMS_OUTPUT.PUT_LINE('yyang test');
9     end loop;
10    end if;
11     end;
12    /
declare type student_test_type IS TABLE OF student_test%ROWTYPE INDEX BY PLS_INTEGER;
*
ERROR at line 1:
ORA-01722: invalid number
ORA-02063: preceding line from YY_CWUK_TEST
ORA-06512: at line 4


你会发现有错误,这是因为A库和B库的第二字字段不一样,而且类型也不一样, 它把‘woman’这个字符串的数据插入到了number(10)类型的字段中,素以显示出invalid number。

遇到这种问题有两种解决办法:

1.在定义类型的时候以远程库的类型为准,也就是在type的时候跟select的时候一样用@dblink。

SQL> declare type student_test_type IS TABLE OF student_test@yy_cwuk_test%ROWTYPE INDEX BY PLS_INTEGER;
2        stu_test_tab student_test_type;
BEGIN
3    4    SELECT * BULK collect  INTO stu_test_tab FROM student_test@yy_cwuk_test;
5       IF stu_test_tab.COUNT > 0 THEN
6         FOR dblink_inx IN 1..stu_test_tab.COUNT
7        loop
8       DBMS_OUTPUT.PUT_LINE('yyang test');
9        end loop;
10       end if;
11       end;
12      /
yyang test

PL/SQL procedure successfully completed.


2.将rowtype改成record

%ROWTYPE和记录(Record)的区别%ROWTYPE可以说是Record的升级简化版。(record:详细请参考:http://blog.csdn.net/qfs_v/article/details/2446941)

区别在与前者结构为表结构,后者为自定义结构。二者在使用上没有很大区别。前者方便,后者灵活。在实际中根据情况来具体决定使用。

Record + PL/SQL表可以进行数据的多行多列存储。

所以我改成以下版本:

SQL> declare type stu_test_rec IS record (
2      student_name  VARCHAR2(100),
student_id    NUMBER(10),
3    4      student_gender VARCHAR2(10)
5  );
6  type stu_test_tab_type IS TABLE OF stu_test_rec;
7
8  stu_test_tab stu_test_tab_type;
9
10        BEGIN
11    SELECT student_name,student_id,student_gender BULK collect  INTO stu_test_tab FROM student_test@yy_cwuk_test;
12       IF stu_test_tab.COUNT > 0 THEN
13         FOR dblink_inx IN 1..stu_test_tab.COUNT
14        loop
15       DBMS_OUTPUT.PUT_LINE('yyang test');
16        end loop;
17       end if;
18       end;
19      /

yyang test

PL/SQL procedure successfully completed.


你可以根据自己的情况选择用那种方法解决你的问题,第一种简单,但是对于有赋值的语句的话要一个字段一个字段的赋值,就会比较麻烦。 第二种是比较灵活的在自定义类型后,在赋值的时候就可以按行赋值了。ok,以后有时间总结一下oracle的基础知识吧。发现太多东西需要学习了,加油。

参考资料:http://bbs.csdn.net/topics/370011975
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: