LONG类型由于过多的限制,Oracle很早就推荐使用LOB类型进行替代,在Oracle的官方文档中给出了几种将LONG类型迁移到LOB类型的方法,这里简单讨论一下。
这一篇讨论利用TO_LOB进行迁移。
官方文档给出的方法如下:
SQL> CREATE TABLE T
2 (ID NUMBER,
3 CONTENTS LONG);
Table created.
SQL> INSERT INTO T
2 SELECT ROWNUM, OWNER || OBJECT_NAME || OBJECT_TYPE
3 FROM ALL_OBJECTS;
75327 rows created.
SQL> COMMIT;
Commit complete.
SQL> CREATE TABLE T_NEW
2 (ID NUMBER,
3 CONTENTS CLOB);
Table created.
SQL> INSERT INTO T_NEW
2 SELECT ID, TO_LOB(CONTENTS)
3 FROM T;
75327 rows created.
SQL> COMMIT;
Commit complete.
SQL> DROP TABLE T PURGE;
Table dropped.
SQL> RENAME T_NEW TO T;
Table renamed.
这种方法需要删除原表,先不说是否会造成业务停顿,光是原表涉及的索引、约束、权限等重建就已经很麻烦了。
其实这个方法可以改进为:
SQL> DROP TABLE T PURGE;
Table dropped.
SQL> CREATE TABLE T
2 (ID NUMBER,
3 CONTENTS LONG);
Table created.
SQL> INSERT INTO T
2 SELECT ROWNUM, OWNER || OBJECT_NAME || OBJECT_TYPE
3 FROM ALL_OBJECTS;
75327 rows created.
SQL> COMMIT;
Commit complete.
SQL> ALTER TABLE T
2 ADD (CONTENTS_NEW CLOB);
Table altered.
SQL> UPDATE T
2 SET CONTENTS_NEW = TO_LOB(CONTENTS);
SET CONTENTS_NEW = TO_LOB(CONTENTS)
*
ERROR at line 2:
ORA-00932: inconsistent datatypes: expected - got LONG
SQL> ALTER TABLE T ADD PRIMARY KEY (ID);
Table altered.
SQL> UPDATE T T1
2 SET CONTENTS_NEW =
3 (SELECT TO_LOB(CONTENTS)
4 FROM T T2
5 WHERE T1.ID = T2.ID);
75327 rows updated.
SQL> ALTER TABLE T DROP COLUMN CONTENTS;
Table altered.
SQL> ALTER TABLE T RENAME COLUMN CONTENTS_NEW TO CONTENTS;
Table altered.
虽然Oracle不支持在UPDATE语句的时候直接使用TO_LOB进行LONG类型的转换,但是可以利用自关联的方式绕过Oracle的限制。
这种方法避免了表的重建,也就避免了索引、约束以及权限等对象的重建。
不过LONG字段删除后,会留下很多的空闲空间分别在表的各个BLOCK中,如果有必要收缩高水位线,可以考虑对表再进行一次MOVE操作。