Search code examples
postgresqlbulkupdate

Bulk update in postgreSQL using unnest


I am trying to do bulk update:

> update ti_table set enabled=T.enabled 
    from (select * from 
         unnest(array['2001622', '2001624', '2007903']) as id,
         unnest(array[15,14,8]) as ver,
         unnest(array['type1', 'type1', 'type1']) as type,
         unnest(array[false, true, true]) as enabled) T 
    where ti_table.id=T.id AND ti_table.ver=T.ver AND ti_table.type=T.type;

However, when I read back:

> select id, ver, type, enabled from ti_table where id in ('2001622', '2001624', '2007903');

I see:

   id    | ver | type  | enabled 
---------+-----+-------+---------
 2001622 |  15 | type1 | f
 2001624 |  14 | type1 | f
 2007903 |   8 | type1 | f

In the last two rows enabled is false while I expected it to be true

Why is this happening and how would I do it correctly?

Thanks.


Solution

  • You are calling unnest 3 times on FROM clause, that means you are doing a CROSS JOIN (cartesian product) of the 3.

    If you are on PostgreSQL 9.4 or higher, you can simple do one call of unnest giving each array as input:

    select * from 
             unnest(
                array['2001622', '2001624', '2007903'],
                 array[15,14,8],
                 array['type1', 'type1', 'type1'],
                 array[false, true, true]
            ) as u(id, ver, type, enabled)
    

    Another option, for any version, is to add the call to unnest in SELECT instead of FROM:

    select
       unnest(array['2001622', '2001624', '2007903']) as id,
       unnest(array[15,14,8]) as ver,
       unnest(array['type1', 'type1', 'type1']) as type,
       unnest(array[false, true, true]) as enabled
    

    In both cases, but specially on the last one, you must be sure each array have the exact same number of elements. If it doesn't on the first method each missing row will be filled as NULL, but the second one it will return as many rows as the LCM of the number of rows returned by each, what you probably do not want. Example:

    SELECT * FROM unnest(array[1,2,3,4], array['a','b','c','d','e','f']);
     unnest | unnest 
    --------+--------
          1 | a
          2 | b
          3 | c
          4 | d
     [null] | e
     [null] | f
    (6 rows)
    
    SELECT unnest(array[1,2,3,4]), unnest(array['a','b','c','d','e','f']);
     unnest | unnest 
    --------+--------
          1 | a
          2 | b
          3 | c
          4 | d
          1 | e
          2 | f
          3 | a
          4 | b
          1 | c
          2 | d
          3 | e
          4 | f
    (12 rows)
    

    Check the documentation on table functions calls for more information.