I have the following ibatis query:
update users
<set>
<if test="reference != null ">
reference = #{reference},
</if>
<if test="status != null">
status_type = #{status},
</if>
</set>
where id = #{id.id}
How I can migrate these checks (XML tags) into SQL checks for PostgreSQL database?
The basic idea is to use coalesce(new_value, old_value) to pick the new value over the old value if the new value is not null:
create table users (id int, reference int, status_type int);
insert into users values (1, 1, 1), (2, 2, 2), (3, 3, 3);
update users
set reference = coalesce(t.reference, users.reference),
status_type = coalesce(t.status_type, users.status_type)
from (values (1, null, 11), (2, 12, null)) t(id,reference,status_type)
where users.id = t.id;
There are other techniques to achieve the same or similar effect, for example CASE expressions.
EDIT
As desired, a version with CASE instead of coalesce:
update users
set reference = case when t.reference is not null
then t.reference else users.reference
end,
status_type = case when t.status_type is not null
then t.status_type else users.status_type
end
from (values (1, null, 11), (2, 12, null)) t(id,reference,status_type)
where users.id = t.id;
It is longer, but to make it shorter, you can omit the not and flip the contents of then ... else ..., but the version with coalesce is very compact.
As suggested by JohnH in the comments, you can suppress unnecessary updates by adding a where clause:
update users
set reference = case when t.reference is not null
then t.reference else users.reference
end,
status_type = case when t.status_type is not null
then t.status_type else users.status_type
end
from (values (1, null, 111), (2, 122, null)) t(id,reference,status_type)
where users.id = t.id
and ( (t.reference IS NOT NULL and t.reference IS DISTINCT FROM users.reference)
or (t.status_type IS NOT NULL and t.status_type IS DISTINCT FROM users.status_type));