Перейти к содержанию

INSERT

DML-команда INSERT используется для записи кортежей в таблицу. На данный момент атомарность записи гарантируется только для одного кортежа в рамках одного запроса.

Синтаксис

INSERT INTO table ( column , ) dql ON CONFLICT DO NOTHING REPLACE FAIL

Выражение

Диаграмма

NOT table . column abs case cast coalesce current_date ilike json_extract_path instance_uuid literal localtimestamp lower pico_config_file_path pico_instance_dir pico_instance_name pico_instance_uuid pico_raft_leader_id pico_raft_leader_uuid pico_replicaset_name pico_tier_name _pico_bucket substr substring to_char to_date trim upper version NOT EXISTS ( dql ( dql expression , ) like IS NOT NULL TRUE FALSE UNKNOWN expression NOT BETWEEN expression AND IN + - * / % <> != >= > <= < = || AND OR expression

Литерал

Диаграмма

TRUE FALSE NULL decimal double integer string unsigned $ unsigned ?

Литерал массива

Диаграмма

ARRAY [ expression , ]

Параметры

  • TABLE — имя таблицы. Соответствует правилам имен для всех объектов в кластере.

Требуемые привилегии

Данная команда требует привилегии WRITE TABLE.

Для варианта INSERT ... ON CONFLICT (...) DO UPDATE см. Вставка с обновлением при конфликте.

См. также:

Примеры вставки данных

Тестовые таблицы

Примеры использования команд включают в себя запросы к тестовым таблицам.

С явным указанием колонок:

INSERT INTO warehouse (id, item, type) VALUES (1, 'bricks', 'heavy');

Без указания колонок (при условии, что передаются значения для всех колонок):

INSERT INTO warehouse VALUES (1, 'bricks', 'heavy');

Со значениями типа ARRAY:

INSERT INTO measurements VALUES (1, ARRAY[0.5, '1.5', 2, NULL]);

Обработка конфликтов

В некоторых случаях вставка кортежа может вернуть ошибку, например, при попытке вставить кортеж с уже существующим индексом:

INSERT INTO warehouse (id, item, type)
VALUES (1, 'bricks', 'heavy');

Результат:

---
sbroad: Lua error (IR dispatch): LuaError(ExecutionError("sbroad: failed to create transaction: RolledBack(FailedTo(Insert, Some(Space), \"TupleFound: Duplicate key exists in unique index \\\"WAREHOUSE_pkey\\\" in space \\\"WAREHOUSE\\\" with old tuple - [1, 1934, \\\"bricks\\\", \\\"heavy\\\"] and new tuple - [1, 1934, \\\"bricks\\\", \\\"heavy\\\"]\"))"))

Для обработки таких ситуаций можно использовать необязательный параметр ON CONFLICT. На данный момент поддерживаются следующие режимы:

  • DO FAIL, вернуть ошибку в случае конфликта
  • DO REPLACE, затереть старый кортеж новым по первичному ключу
  • DO NOTHING, ничего не делать (оставить старую версию кортежа)
  • DO UPDATE, вставить новый кортеж или, при конфликте по явно указанному списку колонок, обновить существующий. Подробности и ограничения см. в разделе Вставка с обновлением при конфликте

Вариант с DO FAIL предполагает, что запрос будет возвращать ошибку в случае конфликта вставки. Может возникнуть ситуация, когда запрос успешно вставит данные на части узлов хранения, но вернет ошибку на остальных (данные на них откатятся), что приведет к неконсистентному состоянию кластера.

Чтобы решить эту проблему, можно повторить вставку с другими параметрами разрешения конфликта — например, DO REPLACE (замена кортежа на новый).

Вариант с DO REPLACE решает проблему конфликтов только в первичном ключе. Если таблица содержит несколько уникальных индексов (помимо первичного ключа) и конфликт произошел в одном из них, DO REPLACE вернет ошибку. На узле хранения, где произошел конфликт, данные не будут зафиксированы в таблице.

Вариант с DO NOTHING никогда не возвращает ошибку из-за конфликтов в уникальных индексах, т.к. просто оставляет старую версию кортежа в таблице. При такой вставке в результате вернется только количество успешно вставленных новых кортежей (кортежи, где был конфликт и остались прежние данные, в подсчет не попадают).

Вариант с DO UPDATE реализует вставку с обновлением при конфликте. Он требует явный список колонок в ON CONFLICT и позволяет обновлять существующий кортеж по первичному ключу или уникальному индексу. Этот режим поддерживается только внутри транзакционных блоков для шардированных таблиц, поэтому детали и ограничения вынесены в отдельную страницу Вставка с обновлением при конфликте.

Например, для таблицы account_balances(id, amount):

DO $$
BEGIN
  INSERT INTO account_balances VALUES (1, 25)
  ON CONFLICT (id) DO UPDATE
  SET amount = amount + 25;
END $$;

Если параметр ON CONFLICT не указан, то по умолчанию используется поведение DO FAIL.

INSERT INTO warehouse (id, item, type)
VALUES (1, 'bricks', 'heavy')
ON CONFLICT DO NOTHING;

Результат:

0

Для успешной вставки (замены кортежа) следует использовать вариант DO REPLACE:

INSERT INTO warehouse (id, item, type)
VALUES (1, 'bricks', 'heavy')
ON CONFLICT DO REPLACE;

Результат:

1

Ошибка вставки может также быть вызвана ограничениями неблокирующего SQL. Если речь идет о запросе на вставку более одного кортежа, то для исправления неконсистентного состояния кластера следует повторить запрос с другим способом разрешения конфликтов DO NOTHING.

Примечание

При вставке в таблицу большого числа строк может сработать ограничение на число инструкций и/или размер результирующей виртуальной таблицы. Для обхода ограничений используйте дополнительные параметры, описанные в разделе Неблокирующие запросы.

Параметризация

Параметризация значений при INSERT влияет на тип данных при выполнении запроса. Так, в обычном виде дробные числа конвертируются в числа с фиксированной запятой (например, values(2.5) в decimal 2.5). В параметризированном виде дробному числу будет назначен типа с плавающей запятой (например, values(?), {2.5} в double 2.5). См. подробнее о типах данных.