1、测试
在sys用户下创建测试表:
SQL> create table t as select object_id,object_name from dba_objects;
表已创建。
SQL> select count(*)from t ;
COUNT(*)
----------
48940
删除object_name 列:
SQL> alter table t drop column object_name;
alter table t drop column object_name
*
第 1 行出现错误:
ORA-12988: cannot drop column from table owned by SYS
我去。。。在sys用户下面的表是不能删除列的。。。。这下肿么办?简单。。。换个表空间,换个用户解决:
SQL> create table scott.t2 tablespace users as select * from t ;
表已创建。
给表建个索引,一会测试用:
SQL> create index i_t1 on t2(object_id);
索引已创建。
SQL> select segment_name,partition_name,segment_type,tablespace_name,bytes,blocks,extents from user_segments where segment_name like '%T2%' ;
SEGMENT_NAME PARTITION_NAME SEGMENT_TYPE TABLESPACE BYTES BLOCKS EXTENTS
--------------- -------------------- ------------------ ---------- ---------- ------ -------
I_T2 INDEX USERS 983040 120 15
T2 TABLE USERS 2097152 256 17
删除列,需要一段时间,其中会牵涉到表内锁的锁定。
SQL> alter table t2 drop column object_id;
表已更改。
再次查询段结构:
SQL> select segment_name,partition_name,segment_type,tablespace_name,bytes,blocks,extents from user_segments where segment_name like '%T2%';
索引也会一并删除的。。。。
注意:在大表上删除列的时候,一定要注意,它会花费很长的时间,锁住表,影响数据库性能。
在oracle数据库中,还有一种方法用来删除列:
SQL> alter table t2 set unused column object_id;
表已更改。
这条语句的意思是把object_id置为不可用,更改此列的名称(oracle内部明白),但是不会释放此列对应的空间。(我测试的时候,如果删除的列时索引列,然后再去找索引就找不到了,查得dba_indexes视图中的index_name 没有了,总行数也少了一行。猜测应该是索引也重命名了,已经不是索引了。但是空间估计也不会释放的。没有测试。。。)这个执行非常快,和truncate的机制差不多,在生产库中如果需要紧急应用,为了避免drop column操作锁住表,可以使用这个语句。等到系统有充足的时间时,我们再用另一个语句来释放空间:
alter table t2 drop unused columns;
表已更改。
这个操作是比较慢的。。