sql >> Database >  >> RDS >> PostgreSQL

Retour-ID als een rij bestaat, anders INSERT

Een oplossing in één SQL-statement. Vereist PostgreSQL 8.4 of later.
Beschouw de volgende demo:

Testopstelling:

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');

INSERT / SELECT commando:

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;
  • De eerste CTE v is niet strikt noodzakelijk, maar bereikt dat u uw waarden . moet invoeren slechts één keer.

  • De tweede CTE s selecteert de id van tbl als de "rij" bestaat.

  • De derde CTE i voegt de "rij" in tbl als (en alleen als) het niet bestaat, wordt id . geretourneerd .

  • De laatste SELECT geeft de id . terug . Ik heb een kolom toegevoegd src met vermelding van de "bron" - of de "rij" al bestond en id komt van een SELECT, of de "rij" was nieuw en dat geldt ook voor de id .

  • Deze versie zou zo snel mogelijk moeten zijn aangezien er geen extra SELECT van tbl nodig is en gebruikt in plaats daarvan de CTE's.

Om dit te beveiligen tegen mogelijke race-omstandigheden in een omgeving met meerdere gebruikers:
Ook voor bijgewerkte technieken met behulp van de nieuwe UPSERT in Postgres 9.5 of later:

  • Is SELECT of INSERT in een functie die vatbaar is voor race-omstandigheden?


  1. Referentie:wat is een perfect codevoorbeeld met de MySQL-extensie?

  2. Controleer of een tekenreeks een subtekenreeks bevat in SQL Server 2005, met behulp van een opgeslagen procedure

  3. Hoe MySQL 5.5 naar 5.6 te upgraden op Ubuntu 14.04

  4. Kamerbibliotheek kan db uit de activamap kopiëren?