Oracle修改字段類型時報"要更改的列必須爲空"處理方法

執行以下語句報"要修改數據類型,則要更改的列必須爲空"
     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



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章