W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
當(dāng)我們已經(jīng)創(chuàng)建了一個(gè)表并意識(shí)到犯了一個(gè)錯(cuò)誤或者應(yīng)用需求發(fā)生改變時(shí),我們可以移除表并重新創(chuàng)建它。但如果表中已經(jīng)被填充數(shù)據(jù)或者被其他數(shù)據(jù)庫(kù)對(duì)象引用(例如有一個(gè)外鍵約束),這種做法就顯得很不方便。因此,PostgreSQL提供了一族命令來(lái)對(duì)已有的表進(jìn)行修改。注意這和修改表中所包含的數(shù)據(jù)是不同的,這里要做的是對(duì)表的定義或者說(shuō)結(jié)構(gòu)進(jìn)行修改。
利用這些命令,我們可以:
增加列
移除列
增加約束
移除約束
修改默認(rèn)值
修改列數(shù)據(jù)類(lèi)型
重命名列
重命名表
所有這些動(dòng)作都由ALTER TABLE命令執(zhí)行,其參考頁(yè)面中包含更詳細(xì)的信息。
要增加一個(gè)列,可以使用這樣的命令:
ALTER TABLE products ADD COLUMN description text;
新列將被默認(rèn)值所填充(如果沒(méi)有指定DEFAULT
子句,則會(huì)填充空值)。
從 PostgreSQL 11開(kāi)始,添加一個(gè)具有常量默認(rèn)值的列不再意味著在執(zhí)行ALTER TABLE
語(yǔ)句時(shí)需要更新表的每一行。
相反,默認(rèn)值將在下次訪問(wèn)該行時(shí)返回,并在表被重寫(xiě)時(shí)應(yīng)用,從而使得ALTER TABLE
即使在大表上也非??臁?
但是,如果默認(rèn)值是可變的(例如clock_timestamp()
),則每一行需要被ALTER TABLE
被執(zhí)行時(shí)計(jì)算的值更新。
為避免潛在的長(zhǎng)時(shí)間的更新操作,特別是如果你想要用大多數(shù)非默認(rèn)值填充列,那么最好添加沒(méi)有默認(rèn)值的列,再用 UPDATE
插入正確的值,然后按照下面所述添加任何期望的默認(rèn)值。
也可以同時(shí)為列定義約束,語(yǔ)法:
ALTER TABLE products ADD COLUMN description text CHECK (description <> '');
事實(shí)上CREATE TABLE
中關(guān)于一列的描述都可以應(yīng)用在這里。記住不管怎樣,默認(rèn)值必須滿足給定的約束,否則ADD
將會(huì)失敗。也可以先將新列正確地填充好,然后再增加約束(見(jiàn)后文)。
為了移除一個(gè)列,使用如下的命令:
ALTER TABLE products DROP COLUMN description;
列中的數(shù)據(jù)將會(huì)消失。涉及到該列的表約束也會(huì)被移除。然而,如果該列被另一個(gè)表的外鍵所引用,PostgreSQL不會(huì)安靜地移除該約束。我們可以通過(guò)增加CASCADE
來(lái)授權(quán)移除任何依賴(lài)于被刪除列的所有東西:
ALTER TABLE products DROP COLUMN description CASCADE;
關(guān)于這個(gè)操作背后的一般性機(jī)制請(qǐng)見(jiàn)第 5.14 節(jié)。
為了增加一個(gè)約束,可以使用表約束的語(yǔ)法,例如:
ALTER TABLE products ADD CHECK (name <> '');
ALTER TABLE products ADD CONSTRAINT some_name UNIQUE (product_no);
ALTER TABLE products ADD FOREIGN KEY (product_group_id) REFERENCES product_groups;
要增加一個(gè)不能寫(xiě)成表約束的非空約束,可使用語(yǔ)法:
ALTER TABLE products ALTER COLUMN product_no SET NOT NULL;
該約束會(huì)立即被檢查,所以表中的數(shù)據(jù)必須在約束被增加之前就已經(jīng)符合約束。
為了移除一個(gè)約束首先需要知道它的名稱(chēng)。如果在創(chuàng)建時(shí)已經(jīng)給它指定了名稱(chēng),那么事情就變得很容易。否則約束的名稱(chēng)是由系統(tǒng)生成的,我們必須先找出這個(gè)名稱(chēng)。psql的命令\d
將會(huì)對(duì)此有所幫助,其他接口也會(huì)提供方法來(lái)查看表的細(xì)節(jié)。因此命令是:
表名
ALTER TABLE products DROP CONSTRAINT some_name;
(如果處理的是自動(dòng)生成的約束名稱(chēng),如$2
,別忘了用雙引號(hào)使它變成一個(gè)合法的標(biāo)識(shí)符。)
和移除一個(gè)列相似,如果需要移除一個(gè)被某些別的東西依賴(lài)的約束,也需要加上CASCADE
。一個(gè)例子是一個(gè)外鍵約束依賴(lài)于被引用列上的一個(gè)唯一或者主鍵約束。
這對(duì)除了非空約束之外的所有約束類(lèi)型都一樣有效。為了移除一個(gè)非空約束可以用:
ALTER TABLE products ALTER COLUMN product_no DROP NOT NULL;
(回憶一下,非空約束是沒(méi)有名稱(chēng)的,所以不能用第一種方式。)
要為一個(gè)列設(shè)置一個(gè)新默認(rèn)值,使用命令:
ALTER TABLE products ALTER COLUMN price SET DEFAULT 7.77;
注意這不會(huì)影響任何表中已經(jīng)存在的行,它只是為未來(lái)的INSERT
命令改變了默認(rèn)值。
要移除任何默認(rèn)值,使用:
ALTER TABLE products ALTER COLUMN price DROP DEFAULT;
這等同于將默認(rèn)值設(shè)置為空值。相應(yīng)的,試圖刪除一個(gè)未被定義的默認(rèn)值并不會(huì)引發(fā)錯(cuò)誤,因?yàn)槟J(rèn)值已經(jīng)被隱式地設(shè)置為空值。
為了將一個(gè)列轉(zhuǎn)換為一種不同的數(shù)據(jù)類(lèi)型,使用如下命令:
ALTER TABLE products ALTER COLUMN price TYPE numeric(10,2);
只有當(dāng)列中的每一個(gè)項(xiàng)都能通過(guò)一個(gè)隱式造型轉(zhuǎn)換為新的類(lèi)型時(shí)該操作才能成功。如果需要一種更復(fù)雜的轉(zhuǎn)換,應(yīng)該加上一個(gè)USING
子句來(lái)指定應(yīng)該如何把舊值轉(zhuǎn)換為新值。
PostgreSQL將嘗試把列的默認(rèn)值轉(zhuǎn)換為新類(lèi)型,其他涉及到該列的任何約束也是一樣。但是這些轉(zhuǎn)換可能失敗或者產(chǎn)生奇特的結(jié)果。因此最好在修改類(lèi)型之前先刪除該列上所有的約束,然后在修改完類(lèi)型后重新加上相應(yīng)修改過(guò)的約束。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: