文章已同步至我的GAE博客 和WordPress博客
注: 1) ALTER TABLE 表名 ADD CONSTRAINT 新的約束名 約束
2) ALTER TABLE 表名 DROP CONSTRAINT 舊的約束名
3) ALTER TABLE 表名 RENAME 新的約束名 TO 新的約束名 (RENAME不適合SQL Server 2000,2005及以後的沒測試過)
當CHECK約束的條件發生變化時,Oracle沒有辦法直接修改約束的條件,而只能通過刪除約束並重建的方式。
前兩天在讀TOM的Effective Oracle by Design時候,突然意識到以前自己的操作是有問題的。
SQL> CREATE TABLE T
2 (ID NUMBER,
3 NAME VARCHAR2(30),
4 AGE NUMBER CONSTRAINT CK_AGE CHECK (AGE > 16)
5 );
表已創建。
如果需要修改約束CK_AGE的約束條件,已往我的做法如下:
SQL> ALTER TABLE T DROP CONSTRAINT CK_AGE;
表已更改。
SQL> ALTER TABLE T ADD CONSTRAINT CK_AGE1 CHECK(AGE > 18);
表已更改。
但是看TOM的文章的時候,發現TOM是這麼說 的:"我會用兩條命令:一條增加一個新的約束,另一條刪除舊的約束。"開始我還在奇怪,爲什麼TOM先說增加而後說刪除呢。這時我想起TOM在 EXPERT ONE ON ONE ORACLE的EXP那一章似乎介紹過,約束條件完全相同的約束可以重複加在同一張表上。於是,我明白了先增加約束的含義,這樣可以使表中的數據自始至終 都處於約束條件的限制之下,而如果先刪除約束的話,在兩個DDL語句執行之間,對錶執行的DML操作則不會收到約束的限制,雖然這個間隔時間可能很短,但 是不能排除出現這種情況的可能性。
因此正確的操作順序應該是:
SQL> DROP TABLE T;
表已丟棄。
SQL> CREATE TABLE T
2 (ID NUMBER,
3 NAME VARCHAR2(30),
4 AGE NUMBER CONSTRAINT CK_AGE CHECK (AGE > 16)
5 );
表已創建。
SQL> ALTER TABLE T ADD CONSTRAINT CK_AGE1 CHECK(AGE > 18);
表已更改。
SQL> ALTER TABLE T DROP CONSTRAINT CK_AGE;
表已更改。
約束的名稱對應用系統來說沒有實際意義,因此約束名的改變不會造成什麼影響,當然如果追求數據結構和修改前一致,可以通過RENAME CONSTRAINT的方式進行修改。
SQL> ALTER TABLE T RENAME CONSTRAINT CK_AGE1 TO CK_AGE;
表已更改。
採用這種方式,就可以保證表中的數據始終處於約束的限制之下。
大家在讀Oracle的官方文檔或TOM這種大師級的著作時,儘量把每句話的意思都搞清楚,也許只是隨便的一句話,就可以推敲出很多東西,而使你獲益匪淺。