W3Cschool
恭喜您成為首批注冊(cè)用戶
獲得88經(jīng)驗(yàn)值獎(jiǎng)勵(lì)
INSERT — 在一個(gè)表中創(chuàng)建新行
[ 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 * | output_expression
[ [ AS ] output_name
] [, ...] ]
其中 conflict_target
可以是以下之一:
( { index_column_name
| ( index_expression
) } [ COLLATE collation
] [ opclass
] [, ...] ) [ WHERE index_predicate
]
ON CONSTRAINT constraint_name
并且 conflict_action
是以下之一:
DO NOTHING
DO UPDATE SET { column_name
= { expression
| DEFAULT } |
( column_name
[, ...] ) = [ ROW ] ( { expression
| DEFAULT } [, ...] ) |
( column_name
[, ...] ) = ( sub-SELECT
)
} [, ...]
[ WHERE condition
]
INSERT
將新行插入到一個(gè)表中。我們可以 插入一個(gè)或者更多由值表達(dá)式指定的行,或者插入來(lái)自一個(gè)查詢的零行 或者更多行。
目標(biāo)列的名稱可以以任意順序列出。如果沒(méi)有給出列名列表,則有兩種確定 目標(biāo)列的可能性。第一種是以被聲明的順序列出該表的所有列。另一種可能 性是,如果VALUES
子句或者query
只提 供N
個(gè)列,則以被聲明的順序列出該表的前 N
列。
VALUES
子句或者 query
提供的值會(huì)被從左至右關(guān)聯(lián)到這些顯式或者隱式 給出的目標(biāo)列。
每一個(gè)沒(méi)有出現(xiàn)在顯式或者隱式列列表中的列都將被默認(rèn)填充,如果為該列 聲明過(guò)默認(rèn)值則用默認(rèn)值填充,否則用空值填充。
如果任意列的表達(dá)式不是正確的數(shù)據(jù)類型,將會(huì)嘗試自動(dòng)類型轉(zhuǎn)換。
ON CONFLICT
可以用來(lái)指定發(fā)生唯一約束或者排除約束 違背錯(cuò)誤時(shí)的替換動(dòng)作(見(jiàn)下文的ON CONFLICT 子句)。
可選的RETURNING
子句讓INSERT
根據(jù) 實(shí)際被插入(如果使用了ON CONFLICT DO UPDATE
子句, 可能是被更新)的每一行來(lái)計(jì)算和返回值。這主要用來(lái)獲取由默認(rèn)值提供 的值,例如一個(gè)序列號(hào)。不過(guò),允許在其中包括使用該表列的任何表達(dá)式。 RETURNING
列表的語(yǔ)法與
SELECT
的輸出 列表的相同。只有被成功地插入或者更新的行才將被返回。例如,如果一 行被鎖定但由于不滿足ON CONFLICT DO UPDATE
... WHERE
clause condition
沒(méi)有被更新,該行將 不被返回。
為了向表中插入,你必須具有其上的INSERT
特權(quán)。 如果存在ON CONFLICT DO UPDATE
子句,還要求該表上 的UPDATE
特權(quán)。
如果一個(gè)列列表被指定,你只需要其中的列上的INSERT
特權(quán)。類似地,在指定了ON CONFLICT DO UPDATE
時(shí),你只 需要被列出要更新的列上的UPDATE
特權(quán)。不過(guò), ON CONFLICT DO UPDATE
還要求其值被 ON CONFLICT DO UPDATE
表達(dá)式或者
condition
使用的列上的SELECT
特權(quán)。
使用RETURNING
子句需要RETURNING
中提到的所有列的 SELECT
權(quán)限。 如果使用query
子句從查詢中插入行, 則當(dāng)然需要對(duì)查詢中使用的任何表或列具有SELECT
權(quán)限。
這個(gè)小節(jié)介紹了在只插入新行時(shí)可以使用的參數(shù)。 專門用于ON CONFLICT
子句的 參數(shù)會(huì)單獨(dú)介紹。
with_query
WITH
子句允許指定一個(gè)或者更多子查詢,在 INSERT
查詢中可以用名稱引用這些子查詢。詳見(jiàn) 第 7.8 節(jié)以及
SELECT
。
query
(SELECT
語(yǔ)句)也可以包含一個(gè) WITH
子句。在這種情況下 query
中可以引用 兩組with_query
,但是第二個(gè)優(yōu)先級(jí)更
高(因?yàn)樗磺短赘?/p>
table_name
一個(gè)已有表的名稱(可以被模式限定)。
alias
table_name
的替補(bǔ)名稱。當(dāng)提供了一個(gè)別名時(shí),它會(huì)完全隱藏掉表的實(shí)際名稱。 當(dāng)ON CONFLICT DO UPDATE
的目標(biāo)是一個(gè)被排除的
表時(shí)這特別有用,因?yàn)槟菍⒈划?dāng)作表示要被插入行的特殊表的名稱。
column_name
名為table_name
的表中的一個(gè)列 的名稱。如有必要,列名可以用一個(gè)子域名或者數(shù)組下標(biāo)限定(指向 一個(gè)組合列的某些列中插入會(huì)讓其他域?yàn)榭眨?。?dāng)用 ON CONFLICT DO UPDATE
引用一列時(shí),不要在一個(gè) 目標(biāo)列的說(shuō)明中國(guó)包括表名。例如, INSERT INTO table_name ... ON CONFLICT DO UPDATE
SET table_name.col = 1
是非法的(這遵循UPDATE
的一般行為)。
OVERRIDING SYSTEM VALUE
如果指定了此子句,那么為標(biāo)識(shí)列提供的任何值都將覆蓋默認(rèn)的序列生成的值。
對(duì)于定義為GENERATED ALWAYS
的標(biāo)識(shí)列,插入顯式值(DEFAULT
除外)而不指定 OVERRIDING SYSTEM VALUE
或OVERRIDING USER VALUE
是錯(cuò)誤的。(對(duì)于定義 為GENERATED BY DEFAULT
的標(biāo)識(shí)列,
OVERRIDING SYSTEM VALUE
是正常行為, 并指定其不執(zhí)行任何操作,但是PostgreSQL允許它作為擴(kuò)展名。)
OVERRIDING USER VALUE
如果指定了此子句,則將忽略為標(biāo)識(shí)列提供的任何值,并應(yīng)用默認(rèn)的序列生成的值。
例如,當(dāng)在表之間拷貝值時(shí),這個(gè)子句有能派上用場(chǎng)。INSERT INTO tbl2 OVERRIDING USER VALUE SELECT * FROM tbl1
將從tbl1
中拷貝所有在tbl2
中不是標(biāo)識(shí)列的列,而tbl2
中標(biāo)識(shí)列的值將由與tbl2
關(guān)聯(lián)的序列產(chǎn)生。
DEFAULT VALUES
所有列都將被其默認(rèn)值填充,就像為每個(gè)列顯式指定了DEFAULT
。 (例如這種形式下不允許OVERRIDING
子句)。
expression
要賦予給相應(yīng)列的表達(dá)式或者值。
DEFAULT
相應(yīng)的列將填充其默認(rèn)值。標(biāo)識(shí)列將由關(guān)聯(lián)序列生成的新值填充。對(duì)于生成的列,允許指定該值,但僅指定根據(jù)其生成表達(dá)式計(jì)算該列的正常行為。
query
提供要被插入行的查詢(SELECT
語(yǔ)句)。 其語(yǔ)法描述請(qǐng)參考SELECT語(yǔ)句。
output_expression
在每一行被插入或更新后由INSERT
命令計(jì)算并且返回的 表達(dá)式。該表達(dá)式可以使用table_name
指定的表中的任何列。寫(xiě)成*
可返回被插入或更新行的所有列。
output_name
要用于被返回列的名稱。
ON CONFLICT
子句可選的ON CONFLICT
子句為出現(xiàn)唯一性違背或排除 約束違背錯(cuò)誤時(shí)提供另一種可供選擇的動(dòng)作。對(duì)于每一個(gè)要插入的行, 不管是插入進(jìn)行下去還是由conflict_target
指定的一個(gè)仲裁者約束或者索引被違背,都會(huì) 采取可供選擇的conflict_action
。
ON CONFLICT DO NOTHING
簡(jiǎn)單地把避免插入行。 ON CONFLICT DO UPDATE
則會(huì) 更新與要插入的行沖突的已有行。
conflict_target
可以執(zhí)行 唯一索引推斷。在執(zhí)行推斷時(shí),它由一個(gè)或者多個(gè) index_column_name
列或者 index_expression
表達(dá)式以及一個(gè)可選的
index_predicate
構(gòu)成。所有剛好包含 conflict_target
指定的列/表達(dá)式的table_name
唯一索引(不管順序)都 會(huì)被推斷為(選擇為)仲裁者索引。如果指定了 index_predicate
,它 必須滿足仲裁者索引(也是推斷過(guò)程的一個(gè)進(jìn)一步的要求)。注意這意味著如果
有一個(gè)滿足其他條件的非部分唯一索引(沒(méi)有謂詞的唯一索引)可用,它將被 推斷為仲裁者(并且會(huì)被ON CONFLICT
使用)。如果推斷 嘗試不成功,則會(huì)發(fā)生一個(gè)錯(cuò)誤。
ON CONFLICT DO UPDATE
保證一個(gè)原子的 INSERT
或者 UPDATE
結(jié)果。在沒(méi)有無(wú)關(guān)錯(cuò)誤的前提下,這兩種 結(jié)果之一可以得到保證,即使在很高的并發(fā)度也能保證。這也可以被稱作 UPSERT — “UPDATE 或
INSERT”。
conflict_target
通過(guò)選擇仲裁者索引來(lái)指定哪些行與 ON CONFLICT
在其上采取可替代動(dòng)作的行相沖突。 要么執(zhí)行唯一索引推斷,要么顯式命名一個(gè) 約束。對(duì)于ON CONFLICT DO NOTHING
來(lái)說(shuō), 它對(duì)于指定一個(gè)conflict_target
是可選的。
在被省略時(shí),與所有有效約束(以及唯一索引)的沖突都會(huì)被處理。對(duì)于 ON CONFLICT DO UPDATE
,必須
提供一個(gè)conflict_target
。
conflict_action
conflict_action
指定一個(gè)可替換的 ON CONFLICT
動(dòng)作。它可以是 DO NOTHING
,也可以是一個(gè)指定在沖突情況下 要被執(zhí)行的UPDATE
動(dòng)作細(xì)節(jié)的DO
UPDATE
子句。ON CONFLICT DO
UPDATE
中的SET
和 WHERE
子句能夠使用該表的名稱(或者別名) 訪問(wèn)現(xiàn)有的行,并且可以用特殊的被排除
表訪問(wèn)要插入的行。這個(gè)動(dòng)作要求被排除
列所在目標(biāo)表的任何列上的SELECT
特權(quán)。
注意所有行級(jí)BEFORE INSERT
觸發(fā)器的效果都會(huì) 反映在被排除
值中,因?yàn)槟切┬Ч赡軙?huì) 讓該行避免被插入。
index_column_name
一個(gè)table_name
列 的名稱。它被用來(lái)推斷仲裁者索引。它遵循CREATE
INDEX
格式。這要求 index_column_name
上的SELECT
特權(quán)。
index_expression
和index_column_name
類似,但是 被用來(lái)推斷出現(xiàn)在索引定義中的table_name
列(非簡(jiǎn)單列)上的 表達(dá)式。遵循CREATE INDEX
格式。這要求 任何出現(xiàn)在index_expression
中的列上的
SELECT
特權(quán)。
collation
指定時(shí),強(qiáng)制相應(yīng)的index_column_name
或 index_expression
使用一種特定的排序規(guī)則以便在推斷期間能被匹配上。通常 會(huì)被省略,因?yàn)榕判蛞?guī)則通常不會(huì)影響約束違背的發(fā)生。遵循 CREATE INDEX
格式。
opclass
指定時(shí),強(qiáng)制相應(yīng)的index_column_name
或 index_expression
使用特定的操作符類以便在推斷期間能被匹配上。通常會(huì)被省略, 因?yàn)?span id="kpamstl" class="emphasis">相等語(yǔ)義在一種類型的操作符類 之間都是等價(jià)的,或者因?yàn)樽阋孕湃我讯x的唯一索引具有適當(dāng)?shù)?相等定義。遵循
CREATE INDEX
格式。
index_predicate
用于允許推斷部分唯一索引。任何滿足該謂詞(不一定需要真的是 部分索引)的索引都能被推斷。遵循CREATE
INDEX
格式。這要求任何出現(xiàn)在index_predicate
中的列上 的SELECT
特權(quán)。
constraint_name
用名稱顯式地指定一個(gè)仲裁者約束, 而不是推斷一個(gè)約束或者索引。
condition
一個(gè)能返回boolean
值的表達(dá)式。只有讓這個(gè)表達(dá)式返回 true
的行才將被更新,不過(guò)在采用 ON CONFLICT DO UPDATE
動(dòng)作時(shí)所有的行都會(huì)被鎖定。 注意condition
會(huì)被最后計(jì)算,即一個(gè)沖突 被標(biāo)識(shí)為要更新的候選對(duì)象之后。
注意不支持把排除約束作為ON CONFLICT DO UPDATE
的 仲裁者。在所有的情況中,只支持NOT DEFERRABLE
約束和 唯一索引作為仲裁者。
帶有ON CONFLICT DO UPDATE
子句的 INSERT
是一種“確定性的”語(yǔ)句。這表明不允許該命令影響任何單個(gè)現(xiàn)有行超過(guò)一次,如果發(fā)生則會(huì) 發(fā)生一個(gè)基數(shù)違背錯(cuò)誤。要插入的行不應(yīng)該在仲裁者索引或約束所限制的 屬性上相重復(fù)。
注意,當(dāng)前不支持用分區(qū)表上的INSERT
的ON CONFLICT DO UPDATE
子句更新沖突行的分區(qū)鍵,因?yàn)槟菢訒?huì)讓行移動(dòng)到新的分區(qū)中。
使用唯一索引推斷通常比使用ON CONFLICT ON CONSTRAINT
constraint_name
直接提名一個(gè)約束更好。當(dāng)?shù)讓铀饕灰灾丿B方式替換成另一個(gè)或多或少等效的索引時(shí),推斷將能繼續(xù)正確地工作,例如在刪除要被替換的索引之前使用CREATE UNIQUE INDEX ... CONCURRENTLY
。
成功完成時(shí),INSERT
命令會(huì)返回以下形式的命令標(biāo)簽:
INSERT oid
count
count
是被插入或更新的行數(shù)。 oid
總是0(過(guò)去,如果count
恰好為1, 并且目標(biāo)表被聲明為WITH OIDS
,則它是分配給插入行的OID,
否則為0, 但現(xiàn)在已不再支持創(chuàng)建WITH OIDS
表)。
如果INSERT
命令包含RETURNING
子句, 其結(jié)果會(huì)類似于包含RETURNING
列表中定義的列和值的 SELECT
語(yǔ)句,這些結(jié)果是由該命令在被插入或更新行上 計(jì)算得到。
如果指定的表是一個(gè)分區(qū)表,每一行都會(huì)被路由到合適的分區(qū)并且插入其中。如果指定的表是一個(gè)分區(qū),如果輸入行之一違背該分區(qū)的約束則將發(fā)生錯(cuò)誤。
向films
中插入一行:
INSERT INTO films VALUES
('UA502', 'Bananas', 105, '1971-07-13', 'Comedy', '82 minutes');
在這個(gè)例子中,len
列被省略并且因此會(huì)具有默認(rèn)值:
INSERT INTO films (code, title, did, date_prod, kind)
VALUES ('T_601', 'Yojimbo', 106, '1961-06-16', 'Drama');
這個(gè)例子為日期列使用DEFAULT
子句而不是指定一個(gè)值:
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');
插入一個(gè)完全由默認(rèn)值構(gòu)成的行:
INSERT INTO films DEFAULT VALUES;
用多行VALUES
語(yǔ)法插入多個(gè)行:
INSERT INTO films (code, title, did, date_prod, kind) VALUES
('B6717', 'Tampopo', 110, '1985-02-10', 'Comedy'),
('HG120', 'The Dinner Game', 140, DEFAULT, 'Comedy');
這個(gè)例子從表tmp_films
中獲得一些行插入到表 films
中,兩個(gè)表具有相同的列布局:
INSERT INTO films SELECT * FROM tmp_films WHERE date_prod < '2004-05-07';
這個(gè)例子插入數(shù)組列:
-- 為 noughts-and-crosses 游戲創(chuàng)建一個(gè)空的 3x3 棋盤(pán)
INSERT INTO tictactoe (game, board[1:3][1:3])
VALUES (1, '{{" "," "," "},{" "," "," "},{" "," "," "}}');
-- 實(shí)際上可以不用上面例子中的下標(biāo)
INSERT INTO tictactoe (game, board)
VALUES (2, '{{X," "," "},{" ",O," "},{" ",X," "}}');
向表distributors
中插入一行,返回由 DEFAULT
子句生成的序號(hào):
INSERT INTO distributors (did, dname) VALUES (DEFAULT, 'XYZ Widgets')
RETURNING did;
增加為 Acme Corporation 管理賬戶的銷售人員的銷量,并且把整個(gè)被 更新的行以及當(dāng)前時(shí)間記錄到一個(gè)日志表中:
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;
酌情插入或者更新新的 distributor。假設(shè)已經(jīng)定義了一個(gè)唯一索引來(lái)約束 出現(xiàn)在did
列中的值。注意,特殊的 excluded
表被用來(lái)引用原來(lái)要插入的值:
INSERT INTO distributors (did, dname)
VALUES (5, 'Gizmo Transglobal'), (6, 'Associated Computing, Inc')
ON CONFLICT (did) DO UPDATE SET dname = EXCLUDED.dname;
插入一個(gè) distributor,或者在一個(gè)被排除的行(具有一個(gè)匹配約束的列或者 會(huì)讓行級(jí)前(或者后)插入觸發(fā)器引發(fā)的列的行)存在時(shí)不處理要插入的行。 例子假設(shè)已經(jīng)定義了一個(gè)唯一觸發(fā)器來(lái)約束出現(xiàn)在did
列 中的值:
INSERT INTO distributors (did, dname) VALUES (7, 'Redline GmbH')
ON CONFLICT (did) DO NOTHING;
酌情插入或者更新新的 distributor。例子假設(shè)已經(jīng)定義了一個(gè)唯一觸發(fā)器來(lái) 約束出現(xiàn)在did
列中的值。WHERE
子句被用 來(lái)限制實(shí)際被更新的行(不過(guò),任何沒(méi)有被更新的已有行仍將被鎖定):
-- 根據(jù)一個(gè)特定的 ZIP 編碼更新 distributors
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';
-- 直接在語(yǔ)句中命名一個(gè)約束(使用相關(guān)的索引來(lái)判斷是否做
-- DO NOTHING 動(dòng)作)
INSERT INTO distributors (did, dname) VALUES (9, 'Antwerp Design')
ON CONFLICT ON CONSTRAINT distributors_pkey DO NOTHING;
如果可能就插入新的 distributor,否則DO NOTHING
。 例子假設(shè)已經(jīng)定義了一個(gè)唯一索引,它約束讓is_active
布爾列為true
的行子集上did
列中的值:
-- 這個(gè)語(yǔ)句可能推斷出一個(gè)在 "did" 上帶有謂詞 "WHERE is_active"
-- 的部分唯一索引,但是它可能也只是使用了 "did" 上的一個(gè)常規(guī)唯一約束
INSERT INTO distributors (did, dname) VALUES (10, 'Conrad International')
ON CONFLICT (did) WHERE is_active DO NOTHING;
INSERT
符合 SQL 標(biāo)準(zhǔn),不過(guò) RETURNING
子句是一種 PostgreSQL擴(kuò)展, 在 INSERT
中使用WITH
也是, 用ON CONFLICT
指定一個(gè)替代動(dòng)作也是擴(kuò)展。
還有,標(biāo)準(zhǔn)不允許省略列名列表但不通過(guò) VALUES
子句或者query
填充 所有列的情況。
SQL標(biāo)準(zhǔn)指定只有存在一個(gè)總是會(huì)生成值的標(biāo)識(shí)列時(shí)才能指定OVERRIDING SYSTEM VALUE
。而PostgreSQL在任何情況下都允許這個(gè)子句,并且在不適用時(shí)會(huì)忽略它。
query
子句可能的限制在 SELECT有介紹。
Copyright©2021 w3cschool編程獅|閩ICP備15016281號(hào)-3|閩公網(wǎng)安備35020302033924號(hào)
違法和不良信息舉報(bào)電話:173-0602-2364|舉報(bào)郵箱:jubao@eeedong.com
掃描二維碼
下載編程獅App
編程獅公眾號(hào)
聯(lián)系方式:
更多建議: