sql >> Databáze >  >> RDS >> PostgreSQL

Vraťte id, pokud řádek existuje, jinak INSERT

Řešení v jediném SQL příkazu. Vyžaduje PostgreSQL 8.4 nebo později.
Zvažte následující ukázku:

Testovací nastavení:

CREATE TEMP TABLE tbl (
  id  serial PRIMARY KEY
 ,txt text   UNIQUE   -- obviously there is unique column (or set of columns)
);

INSERT INTO tbl(txt) VALUES ('one'), ('two');

Příkaz INSERT / SELECT:

WITH v AS (SELECT 'three'::text AS txt)
    ,s AS (SELECT id FROM tbl JOIN v USING (txt))
    ,i AS (
       INSERT INTO tbl (txt)
       SELECT txt
       FROM   v
       WHERE  NOT EXISTS (SELECT * FROM s)
       RETURNING id
       )
SELECT id, 'i'::text AS src FROM i
UNION  ALL
SELECT id, 's' FROM s;
  • První CTE v není nezbytně nutné, ale dosáhnete toho, že musíte zadat své hodnoty pouze jednou.

  • Druhý vybere CTE id z tbl pokud "řádek" existuje.

  • Třetí vložky CTE i "řádek" do tbl pokud (a pouze pokud) neexistuje, vrací id .

  • Poslední SELECT vrátí id . Přidal jsem sloupec src označující „zdroj“ – zda ​​„řádek“ dříve existoval a id pochází z SELECT, nebo byl "řádek" nový, stejně jako id .

  • Tato verze by měla být co nejrychlejší, protože nepotřebuje další SELECT z tbl a místo toho používá CTE.

Aby to bylo bezpečné proti možným závodním podmínkám v prostředí s více uživateli:
Také pro aktualizované techniky pomocí nového UPSERT v Postgres 9.5 nebo později:

  • Je SELECT nebo INSERT ve funkci náchylný k závodům?


  1. Jak MAKETIME() funguje v MariaDB

  2. Jak zobrazit seznam souborů ve složce s SQL Server

  3. SQL Server - spojte řádky do seznamu odděleného čárkou

  4. Základní správa MaxScale pomocí MaxCtrl pro MariaDB Cluster