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

INSERT

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

Синтаксис

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

Выражение

Диаграмма

NOT table . column literal case cast current_date like ilike substr to_char to_date trim lower upper ( expression , dql NOT EXISTS ( dql ) IS NOT NULL expression NOT BETWEEN expression AND IN + - * / <> != >= > <= < = || AND OR expression

Литерал

Диаграмма

TRUE FALSE NULL decimal double integer string unsigned $ unsigned ?

Параметры

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

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

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

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

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

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

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

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

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

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

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, который может принимать одно из трех значений:

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

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

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

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

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

Если параметр 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). См. подробнее о типах данных.