2025年9月25日: PostgreSQL 18 釋出!
支援的版本: 當前 (18) / 17 / 16 / 15 / 14 / 13
開發版本: devel
不支援的版本: 12 / 11 / 10 / 9.6 / 9.5 / 9.4 / 9.3 / 9.2 / 9.1 / 9.0 / 8.4 / 8.3 / 8.2 / 8.1 / 8.0 / 7.4 / 7.3 / 7.2 / 7.1

ALTER TABLE

ALTER TABLE — 更改表定義

概要

ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
    action [, ... ]
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
    RENAME [ COLUMN ] column_name TO new_column_name
ALTER TABLE [ IF EXISTS ] [ ONLY ] name [ * ]
    RENAME CONSTRAINT constraint_name TO new_constraint_name
ALTER TABLE [ IF EXISTS ] name
    RENAME TO new_name
ALTER TABLE [ IF EXISTS ] name
    SET SCHEMA new_schema
ALTER TABLE ALL IN TABLESPACE name [ OWNED BY role_name [, ... ] ]
    SET TABLESPACE new_tablespace [ NOWAIT ]
ALTER TABLE [ IF EXISTS ] name
    ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT }
ALTER TABLE [ IF EXISTS ] name
    DETACH PARTITION partition_name [ CONCURRENTLY | FINALIZE ]

where action is one of:

    ADD [ COLUMN ] [ IF NOT EXISTS ] column_name data_type [ COLLATE collation ] [ column_constraint [ ... ] ]
    DROP [ COLUMN ] [ IF EXISTS ] column_name [ RESTRICT | CASCADE ]
    ALTER [ COLUMN ] column_name [ SET DATA ] TYPE data_type [ COLLATE collation ] [ USING expression ]
    ALTER [ COLUMN ] column_name SET DEFAULT expression
    ALTER [ COLUMN ] column_name DROP DEFAULT
    ALTER [ COLUMN ] column_name { SET | DROP } NOT NULL
    ALTER [ COLUMN ] column_name SET EXPRESSION AS ( expression )
    ALTER [ COLUMN ] column_name DROP EXPRESSION [ IF EXISTS ]
    ALTER [ COLUMN ] column_name ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ]
    ALTER [ COLUMN ] column_name { SET GENERATED { ALWAYS | BY DEFAULT } | SET sequence_option | RESTART [ [ WITH ] restart ] } [...]
    ALTER [ COLUMN ] column_name DROP IDENTITY [ IF EXISTS ]
    ALTER [ COLUMN ] column_name SET STATISTICS { integer | DEFAULT }
    ALTER [ COLUMN ] column_name SET ( attribute_option = value [, ... ] )
    ALTER [ COLUMN ] column_name RESET ( attribute_option [, ... ] )
    ALTER [ COLUMN ] column_name SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT }
    ALTER [ COLUMN ] column_name SET COMPRESSION compression_method
    ADD table_constraint [ NOT VALID ]
    ADD table_constraint_using_index
    ALTER CONSTRAINT constraint_name [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ]
    ALTER CONSTRAINT constraint_name [ INHERIT | NO INHERIT ]
    VALIDATE CONSTRAINT constraint_name
    DROP CONSTRAINT [ IF EXISTS ]  constraint_name [ RESTRICT | CASCADE ]
    DISABLE TRIGGER [ trigger_name | ALL | USER ]
    ENABLE TRIGGER [ trigger_name | ALL | USER ]
    ENABLE REPLICA TRIGGER trigger_name
    ENABLE ALWAYS TRIGGER trigger_name
    DISABLE RULE rewrite_rule_name
    ENABLE RULE rewrite_rule_name
    ENABLE REPLICA RULE rewrite_rule_name
    ENABLE ALWAYS RULE rewrite_rule_name
    DISABLE ROW LEVEL SECURITY
    ENABLE ROW LEVEL SECURITY
    FORCE ROW LEVEL SECURITY
    NO FORCE ROW LEVEL SECURITY
    CLUSTER ON index_name
    SET WITHOUT CLUSTER
    SET WITHOUT OIDS
    SET ACCESS METHOD { new_access_method | DEFAULT }
    SET TABLESPACE new_tablespace
    SET { LOGGED | UNLOGGED }
    SET ( storage_parameter [= value] [, ... ] )
    RESET ( storage_parameter [, ... ] )
    INHERIT parent_table
    NO INHERIT parent_table
    OF type_name
    NOT OF
    OWNER TO { new_owner | CURRENT_ROLE | CURRENT_USER | SESSION_USER }
    REPLICA IDENTITY { DEFAULT | USING INDEX index_name | FULL | NOTHING }

and partition_bound_spec is:

IN ( partition_bound_expr [, ...] ) |
FROM ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] )
  TO ( { partition_bound_expr | MINVALUE | MAXVALUE } [, ...] ) |
WITH ( MODULUS numeric_literal, REMAINDER numeric_literal )

and column_constraint is:

[ CONSTRAINT constraint_name ]
{ NOT NULL [ NO INHERIT ] |
  NULL |
  CHECK ( expression ) [ NO INHERIT ] |
  DEFAULT default_expr |
  GENERATED ALWAYS AS ( generation_expr ) [ STORED | VIRTUAL ] |
  GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ ( sequence_options ) ] |
  UNIQUE [ NULLS [ NOT ] DISTINCT ] index_parameters |
  PRIMARY KEY index_parameters |
  REFERENCES reftable [ ( refcolumn ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ]
    [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ]

and table_constraint is:

[ CONSTRAINT constraint_name ]
{ CHECK ( expression ) [ NO INHERIT ] |
  NOT NULL column_name [ NO INHERIT ] |
  UNIQUE [ NULLS [ NOT ] DISTINCT ] ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) index_parameters |
  PRIMARY KEY ( column_name [, ... ] [, column_name WITHOUT OVERLAPS ] ) index_parameters |
  EXCLUDE [ USING index_method ] ( exclude_element WITH operator [, ... ] ) index_parameters [ WHERE ( predicate ) ] |
  FOREIGN KEY ( column_name [, ... ] [, PERIOD column_name ] ) REFERENCES reftable [ ( refcolumn [, ... ]  [, PERIOD refcolumn ] ) ]
    [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETE referential_action ] [ ON UPDATE referential_action ] }
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] [ ENFORCED | NOT ENFORCED ]

