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

PostgreSQL-funktion til sidst indsatte ID

( tl;dr :gå til mulighed 3:INDSÆT med RETURNERING )

Husk, at der i postgresql ikke er noget "id"-koncept for tabeller, kun sekvenser (som typisk, men ikke nødvendigvis bruges som standardværdier for primære surrogatnøgler, med SERIAL-pseudotypen).

Hvis du er interesseret i at få id'et for en nyligt indsat række, er der flere måder:

Mulighed 1:CURRVAL(<sequence name>); .

For eksempel:

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John'); SELECT currval('persons_id_seq');

Navnet på sekvensen skal være kendt, det er virkelig vilkårligt; i dette eksempel antager vi, at tabellen persons har et id kolonne oprettet med SERIAL pseudo-type. For at undgå at stole på dette og for at føle dig mere ren, kan du i stedet bruge pg_get_serial_sequence :

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John'); SELECT currval(pg_get_serial_sequence('persons','id'));

Advarsel:currval() virker kun efter en INSERT (som har udført nextval() ), i samme session .

Mulighed 2:LASTVAL();

Dette ligner det foregående, kun at du ikke behøver at angive sekvensnavnet:det leder efter den senest ændrede sekvens (altid inde i din session, samme forbehold som ovenfor).

Begge CURRVAL og LASTVAL er fuldstændig samtidig sikre. Sekvensadfærden i PG er designet således, at en anden session ikke vil forstyrre, så der er ingen risiko for raceforhold (hvis en anden session indsætter en anden række mellem min INSERT og min SELECT, får jeg stadig min korrekte værdi).

Men de har et subtilt potentielt problem. Hvis databasen har en TRIGGER (eller REGEL), der ved indsættelse i persons tabel, laver nogle ekstra indsættelser i andre tabeller... derefter LASTVAL vil sandsynligvis give os den forkerte værdi. Problemet kan endda opstå med CURRVAL , hvis de ekstra indsættelser udføres i de samme persons tabel (dette er meget mindre sædvanligt, men risikoen eksisterer stadig).

Mulighed 3:INSERT med RETURNING

INSERT INTO persons (lastname,firstname) VALUES ('Smith', 'John') RETURNING id;
 

Dette er den mest rene, effektive og sikre måde at få id'et på. Det har ikke nogen af ​​de tidligere risici.

Ulemper? Næsten ingen:du skal muligvis ændre den måde, du kalder din INSERT-sætning på (i værste tilfælde forventer dit API- eller DB-lag måske ikke, at en INSERT returnerer en værdi); det er ikke standard SQL (hvem bekymrer sig); den er tilgængelig siden Postgresql 8.2 (dec. 2006...)

Konklusion:Hvis du kan, så gå efter mulighed 3. Andetsteds, foretræk 1.

Bemærk:alle disse metoder er ubrugelige, hvis du har til hensigt at få det sidst indsatte id globalt (ikke nødvendigvis ved din session). Til dette skal du ty til SELECT max(id) FROM table (selvfølgelig vil dette ikke læse ukommitterede indstik fra andre transaktioner).

Omvendt bør du aldrig brug SELECT max(id) FROM table i stedet for en af ​​de 3 muligheder ovenfor, for at få id'et lige genereret af din INSERT sætning, fordi (bortset fra ydeevne) dette ikke er samtidig sikkert:mellem din INSERT og din SELECT en anden session kan have indsat en anden post.



  1. Sådan opretter du udsigt i oracle

  2. ORA-38868

  3. PHP-array til postgres-array

  4. Forbind Metabase med MySQL til dataudforskning