INSERT¶
DML-команда INSERT используется для записи кортежей в
таблицу. На данный момент атомарность записи гарантируется только для
одного кортежа в рамках одного запроса.
Синтаксис¶
Выражение¶
Диаграмма
Литерал¶
Диаграмма
Литерал массива¶
Диаграмма
Параметры¶
- 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). См. подробнее о типах данных.