and table_constraint_using_index is:

    [ CONSTRAINT constraint_name ]
    { UNIQUE | PRIMARY KEY } USING INDEX index_name
    [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]

index_parameters in UNIQUE, PRIMARY KEY, and EXCLUDE constraints are:

[ INCLUDE ( column_name [, ... ] ) ]
[ WITH ( storage_parameter [= value] [, ... ] ) ]
[ USING INDEX TABLESPACE tablespace_name ]

exclude_element in an EXCLUDE constraint is:

{ column_name | ( expression ) } [ COLLATE collation ] [ opclass [ ( opclass_parameter = value [, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]

referential_action in a FOREIGN KEY/REFERENCES constraint is:

{ NO ACTION | RESTRICT | CASCADE | SET NULL [ ( column_name [, ... ] ) ] | SET DEFAULT [ ( column_name [, ... ] ) ] }

描述

ALTER TABLE 更改現有表的定義。下面描述了幾種子形式。請注意,每種子形式可能需要的鎖級別不同。除非另有明確說明,否則將獲得 ACCESS EXCLUSIVE 鎖。當給出多個子命令時,獲得的鎖將是任何子命令所需的最嚴格的鎖。

ADD COLUMN [ IF NOT EXISTS ] #

此形式在表中新增一個新列,使用與 CREATE TABLE 相同的語法。如果指定了 IF NOT EXISTS 且同名的列已存在,則不會丟擲錯誤。

DROP COLUMN [ IF EXISTS ] #

此形式從表中刪除一列。涉及該列的索引和表約束也將被自動刪除。如果刪除該列會導致統計資訊僅包含單個列的資料,則引用該列的多變數統計資訊也將被刪除。如果表外有任何內容依賴於該列(例如,外部索引鍵引用或檢視),則需要說 CASCADE。如果指定了 IF EXISTS 且該列不存在,則不會丟擲錯誤。在這種情況下,會發出通知。

SET DATA TYPE #

此形式更改表中列的資料型別。涉及該列的索引和簡單表約束將透過重新解析原始提供的表示式自動轉換為使用新的列型別。可選的 COLLATE 子句指定新列的排序規則;如果省略,則排序規則為新列型別的預設值。可選的 USING 子句指定如何從舊值計算新列值;如果省略,則預設轉換與從舊資料型別到新資料型別的賦值轉換相同。如果舊型別到新型別沒有隱式轉換或賦值轉換,則必須提供 USING 子句。

使用此形式時,將刪除該列的統計資訊,因此建議稍後在表上執行 ANALYZE。對於生成的虛擬列,不需要 ANALYZE,因為這類列從不具有統計資訊。

SET/DROP DEFAULT #

這些形式設定或刪除列的預設值(刪除等同於將預設值設定為 NULL)。新的預設值僅適用於後續的 INSERTUPDATE 命令;它不會導致表中已有的行發生更改。

SET/DROP NOT NULL #

這些形式更改列是否被標記為允許 NULL 值或拒絕 NULL 值。

SET NOT NULL 僅可應用於滿足以下條件的列:表中沒有任何記錄包含該列的 NULL 值。通常,這會在 ALTER TABLE 期間透過掃描整個表來檢查,除非指定了 NOT VALID;然而,如果存在一個有效的 CHECK 約束(並且在同一命令中未刪除),該約束證明不會出現 NULL,則將跳過表掃描。如果列具有無效的非空約束,則 SET NOT NULL 將對其進行驗證。

如果此表是分割槽表,則無法對標記為 NOT NULL 的父表中的列執行 DROP NOT NULL。要刪除所有分割槽中的 NOT NULL 約束,請在父表上執行 DROP NOT NULL。即使父表上沒有 NOT NULL 約束,也可以根據需要將其新增到單個分割槽中;也就是說,子分割槽可以禁止 null 值,即使父分割槽允許,反之則不行。也可以僅從父表 ONLY 刪除 NOT NULL 約束,這不會從子分割槽中刪除它。

SET EXPRESSION AS #

此形式替換生成列的表示式。儲存的生成列中的現有資料將被重寫,並且所有未來的更改都將應用新的生成表示式。

當此形式用於儲存的生成列時,其統計資訊將被刪除,因此建議稍後在表上執行 ANALYZE。對於虛擬生成列,不需要 ANALYZE,因為這類列從不具有統計資訊。

DROP EXPRESSION [ IF EXISTS ] #

此形式將儲存的生成列轉換為普通的基準列。列中的現有資料將被保留,但未來的更改將不再應用生成表示式。

此形式目前僅支援儲存的生成列(不支援虛擬的)。

如果指定了 DROP EXPRESSION IF EXISTS 且該列不是生成列,則不會丟擲錯誤。在這種情況下,會發出通知。

ADD GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY
SET GENERATED { ALWAYS | BY DEFAULT }
DROP IDENTITY [ IF EXISTS ] #

這些形式更改列是否為標識列,或更改現有標識列的生成屬性。有關詳細資訊,請參閱 CREATE TABLE。與 SET DEFAULT 類似,這些形式僅影響後續 INSERTUPDATE 命令的行為;它們不會導致表中已有的行發生更改。

如果指定了 DROP IDENTITY IF EXISTS 且該列不是標識列,則不會丟擲錯誤。在這種情況下,會發出通知。

SET sequence_option
RESTART #

這些形式修改現有標識列的基礎序列。 sequence_optionALTER SEQUENCE 支援的選項,例如 INCREMENT BY

SET STATISTICS #

此形式設定列的每列統計資訊收集目標,供後續的 ANALYZE 操作使用。目標可以在 0 到 10000 的範圍內設定。將其設定為 DEFAULT 以恢復使用系統預設統計資訊目標(default_statistics_target)。(設定為 -1 是一個過時的拼寫方式,得到相同的結果。)有關 PostgreSQL 查詢規劃器使用統計資訊的更多資訊,請參閱 第 14.2 節

SET STATISTICS 會獲取一個 SHARE UPDATE EXCLUSIVE 鎖。

SET ( attribute_option = value [, ... ] )
RESET ( attribute_option [, ... ] ) #

此形式設定或重置每屬性選項。當前,唯一定義的每屬性選項是 n_distinctn_distinct_inherited,它們會覆蓋後續 ANALYZE 操作進行的不同的值數量估計。 n_distinct 影響表本身的統計資訊,而 n_distinct_inherited 影響為表及其繼承子項收集的統計資訊。當設定為正值時,ANALYZE 將假定該列包含指定數量的不同非空值。當設定為負值(必須大於或等於 -1)時,ANALYZE 將假定列中不同非空值的數量與表的大小成正比;確切的計數透過將估計的表大小乘以給定數字的絕對值來計算。例如,值 -1 表示列中的所有值都不同,而值 -0.5 表示每個值平均出現兩次。當表的大小隨時間變化時,這可能很有用,因為與行數的乘法是在查詢規劃時進行的。指定值為 0 可恢復到正常估計不同值的數量。有關 PostgreSQL 查詢規劃器使用統計資訊的更多資訊,請參閱 第 14.2 節

更改每屬性選項會獲取一個 SHARE UPDATE EXCLUSIVE 鎖。

SET STORAGE { PLAIN | EXTERNAL | EXTENDED | MAIN | DEFAULT } #

此形式設定列的儲存模式。這控制是內聯儲存還是在輔助表中儲存該列,以及資料是否應被壓縮。TOASTPLAIN 必須用於固定長度值,如 integer,它是內聯、未壓縮的。MAIN 用於內聯、可壓縮資料。EXTERNAL 用於外部、未壓縮資料,EXTENDED 用於外部、壓縮資料。寫入 DEFAULT 將儲存模式設定為列資料型別的預設模式。對於大多數支援非 PLAIN 儲存的資料型別,EXTENDED 是預設值。使用 EXTERNAL 可以加快非常大的 textbytea 值的子字串操作的速度,但會增加儲存空間。請注意,ALTER TABLE ... SET STORAGE 本身不會改變表中的任何內容;它只會設定未來表更新要遵循的策略。有關更多資訊,請參閱 第 66.2 節

SET COMPRESSION compression_method #

此形式設定列的壓縮方法,決定了未來插入的值將如何被壓縮(如果儲存模式允許壓縮)。這不會導致表被重寫,因此現有資料可能仍會以其他壓縮方法進行壓縮。如果使用 pg_restore 恢復表,那麼所有值都將以配置的壓縮方法重寫。但是,當資料從另一個關係插入時(例如,透過 INSERT ... SELECT),源表中的值不一定會被解壓,因此任何先前壓縮的資料可能會保留其現有的壓縮方法,而不是以目標列的壓縮方法重新壓縮。支援的壓縮方法是 pglzlz4。(只有在使用 --with-lz4 構建 PostgreSQL 時,lz4 才可用。)此外,compression_method 可以是 default,它選擇預設行為,即在資料插入時諮詢 default_toast_compression 設定以確定要使用的方法。

ADD table_constraint [ NOT VALID ] #

此形式在表中新增一個新約束,使用與 CREATE TABLE 相同的約束語法,加上 NOT VALID 選項,該選專案前僅允許用於外部索引鍵、CHECK 和非空約束。

通常,此形式將導致掃描表以驗證表中所有現有行是否滿足新約束。但如果使用 NOT VALID 選項,則會跳過這個可能很耗時的掃描。該約束仍然會應用於後續的插入或更新(也就是說,它們將失敗,除非在引用表中存在匹配的行(對於外部索引鍵),或者它們將失敗,除非新行符合指定的檢查條件)。但是,資料庫不會假定該約束適用於表中的所有行,直到使用 VALIDATE CONSTRAINT 選項對其進行驗證為止。有關使用 NOT VALID 選項的更多資訊,請參閱下面的 Notes

雖然大多數形式的 ADD table_constraint 都需要 ACCESS EXCLUSIVE 鎖,但 ADD FOREIGN KEY 僅需要 SHARE ROW EXCLUSIVE 鎖。請注意,ADD FOREIGN KEY 除了在宣告約束的表上獲取鎖外,還會獲取引用表上的 SHARE ROW EXCLUSIVE 鎖。

當向分割槽表新增唯一或主鍵約束時,會應用其他限制;請參閱 CREATE TABLE

ADD table_constraint_using_index #

此形式根據現有唯一索引在表中新增新的 PRIMARY KEYUNIQUE 約束。索引的所有列都將包含在約束中。

該索引不能包含表示式列,也不能是部分索引。此外,它必須是一個具有預設排序順序的 b-tree 索引。這些限制確保該索引等同於透過常規 ADD PRIMARY KEYADD UNIQUE 命令構建的索引。

如果指定了 PRIMARY KEY,並且索引的列尚未標記為 NOT NULL,那麼此命令將嘗試對每個這樣的列執行 ALTER COLUMN SET NOT NULL。這需要進行完整的表掃描來驗證列不包含 null 值。在所有其他情況下,這是一個快速操作。

如果提供了約束名稱,則索引將重新命名為與約束名稱匹配。否則,約束將與索引同名。

執行此命令後,該索引將像透過常規 ADD PRIMARY KEYADD UNIQUE 命令構建的索引一樣被約束 擁有。特別是,刪除約束也將使索引消失。

此形式目前不支援分割槽表。

注意

使用現有索引新增約束在需要新增新約束而又不想長時間阻止表更新的情況下很有幫助。為此,可以使用 CREATE UNIQUE INDEX CONCURRENTLY 建立索引,然後使用此語法將其轉換為約束。請參閱下面的示例。

ALTER CONSTRAINT #

此形式修改先前建立的約束的屬性。目前只有外部索引鍵約束可以透過這種方式修改,但請參閱下文。

ALTER CONSTRAINT ... INHERIT
ALTER CONSTRAINT ... NO INHERIT #

這些形式修改一個可繼承約束,使其變為不可繼承,或反之。目前只能以這種方式修改非空約束。除了更改約束的可繼承狀態外,當一個不可繼承約束被標記為可繼承時,如果表有子表,則等效的約束將被新增到子表中。當將一個可繼承約束標記為不可繼承時,如果在有子表的表上執行,則子表上的相應約束將被標記為不再繼承,但不會被刪除。

VALIDATE CONSTRAINT #

此形式透過掃描表以確保沒有不滿足約束的行,來驗證先前建立為 NOT VALID 的外部索引鍵、檢查或非空約束。如果約束被設定為 NOT ENFORCED,則會丟擲錯誤。如果約束已被標記為有效,則什麼也不做。(有關此命令用處的解釋,請參閱下面的 Notes。)

此命令獲取一個 SHARE UPDATE EXCLUSIVE 鎖。

DROP CONSTRAINT [ IF EXISTS ] #

此形式刪除表上指定的約束以及約束支援的任何索引。如果指定了 IF EXISTS 且約束不存在,則不會丟擲錯誤。在這種情況下,會發出通知。

DISABLE/ENABLE [ REPLICA | ALWAYS ] TRIGGER #

這些形式配置屬於表的觸發器(們)的觸發。停用的觸發器仍然為系統所知,但在其觸發事件發生時不會執行。(對於延遲觸發器,將在事件發生時檢查啟用狀態,而不是在觸發函式實際執行時。)可以按名稱指定單個觸發器來停用或啟用它,或啟用或停用表上的所有觸發器,或者僅啟用或停用使用者觸發器(此選項排除了內部生成的約束觸發器,例如那些用於實現外部索引鍵約束或可延遲唯一約束和排除約束的觸發器)。停用或啟用內部生成的約束觸發器需要超級使用者許可權;應謹慎操作,因為如果觸發器未執行,當然無法保證約束的完整性。

觸發器觸發機制還受到 session_replication_role 配置變數的影響。簡單啟用的觸發器(預設)將在複製角色為 origin(預設)或 local 時觸發。配置為 ENABLE REPLICA 的觸發器僅在會話處於 replica 模式時觸發,而配置為 ENABLE ALWAYS 的觸發器無論當前複製角色如何都會觸發。

此機制的效果是,在預設配置中,觸發器在副本上不觸發。這很有用,因為如果觸發器在源上用於在表之間傳播資料,那麼複製系統也將複製傳播的資料;因此觸發器不應在副本上觸發第二次,因為這會導致重複。然而,如果觸發器用於其他目的,例如建立外部警報,那麼將其設定為 ENABLE ALWAYS 以便在副本上也觸發可能很合適。

當此命令應用於分割槽表時,相應分割槽克隆觸發器的狀態也會被更新,除非指定了 ONLY

此命令獲取一個 SHARE ROW EXCLUSIVE 鎖。

DISABLE/ENABLE [ REPLICA | ALWAYS ] RULE #

這些形式配置表的重寫規則的觸發。停用的規則仍然為系統所知,但在查詢重寫期間不應用。語義與停用的/啟用的觸發器相同。對於 ON SELECT 規則,此配置將被忽略,這些規則始終應用,以使檢視即使在當前會話處於非預設複製角色時也能正常工作。

規則觸發機制也受到 session_replication_role 配置變數的影響,類似於上面描述的觸發器。

DISABLE/ENABLE ROW LEVEL SECURITY #

這些形式控制表的行安全策略的應用。如果啟用且表沒有策略,則會應用預設拒絕策略。請注意,即使行級安全性被停用,表也可以存在策略。在這種情況下,策略將被應用,並且策略將被忽略。另請參閱 CREATE POLICY

NO FORCE/FORCE ROW LEVEL SECURITY #

這些形式控制當用戶是表所有者時,表的行安全策略的應用。如果啟用,當用戶是表所有者時將應用行級安全策略。如果停用(預設),則當用戶是表所有者時,行級安全性將不被應用。另請參閱 CREATE POLICY

CLUSTER ON #

此形式選擇未來 CLUSTER 操作的預設索引。它實際上不會重新聚類表。

更改群集選項會獲取一個 SHARE UPDATE EXCLUSIVE 鎖。

SET WITHOUT CLUSTER #

此形式從表中刪除最近使用的 CLUSTER 索引規範。這會影響不指定索引的未來群集操作。

更改群集選項會獲取一個 SHARE UPDATE EXCLUSIVE 鎖。

SET WITHOUT OIDS #

刪除 oid 系統列的相容舊語法的命令。由於 oid 系統列無法再新增,因此此命令永遠不會產生任何效果。

SET ACCESS METHOD #

此形式透過使用指定的訪問方法重寫表來更改表的訪問方法;指定 DEFAULT 會選擇作為 default_table_access_method 配置引數設定的訪問方法。有關更多資訊,請參閱 第 62 章

當應用於分割槽表時,沒有資料需要重寫,但之後建立的分割槽將預設為給定的訪問方法,除非被 USING 子句覆蓋。指定 DEFAULT 會刪除先前的值,導致未來的分割槽預設為 default_table_access_method

SET TABLESPACE #

此形式將表的表空間更改為指定的表空間,並將與表相關聯的資料檔案移動到新的表空間。表上的索引(如果存在)不會被移動;但可以使用額外的 SET TABLESPACE 命令單獨移動它們。當應用於分割槽表時,不會移動任何內容,但之後使用 CREATE TABLE PARTITION OF 建立的任何分割槽將使用該表空間,除非被 TABLESPACE 子句覆蓋。

可以使用 ALL IN TABLESPACE 形式移動當前資料庫中某個表空間的所有表,該形式將首先鎖定所有要移動的表,然後逐個移動。此形式還支援 OWNED BY,它只會移動由指定角色擁有的表。如果指定了 NOWAIT 選項,則如果無法立即獲取所有必需的鎖,該命令將失敗。請注意,系統目錄不會被此命令移動;如果需要,請使用 ALTER DATABASE 或顯式的 ALTER TABLE 呼叫。 information_schema 關係不被視為系統目錄的一部分,並且將被移動。另請參閱 CREATE TABLESPACE

SET { LOGGED | UNLOGGED } #

此形式將表從非持久化更改為持久化或反之(請參閱 UNLOGGED)。它不能應用於臨時表。

這也將更改與表關聯的任何序列的永續性(用於標識列或序列列)。但是,也可以單獨更改這些序列的永續性。

此形式不支援分割槽表。

SET ( storage_parameter [= value] [, ... ] ) #

此形式更改表的儲存引數。有關可用引數的詳細資訊,請參閱 CREATE TABLE 文件中的 儲存引數。請注意,此命令不會立即修改表的內容;根據引數的不同,您可能需要重寫表才能獲得所需的效果。這可以透過 VACUUM FULLCLUSTERALTER TABLE 的某種形式來強制重寫表來實現。對於與規劃器相關的引數,更改將在下次鎖定表時生效,因此當前正在執行的查詢不會受到影響。

對於 fillfactor、toast 和 autovacuum 儲存引數,以及規劃器引數 parallel_workers,將獲取 SHARE UPDATE EXCLUSIVE 鎖。

RESET ( storage_parameter [, ... ] ) #

此形式將一個或多個儲存引數重置為其預設值。與 SET 一樣,可能需要重寫表才能完全更新表。

INHERIT parent_table #

此形式將目標表新增為指定父表的新的子表。之後,對父表的查詢將包含目標表的記錄。要被新增為子表,目標表必須已經包含與父表相同的列(它也可以有額外的列)。列必須具有匹配的資料型別。

此外,父表上的所有 CHECKNOT NULL 約束也必須存在於子表中,除了那些被標記為非繼承的(即,使用 ALTER TABLE ... ADD CONSTRAINT ... NO INHERIT 建立的)約束,這些約束將被忽略。所有匹配的子表約束不得被標記為非繼承。目前 UNIQUEPRIMARY KEYFOREIGN KEY 約束不被考慮,但這將來可能會改變。

NO INHERIT parent_table #

此形式將目標表從指定父表的子表列表中移除。對父表的查詢將不再包含從目標表中提取的記錄。

OF type_name #

此形式將表與複合型別關聯起來,就像 CREATE TABLE OF 已將其格式化一樣。表的列名和型別列表必須與複合型別的精確匹配。該表不得繼承自任何其他表。這些限制確保 CREATE TABLE OF 會允許等效的表定義。

NOT OF #

此形式將型別化表與其型別解除關聯。

OWNER TO #

此形式將表、序列、檢視、物化檢視或外部表的擁有者更改為指定的當前使用者。

REPLICA IDENTITY #

此形式更改寫入預寫日誌以標識已更新或刪除的行的資訊。在大多數情況下,僅當舊值與新值不同時才記錄每列的舊值;但是,如果舊值儲存在外部,則無論是否更改,都會始終記錄舊值。此選項沒有影響,除非在進行邏輯複製時。

DEFAULT #

記錄主鍵列的舊值。這是非系統表的預設值。當沒有主鍵時,行為與 NOTHING 相同。

USING INDEX index_name #

記錄被命名索引覆蓋的列的舊值,該索引必須是唯一的、非部分的、非延遲的,並且只包含標記為 NOT NULL 的列。如果此索引被刪除,行為與 NOTHING 相同。

FULL #

記錄行中所有列的舊值。

NOTHING #

不記錄有關舊行的任何資訊。這是系統表的預設設定。

RENAME #

RENAME 形式用於更改表(或索引、序列、檢視、物化檢視或外部表)的名稱、表中單個列的名稱或表約束的名稱。重新命名具有底層索引的約束時,索引也會被重新命名。對儲存的資料沒有影響。

SET SCHEMA #

此形式用於將表移動到另一個模式。表列擁有的相關索引、約束和序列也會被移動。

ATTACH PARTITION partition_name { FOR VALUES partition_bound_spec | DEFAULT } #

此形式將現有表(可能本身是分割槽的)附加為目標表的單個分割槽。可以使用 FOR VALUES 將表作為特定值的分割槽附加,或使用 DEFAULT 作為預設分割槽附加。對於目標表中的每個索引,將在附加的表中建立一個對應的索引;或者,如果已存在等效索引,則將其附加到目標表的索引,如同執行了 ALTER INDEX ATTACH PARTITION 一樣。請注意,如果現有表是外部表,目前不允許將該表作為目標表的單個分割槽附加,如果目標表上有 UNIQUE 索引的話。(另請參閱 CREATE FOREIGN TABLE。)對於目標表中存在的每個使用者定義的行級觸發器,將在附加的表中建立一個對應的觸發器。

使用 FOR VALUES 的分割槽使用與 CREATE TABLE 相同的 partition_bound_spec 語法。分割槽邊界規範必須與目標表的定義策略和分割槽鍵匹配。要附加的表必須具有與目標表相同的所有列,並且不多不少;此外,列型別也必須匹配。另外,它必須具有目標表的所有 NOT NULLCHECK 約束,且未標記為 NO INHERIT。目前 FOREIGN KEY 約束不被考慮。父表中的 UNIQUEPRIMARY KEY 約束將在分割槽中建立(如果它們尚不存在)。

如果新分割槽是常規表,將執行完整的表掃描以檢查表中現有的行是否違反分割槽約束。可以透過向表中新增一個有效的 CHECK 約束來避免此掃描,該約束只允許滿足所需分割槽約束的行在執行此命令之前。將使用 CHECK 約束來確定是否需要掃描表來驗證分割槽約束。但是,如果任何分割槽鍵是表示式且分割槽不接受 NULL 值,則此方法無效。如果附加一個不接受 NULL 值的列表分割槽,請同時向分割槽鍵列新增 NOT NULL 約束,除非它是表示式。

如果新分割槽是外部表,將不會執行任何操作來驗證外部表中的所有行是否符合分割槽約束。(有關外部表上的約束的討論,請參閱 CREATE FOREIGN TABLE。)

當表具有預設分割槽時,定義新分割槽會更改預設分割槽的分割槽約束。預設分割槽不能包含任何需要移動到新分割槽的行,並將被掃描以驗證其中沒有行。此掃描(如新分割槽的掃描)如果存在適當的 CHECK 約束,則可以避免。同樣,與新分割槽的掃描一樣,當預設分割槽是外部表時,此掃描總是被跳過。

附加分割槽會在父表上獲取一個 SHARE UPDATE EXCLUSIVE 鎖,此外還會獲得對要附加的表以及預設分割槽(如果有)的 ACCESS EXCLUSIVE 鎖。

如果正在附加的表本身是分割槽的,則還必須持有對所有子分割槽的鎖。同樣,如果預設分割槽本身是分割槽的,也必須持有對所有子分割槽的鎖。可以透過新增 CHECK 約束來避免對子分割槽的鎖定,如 Section 5.12.2.2 中所述。

DETACH PARTITION partition_name [ CONCURRENTLY | FINALIZE ] #

此形式分離目標表的指定分割槽。分離的分割槽將繼續作為獨立表存在,但不再與從中分離的表有任何關聯。任何附加到目標表索引的索引將被分離。作為目標表克隆建立的任何觸發器將被刪除。SHARE 鎖將獲取在任何引用此分割槽表的表中,這些表在這些表中擁有外部索引鍵約束。

如果指定了 CONCURRENTLY,它將使用降低的鎖級別執行,以避免阻塞可能正在訪問分割槽表的其他會話。在此模式下,內部使用兩個事務。在第一個事務中,將對父表和分割槽都獲取 SHARE UPDATE EXCLUSIVE 鎖,並將分割槽標記為正在分離;此時,事務將提交,並將等待所有其他使用該分割槽表的事務完成。一旦所有這些事務都完成後,第二個事務將獲取對分割槽表的 SHARE UPDATE EXCLUSIVE 鎖以及對分割槽的 ACCESS EXCLUSIVE 鎖,然後分離過程完成。一個複製分割槽約束的 CHECK 約束將被新增到該分割槽。CONCURRENTLY 不能在事務塊中執行,並且如果分割槽表包含預設分割槽,則不允許使用。

如果指定了 FINALIZE,則將完成先前被取消或中斷的 DETACH CONCURRENTLY 呼叫。一個分割槽表一次最多隻能有一個分割槽處於待分離狀態。

所有作用於單個表的 ALTER TABLE 形式,除了 RENAMESET SCHEMAATTACH PARTITIONDETACH PARTITION,都可以組合成一個列表,同時應用多個修改。例如,可以在一個命令中新增多個列和/或更改多個列的型別。這對於大表尤其有用,因為只需對錶進行一次掃描。

要使用 ALTER TABLE,您必須擁有該表。要更改表的模式或表空間,您還必須在新模式或表空間上擁有 CREATE 許可權。要將表新增為父表的新子表,您還必須擁有父表。此外,要將表附加為該表的新分割槽,您必須擁有要附加的表。要更改所有者,您必須能夠 SET ROLE 到新的所有者角色,並且該角色必須在表的模式上擁有 CREATE 許可權。(這些限制確保更改所有者不會執行您無法透過刪除和重新建立表來完成的操作。但是,超級使用者可以更改任何表的擁有權。)要新增列、更改列型別或使用 OF 子句,您還必須在資料型別上擁有 USAGE 許可權。

引數

IF EXISTS #

如果表不存在,則不丟擲錯誤。在這種情況下會發出一個通知。

name #

要修改的現有表的名稱(可選模式限定)。如果表名之前指定了 ONLY,則只修改該表。如果未指定 ONLY,則修改該表及其所有後代表(如果有)。可以選擇在表名後指定 * 來明確表示包含後代表。

column_name #

新列或現有列的名稱。

new_column_name #

現有列的新名稱。

new_name #

表的名稱。

data_type #

新列的資料型別,或現有列的新資料型別。

table_constraint #

表的新表約束。

constraint_name #

新約束或現有約束的名稱。

CASCADE #

自動刪除依賴於被刪除列或約束的物件(例如,引用該列的檢視),以及反過來依賴於這些物件的所有物件(參見 Section 5.15)。

RESTRICT #

如果存在任何依賴物件,則拒絕刪除列或約束。這是預設行為。

trigger_name #

要停用或啟用的單個觸發器的名稱。

ALL #

停用或啟用表的所有觸發器。(如果任何觸發器是內部生成的約束觸發器,例如用於實現外部索引鍵約束或延遲唯一性約束和排斥約束的觸發器,則需要超級使用者許可權。)

USER #

停用或啟用表的所有觸發器,但內部生成的約束觸發器除外,例如用於實現外部索引鍵約束或延遲唯一性約束和排斥約束的觸發器。

index_name #

現有索引的名稱。

storage_parameter #

表儲存引數的名稱。

value #

表儲存引數的新值。根據引數的不同,這可能是一個數字或一個單詞。

parent_table #

要與此表關聯或解除關聯的父表。

new_owner #

表的新所有者的使用者名稱。

new_access_method #

表將轉換到的訪問方法的名稱。

new_tablespace #

表將要移動到的表空間的名稱。

new_schema #

表將要移動到的模式的名稱。

partition_name #

要作為新分割槽附加或從此表分離的表的名稱。

partition_bound_spec #

新分割槽的分割槽邊界規範。有關相同語法的更多詳細資訊,請參閱 CREATE TABLE

註釋

關鍵字 COLUMN 是多餘的,可以省略。

當使用 ADD COLUMN 新增列並指定了非易失性 DEFAULT 時,預設值將在語句執行時進行評估,並將結果儲存在表的元資料中,當訪問任何現有行時,該結果將被返回。該值僅在表被重寫時應用,這使得 ALTER TABLE 即使對於大表也非常快速。如果未指定任何列約束,則 DEFAULT 使用 NULL。在這兩種情況下,都不需要重寫表。

新增具有易失性 DEFAULT(例如 clock_timestamp())、已儲存的生成列、標識列或具有約束的域資料型別的列將導致整個表及其索引被重寫。新增虛擬生成列永遠不需要重寫。

更改現有列的型別通常會導致整個表及其索引被重寫。作為例外,當更改現有列的型別時,如果 USING 子句不更改列內容,並且舊型別是可二進位制強制轉換為新型別或是不受約束的、基於新型別的域,則不需要重寫表。但是,索引仍會被重建,除非系統能夠驗證新索引在邏輯上等同於現有索引。例如,如果更改了列的排序規則,則需要重建索引,因為新的排序順序可能不同。但是,在沒有排序規則更改的情況下,可以將列從 text 更改為 varchar(反之亦然),而無需重建索引,因為這些資料型別排序相同。

對於大表,表和/或索引的重建可能需要大量時間,並且將臨時需要多達兩倍的磁碟空間。

新增 CHECKNOT NULL 約束需要掃描表以驗證現有行是否滿足約束,但不需要重寫表。如果 CHECK 約束被新增為 NOT ENFORCED,則不會執行驗證。

同樣,在附加新分割槽時,可能會對其進行掃描以驗證現有行是否滿足分割槽約束。

在單個 ALTER TABLE 命令中指定多個更改的主要原因是可以將多個表掃描或重寫合併為一次表掃描。

掃描大表以驗證新的外部索引鍵、檢查或非空約束可能需要很長時間,並且其他對錶的更新將被鎖定,直到 ALTER TABLE ADD CONSTRAINT 命令提交。 NOT VALID 約束選項的主要目的是減少新增約束對併發更新的影響。使用 NOT VALID 時,ADD CONSTRAINT 命令不會掃描表,可以立即提交。之後,可以發出 VALIDATE CONSTRAINT 命令來驗證現有行是否滿足約束。驗證步驟不需要鎖定併發更新,因為它知道其他事務將對它們插入或更新的行強制執行約束;只需要檢查預先存在的行。因此,驗證只獲取對要修改的表 SHARE UPDATE EXCLUSIVE 鎖。(如果約束是外部索引鍵,則還需要對約束引用的表獲取 ROW SHARE 鎖。)除了提高併發性外,在已知表中包含預先存在的違反約束的情況時,使用 NOT VALIDVALIDATE CONSTRAINT 也是有用的。一旦約束到位,就不能插入新的違規,現有的問題可以隨意糾正,直到 VALIDATE CONSTRAINT 最終成功。

DROP COLUMN 形式不會物理刪除該列,而只是使其對 SQL 操作不可見。後續對該表的插入和更新操作將為該列儲存一個 null 值。因此,刪除列非常快速,但不會立即減小表在磁碟上的大小,因為被刪除列佔用的空間不會被回收。隨著現有行的更新,空間將隨著時間的推移而被回收。

要強制立即回收被刪除列佔用的空間,可以執行 ALTER TABLE 的一種形式,該形式會重寫整個表。這將導致重構每一行,並將被刪除的列替換為 null 值。

重寫形式的 ALTER TABLE 不是 MVCC 安全的。在表重寫之後,對於併發事務來說,表將顯示為空,如果它們使用的是在重寫發生之前拍攝的快照。有關更多詳細資訊,請參閱 Section 13.6

SET DATA TYPEUSING 選項實際上可以指定涉及行舊值的任何表示式;也就是說,它可以引用其他列以及正在轉換的列。這允許使用 SET DATA TYPE 語法進行非常通用的轉換。由於這種靈活性,USING 表示式不應用於列的預設值(如果有);結果可能不是預設值所需的常量表達式。這意味著,當從舊型別到新型別沒有隱式轉換或賦值轉換時,即使提供了 USING 子句,SET DATA TYPE 也可能無法轉換預設值。在這種情況下,請使用 DROP DEFAULT 刪除預設值,執行 ALTER TYPE,然後使用 SET DEFAULT 新增適當的新預設值。類似的考慮也適用於涉及該列的索引和約束。

如果一個表有任何後代表,則不允許在父表中新增、重新命名或更改列的型別而不對後代表執行相同操作。這確保了後代表總是具有與父表匹配的列。同樣,在父表中重新命名 CHECK 約束時,也必須在所有後代表中重新命名,以便 CHECK 約束在父表及其後代表之間也匹配。(然而,該限制不適用於基於索引的約束。)此外,由於從父表選擇也從其後代表選擇,因此不能將父表上的約束標記為有效,除非它對這些後代表也標記為有效。在所有這些情況下,ALTER TABLE ONLY 都將被拒絕。

遞迴的 DROP COLUMN 操作僅在後代表不從任何其他父表繼承該列且從未獨立定義該列時,才會刪除後代表的列。非遞迴的 DROP COLUMN(即 ALTER TABLE ONLY ... DROP COLUMN)永遠不會刪除任何後代列,而是將它們標記為獨立定義而非繼承。對於分割槽表,非遞迴的 DROP COLUMN 命令將失敗,因為表的所有分割槽都必須與分割槽根具有相同的列。

標識列(ADD GENERATEDSET 等,DROP IDENTITY)的操作,以及 CLUSTEROWNERTABLESPACE 操作,永遠不會遞迴到後代表;也就是說,它們總是像指定了 ONLY 一樣執行。影響觸發器狀態的操作會遞迴到分割槽表的子分割槽(除非指定了 ONLY),但永遠不會遞迴到傳統繼承的後代表。新增約束只遞迴 CHECK 約束,這些約束未被標記為 NO INHERIT

不允許更改系統目錄表的任何部分。

有關有效引數的進一步說明,請參閱 CREATE TABLEChapter 5 包含有關繼承的更多資訊。

示例

向表中新增 varchar 型別列

ALTER TABLE distributors ADD COLUMN address varchar(30);

這將導致表中所有現有行的新列填充為 null 值。

新增帶有非空預設值的列

ALTER TABLE measurements
  ADD COLUMN mtime timestamp with time zone DEFAULT now();

現有行將被當前時間填充為新列的值,然後新行將在插入時接收其插入時間。

新增列並用一個與之後將使用的預設值不同的值填充

ALTER TABLE transactions
  ADD COLUMN status varchar(30) DEFAULT 'old',
  ALTER COLUMN status SET default 'current';

現有行將被填充為 old,但之後後續命令的預設值將是 current。效果與兩個子命令在單獨的 ALTER TABLE 命令中發出時相同。

從表中刪除列

ALTER TABLE distributors DROP COLUMN address RESTRICT;

在一個操作中更改兩個現有列的型別

ALTER TABLE distributors
    ALTER COLUMN address TYPE varchar(80),
    ALTER COLUMN name TYPE varchar(100);

透過 USING 子句將包含 Unix 時間戳的整數列更改為 timestamp with time zone

ALTER TABLE foo
    ALTER COLUMN foo_timestamp SET DATA TYPE timestamp with time zone
    USING
        timestamp with time zone 'epoch' + foo_timestamp * interval '1 second';

相同,當列具有不會自動轉換為新資料型別的預設表示式時

ALTER TABLE foo
    ALTER COLUMN foo_timestamp DROP DEFAULT,
    ALTER COLUMN foo_timestamp TYPE timestamp with time zone
    USING
        timestamp with time zone 'epoch' + foo_timestamp * interval '1 second',
    ALTER COLUMN foo_timestamp SET DEFAULT now();

重新命名現有列

ALTER TABLE distributors RENAME COLUMN address TO city;

重新命名現有表

ALTER TABLE distributors RENAME TO suppliers;

重新命名現有約束

ALTER TABLE distributors RENAME CONSTRAINT zipchk TO zip_check;

向列新增非空約束

ALTER TABLE distributors ALTER COLUMN street SET NOT NULL;

從列中刪除非空約束

ALTER TABLE distributors ALTER COLUMN street DROP NOT NULL;

向表及其所有子表新增檢查約束

ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5);

僅向表新增檢查約束,而不向其子表新增

ALTER TABLE distributors ADD CONSTRAINT zipchk CHECK (char_length(zipcode) = 5) NO INHERIT;

(將來的子表也不會繼承此檢查約束。)

從表及其所有子表中刪除檢查約束

ALTER TABLE distributors DROP CONSTRAINT zipchk;

僅從一個表中刪除檢查約束

ALTER TABLE ONLY distributors DROP CONSTRAINT zipchk;

(檢查約束將保留在子表中。)

向表中新增外部索引鍵約束

ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address);

向表新增外部索引鍵約束,同時對其他工作的影響最小

ALTER TABLE distributors ADD CONSTRAINT distfk FOREIGN KEY (address) REFERENCES addresses (address) NOT VALID;
ALTER TABLE distributors VALIDATE CONSTRAINT distfk;

向表中新增(多列)唯一約束

ALTER TABLE distributors ADD CONSTRAINT dist_id_zipcode_key UNIQUE (dist_id, zipcode);

向表新增自動命名的主鍵約束,請注意,表只能有一個主鍵

ALTER TABLE distributors ADD PRIMARY KEY (dist_id);

將表移動到不同的表空間

ALTER TABLE distributors SET TABLESPACE fasttablespace;

將表移動到不同的模式

ALTER TABLE myschema.distributors SET SCHEMA yourschema;

重新建立主鍵約束,而不阻塞索引重建期間的更新

CREATE UNIQUE INDEX CONCURRENTLY dist_id_temp_idx ON distributors (dist_id);
ALTER TABLE distributors DROP CONSTRAINT distributors_pkey,
    ADD CONSTRAINT distributors_pkey PRIMARY KEY USING INDEX dist_id_temp_idx;

將分割槽附加到範圍分割槽的表

ALTER TABLE measurement
    ATTACH PARTITION measurement_y2016m07 FOR VALUES FROM ('2016-07-01') TO ('2016-08-01');

將分割槽附加到列表分割槽的表

ALTER TABLE cities
    ATTACH PARTITION cities_ab FOR VALUES IN ('a', 'b');

將分割槽附加到雜湊分割槽的表

ALTER TABLE orders
    ATTACH PARTITION orders_p4 FOR VALUES WITH (MODULUS 4, REMAINDER 3);

將預設分割槽附加到分割槽表

ALTER TABLE cities
    ATTACH PARTITION cities_partdef DEFAULT;

將分割槽從分割槽表中分離

ALTER TABLE measurement
    DETACH PARTITION measurement_y2015m12;

相容性

ADD [COLUMN]DROP [COLUMN]DROP IDENTITYRESTARTSET DEFAULTSET DATA TYPE(無 USING)、SET GENERATEDSET sequence_option 形式符合 SQL 標準。ADD table_constraint 形式符合 SQL 標準,當省略 USING INDEXNOT VALID 子句且約束型別是 CHECKUNIQUEPRIMARY KEYREFERENCES 之一時。其他形式是 SQL 標準的 PostgreSQL 擴充套件。此外,能夠在一個 ALTER TABLE 命令中指定多個修改也是一項擴充套件。

ALTER TABLE DROP COLUMN 可用於刪除表的唯一列,留下一個零列表。這是 SQL 的擴充套件,SQL 不允許零列表。

另請參閱

CREATE TABLE

提交更正

如果您在文件中看到任何不正確的內容、與您對特定功能的體驗不符或需要進一步說明的內容,請使用 此表單 來報告文件問題。