INSERT
— 建立表中的新行
[ WITH [ RECURSIVE ]with_query
[, ...] ] INSERT INTOtable_name
[ ASalias
] [ (column_name
[, ...] ) ] [ OVERRIDING { SYSTEM | USER } VALUE ] { DEFAULT VALUES | VALUES ( {expression
| DEFAULT } [, ...] ) [, ...] |query
} [ ON CONFLICT [conflict_target
]conflict_action
] [ RETURNING [ WITH ( { OLD | NEW } ASoutput_alias
[, ...] ) ] { * |output_expression
[ [ AS ]output_name
] } [, ...] ] whereconflict_target
can be one of: ( {index_column_name
| (index_expression
) } [ COLLATEcollation
] [opclass
] [, ...] ) [ WHEREindex_predicate
] ON CONSTRAINTconstraint_name
andconflict_action
is one of: DO NOTHING DO UPDATE SET {column_name
= {expression
| DEFAULT } | (column_name
[, ...] ) = [ ROW ] ( {expression
| DEFAULT } [, ...] ) | (column_name
[, ...] ) = (sub-SELECT
) } [, ...] [ WHEREcondition
]
INSERT
用於在表中插入新行。可以透過值表示式指定一行或多行,或者透過查詢結果指定零行或多行。
目標列名可以按任何順序給出。如果根本沒有給出列名列表,則預設情況下是表中所有列,按宣告的順序排列;或者,如果 VALUES
子句或 query
只提供了 N
個列名,則預設是前 N
個列名。由 VALUES
子句或 query
提供的這些值將從左到右與顯式或隱式指定的列列表對應。
顯式或隱式列列表中不存在的每一列都將用預設值填充,如果聲明瞭預設值,則使用宣告的預設值,否則使用 NULL。
如果任何列的表示式不是正確的資料型別,將嘗試自動型別轉換。
INSERT
到沒有唯一索引的表不會被併發活動阻止。具有唯一索引的表可能會被阻止,如果併發會話執行的操作鎖定或修改與要插入的唯一索引值匹配的行;詳細資訊請參閱 第 63.5 節。可以使用 ON CONFLICT
指定一個替代操作,以代替引發唯一約束或排除約束衝突錯誤。(請參閱下面的 ON CONFLICT 子句。)
可選的 RETURNING
子句會導致 INSERT
根據實際插入(或更新,如果使用了 ON CONFLICT DO UPDATE
子句)的每一行計算並返回值。這主要用於獲取由預設值提供的值,例如序列號。但是,允許使用表列的任何表示式。 RETURNING
列表的語法與 SELECT
的輸出列表相同。只有成功插入或更新的行才會被返回。例如,如果一行被鎖定但未被更新,因為 ON CONFLICT DO UPDATE ... WHERE
子句的 condition
未滿足,則該行不會被返回。
為了插入資料,您必須對目標表具有 INSERT
許可權。如果存在 ON CONFLICT DO UPDATE
,則還需要對該表具有 UPDATE
許可權。
如果指定了列列表,則只需要對列出的列具有 INSERT
許可權。類似地,在指定 ON CONFLICT DO UPDATE
時,只需要對要更新的列具有 UPDATE
許可權。但是,ON CONFLICT DO UPDATE
還要求對在 ON CONFLICT DO UPDATE
表示式或 condition
中讀取的任何列具有 SELECT
許可權。
使用 RETURNING
子句需要對 RETURNING
中提到的所有列具有 SELECT
許可權。如果您使用 query
子句從查詢中插入行,您當然需要對查詢中使用的任何表或列具有 SELECT
許可權。
本節介紹僅在插入新行時可能使用的引數。 僅與 ON CONFLICT
子句一起使用的引數將單獨描述。
with_query
WITH
子句允許您指定一個或多個子查詢,這些子查詢可以在 INSERT
查詢中透過名稱引用。有關詳細資訊,請參閱 第 7.8 節 和 SELECT。
可以使 query
(SELECT
語句)也包含 WITH
子句。在這種情況下,兩個 with_query
都可以引用 query
內部,但第二個優先順序更高,因為它巢狀得更深。
table_name
一個現有表的名稱(可選擇模式限定)。
alias
table_name
的替代名稱。提供別名時,它會完全隱藏表的實際名稱。當 ON CONFLICT DO UPDATE
目標表名為 excluded
時,這特別有用,因為否則它會被解釋為表示要插入的行的特殊表的名稱。
column_name
table_name
指定的表中的列的名稱。如果需要,列名可以由子欄位名或陣列下標限定。(僅插入複合列的某些欄位會將其他欄位保留為 NULL。)引用列名時,請不要在目標列的規範中包含表名。例如,INSERT INTO table_name ... ON CONFLICT DO UPDATE SET table_name.col = 1
是無效的(這遵循 UPDATE
的一般行為)。
OVERRIDING SYSTEM VALUE
如果指定了此子句,則為標識列提供的任何值將覆蓋預設的序列生成值。
對於定義為 GENERATED ALWAYS
的標識列,在不指定 OVERRIDING SYSTEM VALUE
或 OVERRIDING USER VALUE
的情況下,插入顯式值(DEFAULT
除外)是錯誤的。(對於定義為 GENERATED BY DEFAULT
的標識列,OVERRIDING SYSTEM VALUE
是正常行為,指定它什麼也不做,但 PostgreSQL 作為擴充套件允許它。)
OVERRIDING USER VALUE
如果指定了此子句,則將忽略為標識列提供的任何值,並應用預設的序列生成值。
此子句對於將值複製到表之間很有用。例如,編寫 INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1
將從 tbl1
複製 tbl2
中所有不是標識列的列,而 tbl2
中標識列的值將由與 tbl2
關聯的序列生成。
DEFAULT VALUES
所有列都將用其預設值填充,就像為每列顯式指定了 DEFAULT
一樣。(此形式不允許使用 OVERRIDING
子句。)
expression
分配給相應列的表示式或值。
DEFAULT
相應列將用其預設值填充。標識列將用關聯序列生成的新值填充。對於生成列,指定此項是允許的,但只是指定了從生成表示式計算該列的正常行為。
query
一個提供要插入的行的查詢(SELECT
語句)。有關語法說明,請參閱 SELECT 語句。
output_alias
RETURNING
列表中的 OLD
或 NEW
行的可選替代名稱。
預設情況下,可以透過編寫 OLD.
或 column_name
OLD.*
返回目標表中的舊值,透過編寫 NEW.
或 column_name
NEW.*
返回新值。提供別名時,將隱藏這些名稱,並且必須使用別名引用舊行或新行。例如 RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*
。
output_expression
INSERT
命令在插入或更新每一行後計算並返回的值。該表示式可以使用 table_name
指定的表中的任何列名。編寫 *
以返回插入或更新行中的所有列。
列名或 *
可以使用 OLD
或 NEW
,或者 OLD
或 NEW
的相應 output_alias
來限定,以返回舊值或新值。不限定的列名,或 *
,或使用目標表名或別名限定的列名或 *
將返回新值。
對於簡單的 INSERT
,所有舊值都將是 NULL
。但是,對於帶有 ON CONFLICT DO UPDATE
子句的 INSERT
,舊值可能不是 NULL
。
output_name
用於返回列的名稱。
ON CONFLICT
Clause可選的 ON CONFLICT
子句指定一個替代操作,以代替引發唯一衝突或排除約束衝突錯誤。對於要插入的每一行,要麼繼續插入,要麼,如果 conflict_target
指定的 仲裁約束或索引被違反,則執行替代的 conflict_action
。ON CONFLICT DO NOTHING
僅避免插入一行作為其替代操作。ON CONFLICT DO UPDATE
將要插入的行與已有的衝突行進行更新作為其替代操作。
conflict_target
可以執行 唯一索引推斷。在進行推斷時,它由一個或多個 index_column_name
列和/或 index_expression
表示式組成,以及一個可選的 index_predicate
。所有 table_name
的唯一索引,如果不考慮順序,完全包含 conflict_target
指定的列/表示式,將被推斷(選擇)為仲裁索引。如果指定了 index_predicate
,則它必須作為推斷的進一步要求,滿足仲裁索引。請注意,這意味著非部分唯一索引(沒有謂詞的唯一索引)將被推斷(因此由 ON CONFLICT
使用),前提是存在滿足所有其他標準的索引。如果推斷嘗試失敗,則會引發錯誤。
ON CONFLICT DO UPDATE
保證了原子 INSERT
或 UPDATE
的結果;只要沒有獨立錯誤,即使在高併發下,也會保證其中一個結果。這也稱為 UPSERT —— “更新或插入”。
conflict_target
透過選擇 仲裁索引 指定 ON CONFLICT
執行替代操作的衝突。要麼執行 唯一索引推斷,要麼顯式命名一個約束。對於 ON CONFLICT DO NOTHING
,指定 conflict_target
是可選的;省略時,會處理所有可用約束(和唯一索引)的衝突。對於 ON CONFLICT DO UPDATE
,必須提供 conflict_target
。
conflict_action
conflict_action
指定一個替代的 ON CONFLICT
操作。它可以是 DO NOTHING
,或者是一個 DO UPDATE
子句,指定在發生衝突時要執行的 UPDATE
操作的確切詳細資訊。ON CONFLICT DO UPDATE
中的 SET
和 WHERE
子句可以使用表的名稱(或別名)訪問現有行,並使用特殊表 excluded
訪問要插入的行。在目標表中讀取相應 excluded
列的任何列都需要 SELECT
許可權。
請注意,所有逐行 BEFORE INSERT
觸發器的效果都反映在 excluded
值中,因為這些效果可能導致該行被排除在插入之外。
index_column_name
table_name
列的名稱。用於推斷仲裁索引。遵循 CREATE INDEX
格式。index_column_name
需要 SELECT
許可權。
index_expression
與 index_column_name
類似,但用於推斷出現在索引定義(非簡單列)中的 table_name
列上的表示式。遵循 CREATE INDEX
格式。 index_expression
中出現的任何列都需要 SELECT
許可權。
collation
指定時,強制相應的 index_column_name
或 index_expression
使用特定的排序規則,以便在推斷期間匹配。通常省略此項,因為排序規則通常不影響約束衝突是否發生。遵循 CREATE INDEX
格式。
opclass
指定時,強制相應的 index_column_name
或 index_expression
使用特定的運算子類,以便在推斷期間匹配。通常省略此項,因為對於某個型別的運算子類而言,相等性語義通常是等效的,或者因為信任已定義的唯一索引具有相關的相等性定義就足夠了。遵循 CREATE INDEX
格式。
index_predicate
用於允許推斷部分唯一索引。任何滿足該謂詞的索引(不必是部分索引)都可以被推斷。遵循 CREATE INDEX
格式。 index_predicate
中出現的任何列都需要 SELECT
許可權。
constraint_name
透過名稱顯式指定仲裁 約束,而不是推斷約束或索引。
condition
返回 boolean
型別值的表示式。只有當該表示式返回 true
時,才會更新行,儘管在採取 ON CONFLICT DO UPDATE
操作時,所有行都會被鎖定。請注意,condition
是最後計算的,在衝突被確定為要更新的候選之後。
請注意,排除約束不支援作為 ON CONFLICT DO UPDATE
的仲裁器。在所有情況下,僅支援 NOT DEFERRABLE
約束和唯一索引作為仲裁器。
INSERT
帶有 ON CONFLICT DO UPDATE
子句是一個 “確定性” 語句。這意味著該命令不允許影響任何單個現有行超過一次;當這種情況發生時,將引發基數衝突錯誤。要插入的行在由仲裁索引或約束約束的屬性方面不應相互重複。
請注意,目前不支援將應用於分割槽表的 INSERT
的 ON CONFLICT DO UPDATE
子句更新衝突行的分割槽鍵,使其需要將行移動到新分割槽。
通常最好使用唯一索引推斷,而不是直接命名約束,例如使用 ON CONFLICT ON CONSTRAINT
constraint_name
。當底層索引被另一個或多或少等效的索引以重疊方式替換時,推斷將繼續正常工作,例如在使用 CREATE UNIQUE INDEX ... CONCURRENTLY
之後刪除被替換的索引。
成功完成時,INSERT
命令將返回一個命令標籤,格式為
INSERToid
count
count
是插入或更新的行數。 oid
始終為 0(它以前是OID如果 count
恰好為一且目標表宣告為 WITH OIDS
,則分配給插入的行,否則為 0,但建立 WITH OIDS
的表不再受支援)。
如果 INSERT
命令包含 RETURNING
子句,則結果將類似於 SELECT
語句,其中包含 RETURNING
列表定義的列和值,這些值是在命令插入或更新的行上計算的。
如果指定的表是分割槽表,則每行將被路由到相應分割槽並插入其中。如果指定的表是分割槽,則如果任何輸入行違反了分割槽約束,將發生錯誤。
您可能還希望考慮使用 MERGE
,因為它允許在單個語句中混合 INSERT
、UPDATE
和 DELETE
。請參閱 MERGE。
將單行插入 films
表
INSERT INTO films VALUES ('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes');
在此示例中,省略了 len
列,因此它將具有預設值
INSERT INTO films (code, title, did, date_prod, kind) VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');
此示例使用 DEFAULT
子句為日期列設定值,而不是指定一個值
INSERT INTO films VALUES ('UA502', 'Bananas', 105, DEFAULT, 'Comedy', '82 minutes'); INSERT INTO films (code, title, did, date_prod, kind) VALUES ('T_601', 'Yojimbo', 106, DEFAULT, 'Drama');
插入完全由預設值組成的行
INSERT INTO films DEFAULT VALUES;
使用多行 VALUES
語法插入多行
INSERT INTO films (code, title, did, date_prod, kind) VALUES ('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'), ('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');
此示例將一些行從 tmp_films
表插入到 films
表中,tmp_films
表的列布局與 films
表相同
INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07';
此示例插入到陣列列
-- Create an empty 3x3 gameboard for noughts-and-crosses INSERT INTO tictactoe (game, board[1:3][1:3]) VALUES (1, '{{" "," "," "},{" "," "," "},{" "," "," "}}'); -- The subscripts in the above example aren't really needed INSERT INTO tictactoe (game, board) VALUES (2, '{{X," "," "},{" ",O," "},{" ",X," "}}');
將單行插入 distributors
表,並返回由 DEFAULT
子句生成的序列號
INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets') RETURNING did;
增加管理 Acme Corporation 客戶的銷售人員的銷售計數,並將整個更新後的行與當前時間一起記錄到日誌表中
WITH upd AS ( UPDATE employees SET sales_count = sales_count + 1 WHERE id = (SELECT sales_person FROM accounts WHERE name = 'Acme Corporation') RETURNING * ) INSERT INTO employees_log SELECT *, current_timestamp FROM upd;
根據需要插入或更新分銷商。假設已定義了一個唯一索引,該索引約束了 did
列中出現的值。請注意,特殊表 excluded
用於引用最初提議插入的值
INSERT INTO distributors (did, dname) VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc') ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;
如上所示插入或更新新的分銷商,並返回有關已更新的任何現有值以及新插入的資料的資訊。請注意,對於非衝突行,old_did
和 old_dname
的返回值將是 NULL
INSERT INTO distributors (did, dname) VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc') ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname RETURNING old.did AS old_did, old.dname AS old_dname, new.did AS new_did, new.dname AS new_dname;
插入一個分銷商,或者在存在現有、已排除的行(在 before row insert 觸發器觸發後,具有匹配的約束列或列的行)時,對提議插入的行不做任何操作。示例假定已定義了一個唯一索引,該索引約束了 did
列中出現的值
INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH') ON CONFLICT (did) DO NOTHING;
根據需要插入或更新新的分銷商。示例假定已定義了一個唯一索引,該索引約束了 did
列中出現的值。WHERE
子句用於限制實際更新的行(儘管任何未更新的現有行仍將被鎖定)
-- Don't update existing distributors based in a certain ZIP code INSERT INTO distributors AS d (did, dname) VALUES (8, 'Anvil Distribution') ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname || ' (formerly ' || d.dname || ')' WHERE d.zipcode <> '21201'; -- Name a constraint directly in the statement (uses associated -- index to arbitrate taking the DO NOTHING action) INSERT INTO distributors (did, dname) VALUES (9, 'Antwerp Design') ON CONFLICT ON CONSTRAINT distributors_pkey DO NOTHING;
如果可能,插入新的分銷商;否則 DO NOTHING
。示例假定已定義了一個唯一索引,該索引約束了 did
列中出現的值,該列的值在 is_active
布林列求值為 true
的行的子集上
-- This statement could infer a partial unique index on "did" -- with a predicate of "WHERE is_active", but it could also -- just use a regular unique constraint on "did" INSERT INTO distributors (did, dname) VALUES (10, 'Conrad International') ON CONFLICT (did) WHERE is_active DO NOTHING;
INSERT
符合 SQL 標準,但 RETURNING
子句是 PostgreSQL 的擴充套件,INSERT
使用 WITH
的能力,以及指定替代操作 ON CONFLICT
的能力也是如此。此外,標準不允許省略列名列表,但 VALUES
子句或 query
未填充所有列的情況。如果您偏好比 ON CONFLICT
更符合 SQL 標準的語句,請參閱 MERGE。
SQL 標準規定,只有在存在總是生成的標識列時才能指定 OVERRIDING SYSTEM VALUE
。PostgreSQL 在任何情況下都允許此子句,如果它不適用則忽略它。
query
子句的可能限制已在 SELECT 下進行了說明。
如果您在文件中看到任何不正確、與您的實際使用經驗不符或需要進一步澄清的內容,請使用 此表格 來報告文件問題。