Bulk/batch update/upsert in PostgreSQL

前端 未结 5 1417
慢半拍i
慢半拍i 2020-11-29 00:27

I\'m writing a Django-ORM enchancement that attempts to cache models and postpone model saving until the end of the transaction. It\'s all almost done, however I came across

5条回答
  •  慢半拍i
    慢半拍i (楼主)
    2020-11-29 01:04

    Bulk insert

    You can modify the bulk insert of three columns by Ketema:

    INSERT INTO "table" (col1, col2, col3)
      VALUES (11, 12, 13) , (21, 22, 23) , (31, 32, 33);
    

    It becomes:

    INSERT INTO "table" (col1, col2, col3)
      VALUES (unnest(array[11,21,31]), 
              unnest(array[12,22,32]), 
              unnest(array[13,23,33]))
    

    Replacing the values with placeholders:

    INSERT INTO "table" (col1, col2, col3)
      VALUES (unnest(?), unnest(?), unnest(?))
    

    You have to pass arrays or lists as arguments to this query. This means you can do huge bulk inserts without doing string concatenation (and all its hazzles and dangers: sql injection and quoting hell).

    Bulk update

    PostgreSQL has added the FROM extension to UPDATE. You can use it in this way:

    update "table" 
      set value = data_table.new_value
      from 
        (select unnest(?) as key, unnest(?) as new_value) as data_table
      where "table".key = data_table.key;
    

    The manual is missing a good explanation, but there is an example on the postgresql-admin mailing list. I tried to elaborate on it:

    create table tmp
    (
      id serial not null primary key,
      name text,
      age integer
    );
    
    insert into tmp (name,age) 
    values ('keith', 43),('leslie', 40),('bexley', 19),('casey', 6);
    
    update tmp set age = data_table.age
    from
    (select unnest(array['keith', 'leslie', 'bexley', 'casey']) as name, 
            unnest(array[44, 50, 10, 12]) as age) as data_table
    where tmp.name = data_table.name;
    

    There are also other posts on StackExchange explaining UPDATE...FROM.. using a VALUES clause instead of a subquery. They might by easier to read, but are restricted to a fixed number of rows.

提交回复
热议问题