PostgreSQL 修改表

2021-08-26 10:00 更新
5.6.1. 增加列
5.6.2. 移除列
5.6.3. 增加約束
5.6.4. 移除約束
5.6.5. 更改列的默認(rèn)值
5.6.6. 修改列的數(shù)據(jù)類(lèi)型
5.6.7. 重命名列
5.6.8. 重命名表

當(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ì)的信息。

5.6.1. 增加列

要增加一個(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)后文)。

5.6.2. 移除列

為了移除一個(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é)。

5.6.3. 增加約束

為了增加一個(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)符合約束。

5.6.4. 移除約束

為了移除一個(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)的,所以不能用第一種方式。)

5.6.5. 更改列的默認(rèn)值

要為一個(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è)置為空值。

5.6.6. 修改列的數(shù)據(jù)類(lèi)型

為了將一個(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ò)的約束。

5.6.7. 重命名列

要重命名一個(gè)列:

ALTER TABLE products RENAME COLUMN product_no TO product_number;

5.6.8. 重命名表

要重命名一個(gè)表:

ALTER TABLE products RENAME TO items;


以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)