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

INSERT

INSERT — 建立表中的新行

概要

[ WITH [ RECURSIVE ] with_query [, ...] ]
INSERT INTO table_name [ AS alias ] [ ( column_name [, ...] ) ]
    [ OVERRIDING { SYSTEM | USER } VALUE ]
    { DEFAULT VALUES | VALUES ( { expression | DEFAULT } [, ...] ) [, ...] | query }
    [ ON CONFLICT [ conflict_target ] conflict_action ]
    [ RETURNING [ WITH ( { OLD | NEW } AS output_alias [, ...] ) ]
                { * | output_expression [ [ AS ] output_name ] } [, ...] ]

where conflict_target can be one of:

    ( { index_column_name | ( index_expression ) } [ COLLATE collation ] [ opclass ] [, ...] ) [ WHERE index_predicate ]
    ON CONSTRAINT constraint_name

and conflict_action is one of:

    DO NOTHING
    DO UPDATE SET { column_name = { expression | DEFAULT } |
                    ( column_name [, ...] ) = [ ROW ] ( { expression | DEFAULT } [, ...] ) |
                    ( column_name [, ...] ) = ( sub-SELECT )
                  } [, ...]
              [ WHERE condition ]

描述

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

可以使 querySELECT 語句)也包含 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 VALUEOVERRIDING 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 列表中的 OLDNEW 行的可選替代名稱。

預設情況下,可以透過編寫 OLD.column_nameOLD.* 返回目標表中的舊值,透過編寫 NEW.column_nameNEW.* 返回新值。提供別名時,將隱藏這些名稱,並且必須使用別名引用舊行或新行。例如 RETURNING WITH (OLD AS o, NEW AS n) o.*, n.*

output_expression

INSERT 命令在插入或更新每一行後計算並返回的值。該表示式可以使用 table_name 指定的表中的任何列名。編寫 * 以返回插入或更新行中的所有列。

列名或 * 可以使用 OLDNEW,或者 OLDNEW 的相應 output_alias 來限定,以返回舊值或新值。不限定的列名,或 *,或使用目標表名或別名限定的列名或 * 將返回新值。

對於簡單的 INSERT,所有舊值都將是 NULL。但是,對於帶有 ON CONFLICT DO UPDATE 子句的 INSERT,舊值可能不是 NULL

output_name

用於返回列的名稱。

ON CONFLICT Clause

可選的 ON CONFLICT 子句指定一個替代操作,以代替引發唯一衝突或排除約束衝突錯誤。對於要插入的每一行,要麼繼續插入,要麼,如果 conflict_target 指定的 仲裁約束或索引被違反,則執行替代的 conflict_actionON 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 保證了原子 INSERTUPDATE 的結果;只要沒有獨立錯誤,即使在高併發下,也會保證其中一個結果。這也稱為 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 中的 SETWHERE 子句可以使用表的名稱(或別名)訪問現有行,並使用特殊表 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_nameindex_expression 使用特定的排序規則,以便在推斷期間匹配。通常省略此項,因為排序規則通常不影響約束衝突是否發生。遵循 CREATE INDEX 格式。

opclass

指定時,強制相應的 index_column_nameindex_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 子句是一個 確定性 語句。這意味著該命令不允許影響任何單個現有行超過一次;當這種情況發生時,將引發基數衝突錯誤。要插入的行在由仲裁索引或約束約束的屬性方面不應相互重複。

請注意,目前不支援將應用於分割槽表的 INSERTON CONFLICT DO UPDATE 子句更新衝突行的分割槽鍵,使其需要將行移動到新分割槽。

提示

通常最好使用唯一索引推斷,而不是直接命名約束,例如使用 ON CONFLICT ON CONSTRAINT constraint_name。當底層索引被另一個或多或少等效的索引以重疊方式替換時,推斷將繼續正常工作,例如在使用 CREATE UNIQUE INDEX ... CONCURRENTLY 之後刪除被替換的索引。

輸出

成功完成時,INSERT 命令將返回一個命令標籤,格式為

INSERT oid count

count 是插入或更新的行數。 oid 始終為 0(它以前是OID如果 count 恰好為一且目標表宣告為 WITH OIDS,則分配給插入的行,否則為 0,但建立 WITH OIDS 的表不再受支援)。

如果 INSERT 命令包含 RETURNING 子句,則結果將類似於 SELECT 語句,其中包含 RETURNING 列表定義的列和值,這些值是在命令插入或更新的行上計算的。

註釋

如果指定的表是分割槽表,則每行將被路由到相應分割槽並插入其中。如果指定的表是分割槽,則如果任何輸入行違反了分割槽約束,將發生錯誤。

您可能還希望考慮使用 MERGE,因為它允許在單個語句中混合 INSERTUPDATEDELETE。請參閱 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_didold_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 下進行了說明。

提交更正

如果您在文件中看到任何不正確、與您的實際使用經驗不符或需要進一步澄清的內容,請使用 此表格 來報告文件問題。