CREATE SEQUENCE, nextval, setval în PostgreSQL

Tabele, scheme și tipuri (DDL) PostgreSQL 8.0+ (AS tip: 10+)

O secvență generează numere unice în ordine crescătoare, de exemplu pentru id-uri sau numere de factură.

Sintaxă SQL
CREATE SEQUENCE [IF NOT EXISTS] nume
    [AS bigint] [INCREMENT BY n] [START WITH n] [MINVALUE n] [MAXVALUE n] [CACHE n] [CYCLE];

nextval('nume')   currval('nume')   setval('nume', valoare)

Ce face CREATE SEQUENCE, nextval, setval

O secvență este un contor păstrat de server. nextval('nume') îl crește și returnează valoarea nouă; două conexiuni care cer în același timp primesc numere diferite. currval('nume') returnează ultima valoare obținută în conexiunea ta.

Coloanele serial și GENERATED AS IDENTITY folosesc în spate o secvență creată automat. Numele ei se află cu pg_get_serial_sequence('tabel', 'coloana').

Secvențele nu se dau înapoi: dacă tranzacția face ROLLBACK, numărul luat cu nextval rămâne consumat. Apar „găuri” în numerotare. Pentru documente care cer numerotare fără goluri (unele facturi), ai nevoie de altă soluție, de exemplu un tabel-contor actualizat în aceeași tranzacție.

Parametri

Parametru Descriere
START WITH Prima valoare returnată de nextval.
INCREMENT BY Pasul (poate fi negativ).
CACHE Câte valori rezervă fiecare conexiune deodată (implicit 1).
setval(nume, valoare) Setează contorul; următorul nextval returnează valoare + pas.

Ce returnează

nextval, currval și setval returnează un bigint.

Exemple

Exemplul 1: Numere de factură care încep de la 1001

CREATE SEQUENCE nr_factura START WITH 1001;

SELECT nextval('nr_factura');
SELECT nextval('nr_factura'), currval('nr_factura');

Rezultat în psql

CREATE SEQUENCE
 nextval 
---------
    1001
(1 row)

 nextval | currval 
---------+---------
    1002 |    1002
(1 row)

Exemplul 2: Secvența ca valoare implicită

CREATE TABLE facturi (
    numar  bigint PRIMARY KEY DEFAULT nextval('nr_factura'),
    client text NOT NULL
);
INSERT INTO facturi (client) VALUES ('Ana') RETURNING numar;

Rezultat în psql

CREATE TABLE
 numar 
-------
  1003
(1 row)

INSERT 0 1

Exemplul 3: Repararea secvenței după un import

După un import cu id-uri explicite, secvența a rămas în urmă și următorul INSERT ar da „duplicate key”. setval o mută după cel mai mare id.

SELECT pg_get_serial_sequence('clienti', 'id');
SELECT setval(pg_get_serial_sequence('clienti', 'id'), (SELECT max(id) FROM clienti));

Rezultat în psql

 pg_get_serial_sequence 
------------------------
 public.clienti_id_seq
(1 row)

 setval 
--------
   5230
(1 row)

Greșeli frecvente

  • Apelezi currval înainte de orice nextval în conexiunea curentă și primești currval of sequence "nr_factura" is not yet defined in this session.
  • Calculezi id-ul următor cu SELECT max(id) + 1. Două conexiuni simultane primesc același număr. Folosește secvența.
  • Te aștepți la numere fără goluri. ROLLBACK, erorile și CACHE lasă goluri; este normal.

Comenzi înrudite

  • CREATE TABLE: Creează un tabel nou, cu coloane, tipuri de date și constrângeri: PRIMARY KEY, NOT NULL, UNIQUE, CHECK, DEFAULT, FOREIGN KEY.