執行以下語句報"要修改數據類型,則要更改的列必須爲空"
alter table 表名 modify (目標字段 varchar2(100));
解決步驟:
第一步,在表中加一個臨時字段
alter table 表名 add 臨時字段 目標字段原來的類型;
第二步,將目標字段的值付給臨時字段,並將目標字段置空
update 表名 set 臨時字段=目標字段,目標字段=null;
第三步,修改目標類型
alter table 表名 modify 目標字段 varchar2(100);
第四步,將臨時字段的值付給目標字段,並將臨時字段置空
update 表名 set 目標字段=臨時字段,臨時字段=null;
最後一步,刪除臨時字段
alter table 表名 drop column 臨時字段;
轉載自:http://blog.csdn.net/machinecat0898/article/details/7279464
附:
在日常維護的過程中可能碰到這樣的問題,需要修改表的字段類型。
對於絕大部分正常的情況,都是將表的字段類型的長度擴大,但是有的時候是需要縮小表
的字段長度的,甚至有的時候是要修改表的數據類型的。
SQL> CREATE TABLE T AS SELECT ROWNUM ID, A.* FROM DBA_OBJECTS A;
表已創建。
SQL> DROP TABLE T PURGE;
表已刪除。
SQL> CREATE TABLE T AS
2 SELECT OBJECT_ID, OWNER, OBJECT_NAMEITPUB個人空間 T3D}-`%`@ehR
3 FROM DBA_OBJECTS;
表已創建。
SQL> DESC T
名稱 是否爲空?類型
----------------------------------------- -------- -------------------------
OBJECT_ID NUMBER
OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(128)
SQL> SELECT MAX(LENGTH(TO_CHAR(OBJECT_ID))) FROM T;
MAX(LENGTH(TO_CHAR(OBJECT_ID)))
-------------------------------
5
SQL> ALTER TABLE T MODIFY OBJECT_ID VARCHAR2(10);
ALTER TABLE T MODIFY OBJECT_ID VARCHAR2(10)
*
第1行出現錯誤:
ORA-01439:要更改數據類型,則要修改的列必須爲空
對於這種情況,Oracle要求表的字段爲空,才能進行修改。因此對應的方法一般有兩類,
一類是在表上添加一列,在表內根據原列的值更新目標列。另一類方法是建立一張新表,
根據源表的值更新目標表的值。
其中第一類方法最省事,由於只是表的列發生變化,因此對數據庫的對象的影響相對比較
小,但是這種方法鎖表時間可能會比較長,需要儘可能在比較空閒的時間內進行,對操作
的運行時間有一定的要求。最後這種方式相對容易產生行遷移,影響後續表訪問的性能。
而第二類方法中對系統影響最小的就是在線重定義方式。這種方式鎖表時間最短,基本不
影響業務的在線訪問。可是這種方法也並不是沒有缺點,首先這種方法相對比較複雜,第
一類方法可能僅僅兩、三個SQL就搞定了,而這種方法就需要很多的SQL語句,還要調用很
多Oracle的包,複雜度比第一種情況高很多;第二類方法還需要考慮很多的東西,由於表
被替換掉了,索引、約束、觸發器、過程、權限、統計信息等等這些都是需要考慮和處理
的,否則就很容易造成問題;還有就是這類操作和第一種操作相比,會產生更多的REDO和
UNDO信息;更重要的一點是,這種方式有一定的限制條件,在11g以前,物化視圖的基表
是無法進行在線重定義的。而如果採用這類方法的其他方式,則前面提到的那些優點就不
存在了,而缺點確仍然無法避免。
因此,對於比較繁忙、數據庫可用性要求比較高的系統,對於數據量很大,直接更新要花
費大量時間的表推薦採用在線重定義方式,而對於數據量不大的表,對於系統有充足維護
時間的系統,可以考慮上面的第一類方式。
上面已經提到了,由於只是列的修改,而沒有對刪除原有的表,因此對系統的其他對象影
響比較小。除非採用增加新列刪除舊列的方式,否則不會影響系統中索引、約束、觸發器
、過程、權限和統計信息等對象,如果採用刪除舊列,那麼也只需要關注這個列相關的約
束、索引和統計信息。
如果可以確保維護時間,那麼第一類方法最大的問題就是行遷移,由於增加了新列,且給
新列賦值,記錄的長度增加,會造成行遷移的產生,從而影響表的訪問性能。
SQL> ALTER TABLE T ADD NEW_OBJECT_ID VARCHAR2(10);
表已更改。
SQL> UPDATE T SET NEW_OBJECT_ID = OBJECT_ID;
已更新50599行。
SQL> ALTER TABLE T DROP COLUMN OBJECT_ID;
表已更改。
SQL> ALTER TABLE T RENAME COLUMN NEW_OBJECT_ID TO OBJECT_ID;
表已更改。
雖然這種方式完成了操作,但是留下兩個問題,一個是列的位置發生了變化,這樣可能會
對影響一些編碼風格不好的程序:
SQL> DESC T
名稱 是否爲空?類型
----------------------------------------- -------- --------------------------
--
OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(128)
OBJECT_ID VARCHAR2(10)
SQL> INSERT INTO T (OBJECT_ID, OWNER, OBJECT_NAME) VALUES ('60000', 'YANGTK',
'T');
已創建1行。
SQL> INSERT INTO T VALUES ('60001', 'YANGTK', 'T');
已創建1行。
對於上面的標準寫法,列的順序沒有關係,但是如果採用類似下面的寫法,就會導致錯誤
的出現。
另外一個問題,就是前面提到多次的行遷移:
SQL> @?/RDBMS/ADMIN/UTLCHAIN.SQL
表已創建。
SQL> ANALYZE TABLE T LIST CHAINED ROWS;
表已分析。
SQL> SELECT COUNT(*) FROM CHAINED_ROWS;
COUNT(*)
----------
2107
其實如果採用下面的方法就可以基本上避免上面的這兩個問題:
SQL> CREATE TABLE T AS
2 SELECT OBJECT_ID, OWNER, OBJECT_NAME
3 FROM DBA_OBJECTS;
表已創建。
SQL> ALTER TABLE T ADD COL_TEMP NUMBER;
表已更改。
SQL> UPDATE T SET COL_TEMP = OBJECT_ID, OBJECT_ID = NULL;
已更新50600行。
SQL> ALTER TABLE T MODIFY OBJECT_ID VARCHAR2(10);
表已更改。
SQL> UPDATE T SET OBJECT_ID = COL_TEMP, COL_TEMP = NULL;
已更新50600行。
SQL> ALTER TABLE T DROP COLUMN COL_TEMP;
表已更改。
SQL> DESC T
名稱 是否爲空?類型
----------------------------------------- -------- -------------------------
OBJECT_ID VARCHAR2(10)
OWNER VARCHAR2(30)
OBJECT_NAME VARCHAR2(128)
SQL> ANALYZE TABLE T LIST CHAINED ROWS;
表已分析。
SQL> SELECT COUNT(*) FROM CHAINED_ROWS;
COUNT(*)
----------
0
採用同時更新表中兩個列的方式,可以有效的避免行遷移的產生,因爲在更新的完成後,
表記錄的長度增加十分有限,只是由於OBJECT_ID的NULL出現在中間的位置,而使得每條
記錄的長度增加了1,而再執行第二次操作的時候,這個長度1的代價又被消除掉了,因此
這種方式更新基本上不會產生行遷移。由於列的順序沒有發生變化,也不會對應用構成很
大的影響。而且原始列沒有被刪除,索引、約束等都不需要改變。
這種方法的缺點在於需要更新兩次,更新數據量比較大,而且每次更新產生的REDO和UNDO
都比直接更新一個字段要多。
另外列出一些表結構的更改語法
1.編輯表的字段
修改一個列的數據類型(一般限於修改長度,修改爲一個不同類型時有諸多限制):
語法: ALTER TABLE 表名 MODIFY(列名 數據類型);
eg1: alter table skate_test modify (author number(10,0) )
在修改列的長度時候,只能編輯比現有字段實際存的長度還要大,否則提示下面的錯誤:
ORA-01441: 無法減小列長度, 因爲一些值過大
eg2: alter table skate_test modify (author varchar2(10) )
在修改列的數據類型的時候,所修改的列必須爲空,否則提示下面的錯誤:
ORA-01439: 要更改數據類型, 則要修改的列必須爲空
2.增加一個列
語法: ALTER TABLE 表名 ADD(列名 數據類型);
eg1:ALTER TABLE skate_test ADD(author NUMBER(38,0) not null);
3.給列改名:
語法: ALTER TABLE 表名 RENAME COLUMN 當前列名 TO 新列名;
eg1: ALTER TABLE skate_test RENAME COLUMN author TO authorer_new
4.刪除一個列
語法: ALTER TABLE 表名 DROP COLUMN 列名;
eg1:alter table skate_test drop column author
5、刪除一行
語法:delete from 表名 where 條件;
例:delete from dept where deptno=10;
6.將一個表改名
語法: ALTER TABLE 當前表名 RENAME TO 新表名;
eg1: alter table skate_test rename to test_sakte
7.給表加註釋
comment column on 表名.列名 is '註釋內容'; //修改表的列的註釋
COMMENT ON TABLE MOVO_NEW.TEST_SAKTE IS '註釋內容'; //修改表的註釋
轉載自:http://www.51testing.com/?uid-33873-action-viewspace-itemid-197251