INSERT
Эта страница переведена при помощи нейросети GigaChat.
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 * | 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), либо вставить ноль или более строк, полученных в результате выполнения запроса.
Имена целевых столбцов могут быть указаны в любом порядке. Если список имен столбцов не указан вовсе, то по умолчанию используются все столбцы таблицы в их объявленном порядке, или первые N столбцов, если только N столбцов поставляется через VALUES или запрос. Значения, указанные через VALUES или результаты запроса, сопоставляются со списком столбцов слева направо.
Каждый столбец, отсутствующий в явном или подразумеваемом списке столбцов, будет заполнен значением по умолчанию — либо его объявленным значением по умолчанию, либо NULL, если значение по умолчанию не задано.
Если выражение для какого‑либо столбца не соответствует требуемому типу данных, PostgreSQL попытается выполнить автоматическое преобразование типа.
INSERT в таблицы, у которых нет уникальных индексов, как правило, не блокирует другие операции. В таблицах с уникальными индексами эта операция может блокироваться, если в параллельных сеансах выполняются действия, которые блокируют или изменяют строки, совпадающие с вставляемыми значениями в уникальном индексе; подробнее смотрите раздел Проверки уникальности индекса. Можно использовать ON CONFLICT, чтобы задать альтернативное действие при нарушении уникального или исключающего ограничения.
Необязательный параметр RETURNING позволяет вычислить и вернуть значение или значения на основе каждой реально вставленной или обновленной строки (в случае ON CONFLICT DO UPDATE). Это удобно при необходимости получить значения, задаваемые по умолчанию, например, номер секвенции SERIAL. При этом можно использовать любое выражение с использованием столбцов таблицы. Синтаксис RETURNING идентичен синтаксису списка вывода SELECT. Возвращаются только строки, которые были реально вставлены или обновлены. Например, если строка не была обновлена из‑за несоответствия условия ON CONFLICT ... WHERE, она не включается в возвращаемый результат.
Для выполнения INSERT требуется привилегия INSERT на целевую таблицу. При использовании ON CONFLICT DO UPDATE также требуется привилегия UPDATE на таблицу.
Если указан список столбцов, привилегии INSERT нужны только на указанные столбцы. Аналогично, при использовании ON CONFLICT DO UPDATE привилегии UPDATE требуются только на столбцы, которые будут обновляться. Однако сам ON CONFLICT DO UPDATE также требует привилегии SELECT на любые столбцы, значения которых используются в его выражениях или условиях.
Использование RETURNING также требует привилегии SELECT на все упоминаемые в нем столбцы. При вставке строк из запроса необходима привилегия SELECT на все таблицы и столбцы, используемые в этом запросе.
Параметры
Вставка
Этот раздел охватывает параметры, которые могут использоваться только при вставке новых строк. Параметры исключительно используются с предложением ON CONFLICT описываются отдельно.
with_query- Предложение
WITHпозволяет определить один или несколько подзапросов, доступных по имени внутри командыINSERT. Подробнее смотрите документацию по SELECT.Если сама команда
SELECT, используемая внутриINSERT, содержит свойWITH, то можно ссылаться на оба, но вложенныйWITHимеет приоритет.
table_name- Имя существующей таблицы, при необходимости дополненное схемой.
alias- Замещающее имя для
table_name. После его указания таблица скрывается за псевдонимом. Это полезно приON CONFLICT DO UPDATE, чтобы избежать конфликтов имен с системной таблицейexcluded.
column_name- Имя столбца в таблице
table_name. Это имя столбца при необходимости может быть дополнено именем вложенного поля или индексом в массиве. Когда данные вставляются только в некоторые поля столбца составного типа, в другие поля записываетсяNULL. Обращаясь к столбцу в предложенииON CONFLICT DO UPDATE, включать имя таблицы в ссылку на целевой столбец не нужно. Например, запись INSERT INTO table_name ... ON CONFLICT DO UPDATE SET table_name.col = 1некорректна (это согласуется с общим поведением командыUPDATE).
OVERRIDING SYSTEM VALUE- Если этот параметр указан, то любые значения, предоставленные для столбцов идентичности, заменят значения, генерируемые по умолчанию последовательностью.
Для столбца идентичности, определенного как
GENERATED ALWAYS, возникает ошибка при вставке явного значения (кромеDEFAULT) без указания либоOVERRIDING SYSTEM VALUE, либоOVERRIDING USER VALUE. Для столбца идентичности, определенного как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_expression- Выражение, которое должно быть вычислено и возвращено командой
INSERTпосле вставки или обновления каждой строки. Выражение может использовать любые имена столбцов таблицы, указанной вtable_name. Используйте*, чтобы вернуть все столбцы вставленной или обновленной строки (строк).
output_name- Имя возвращаемого столбца.
Предложение ON CONFLICT
Опциональное предложение 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 гарантирует атомарность выполнения — либо вставка, либо обновление, но не обе сразу. Если не возникло других ошибок, гарантируется одно из двух действий, даже при высокой параллельности. Такое поведение также известно как UPSERT (объединение UPDATE и INSERT).
conflict_target- Указывает, на какие конфликты
ON CONFLICTдолжен реагировать, выбирая арбитражные индексы. Либо выполняется вывод уникального индекса, либо явно указывается ограничение. ДляON CONFLICT DO NOTHINGуказыватьconflict_targetнеобязательно — при его отсутствии обрабатываются конфликты со всеми применимыми ограничениями и уникальными индексами. ДляON CONFLICT DO UPDATEуказаниеconflict_targetобязательно.
conflict_action- Указывает альтернативное действие, которое следует предпринять при конфликте. Это может быть либо
DO NOTHING, либо предложениеDO UPDATE, которое определяет точные действия по обновлению конфликтующей строки.Внутри
SETиWHEREвON CONFLICT DO UPDATEдоступ к существующей строке осуществляется по имени таблицы (или псевдониму), а к предложенной для вставки строке — через специальную таблицуexcluded. Для использованияexcludedтребуется привилегияSELECTна все читаемые в выражениях столбцы целевой таблицы.Обратите внимание, все триггеры уровня строки
BEFORE INSERTвлияют на значения вexcluded, так как их действия могли повлиять на то, что строка была исключена из вставки.
index_column_name- Имя столбца в таблице
table_name. Используется для вывода арбитражных индексов. Формат такой же, как вCREATE INDEX. Необходима привилегияSELECTна указанный столбец.
index_expression- Аналогично
index_column_name, но используется для выражений в определениях индексов, не являющихся простыми столбцами. Формат соответствуетCREATE INDEX. Требуется привилегияSELECTна все столбцы, используемые в выражении.
collation- Требует, чтобы соответствующие
index_column_nameилиindex_expressionиспользовали определенную сортировку. Обычно не указывается, так как сортировка редко влияет на нарушения ограничений. Формат аналогичен CREATE INDEX.
opclass- Требует использование конкретного класса операторов для соответствующего
index_column_nameилиindex_expressionпри выводе индексов. Обычно не требуется, так как семантика равенства одинакова для большинства классов. Формат также аналогиченCREATE INDEX.
index_predicate- Используется для вывода частичных уникальных индексов. Можно выводить любой индекс, удовлетворяющий предикату, даже если он сам по себе не является частичным. Формат такой же, как в
CREATE INDEX. Требуется привилегияSELECTна все используемые в выражении столбцы.
constraint_name- Указывает явно имя ограничения для использования в качестве арбитражного, вместо вывода индекса или ограничения.
condition- Задает выражение, возвращающее значение типа
boolean. Обновлены будут только те строки, для которых это выражение возвращаетtrue. Однако при выполнении действияON CONFLICT DO UPDATEвсе конфликтующие строки блокируются. Обратите внимание,conditionвычисляется после определения конфликта, на основании которого происходит выбор строки для обновления.
Ограничения исключения не поддерживаются как арбитры для ON CONFLICT DO UPDATE. Во всех случаях поддерживаются только ограничения NOT DEFERRABLE и уникальные индексы.
INSERT с ON CONFLICT DO UPDATE является детерминированным: команда не может повлиять на одну и ту же строку более одного раза. В случае, если строки, предложенные к вставке, дублируют друг друга по атрибутам, охваченным арбитражным индексом или ограничением, будет вызвана ошибка нарушения кардинальности.
Также обратите внимание: в настоящий момент не поддерживается выполнение ON CONFLICT DO UPDATE в INSERT, примененном к партиционированной таблице, если это приведет к необходимости переместить строку в другую партицию.
Предпочтительнее использовать вывод уникального индекса, а не явное указание ограничения через ON CONFLICT ON CONSTRAINT constraint_name.
Вывод продолжит работать корректно, даже если исходный индекс будет заменен другим эквивалентным, например, при использовании CREATE UNIQUE INDEX ... CONCURRENTLY перед удалением старого индекса.
Выводимая информация
При успешном завершении команда INSERT возвращает тег команды следующего вида:
INSERT oid count
где count - это количество вставленных или обновленных строк, oid — всегда 0. Раньше это был OID вставленной строки при таблицах WITH OIDS, но сейчас этот режим устарел.
Если использован RETURNING, будет возвращен набор строк, аналогичный SELECT.
Примечания
Если указанная таблица является партиционированной, каждая строка автоматически направляется в соответствующую партицию и вставляется в нее. Если указанная таблица является партицией, произойдет ошибка, если одна из входных строк нарушает ограничение раздела.
Также можно рассмотреть возможность использования 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');
В этом примере в таблицу 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;
Добавление дистрибьютора или отсутствие действий для строк, предложенных для добавления, если уже есть существующая исключающая строка (строка, содержащая конфликтующие значения в столбце или столбцах после срабатывания триггеров перед добавлением строки). В данном примере предполагается, что определен уникальный индекс, ограничивающий значения в столбце 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; - использование
WITHсовместно сINSERT; - возможность указания альтернативного действия через
ON CONFLICT.
Кроме того, стандарт SQL не допускает случай, когда список имен столбцов опущен, но при этом в VALUES или запросе указаны значения не для всех столбцов. Если нужно более соответствующее стандарту SQL утверждение, чем ON CONFLICT, смотрите MERGE.
Стандарт SQL указывает, что OVERRIDING SYSTEM VALUE можно указывать только в том случае, если существует всегда генерируемый столбец идентичности. PostgreSQL позволяет использовать это условие в любом случае и игнорирует его, если оно неприменимо.
Возможные ограничения условия query описаны в разделе SELECT.