UPSERT VALUES
Содержание раздела
- Поддерживаемые сущности
- Поддерживаемые СУБД
- Особенности вставки данных в standalone-таблицы
- Как работает запрос
- Перезапуск и отмена операций
- Синтаксис
- Варианты ответа
- Ограничения
- Примеры
- Вставка данных во все столбцы логической таблицы
- Вставка данных в указанные столбцы снапшот-таблицы
- Вставка данных во все столбцы прокси-таблицы
- Вставка данных во все столбцы standalone-таблицы
- Вставка данных в указанные столбцы standalone-таблицы
- Вставка данных в указанные столбцы партиционированной таблицы
- Вставка данных в указанные столбцы партиции
- Перезапуск операции по вставке записей
Поддерживается в версиях: 7.6 / 7.5 / 7.4 / 7.3 / 7.2 / 7.1 / 7.0 / 6.12 / 6.11 / 6.10 / 6.9 / 6.8 / 6.7 / 6.6 / 6.5 / 6.4 / 6.3 / 6.2 / 6.1 / 6.0 / 5.8 / 5.7 / 5.6 / 5.5 / 5.4.
Запрос обновляет текущие или вставляет новые записи в таблицу поддерживаемого типа.
Чтобы вставить большой объем данных, используйте загрузку данных.
Поддерживаемые сущности
Вставка и обновление записей доступны в следующие таблицы:
При вставке данных в прокси-таблицы и standalone-таблицы учитывайте ограничения таблиц целевой СУБД.
Поддерживаемые СУБД
Запрос поддерживается для СУБД ADB и ADP.
Особенности вставки данных в standalone-таблицы
Вставка данных в standalone-таблицы выполняется через внешние writable-таблицы.
Вставка недоступна, если запрос содержит внешнюю writable-таблицу без первичного ключа.
Как работает запрос
Добавление и обновление записей
Обработка каждой вставляемой записи зависит от наличия/отсутствия в таблице записи с таким же первичным ключом (PK) и значения опции set.on.conflict.do таблицы (для снапшот-таблиц), как показано ниже.
| Таблица | PK новый или отсутствует | PK совпадает |
|---|---|---|
| Логическая таблица | Добавление новой записи | Обновление текущей записи |
| Снапшот-таблица | Добавление новой записи |
|
| Прокси-, standalone-таблица | Добавление новой записи | Обновление текущей записи |
Особенности вставки в партиции
Вставка в партиции имеет особенности:
- [через партиционированную таблицу] записи распределяются по партициям; записи вне диапазонов партиций игнорируются;
- [напрямую в партиции] записи вне диапазонов партиции игнорируются.
Заполнение столбцов таблицы
При вставке данных все столбцы, указанные в запросе, заполняются значениями из запроса, а пропущенные nullable-столбцы:
- [в новой записи] заполняются значениями, используемыми по умолчанию в СУБД;
- [в текущей записи] остаются без изменений.
Пропущенные обязательные столбцы (NOT NULL) остаются без изменений при обновлении записей в логических, прокси- и standalone-таблицах. В остальных случаях пропуск таких столбцов приводит к ошибке.
Выполнение при отключенном датасорсе
Отключенный датасорс пропускается при исполнении запроса. Вставка данных считается успешной, если данные сохранены в необходимые датасорсы.
Статистика
Запросы UPSERT VALUES учитываются в категории WRITE статистики. Подробнее о категориях запросов в статистике см. в разделе GET_ENTITY_STATISTICS, о способах просмотра статистики — в разделе Управление статистикой.
Перезапуск и отмена операций
Кластер с кворумом нод автоматически отменяет сбойные операции записи при типовых сбоях, исключая необходимость ручного вмешательства.
Возможности по ручному управлению операциями описаны в разделе Управление операциями записи.
Синтаксис
[RETRY] UPSERT INTO [db_name.]table_name [(column_name[, ... ])]
VALUES (column_value[, ... ]) [, ... ]
Параметры:
db_name-
Имя логической базы данных. Опционально, если выбрана логическая БД, используемая по умолчанию.
table_name-
Имя таблицы, в которую вставляются данные. Возможные значения:
- имя логической таблицы,
- имя снапшот-таблицы,
- имя прокси-таблицы,
- имя внешней writable-таблицы, указывающей на нужную standalone-таблицу.
Логическая таблица может быть любого вида.
column_name-
Имя столбца, куда вставляются данные. Список опционален, если количество и порядок вставляемых значений соответствуют количеству и порядку столбцов в таблице.
Про обработку пропущенных столбцов см. в секции Заполнение столбцов таблицы.
Ключевое слово VALUES (column_value[, ... ]) [, ... ]
Задает список значений, вставляемых в соответствующие столбцы таблицы. Каждый набор значений в круглых скобках — это одна строка, вставляемая в таблицу.
Ключевое слово RETRY
При типовых сбоях (перебои в сети, сбой ноды и т.п.) операции отменяются автоматически и не требуют ручного управления с помощью RETRY или других команд.
Перезапускает обработку операции записи со статусом 0 (Выполняется) в логической таблице. Если указано, после него должна следовать копия исходного запроса, создавшего перезапускаемую операцию.
Не поддерживается для других таблиц:
- игнорируется для прокси- и standalone-таблиц;
- приводит к ошибке для снапшот-таблиц.
Если ключевое слово не указано, система обрабатывает запрос как новый, а не перезапущенный.
Варианты ответа
В ответе возвращается:
- объект ResultSet c одной записью при успешном выполнении запроса;
- исключение при неуспешном выполнении запроса.
Успешный ответ содержит столбцы:
sysCn:- номер выполненной операции записи — при вставке в логическую или снапшот-таблицу;
- пустое значение — при вставке в прокси-таблицу или во внешнюю writable-таблицу;
ts:- дата и время завершения операции записи в формате
YYYY-MM-DD hh:mm:ss.SSSSSS— при выполнении операции вне дельты; - пустое значение — при выполнении операции в дельте;
- дата и время завершения операции записи в формате
rowsAffected— количество затронутых (добавленных, измененных и удаленных) строк. Расчет значения поддерживается для СУБД ADB и ADP.
Запрос с RETRY возвращает в rowsAffected количество строк, затронутых перезапущенной операцией записи. Строки, обработанные до перезапуска операции, не учитываются.
Ограничения
Ограничения выполнения
- Выполнение запроса к логической или снапшот-таблице недоступно, если она участвует в незавершенной операции по изменению схемы.
- Выполнение запроса вне дельты недоступно, если последняя дельта закрыта с меткой времени, превышающей серверное время.
- Не допускается параллельное выполнение идентичных запросов.
Ограничения СУБД
- Запрос не поддерживает вставку данных в СУБД ADQM и ADG.
Ограничения сущностей
- Запрос недоступен для логических и материализованных представлений.
- Обновление текущих записей невозможно в снапшот-таблицах с опциями
set.on.conflict.do=error(возвращается ошибка) иset.on.conflict.do=nothing(пропускаются записи с дубликатами первичного ключа).
Ограничения партиционирования
- При вставке данных в партиционированную таблицу все записи, для которых нет подходящей партиции, игнорируются.
- Одновременная запись данных (загрузка, вставка и удаление) в партиционированную таблицу и ее партиции недоступна.
Другие ограничения
- Ключевое слово
RETRYдоступно только для логических таблиц; для других таблиц игнорируется или приводит к ошибке. - Значения всех обязательных столбцов (
NOT NULL) снапшот-таблицы должны быть указаны в запросе. - При обработке запроса отключенные (Датасорс, отключенный системой из-за сбоя или администратором
) датасорсы (СУБД или кластер СУБД хранилища
) пропускаются без возврата ошибки. Ошибка возвращается, если не осталось включенных (Датасорс, работающий в штатном режиме
) датасорсов, необходимых для записи данных.
Примеры
Вставка данных во все столбцы логической таблицы
Вставка данных в дельте:
-- выбор логической базы данных marketing_new в качестве базы данных по умолчанию
USE marketing_new;
-- открытие новой дельты
BEGIN DELTA;
-- вставка трех записей в логическую таблицу sales (данные таблицы расположены в датасорсе adp)
UPSERT INTO sales
VALUES (200011, '2021-08-21 23:34:10', 'ABC0001', 2, 123, 'Покупка по акции "1+1"'),
(200012, '2021-08-22 10:05:56', 'ABC0001', 1, 234, 'Покупка без акций'),
(200013, '2021-08-22 13:17:47', 'ABC0002', 4, 123, 'Покупка по акции "Лето"');
-- закрытие дельты
COMMIT DELTA;
Вставка данных вне дельты:
-- вставка двух записей в логическую таблицу sales вне дельты
INSERT INTO marketing.sales
VALUES (800011, '2021-07-11 23:34:10', 'ABC0004', 2, 123, 'Покупка по акции "1+1"'),
(800012, '2021-07-23 10:05:56', 'ABC0017', 5, 234, 'Покупка без акций')
Вставка данных в указанные столбцы снапшот-таблицы
-- вставка двух записей в снапшот-таблицу sales_snapshot (без опционального значения description)
UPSERT INTO sales
(id, transaction_date, product_code, product_units, store_id)
VALUES (200014, '2025-08-23 09:34:10', 'ABC0003', 3, 123),
(200012, '2025-08-23 20:05:56', 'ABC0001', 6, 234);
Вставка данных во все столбцы прокси-таблицы
-- вставка одной новой записи с id=103 и обновление существующей записи с id=100
UPSERT INTO marketing.payments_proxy
VALUES (103, 444444, 'AG', 1023, 'RUB', 'Номер чека 8352'),
(100, 111111, 'AC', 12002.53, 'RUB', 'Номер чека 1234500')
Вставка данных во все столбцы standalone-таблицы
-- вставка записей в standalone-таблицу, на которую указывает внешняя writable-таблица agreements_ext_write_adp
UPSERT INTO marketing.agreements_ext_write_adp
VALUES (200, 444444, 'AB22222', '2022-02-08', '2022-02-09', '2024-02-09', ''),
(201, 555555, 'AB33333', '2022-02-10', '2022-02-11', '2025-02-11', 'Договор с ООО "Овал"');
Вставка данных в указанные столбцы standalone-таблицы
-- вставка записей в standalone-таблицу, на которую указывает внешняя writable-таблица agreements_ext_write_adp,
-- без некоторых опциональных значений
UPSERT INTO marketing.agreements_ext_write_adp (id, client_id, number, signature_date)
VALUES (202, 999999, 'AB44444', '2022-01-01');
Вставка данных в указанные столбцы партиционированной таблицы
-- выбор логической базы данных marketing в качестве базы данных по умолчанию
USE marketing;
-- открытие новой дельты
BEGIN DELTA;
-- вставка трех записей в партиционированную таблицу sales_partitioned
UPSERT INTO sales_partitioned (id, transaction_date, store_id)
VALUES (500011, '2023-01-11 23:34:10', 124),
(600012, '2023-01-18 10:05:56', 234),
(600113, '2023-02-22 13:17:47', 123);
-- закрытие дельты
COMMIT DELTA;
Вставка данных в указанные столбцы партиции
-- выбор логической базы данных marketing в качестве базы данных по умолчанию
USE marketing;
-- открытие новой дельты
BEGIN DELTA;
-- вставка трех записей в партицию sales_jan_2023
---- последняя запись будет проигнорирована, так как дата транзакции в ней не принадлежит партиции sales_jan_2023
UPSERT INTO sales_jan_2023 (id, transaction_date, store_id)
VALUES (500011, '2023-01-11 23:34:10', 124),
(600012, '2023-01-18 10:05:56', 234),
(600113, '2023-02-22 13:17:47', 123);
-- закрытие дельты
COMMIT DELTA;
Перезапуск операции по вставке записей
-- выбор логической базы данных marketing_new в качестве базы данных по умолчанию
USE marketing_new;
-- открытие новой дельты
BEGIN DELTA;
-- вставка записи в логическую таблицу sales (без опционального значения description)
UPSERT INTO sales
(id, transaction_date, product_code, product_units, store_id)
VALUES (200015, '2021-10-15 10:11:01', 'ABC0003', 1, 123);
-- перезапуск обработки операции по вставке записи
RETRY UPSERT INTO sales
(id, transaction_date, product_code, product_units, store_id)
VALUES (200015, '2021-10-15 10:11:01', 'ABC0003', 1, 123);
-- закрытие дельты
COMMIT DELTA;