BigQuery: как сделать так, чтобы операция слияния завершилась неудачей при некоторых условиях?

#sql #google-bigquery #sql-update #sql-merge

#sql #google-bigquery #sql-update #sql-merge

Вопрос:

Я хочу обновить целевую таблицу ( target ) в соответствии со строками в исходной таблице ( source ). Для этого я использую MERGE инструкцию. Однако я хотел бы, чтобы вся MERGE операция завершилась неудачей при некоторых условиях, но не могу понять, как это сделать.

Пример

target Таблица содержит :

 id
==
1
2
  

source Таблица содержит :

 id | operation
==============
3  | ADD
4  | DELETE
  

Ожидаемая target таблица после MERGE (я не хочу никаких обновлений здесь, потому что 4 соответствует DELETE операции, и поскольку в 4 таблице нет target строки, это рассматривается как ошибка и MERGE должно завершиться атомарно) :

 id
==
1
2
  

На данный момент я использую следующий запрос :

 MERGE `target` target
USING `source` source
ON target.id = source.id
WHEN not matched AND source.operation = "ADD" THEN
  INSERT (id)
  VALUES (source.id)
  

Но, очевидно, я получил :

 id
==
1
2
3
  

Возможно ли добавить в мой запрос предложение типа :

 WHEN not matched AND source.operation = "DELETE" THEN ERROR("...")
  

Это не работает ( ERROR неожиданно) :

Синтаксическая ошибка: Ожидалось удаление ключевого слова, или вставка ключевого слова, или обновление ключевого слова, но получен идентификатор «ОШИБКА»

Если это невозможно с помощью MERGE запроса, есть ли способ переписать его в аналогичный запрос, чтобы атомарно обновить мою target таблицу, как я ожидаю?

Ответ №1:

Вы могли бы сами сгенерировать ошибку. Что-то вроде:

 WHEN not matched AND source.operation = 'DELETE' THEN 
    INSERT (id)
       VALUES ( CAST(source.operation as int64) )
  

Я не пытался намеренно генерировать ошибки в BigQuery, но я не думаю, что существует функция, которая автоматически это делает.

По предложению @norbjd:

 WHEN not matched AND source.operation = 'DELETE' THEN 
    INSERT (id)
       VALUES ( ERROR('ERROR:  DELETE operation encountered') )
  

Комментарии:

1. Спасибо за ваш ответ. Тип назначения в CAST не может быть int (недопустимый тип BigQuery), но numeric , int64 или что-то другое допустимо; однако решение все еще применяется.

2. В BigQuery существует ERROR функция для генерации ошибки ( cloud.google.com/bigquery/docs/reference/standard-sql /… ), но не может использоваться как есть, так как ожидается только DELETE или INSERT после WHEN ... THEN . Но, основываясь на вашем решении, я мог бы написать : INSERT (id) VALUES (ERROR('Error message')) чтобы получить более четкое сообщение, даже если это кажется взломом.