sql >> データベース >  >> RDS >> PostgreSQL

postgresでUPSERT操作のINSERTED行とUPDATED行を取得するにはどうすればよいですか?

    ブール値の更新された列をpeopleに追加した場合 表:

    ALTER TABLE people ADD COLUMN updated bool DEFAULT FALSE;
    

    次に、updated = TRUEを設定することで、更新された行を識別できます。 DO UPDATE SETで 条項:

    INSERT INTO people (SELECT * FROM people_update)
      ON CONFLICT (name,surname)
        DO UPDATE SET age = EXCLUDED.age , street = EXCLUDED.street , city = EXCLUDED.city 
            , postal = EXCLUDED.postal
            , updated = TRUE
        WHERE 
          (people.age,people.street,people.city,people.postal) IS DISTINCT FROM 
          (EXCLUDED.age,EXCLUDED.street,EXCLUDED.city,EXCLUDED.postal)
    RETURNING *;
    

    たとえば、

    CREATE TABLE test.people (
        name text
        , surname text
        , age float
        , street text
        , city text
        , postal int
    );
    CREATE UNIQUE INDEX people_idx on people (name, surname);
    ALTER TABLE people ADD COLUMN updated bool;
    ALTER TABLE people ADD COLUMN prior_age float;
    ALTER TABLE people ADD COLUMN prior_street text;
    ALTER TABLE people ADD COLUMN prior_city text;
    ALTER TABLE people ADD COLUMN prior_postal int;
    
    INSERT INTO people (name, surname, age, street, city, postal) VALUES 
    ('Sancho', 'Panza', 414, '1 Manchego', 'Barcelona', 01605)
    , ('Oliver', 'Twist', 182, '2 Stilton', 'London', 01837)
    , ('Quasi', 'Modo', 188, $$3 Rue d'Arcole$$, 'Paris' , 01831 )
    ;
    
    CREATE TABLE test.people_update (
        name text
        , surname text
        , age float
        , street text
        , city text
        , postal int
    );
    
    INSERT INTO people_update (name, surname, age, street, city, postal) VALUES 
    ('Sancho', 'Panza', 4140, '10 Idiazabal', 'Montserrat', 16050)
    , ('Quasi', 'Modo', 1880, $$30 Champs Elysée$$ , 'Paris', 18310 )
    , ('Pinocchio', 'Geppetto', 1380, '40 Nerbone', 'Florence', 18810)
    ;
    
    INSERT INTO people (SELECT * FROM people_update)
      ON CONFLICT (name,surname)
        DO UPDATE SET 
            updated = TRUE
            , prior_age = (CASE WHEN people.age = EXCLUDED.age THEN NULL ELSE people.age END)
            , prior_street = (CASE WHEN people.street = EXCLUDED.street THEN NULL ELSE people.street END)
            , prior_city = (CASE WHEN people.city = EXCLUDED.city THEN NULL ELSE people.city END)
            , prior_postal = (CASE WHEN people.postal = EXCLUDED.postal THEN NULL ELSE people.postal END)
            , age = EXCLUDED.age 
            , street = EXCLUDED.street 
            , city = EXCLUDED.city 
            , postal = EXCLUDED.postal
        WHERE 
          (people.age,people.street,people.city,people.postal) IS DISTINCT FROM 
          (EXCLUDED.age,EXCLUDED.street,EXCLUDED.city,EXCLUDED.postal)
    RETURNING *;
    

    収量

    | name       | surname  |  age | street           | city       | postal | updated | prior_age | prior_street   | prior_city | prior_postal |
    |------------+----------+------+------------------+------------+--------+---------+-----------+----------------+------------+--------------|
    | Sancho     | Panza    | 4140 | 10 Idiazabal     | Montserrat |  16050 | t       |       414 | 1 Manchego     | Barcelona  |         1605 |
    | Quasi      | Modo     | 1880 | 30 Champs Elysée | Paris      |  18310 | t       |       188 | 3 Rue d'Arcole |            |         1831 |
    | Pinocchio  | Geppetto | 1380 | 40 Nerbone       | Florence   |  18810 | f       |           |                |            |              |
    

    updated 列には('Sancho', 'Panza')が表示されます および('Quasi', 'Modo') 行が更新され、('Pinocchio', 'Geppetto') は新しいインサートです。




    1. OracleのJOINでFORUPDATEを使用するにはどうすればよいですか?

    2. 区切られた文字列値を行に分割します

    3. PHPとMySQLのユーザー名送信の問題

    4. mysqli_multi_queryを実行して、最後のクエリの結果を使用する方法を理解できません