《Oracle管理员指南》说:
使用ALTER TABLE ... MODIFY语句修改现有的列定义。您可以修改列数据类型,默认值,列约束,列表达式(对于虚拟列)和列加密。
如果所有现有数据都满足新长度,则可以增加或减少现有列的长度。您可以将列从字节语义更改为CHAR语义,反之亦然。您必须设置初始化参数BLANK_TRIMMING = TRUE来减少非空CHAR列的长度。
如果要修改表以增加数据类型为CHAR的列的长度,请意识到这可能是一项耗时的操作,并且可能需要大量的额外存储,尤其是在表包含许多行的情况下。这是因为每行中的CHAR值都必须空白填充才能满足新的列长度。
《Oracle SQL语言参考》提供了更多详细信息,包括以下内容:
如果列的所有行都包含空值,则可以更改任何列的数据类型。但是,如果更改实例化视图容器表中列的数据类型,则Oracle数据库会使相应的实例化视图无效。
无论所有行是否都包含空值,都可以始终增加字符或原始列的大小或数字列的精度。只要更改不需要修改数据,就可以减小列的数据类型的大小。如果存在的数据超过新的长度限制,则数据库将扫描现有数据并返回错误。
您可以将DATE列修改为TIMESTAMP或TIMESTAMP WITH LOCAL TIME ZONE。您可以将任何具有本地时区的TIMESTAMP修改为DATE列。
如果表为空,则可以增加或减少datetime或interval列的前导字段或小数秒值。如果表不为空,则只能增加日期时间或间隔列的前导字段或小数秒。
对于CHAR和VARCHAR2列,可以通过指定CHAR(指示最初以字节为单位指定的列的字符语义)或BYTE(指示最初以字符为单位指定的列的字节语义)来更改长度语义。要了解现有列的长度语义,请查询ALL_,USER_或DBA_TAB_COLUMNS数据字典视图的CHAR_USED列。
上述文档中还有其他信息和限制。这是尝试降低Number列的精度并减小Varchar2的长度的演示。您可以尝试其他更改,以便知道会发生什么。
--Setup.
DROP TABLE FOO;
CREATE TABLE FOO (BAR Number, BAR2 VARCHAR2(300));
INSERT INTO FOO (SELECT Level, RPAD(to_char(Level),10*Level,to_char(Level))
FROM DUAL CONNECT BY Level <=20);
COMMIT;
SELECT * FROM FOO;
--Reduce Number to Number(10).
ALTER TABLE FOO MODIFY (BAR NUMBER (10));
--Reduce Varchar2(300) to Varchar2(100) (data would be truncated).
ALTER TABLE FOO MODIFY (BAR2 VARCHAR2(100));
--Reduce Varchar2(300) to Varchar2(200) (no data would be truncated).
ALTER TABLE FOO MODIFY (BAR2 VARCHAR2(200));
alter语句具有以下输出:
ALTER TABLE FOO MODIFY (BAR NUMBER (10))
Error report:
SQL Error: ORA-01440: column to be modified must be empty to decrease precision or scale
01440. 00000 - "column to be modified must be empty to decrease precision or scale"
ALTER TABLE FOO MODIFY (BAR2 VARCHAR2(100))
Error report:
SQL Error: ORA-01441: cannot decrease column length because some value is too big
01441. 00000 - "cannot decrease column length because some value is too big"
table FOO altered.
通过创建新列来降低精度。
ALTER TABLE FOO ADD (BAR3 NUMBER(10));
UPDATE FOO SET Bar3 = Bar;
ALTER TABLE FOO DROP COLUMN BAR;
ALTER TABLE FOO RENAME COLUMN BAR3 TO BAR;