Write a Postgres Get or Create SQL Query

前端 未结 4 987
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-13 12:42

I want to write a single Postgres SQL statement that says look for a user with color X and brightness Y. If that user exists, return all of its row data. If not, create a new

相关标签:
4条回答
  • 2021-02-13 12:58

    Adding my solution here. It is a tad different than @Clodoaldo Neto and @astef's solutions.

    WITH ins AS (
      INSERT INTO mytable (color, brightness, size, age)
      VALUES ('X', 'Y', 'big', 'old')
      ON CONFLICT (color) DO NOTHING
      RETURNING *
    )
    SELECT * FROM ins
    UNION
    SELECT * FROM mytable
      WHERE color = 'X';
    

    I found astef's solution inadequate for my purposes: it doesn't perform the "get" portion of "get or create"! If the value already existed, nothing would happen.

    The union at the end of the statement ensures that if the value was not inserted (since it already existed) we still retrieve that value from the table.

    0 讨论(0)
  • 2021-02-13 12:59

    In a SQL DBMS, the select-test-insert approach is a mistake: nothing prevents another process from inserting the "missing" row between your select and insert statements. Do this instead:

    insert into mytable (color, brightness, size, age)
    select color, brightness, size, age 
    from mytable
    where not exists (
        select 1 from 
        from mytable
        where color = 'X' and brightness = 'Y'
    );
    SELECT (color, brightness, size, age) 
    FROM mytable 
    WHERE color = 'X' AND brightness= 'Y';
    

    You should be able to pass that entire text as a single "query" to the DBMS. You might want to consider making it into a stored procedure.

    0 讨论(0)
  • 2021-02-13 13:08

    If your columns participate in unique index constraint you can use an approach which is avaible since version 9.5:

    INSERT INTO mytable (color, brightness, size, age)
    VALUES ('X', 'Y', 'big', 'old')
    ON CONFLICT (color) DO NOTHING;
    

    (assuming you have unique index on color).

    Docs are gere: https://www.postgresql.org/docs/9.5/static/sql-insert.html

    0 讨论(0)
  • 2021-02-13 13:17
    with sel as (
        select color, brightness, size, age
        from mytable
        where color = 'X' and brightness = 'Y'
    ), ins as (
        insert into mytable (color, brightness, size, age)
        select 'X', 'Y', 6.2, 40
        where not exists (
            select 1 from sel
        )
        returning color, brightness, size, age
    )
    select color, brightness, size, age
    from ins
    union
    select color, brightness, size, age
    from sel
    
    0 讨论(0)
提交回复
热议问题