PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Wstawić, przy zduplikowanej aktualizacji w PostgreSQL?

PostgreSQL od wersji 9.5 ma składnię UPSERT, z klauzulą ​​ON CONFLICT. z następującą składnią (podobną do MySQL)

INSERT INTO the_table (id, column_1, column_2) 
VALUES (1, 'A', 'X'), (2, 'B', 'Y'), (3, 'C', 'Z')
ON CONFLICT (id) DO UPDATE 
  SET column_1 = excluded.column_1, 
      column_2 = excluded.column_2;

Przeszukiwanie archiwów grup e-mail postgresql w poszukiwaniu „upsert” prowadzi do znalezienia przykładu robienia tego, co prawdopodobnie chcesz zrobić, w instrukcji:

Przykład 38-2. Wyjątki z UPDATE/INSERT

Ten przykład wykorzystuje obsługę wyjątków do wykonania odpowiednio UPDATE lub INSERT:

CREATE TABLE db (a INT PRIMARY KEY, b TEXT);

CREATE FUNCTION merge_db(key INT, data TEXT) RETURNS VOID AS
$$
BEGIN
    LOOP
        -- first try to update the key
        -- note that "a" must be unique
        UPDATE db SET b = data WHERE a = key;
        IF found THEN
            RETURN;
        END IF;
        -- not there, so try to insert the key
        -- if someone else inserts the same key concurrently,
        -- we could get a unique-key failure
        BEGIN
            INSERT INTO db(a,b) VALUES (key, data);
            RETURN;
        EXCEPTION WHEN unique_violation THEN
            -- do nothing, and loop to try the UPDATE again
        END;
    END LOOP;
END;
$$
LANGUAGE plpgsql;

SELECT merge_db(1, 'david');
SELECT merge_db(1, 'dennis');

Na liście dyskusyjnej hakerów jest prawdopodobnie przykład, jak zrobić to zbiorczo, używając CTE w wersji 9.1 i nowszych:

WITH foos AS (SELECT (UNNEST(%foo[])).*)
updated as (UPDATE foo SET foo.a = foos.a ... RETURNING foo.id)
INSERT INTO foo SELECT foos.* FROM foos LEFT JOIN updated USING(id)
WHERE updated.id IS NULL;

Zobacz odpowiedź a_konia_bez_imienia, aby uzyskać jaśniejszy przykład.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy istnieje coś takiego jak funkcja zip() w PostgreSQL, która łączy dwie tablice?

  2. Czy funkcje PostgreSQL są transakcyjne?

  3. Zgrupowane LIMIT w PostgreSQL:pokazać pierwsze N ​​wierszy dla każdej grupy?

  4. Mechanizmy replikacji fizycznej w PostgreSQL

  5. Postgres COUNT liczba wartości kolumn z INNER JOIN