Обновление через подзапрос, что если подзапрос не возвращает строк?

Я использую подзапрос в UPDATE:

UPDATE tableA 
SET x,y,z = ( (SELECT x, y, z 
               FROM tableB b
               WHERE tableA.id = b.id
                 AND (tableA.x != b.x
                      OR tableA.y != b.y
                      OR tableA.z != b.z))) );

Мой вопрос: что произойдет, если в подзапросе нет строк? Будет ли обновление с нулями?

Во-вторых, есть ли лучший способ написать это. Я в основном обновляю три поля в таблице A из таблицы B, но обновление должно происходить только в том случае, если любое из трех полей отличается.

Ответ 1

что произойдет, если подзапрос вернется нет строк? Будет ли он обновлять обнуляет?

Да - вы можете проверить это как:

update YourTable
set col1 = (select 1 where 1=0)

Это заполнит col1 с помощью NULL. Если подзапрос возвращает несколько строк, например:

update YourTable
set col1 = (select 1 union select 2)

В базе данных будет создана ошибка.

Во-вторых, есть ли лучший способ напишите это. Я в основном обновляю три поля в таблице А из таблицы Б, но обновление должно произойти только в том случае, если любое из трех полей отличается.

Интуитивно я не стал бы беспокоиться о производительности. Если вы действительно хотите избежать обновления, вы можете написать его как:

UPDATE a
SET x = b.x, y = b.y, z = b.z
FROM tableA a, tableB b 
WHERE a.id = b.id AND (a.x <> b.x OR a.y <> b.y OR a.z <> b.z)

Предложение WHERE предотвращает обновления с помощью NULL.

Ответ 2

В informix я использовал вариацию решения Andomar:

UPDATE a
SET x,y,z = ( (SELECT x, y, z 
               FROM tableB b
               WHERE tableA.id = b.id) )
WHERE tableA.id IN (SELECT fromTable.id
                    FROM tableA toTable, tableB fromTable
                    WHERE toTable.id = fromTable.id
                      AND ((toTable.x <> fromTable.x) 
                           OR (toTable.y <> fromTable.y)
                           OR (toTable.z <> fromTable.z))