ALTER TABLE — 更改資料表的定義
ALTER TABLE [ IF EXISTS ] [ ONLY ]name
[ * ]action
[, ... ] ALTER TABLE [ IF EXISTS ] [ ONLY ]name
[ * ] RENAME [ COLUMN ]column_name
TOnew_column_name
ALTER TABLE [ IF EXISTS ] [ ONLY ]name
[ * ] RENAME CONSTRAINTconstraint_name
TOnew_constraint_name
ALTER TABLE [ IF EXISTS ]name
RENAME TOnew_name
ALTER TABLE [ IF EXISTS ]name
SET SCHEMAnew_schema
ALTER TABLE ALL IN TABLESPACEname
[ OWNED BYrole_name
[, ... ] ] SET TABLESPACEnew_tablespace
[ NOWAIT ] ALTER TABLE [ IF EXISTS ]name
ATTACH PARTITIONpartition_name
{ FOR VALUESpartition_bound_spec
| DEFAULT } ALTER TABLE [ IF EXISTS ]name
DETACH PARTITIONpartition_name
[ CONCURRENTLY | FINALIZE ] whereaction
is one of: ADD [ COLUMN ] [ IF NOT EXISTS ]column_name
data_type
[ COLLATEcollation
] [column_constraint
[ ... ] ] DROP [ COLUMN ] [ IF EXISTS ]column_name
[ RESTRICT | CASCADE ] ALTER [ COLUMN ]column_name
[ SET DATA ] TYPEdata_type
[ COLLATEcollation
] [ USINGexpression
] ALTER [ COLUMN ]column_name
SET DEFAULTexpression
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 } | SETsequence_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 COMPRESSIONcompression_method
ADDtable_constraint
[ NOT VALID ] ADDtable_constraint_using_index
ALTER CONSTRAINTconstraint_name
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] VALIDATE CONSTRAINTconstraint_name
DROP CONSTRAINT [ IF EXISTS ]constraint_name
[ RESTRICT | CASCADE ] DISABLE TRIGGER [trigger_name
| ALL | USER ] ENABLE TRIGGER [trigger_name
| ALL | USER ] ENABLE REPLICA TRIGGERtrigger_name
ENABLE ALWAYS TRIGGERtrigger_name
DISABLE RULErewrite_rule_name
ENABLE RULErewrite_rule_name
ENABLE REPLICA RULErewrite_rule_name
ENABLE ALWAYS RULErewrite_rule_name
DISABLE ROW LEVEL SECURITY ENABLE ROW LEVEL SECURITY FORCE ROW LEVEL SECURITY NO FORCE ROW LEVEL SECURITY CLUSTER ONindex_name
SET WITHOUT CLUSTER SET WITHOUT OIDS SET ACCESS METHOD {new_access_method
| DEFAULT } SET TABLESPACEnew_tablespace
SET { LOGGED | UNLOGGED } SET (storage_parameter
[=value
] [, ... ] ) RESET (storage_parameter
[, ... ] ) INHERITparent_table
NO INHERITparent_table
OFtype_name
NOT OF OWNER TO {new_owner
| CURRENT_ROLE | CURRENT_USER | SESSION_USER } REPLICA IDENTITY { DEFAULT | USING INDEXindex_name
| FULL | NOTHING } andpartition_bound_spec
is: IN (partition_bound_expr
[, ...] ) | FROM ( {partition_bound_expr
| MINVALUE | MAXVALUE } [, ...] ) TO ( {partition_bound_expr
| MINVALUE | MAXVALUE } [, ...] ) | WITH ( MODULUSnumeric_literal
, REMAINDERnumeric_literal
) andcolumn_constraint
is: [ CONSTRAINTconstraint_name
] { NOT NULL | NULL | CHECK (expression
) [ NO INHERIT ] | DEFAULTdefault_expr
| GENERATED ALWAYS AS (generation_expr
) STORED | GENERATED { ALWAYS | BY DEFAULT } AS IDENTITY [ (sequence_options
) ] | UNIQUE [ NULLS [ NOT ] DISTINCT ]index_parameters
| PRIMARY KEYindex_parameters
| REFERENCESreftable
[ (refcolumn
) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETEreferential_action
] [ ON UPDATEreferential_action
] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] andtable_constraint
is: [ CONSTRAINTconstraint_name
] { CHECK (expression
) [ NO INHERIT ] | UNIQUE [ NULLS [ NOT ] DISTINCT ] (column_name
[, ... ] )index_parameters
| PRIMARY KEY (column_name
[, ... ] )index_parameters
| EXCLUDE [ USINGindex_method
] (exclude_element
WITHoperator
[, ... ] )index_parameters
[ WHERE (predicate
) ] | FOREIGN KEY (column_name
[, ... ] ) REFERENCESreftable
[ (refcolumn
[, ... ] ) ] [ MATCH FULL | MATCH PARTIAL | MATCH SIMPLE ] [ ON DELETEreferential_action
] [ ON UPDATEreferential_action
] } [ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ] andtable_constraint_using_index
is: [ CONSTRAINTconstraint_name
] { UNIQUE | PRIMARY KEY } USING INDEXindex_name
[ DEFERRABLE | NOT DEFERRABLE ] [ INITIALLY DEFERRED | INITIALLY IMMEDIATE ]index_parameters
inUNIQUE
,PRIMARY KEY
, andEXCLUDE
constraints are: [ INCLUDE (column_name
[, ... ] ) ] [ WITH (storage_parameter
[=value
] [, ... ] ) ] [ USING INDEX TABLESPACEtablespace_name
]exclude_element
in anEXCLUDE
constraint is: {column_name
| (expression
) } [ COLLATEcollation
] [opclass
[ (opclass_parameter
=value
[, ... ] ) ] ] [ ASC | DESC ] [ NULLS { FIRST | LAST } ]referential_action
in aFOREIGN 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
。
SET
/DROP DEFAULT
#這些形式會設定或移除欄位的預設值 (其中移除等同於將預設值設定為 NULL)。新的預設值僅適用於後續的 INSERT
或 UPDATE
指令;它不會導致資料表中已存在的列發生變更。
SET
/DROP NOT NULL
#這些形式會變更欄位是否標記為允許空值或拒絕空值。
SET NOT NULL
只能應用於欄位,前提是資料表中沒有任何記錄包含該欄位的 NULL
值。通常,這會在 ALTER TABLE
期間透過掃描整個資料表來檢查;但是,如果找到有效的 CHECK
約束證明不存在 NULL
,則會跳過資料表掃描。
如果此資料表是分割區,則如果父資料表中的欄位標記為 NOT NULL
,則無法在該欄位上執行 DROP NOT NULL
。若要從所有分割區中刪除 NOT NULL
約束,請在父資料表上執行 DROP NOT NULL
。即使父資料表上沒有 NOT NULL
約束,仍然可以將此類約束新增至個別分割區 (如果需要);也就是說,即使父資料表允許空值,子資料表也可以不允許空值,但反之則不然。
SET EXPRESSION AS
#此形式會取代產生欄位的運算式。欄位中的現有資料會被重寫,所有未來的變更都將套用新的產生運算式。
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
類似,這些形式只會影響後續的INSERT
和UPDATE
指令的行為;它們不會導致表格中已存在的列發生變更。
如果指定了DROP IDENTITY IF EXISTS
,且該欄位不是識別欄位,則不會拋出錯誤。 在這種情況下,會改為發出通知。
SET sequence_option
RESTART
#這些形式會變更現有識別欄位所基於的序列。sequence_option
是ALTER 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_distinct
和n_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 }
#此形式設定欄位的儲存模式。 這會控制此欄位是否以內嵌方式或在輔助TOAST表格中保存,以及是否應壓縮資料。PLAIN
必須用於固定長度的值,例如integer
,並且是內嵌、未壓縮的。MAIN
用於內嵌、可壓縮的資料。EXTERNAL
用於外部、未壓縮的資料,而EXTENDED
用於外部、壓縮的資料。 寫入DEFAULT
會將儲存模式設定為欄位資料類型的預設模式。EXTENDED
是支援非PLAIN
儲存的大多數資料類型的預設值。 使用EXTERNAL
會使對非常大的text
和bytea
值執行子字串運算的速度更快,但會增加儲存空間。 請注意,ALTER TABLE ... SET STORAGE
本身不會變更表格中的任何內容;它只會設定在未來的表格更新期間要採用的策略。 有關更多資訊,請參閱第 65.2 節。
SET COMPRESSION compression_method
#此形式設定欄位的壓縮方法,決定未來插入的值將如何壓縮 (如果儲存模式允許壓縮)。 這不會導致重新編寫表格,因此現有資料可能仍會使用其他壓縮方法壓縮。 如果使用pg_restore還原表格,則所有值都會使用已配置的壓縮方法重新編寫。 但是,當從另一個關係插入資料時 (例如,通過INSERT ... SELECT
),來自來源表格的值不一定會被 detoast,因此任何先前壓縮的資料可能會保留其現有的壓縮方法,而不是使用目標欄位的壓縮方法重新壓縮。 支援的壓縮方法是pglz
和lz4
。 (lz4
僅在建置PostgreSQL時使用了--with-lz4
時才可用。) 此外,compression_method
可以是default
,它選擇預設行為,即在資料插入時查詢default_toast_compression設定,以確定要使用的方法。
ADD table_constraint
[ NOT VALID ]
#此形式使用與CREATE TABLE
相同的限制語法向表格新增新的限制,以及選項NOT VALID
,目前僅允許用於外部鍵和CHECK限制。
一般來說,此指令會掃描資料表,以驗證資料表中所有現有資料列是否滿足新的約束條件。但是,如果使用 NOT VALID
選項,則會跳過這個可能耗時的掃描。約束條件仍然會強制執行於後續的插入或更新(也就是說,如果參考資料表中沒有符合的資料列(以外鍵為例),或者新資料列不符合指定的檢查條件,則會失敗)。但是在使用 VALIDATE CONSTRAINT
選項驗證之前,資料庫不會假設約束條件適用於資料表中的所有資料列。有關使用 NOT VALID
選項的更多資訊,請參閱下面的備註。
雖然大多數 ADD
的形式都需要 table_constraint
ACCESS EXCLUSIVE
鎖定,但 ADD FOREIGN KEY
僅需要 SHARE ROW EXCLUSIVE
鎖定。請注意,除了宣告約束條件的資料表上的鎖定之外,ADD FOREIGN KEY
還會在參考資料表上取得 SHARE ROW EXCLUSIVE
鎖定。
將唯一約束條件或主鍵約束條件新增至分割資料表時,會套用其他限制;請參閱CREATE TABLE
。此外,目前分割資料表上的外鍵約束條件不能宣告為 NOT VALID
。
ADD table_constraint_using_index
#此形式會根據現有的唯一索引,將新的 PRIMARY KEY
或 UNIQUE
約束條件新增至資料表。索引的所有欄位都將包含在約束條件中。
索引不能有運算式欄位,也不能是部分索引。此外,它必須是具有預設排序順序的 b-tree 索引。這些限制確保索引等同於由常規 ADD PRIMARY KEY
或 ADD UNIQUE
命令所建立的索引。
如果指定了 PRIMARY KEY
,並且索引的欄位尚未標記為 NOT NULL
,則此命令將嘗試對每個這樣的欄位執行 ALTER COLUMN SET NOT NULL
。這需要完整的資料表掃描,以驗證欄位是否包含空值。在所有其他情況下,這是一個快速操作。
如果提供了約束條件名稱,則索引將重新命名以符合約束條件名稱。否則,約束條件將命名為與索引相同。
執行此命令後,索引將由約束條件「擁有」,就像索引是由常規 ADD PRIMARY KEY
或 ADD UNIQUE
命令建立的一樣。特別是,刪除約束條件也會使索引消失。
目前分割資料表不支援此形式。
在使用現有索引新增約束條件的情況下,這很有用,因為可以在不長時間阻止資料表更新的情況下新增新的約束條件。為此,請使用 CREATE UNIQUE INDEX CONCURRENTLY
建立索引,然後使用此語法將其轉換為約束條件。請參閱下面的範例。
ALTER CONSTRAINT
#此形式會變更先前建立的約束條件的屬性。目前只能變更外鍵約束條件。
VALIDATE CONSTRAINT
#此形式會驗證先前建立為 NOT VALID
的外鍵或檢查約束條件,方法是掃描資料表以確保沒有任何資料列不滿足約束條件。如果約束條件已標記為有效,則不會發生任何事情。(有關此命令用處的說明,請參閱下面的備註。)
此命令取得 SHARE UPDATE EXCLUSIVE
鎖定。
DROP CONSTRAINT [ IF EXISTS ]
#此形式會刪除資料表上指定的約束條件,以及約束條件下的任何索引。如果指定了 IF EXISTS
且約束條件不存在,則不會擲回錯誤。在這種情況下,會發出通知。
DISABLE
/ENABLE [ REPLICA | ALWAYS ] TRIGGER
#這些形式會設定屬於資料表的觸發程序(trigger)的觸發。已停用的觸發程序仍然為系統所知,但當觸發事件發生時不會執行。(對於延遲觸發程序,會在事件發生時檢查啟用狀態,而不是在實際執行觸發程序函數時。)可以停用或啟用按名稱指定的單個觸發程序,或資料表上的所有觸發程序,或僅啟用使用者觸發程序(此選項排除內部產生的約束條件觸發程序,例如用於實作外鍵約束條件或可延遲唯一性和排除約束條件的觸發程序)。停用或啟用內部產生的約束條件觸發程序需要超級使用者權限;應該謹慎執行此操作,因為如果未執行觸發程序,則當然無法保證約束條件的完整性。
觸發程序觸發機制也受到組態變數 session_replication_role 的影響。僅啟用觸發程序(預設)會在複寫角色為「origin」(預設)或「local」時觸發。設定為 ENABLE REPLICA
的觸發程序僅在工作階段處於「replica」模式時觸發,而設定為 ENABLE ALWAYS
的觸發程序無論目前的複寫角色如何都會觸發。
此機制的影響是在預設組態中,觸發程序不會在副本上觸發。這很有用,因為如果在來源上使用觸發程序在資料表之間傳播資料,則複寫系統也會複寫傳播的資料;因此,觸發程序不應在副本上再次觸發,因為這會導致重複。但是,如果觸發程序用於其他目的,例如建立外部警示,則將其設定為 ENABLE ALWAYS
可能很合適,以便它也可以在副本上觸發。
當此命令套用至分割資料表時,除非指定了 ONLY
,否則也會更新分割區中對應的複製觸發程序的狀態。
此命令取得 SHARE ROW EXCLUSIVE
鎖定。
DISABLE
/ENABLE [ REPLICA | ALWAYS ] RULE
#這些形式會設定屬於資料表的重寫規則(rewrite 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 組態參數的存取方法。請參閱 第 61 章 以取得更多資訊。
當應用於分割表格時,沒有要重寫的資料,但是之後建立的分割區將預設為給定的存取方法,除非被 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 FULL
、CLUSTER
或強制表格重寫的 ALTER TABLE
形式之一來完成。對於與規劃器相關的參數,變更將從下次鎖定表格時生效,因此目前正在執行的查詢將不會受到影響。
對於 fillfactor、toast 和 autovacuum 儲存參數,以及規劃器參數 parallel_workers
,將會取得 SHARE UPDATE EXCLUSIVE
鎖定。
RESET ( storage_parameter
[, ... ] )
#這種形式會將一個或多個儲存參數重設為其預設值。與 SET
一樣,可能需要重寫表格才能完全更新表格。
INHERIT parent_table
#這種形式將目標表格新增為指定父表格的新子表格。隨後,針對父表格的查詢將包含目標表格的記錄。要新增為子表格,目標表格必須已經包含與父表格相同的所有欄位(它也可以有其他欄位)。這些欄位必須具有相符的資料類型,並且如果在父表格中具有 NOT NULL
限制,則它們也必須在子表格中具有 NOT NULL
限制。
對於父表格的所有 CHECK
限制,也必須有相符的子表格限制,但那些標記為不可繼承的限制除外(也就是說,使用 ALTER TABLE ... ADD CONSTRAINT ... NO INHERIT
在父表格中建立的限制),這些限制會被忽略;所有相符的子表格限制不得標記為不可繼承。目前不考慮 UNIQUE
、PRIMARY KEY
和 FOREIGN KEY
限制,但未來可能會變更。
NO INHERIT parent_table
#這種形式會從指定父表格的子表格列表中移除目標表格。針對父表格的查詢將不再包含從目標表格提取的記錄。
OF type_name
#此形式將資料表連結到複合型別,如同使用 CREATE TABLE OF
建立的一樣。資料表的欄位名稱和型別列表必須與複合型別的完全一致。資料表不得繼承自任何其他資料表。這些限制確保 CREATE TABLE OF
允許等效的資料表定義。
NOT OF
#此形式將型別資料表與其型別解除關聯。
OWNER TO
#此形式將資料表、序列、檢視、具體化檢視或外部資料表的所有者變更為指定的使用者。
REPLICA IDENTITY
#此形式變更寫入預寫式日誌 (write-ahead log) 的資訊,以識別已更新或刪除的列。在大多數情況下,只有在每個欄位的舊值與新值不同時,才會記錄舊值;但是,如果舊值儲存在外部,則無論它是否已變更,都會始終記錄。
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 NULL
和 CHECK
限制條件,未標記為 NO INHERIT
。目前不考慮 FOREIGN KEY
限制條件。如果分割區中不存在父資料表的 UNIQUE
和 PRIMARY KEY
限制條件,則將在分割區中建立它們。
如果新的分割區是常規資料表,則會執行完整的資料表掃描,以檢查資料表中現有的列是否違反分割區限制條件。可以透過在執行此命令之前,將有效的 CHECK
限制條件新增到僅允許滿足所需分割區限制條件的列的資料表中,來避免此掃描。 CHECK
限制條件將用於確定不需要掃描資料表來驗證分割區限制條件。但是,如果任何分割區鍵是表達式,並且分割區不接受 NULL
值,則此方法無效。如果附加不接受 NULL
值的列表分割區,除非它是表達式,否則還應將 NOT NULL
限制條件新增到分割區鍵欄位。
如果新的分割區是外部資料表,則不會執行任何操作來驗證外部資料表中的所有列是否都遵守分割區限制條件。(請參閱 CREATE FOREIGN TABLE 中關於外部資料表上的限制條件的討論。)
當資料表具有預設分割區時,定義新的分割區會變更預設分割區的分割區限制條件。預設分割區不能包含任何需要移動到新分割區的列,並且將掃描以驗證是否不存在任何列。如果存在適當的 CHECK
限制條件,則可以避免這種掃描,就像掃描新的分割區一樣。與掃描新分割區一樣,當預設分割區是外部資料表時,始終會跳過它。
附加分割區會在父資料表上取得 SHARE UPDATE EXCLUSIVE
鎖定,以及在附加的資料表和預設分割區(如果有的話)上取得 ACCESS EXCLUSIVE
鎖定。
如果附加的資料表本身是分割的資料表,則還必須在所有子分割區上持有其他鎖定。同樣地,如果預設分割區本身是分割的資料表。可以透過新增 第 5.12.2.2 節 中描述的 CHECK
限制條件來避免鎖定子分割區。
DETACH PARTITION partition_name
[ CONCURRENTLY | FINALIZE ]
#這個表單會分離目標資料表的指定分割區。分離後的分割區會以獨立資料表的形式繼續存在,但不再與其分離的資料表有任何關聯。任何附加到目標資料表索引的索引都會被分離。任何作為目標資料表中索引複製品建立的觸發器都會被移除。在以外鍵約束引用此分割資料表的任何資料表上,都會取得 SHARE
鎖定。
如果指定了 CONCURRENTLY
,它會使用降低的鎖定層級執行,以避免封鎖可能正在存取分割資料表的其他工作階段。在這種模式下,內部會使用兩個交易。在第一個交易期間,會在父資料表和分割區上取得 SHARE UPDATE EXCLUSIVE
鎖定,並且分割區會被標記為正在分離;在該時間點,交易會被提交,並且所有其他使用分割資料表的交易都會被等待。一旦所有這些交易完成,第二個交易就會在分割資料表上取得 SHARE UPDATE EXCLUSIVE
,並且在分割區上取得 ACCESS EXCLUSIVE
,並且分離程序完成。一個複製分割區約束的 CHECK
約束會被新增到分割區。CONCURRENTLY
不能在交易區塊中執行,並且如果分割資料表包含預設分割區,則不允許使用。
如果指定了 FINALIZE
,則會完成先前被取消或中斷的 DETACH CONCURRENTLY
呼叫。在分割資料表中,一次最多可以有一個分割區處於待分離狀態。
除了 RENAME
、SET SCHEMA
、ATTACH PARTITION
和 DETACH PARTITION
之外,作用於單個資料表的 ALTER TABLE 的所有形式都可以組合到一個多個變更的清單中,以便一起應用。例如,可以在單個指令中新增多個欄位和/或變更多個欄位的類型。這對於大型資料表特別有用,因為只需要掃描資料表一次。
您必須擁有資料表才能使用 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
新增欄位且指定了非易變性 (non-volatile
) 的 DEFAULT
時,預設值會在語句執行時計算,並將結果儲存在資料表的元資料中。該值將用於所有現有列的欄位。如果沒有指定 DEFAULT
,則使用 NULL。在任何一種情況下,都不需要重寫資料表。
新增具有易變性 (volatile
) DEFAULT
的欄位或變更現有欄位的類型,將需要重寫整個資料表及其索引。但有一個例外,當變更現有欄位的類型時,如果 USING
子句沒有改變欄位內容,且舊類型與新類型之間是二進制可強制轉換的 (binary coercible),或是新類型上的一個無約束網域 (unconstrained domain),則不需要重寫資料表。然而,除非系統可以驗證新的索引在邏輯上與現有的索引等效,否則索引必須始終重建。例如,如果欄位的排序規則 (collation) 已經變更,則始終需要重建索引,因為新的排序順序可能不同。但是,在沒有排序規則變更的情況下,可以將欄位從 text
變更為 varchar
(或反之亦然),而無需重建索引,因為這些資料類型以相同的方式排序。對於大型資料表來說,資料表和/或索引的重建可能需要很長的時間,並且暫時需要高達兩倍的磁碟空間。
新增 CHECK
或 NOT NULL
約束需要掃描資料表以驗證現有列是否符合約束,但不需要重寫資料表。
同樣地,當附加一個新的分割區時,可能會掃描它以驗證現有列是否符合分割區約束。
在單一 ALTER TABLE
中提供指定多個變更選項的主要原因是,藉此可以將多個資料表掃描或重寫合併到單一的資料表掃描中。
掃描大型資料表以驗證新的外部鍵或檢查約束可能需要很長時間,並且對資料表的其他更新將被鎖定,直到 ALTER TABLE ADD CONSTRAINT
命令提交。 NOT VALID
約束選項的主要目的是減少新增約束對並行更新的影響。 使用 NOT VALID
時,ADD CONSTRAINT
命令不會掃描資料表,並且可以立即提交。 之後,可以發出 VALIDATE CONSTRAINT
命令以驗證現有列是否滿足約束。 驗證步驟不需要鎖定並行更新,因為它知道其他交易將強制執行它們插入或更新的列的約束; 只需要檢查預先存在的列。 因此,驗證只會取得被修改資料表的 SHARE UPDATE EXCLUSIVE
鎖。(如果約束是外部鍵,那麼在約束引用的資料表上也需要 ROW SHARE
鎖。) 除了提高並行性之外,在已知資料表包含先前存在的違規的情況下,使用 NOT VALID
和 VALIDATE CONSTRAINT
可能也很有用。 一旦約束到位,就無法插入新的違規,並且可以在閒暇時修正現有的問題,直到 VALIDATE CONSTRAINT
最終成功。
DROP COLUMN
形式並不會實際移除欄位,而只是使其對 SQL 操作不可見。 後續在資料表中的插入和更新操作將為該欄位儲存 NULL 值。 因此,刪除欄位很快,但它不會立即減少資料表的磁碟大小,因為不會回收被刪除欄位佔用的空間。 隨著現有列的更新,空間將隨著時間的推移而被回收。
要強制立即回收被刪除欄位佔用的空間,您可以執行一種執行整個資料表重寫的 ALTER TABLE
形式。 這會導致重新構建每一列,並用 NULL 值替換被刪除的欄位。
重寫形式的 ALTER TABLE
不是 MVCC 安全的。 在資料表重寫之後,如果並行交易使用的快照是在重寫之前取得的,則該資料表對它們來說將顯示為空的。 有關更多詳細資訊,請參閱第 13.6 節。
SET DATA TYPE
的 USING
選項實際上可以指定任何涉及列舊值的表達式; 也就是說,它可以引用其他欄位以及被轉換的欄位。 這允許使用 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
命令將失敗,因為資料表的所有分割區必須具有與分割根相同的欄位。
identity 欄位的動作(ADD GENERATED
、SET
等等、DROP IDENTITY
),以及動作 CLUSTER
、OWNER
和 TABLESPACE
永遠不會遞迴到子資料表;也就是說,它們總是表現得如同指定了 ONLY
。影響觸發程序狀態的動作會遞迴到分割資料表的分割區(除非指定了 ONLY
),但永遠不會遞迴到傳統繼承的子資料表。新增約束條件只會針對未標記為 NO INHERIT
的 CHECK
約束條件進行遞迴。
不允許更改系統目錄資料表的任何部分。
請參閱 CREATE TABLE 以取得有效參數的進一步描述。第 5 章 有關於繼承的更多資訊。
新增一個 varchar
類型的欄位到資料表
ALTER TABLE distributors ADD COLUMN address varchar(30);
這將會導致資料表中所有現有列的新欄位都填入空值。
新增一個具有非空預設值的欄位
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
(沒有 USING INDEX
)、DROP [COLUMN]
、DROP IDENTITY
、RESTART
、SET DEFAULT
、SET DATA TYPE
(沒有 USING
)、SET GENERATED
和 SET
符合 SQL 標準。其他形式是 PostgreSQL 的 SQL 標準擴充。此外,在單一 sequence_option
ALTER TABLE
指令中指定多個操作也是一種擴充。
ALTER TABLE DROP COLUMN
可用於刪除資料表的唯一欄位,留下一個零欄位的資料表。這是 SQL 的擴充,SQL 不允許零欄位的資料表。
如果您在文件中發現任何不正確、與特定功能的體驗不符或需要進一步澄清之處,請使用此表單報告文件問題。