之前用 exp 导出,报了 EXP-00011 的错误,对应的表不存在,问了研发这些都是什么表,不导出对业务有没有影响,得知没影响之后就没去处理了。(现在想一想不去处理好像确实不太好,虽然说表没数据,但是要是突然有一天需要用到这张表,查不到就惨了)今天偶然看到一篇文章有讲到这个问题,随记录下来。

关键知识点:deferred_segment_creation 参数

Oracle 11g 新增一个参数 deferred_segment_creation,它的含义是段延迟创建。默认情况下,这个值是 true,也就是说,当你新建一张表后没有往里插入数据,这个表不会立即分配 extent。

解决方法

方法一 修改deferred_segment_creation参数

修改 deferred_segment_creation 参数,配置之后,只对新创建的表会分配 segment。对之前已经建立的空表是不起作用的。通常情况下,还需要重启数据库,让参数真正生效。

#修改参数
alter system set deferred_segment_creation=FALSE;

#查看参数是否生效
SELECT name, TYPE, VALUE, isses_modifiable, issys_modifiable FROM v$parameter WHERE name LIKE 'defer%';

方法二 在创建表时指定段创建方式

如果你不想修改系统参数,也可以在创建表的时候直接指定是否创建段。

create table test(id number(10)) SEGMENT CREATION IMMEDIATE;

方法三 手动为表分配表

如果你已经创建了空表,并且希望为它们分配段,也可以使用以下方法。

BEGIN 
 DBMS_SPACE_ADMIN.materialize_deferred_segments ( 
 schema_name => 'SCOTT', 
 table_name => 'TEST' 
 ); 
END; 
或者
ALTER TABLE TableName ALLOCATE EXTENT;

#分区表
ALTER TABLE TableName modify partition partition_name ALLOCATE EXTENT;

方法四 手动插入数据

人工插入数据之后删除,嘻嘻,有点费人就是了。

方法五 构建对空表分配空间的 sql 命令

如果你想批量为当前用户下的所有空表分配空间,可以按照以下步骤操作:

首先,查询当前用户下的所有空表:

SELECT table_name
FROM user_tables
WHERE NUM_ROWS = 0;

然后,构建针对空表分配空间的命令语句:

set echo off feed off pages 0
spool temp.sql 

SELECT'alter table ' || table_name || ' allocate extent;'
FROM user_tables 
WHERE num_rows = 0AND partitioned = 'NO'; 

SELECT'alter table '
|| table_name 
|| ' modify partition '
|| partition_name 
|| ' allocate extent;'
FROM USER_TAB_PARTITIONS 
WHERE num_rows = 0; 
spool off 
set echo on feed on

@ temp.sql