AUTOINCREMENT în SQLite

Tabele și tipuri de date Toate versiunile SQLite 3

Garantează că un id nu este refolosit niciodată, nici după ștergere; SQLite ține ultima valoare în tabelul sqlite_sequence.

Sintaxă
CREATE TABLE t (id INTEGER PRIMARY KEY AUTOINCREMENT, ...);

Ce face AUTOINCREMENT

AUTOINCREMENT se poate pune doar după INTEGER PRIMARY KEY. Fără el, SQLite dă noului rând valoarea maximă existentă plus 1, deci un id șters de la final poate fi refolosit. Cu el, SQLite ține minte cel mai mare id dat vreodată și nu coboară niciodată sub el.

Valorile sunt păstrate în tabelul intern sqlite_sequence (coloanele name și seq), creat automat la primul tabel cu AUTOINCREMENT. Fiecare inserare actualizează acest tabel, de aceea AUTOINCREMENT face inserările puțin mai lente.

Documentația SQLite recomandă să nu folosești AUTOINCREMENT decât dacă ai nevoie de garanția că id-urile nu se repetă (de exemplu numere de factură care nu trebuie reatribuite). Pentru majoritatea tabelelor, INTEGER PRIMARY KEY simplu este suficient.

Exemple

Exemplul 1: Un id șters nu mai este dat din nou

Ștergem factura 3, apoi inserăm alta. Ea primește 4, nu 3. sqlite_sequence arată ultima valoare folosită.

CREATE TABLE facturi (id INTEGER PRIMARY KEY AUTOINCREMENT, numar TEXT);
INSERT INTO facturi (numar) VALUES ('F-001'), ('F-002'), ('F-003');
DELETE FROM facturi WHERE id = 3;
INSERT INTO facturi (numar) VALUES ('F-004');
SELECT * FROM facturi;
SELECT name, seq FROM sqlite_sequence;

Rezultat

╭────┬───────╮
│ id │ numar │
╞════╪═══════╡
│  1 │ F-001 │
│  2 │ F-002 │
│  4 │ F-004 │
╰────┴───────╯
╭─────────┬─────╮
│  name   │ seq │
╞═════════╪═════╡
│ facturi │   4 │
╰─────────┴─────╯

Exemplul 2: Comparație: fără AUTOINCREMENT

Același scenariu cu INTEGER PRIMARY KEY simplu: după ștergerea lui 3, noul rând primește din nou 3.

CREATE TABLE facturi (id INTEGER PRIMARY KEY, numar TEXT);
INSERT INTO facturi (numar) VALUES ('F-001'), ('F-002'), ('F-003');
DELETE FROM facturi WHERE id = 3;
INSERT INTO facturi (numar) VALUES ('F-004');
SELECT * FROM facturi;

Rezultat

╭────┬───────╮
│ id │ numar │
╞════╪═══════╡
│  1 │ F-001 │
│  2 │ F-002 │
│  3 │ F-004 │
╰────┴───────╯

Exemplul 3: Valoarea explicită mută contorul

Dacă inserezi un id mai mare, contorul sare la el, iar rândurile următoare continuă de acolo.

CREATE TABLE facturi (id INTEGER PRIMARY KEY AUTOINCREMENT, numar TEXT);
INSERT INTO facturi (numar) VALUES ('F-001');
INSERT INTO facturi (id, numar) VALUES (100, 'F-100');
INSERT INTO facturi (numar) VALUES ('F-101');
SELECT * FROM facturi;

Rezultat

╭─────┬───────╮
│ id  │ numar │
╞═════╪═══════╡
│   1 │ F-001 │
│ 100 │ F-100 │
│ 101 │ F-101 │
╰─────┴───────╯

Greșeli frecvente

  • Scrii AUTO_INCREMENT (MySQL). În SQLite cuvântul este AUTOINCREMENT, fără underscore, și merge doar cu INTEGER PRIMARY KEY.
  • Pui AUTOINCREMENT peste tot „ca să meargă numerotarea”. Numerotarea automată vine din INTEGER PRIMARY KEY; AUTOINCREMENT adaugă doar garanția de nerefolosire, cu un mic cost la fiecare inserare.
  • Crezi că id-urile vor fi consecutive. Nici cu AUTOINCREMENT nu sunt: o tranzacție anulată sau un rând șters lasă goluri.

Comenzi înrudite

  • rowid și INTEGER PRIMARY KEY: Orice tabel SQLite obișnuit are o coloană ascunsă rowid; o coloană INTEGER PRIMARY KEY devine alias al ei și primește automat valori.
  • CREATE TABLE: Creează un tabel nou. În SQLite tipul coloanei este opțional și doar sugerează cum se salvează valorile.
  • RETURNING: Face ca INSERT, UPDATE sau DELETE să returneze rândurile modificate, de exemplu id-ul generat, fără un SELECT separat.
  • INSERT ... ON CONFLICT (upsert): Inserează un rând sau, dacă cheia există deja, actualizează rândul existent (ori nu face nimic), într-o singură comandă.