sql >> Database teknologi >  >> RDS >> PostgreSQL

Returner id, hvis der findes en række, INSERT ellers

En løsning i en enkelt SQL-sætning. Kræver PostgreSQL 8.4 eller senere.
Overvej følgende demo:

Testopsætning:

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 kommando:

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;
  • Den første CTE v er ikke strengt nødvendigt, men opnår, at du skal indtaste dine værdier kun én gang.

  • Den anden CTE s vælger id fra tbl hvis "rækken" findes.

  • Den tredje CTE i indsætter "rækken" ind i tbl hvis (og kun hvis) det ikke eksisterer, returnerer id .

  • Den endelige SELECT returnerer id . Jeg tilføjede en kolonne src angiver "kilden" - om "rækken" eksisterede i forvejen og id kommer fra en SELECT, eller "rækken" var ny, og det samme er id .

  • Denne version skal være så hurtig som muligt, da den ikke behøver en ekstra SELECT fra tbl og bruger CTE'erne i stedet.

For at gøre dette sikkert mod mulige løbsforhold i et flerbrugermiljø:
Også for opdaterede teknikker ved hjælp af den nye UPSERT i Postgres 9.5 eller senere:

  • Er SELECT eller INSERT i en funktion, der er tilbøjelig til løbsforhold?


  1. Sådan opdages og forhindres uventet vækst af SQL Server-databasen TempDB

  2. Søg med kommasepareret værdi mysql

  3. Hvordan indsætter man en fil i Oracle-databasen?

  4. Opret en beregnet kolonne, der bruger data fra en anden tabel i SQL Server