обновляйте таблицу только в том случае, если подзапрос возвращает результат postgres

#sql #postgresql #sql-update #subquery #inner-join

#sql #postgresql #sql-обновление #подзапрос #внутреннее соединение

Вопрос:

У меня есть запрос, который может не возвращать результат, что приведет к НУЛЕВОМУ значению

 update public.test set geom = 
    (select geom from public.test where st_geometrytype(geom) = 'X' limit 1)
 

Я попытался добавить COALESCE для замены на исходное значение, но выдает ошибку

 update public.ec_1_eur_1 set geom = 
        COALESCE(select geom from public.ec_1_eur_1 where 
st_geometrytype(geom) = 'X' limit 1, geom)
 

Также это также выдает ошибку

 with s2 as (select geom from public.test where st_geometrytype(geom) = 'X' limit 1)
update public.test set geom = s2 where s2 is not null
 

Ответ №1:

Я бы использовал здесь синтаксис update / join, поэтому ничего не обновляется, если подзапрос не возвращает строки:

 update public.test t
set geom = t1.geom
from (
    select geom 
    from public.test 
    where st_geometrytype(geom) = 'X' 
    limit 1
) t1
 

Что касается запроса, который вы хотели написать, используя coalesce() : вам нужно было бы заключить подзапрос в круглые скобки, поэтому явно, что он возвращает скаляр:

 update public.test t
set geom = coalesce(
    (select geom from public.test where st_geometrytype(geom) = 'X' limit 1),
    geom
)
 

Однако этот подход менее эффективен, поскольку он по-прежнему обновляет все строки таблицы до их исходного значения, если подзапрос не возвращает строк; в этом отношении предпочтителен подход update / join.

Обратите внимание, однако, что limit without order by имеет мало смысла, поскольку он не является детерминированным; когда подзапрос выдает несколько строк, не определено, какая из них будет выбрана.

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

1. Фактический запрос имеет порядок, по которому проверяется область на основе ее пересекающихся геометрий, но я не хотел писать этот сложный запрос для этой проблемы