PostgreSQL
 sql >> Baza danych >  >> RDS >> PostgreSQL

Funkcja PostgreSQL dla ostatnio wstawionego identyfikatora

( tl;dr :przejdź do opcji 3:INSERT with RETURNING )

Przypomnij sobie, że w postgresql nie ma pojęcia „id” dla tabel, tylko sekwencje (które są zwykle, ale niekoniecznie, używane jako wartości domyślne dla zastępczych kluczy głównych z pseudotypem SERIAL).

Jeśli jesteś zainteresowany uzyskaniem identyfikatora nowo wstawionego wiersza, istnieje kilka sposobów:

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

Na przykład:

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

Nazwa ciągu musi być znana, to naprawdę dowolna; w tym przykładzie zakładamy, że tabela persons ma id kolumna utworzona za pomocą SERIAL pseudotyp. Aby uniknąć polegania na tym i poczuć się bardziej czysto, możesz zamiast tego użyć pg_get_serial_sequence :

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

Zastrzeżenie:currval() działa tylko po INSERT (który wykonał nextval() ), w tej samej sesji .

Opcja 2:LASTVAL();

Jest to podobne do poprzedniego, z tą różnicą, że nie musisz określać nazwy sekwencji:szuka najnowszej zmodyfikowanej sekwencji (zawsze w Twojej sesji, to samo zastrzeżenie jak powyżej).

Oba CURRVAL i LASTVAL są całkowicie bezpieczne jednocześnie. Zachowanie sekwencji w PG jest zaprojektowane tak, aby różne sesje nie przeszkadzały, więc nie ma ryzyka warunków wyścigu (jeśli inna sesja wstawi kolejny wiersz między moim INSERT i moim SELECT, nadal otrzymuję prawidłową wartość).

Jednak mają subtelny potencjalny problem. Jeśli baza danych ma jakiś TRIGGER (lub REGUŁĘ), który po wstawieniu do persons table, wprowadza dodatkowe wstawki w innych tabelach... potem LASTVAL prawdopodobnie da nam złą wartość. Problem może nawet wystąpić w przypadku CURRVAL , jeśli dodatkowe wstawienia są wykonywane w tych samych persons tabeli (jest to znacznie mniej powszechne, ale ryzyko nadal istnieje).

Opcja 3:INSERT z RETURNING

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

To najczystszy, najskuteczniejszy i najbezpieczniejszy sposób na uzyskanie identyfikatora. Nie ma żadnego ryzyka poprzedniego.

Wady? Prawie żaden:być może będziesz musiał zmienić sposób wywoływania instrukcji INSERT (w najgorszym przypadku być może Twoja warstwa API lub DB nie oczekuje, że INSERT zwróci wartość); to nie jest standardowy SQL (kogo to obchodzi); jest dostępny od Postgresql 8.2 (grudzień 2006...)

Wniosek:jeśli możesz, wybierz opcję 3. W innym miejscu wybierz 1.

Uwaga:wszystkie te metody są bezużyteczne, jeśli zamierzasz uzyskać ostatnio wstawiony identyfikator globalnie (niekoniecznie przez twoją sesję). W tym celu musisz skorzystać z SELECT max(id) FROM table (oczywiście nie spowoduje to odczytania niezatwierdzonych wstawek z innych transakcji).

I odwrotnie, nigdy użyj SELECT max(id) FROM table zamiast jednej z 3 powyższych opcji, aby uzyskać identyfikator właśnie wygenerowany przez INSERT oświadczenie, ponieważ (poza wydajnością) nie jest to jednocześnie bezpieczne:między twoim INSERT i twój SELECT inna sesja mogła wstawić inny rekord.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Czy pozycja kolumny id w Postgresql jest ważna?

  2. Aktualizacje oparte na niestandardowych wyzwalaczach dla PostgreSQL

  3. Jak działa justify_hours() w PostgreSQL

  4. JDBCTemplate zestaw zagnieżdżonych POJO z BeanPropertyRowMapper

  5. Funkcja MAX() w PostgreSQL