li
  当前位置:主页 > 性能优化 > 文章内容
li
通过触发器复制包含LONG类型的表
来源: http://yangtingkun.itpub.net/  作者: yangtingkun    时间:2008-01-26   阅读:5  

前两天论坛上有人问如何才能通过触发器来实现对包含LONGLONG RAW类型字段的表的复制。给他做了个最简单的例子,在这里记录一下。


由于在触发器中不能对LONGLONG RAW类型的字段进行引用,所以原本最简单的方式直接将:NEW.COL插入到新表的方法无法奏效,必须采用其他方法解决。

SQL> CREATE TABLE T (ID NUMBER PRIMARY KEY, COMMENTS LONG RAW);

表已创建。

SQL> CREATE TABLE T1 (ID NUMBER PRIMARY KEY, COMMENTS BLOB);

表已创建。

SQL> CREATE OR REPLACE TRIGGER TRI_T BEFORE INSERT ON T FOR EACH ROW
2 BEGIN
3 INSERT INTO T1 VALUES (:NEW.ID, :NEW.COMMENTS);
4 END;
5 /
CREATE OR REPLACE TRIGGER TRI_T BEFORE INSERT ON T FOR EACH ROW
*
ERROR
位于第 1 :
ORA-04093:
不允许在触发器中引用 LONG 类型的列

只能通过查询原表的方式,不过查询原表会面临一个变异表的问题,解决这个变异表的问题一般是通过三个触发器和一个程序包来完成。

SQL> CREATE OR REPLACE PACKAGE P_RECORD_ID AS
2 TYPE T_NUMBER IS TABLE OF NUMBER INDEX BY BINARY_INTEGER;
3 V_ID T_NUMBER;
4 END;
5 /

程序包已创建。

SQL> CREATE OR REPLACE TRIGGER TRI_B_T BEFORE INSERT ON T
2 BEGIN
3 P_RECORD_ID.V_ID.DELETE;
4 END;
5 /

触发器已创建

SQL> CREATE OR REPLACE TRIGGER TRI_B_R_T BEFORE INSERT ON T FOR EACH ROW
2 BEGIN
3 P_RECORD_ID.V_ID(P_RECORD_ID.V_ID.COUNT 1) := :NEW.ID;
4 END;
5 /

触发器已创建

SQL> CREATE OR REPLACE TRIGGER TRI_A_T AFTER INSERT ON T
2 BEGIN
3 FOR I IN 1..P_RECORD_ID.V_ID.COUNT LOOP
4 INSERT INTO T1 SELECT ID, TO_LOB(COMMENTS) FROM T WHERE ID = P_RECORD_ID.V_ID(I);
5 END LOOP;
6 END;
7 /

触发器已创建

简单测试一下:

SQL> INSERT INTO T VALUES (1, '1234567890ABCD');

已创建 1 行。

SQL> SELECT * FROM T;

ID C
---------- -
1 1

IXDBA.NET技术社区

SQL> COL COMMENTS FORMAT A50
SQL> SELECT ID, CAST(COMMENTS AS RAW(255)) COMMENTS FROM T1;

ID COMMENTS
---------- --------------------------------------------------
1 1234567890ABCD

SQL> INSERT INTO T VALUES (2, 'A');

已创建 1 行。

SQL> SELECT ID, CAST(COMMENTS AS RAW(255)) COMMENTS FROM T1;

ID COMMENTS
---------- --------------------------------------------------
1 1234567890ABCD
2 0A

SQL> INSERT INTO T SELECT ID 2, 'ABC' FROM T;

已创建2行。

SQL> SELECT ID, CAST(COMMENTS AS RAW(255)) COMMENTS FROM T1;

ID COMMENTS
---------- --------------------------------------------------
1 1234567890ABCD
2 0A
3 0ABC
4 0ABC

对于8i版本,由于PL/SQL的编译器还不认识TO_LOB函数,可以改用动态SQL

SQL> CREATE OR REPLACE TRIGGER TRI_A_T AFTER INSERT ON T
2 BEGIN
3 FOR I IN 1..P_RECORD_ID.V_ID.COUNT LOOP
4 EXECUTE IMMEDIATE 'INSERT INTO T1 SELECT ID, TO_LOB(COMMENTS) FROM T WHERE ID = :ID'
5 USING P_RECORD_ID.V_ID(I);
6 END LOOP;
7 END;
8 /

触发器已创建

对于LONGLONG RAW类型的复制,用触发器并不是个好的办法,唯一的好处就是相对简单,而且不需要修改程序,完全在数据库级上实现,不过效率肯定不会太高。




  上一篇: 计算月还款的小过程(三)   下一篇: BULK COLLECT的小毛病
li
 §相关评论  
 热点文章

·Resize datafile导致ASM Crash
·在Oracle10g RAC下新增ASM磁盘
·ORACLE SQL性能优化系列 (一)
·oracle性能调优:管理oracle日志
·oracle RAC环境中系统时钟的调
·why:Rac的心跳线不支持交叉线?
·RAC的VIP及实例依赖关系:版本O
·如何启动DataGuard的备用数据库
·系统表空间IO错误 数据损坏处理
·不幸中的万幸:遭遇ORA-00600 [
·用ORACLE的高级复制实现内外网
li
 编辑推荐
·Resize datafile导致ASM Crash
·在Oracle10g RAC下新增ASM磁盘
·ORACLE SQL性能优化系列 (一)
·oracle性能调优:管理oracle日志
·oracle RAC环境中系统时钟的调
·why:Rac的心跳线不支持交叉线?
·RAC的VIP及实例依赖关系:版本O
·如何启动DataGuard的备用数据库
·系统表空间IO错误 数据损坏处理
·不幸中的万幸:遭遇ORA-00600 [
·用ORACLE的高级复制实现内外网
li
 相关篇章
·计算月还款的小过程(三)
·计算月还款的小过程(二)
·计算月还款的小过程(一)
·Deterministic函数(二)
·Deterministic函数
·给用户授予权限时应该尽量避免AN...
·自定义分析函数
·郁闷的911错误
·NUMBER类型转化为二进制
·如何定位DUMP所需的文件号和BLOC...
·BULK COLLECT的小毛病
·日期转换函数的格式参数大小写规...
·FORALL语句的小问题
·判断是否数字类型
·FOR ALL语法浅析
·判断是否数字类型(二)
·编码规范的重要性——一次PLSQL程...
·10g的MAX、MIN的bug
·过程执行报错ORA-4068
·RETURNING语句几个小问题
 
li
设为首页 | 关于我们 | 技术服务 | 收藏本站 | 网站地图 | 联系方式 | 本站友情连接