前两天论坛上有人问如何才能通过触发器来实现对包含LONG或LONG RAW类型字段的表的复制。给他做了个最简单的例子,在这里记录一下。
由于在触发器中不能对LONG或LONG 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
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 /
触发器已创建
对于LONG、LONG RAW类型的复制,用触发器并不是个好的办法,唯一的好处就是相对简单,而且不需要修改程序,完全在数据库级上实现,不过效率肯定不会太高
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/7916042/viewspace-889348/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/7916042/viewspace-889348/