WITHOUT ROWID în SQLite

Creează un tabel fără coloana ascunsă rowid, organizat direct după cheia primară; util pentru chei compuse sau texte scurte.

Sintaxă
CREATE TABLE t (
  ...,
  PRIMARY KEY (col1, col2)
) WITHOUT ROWID;

Ce face WITHOUT ROWID

Un tabel obișnuit este ordonat pe disc după rowid, iar cheia primară declarată (dacă nu este INTEGER PRIMARY KEY) este un index separat. Un tabel WITHOUT ROWID este ordonat direct după cheia primară: dispare indexul în plus și o căutare după cheie citește un singur arbore în loc de doi.

Un astfel de tabel trebuie să aibă o PRIMARY KEY, iar coloanele cheii nu pot fi NULL (la tabelele obișnuite, din motive istorice, pot). Nu are rowid, deci last_insert_rowid() și AUTOINCREMENT nu funcționează.

Merită folosit pentru tabele cu cheie compusă sau cu cheie text scurtă și rânduri mici, de exemplu stocuri pe (depozit, produs) sau traduceri pe (limbă, cheie). Pentru rânduri mari, documentația SQLite recomandă tabelele obișnuite.

Exemple

Exemplul 1: Stoc pe depozit și produs

Cheia este perechea (depozit, cod). Rândurile sunt păstrate în ordinea cheii, de aceea SELECT fără ORDER BY le dă aici sortate; nu te baza pe asta, scrie ORDER BY când ordinea contează. Coloana wr din pragma_table_list este 1 pentru tabelele WITHOUT ROWID.

CREATE TABLE stoc (
  depozit TEXT,
  cod TEXT,
  cantitate INTEGER NOT NULL,
  PRIMARY KEY (depozit, cod)
) WITHOUT ROWID;
INSERT INTO stoc VALUES ('Iași', 'P-02', 5), ('Cluj', 'P-01', 3), ('Iași', 'P-01', 10);
SELECT * FROM stoc;
SELECT name, wr FROM pragma_table_list WHERE name = 'stoc';

Rezultat

╭─────────┬──────┬───────────╮
│ depozit │ cod  │ cantitate │
╞═════════╪══════╪═══════════╡
│ Cluj    │ P-01 │         3 │
│ Iași    │ P-01 │        10 │
│ Iași    │ P-02 │         5 │
╰─────────┴──────┴───────────╯
╭──────┬────╮
│ name │ wr │
╞══════╪════╡
│ stoc │  1 │
╰──────┴────╯

Exemplul 2: Cheie text, STRICT și WITHOUT ROWID împreună

Tabelul de traduceri are cheie compusă din două texte și este și STRICT. Căutarea după limba folosește direct cheia primară. Un SELECT rowid FROM traduceri ar da eroarea no such column: rowid.

CREATE TABLE traduceri (limba TEXT, cheie TEXT, text TEXT, PRIMARY KEY (limba, cheie)) STRICT, WITHOUT ROWID;
INSERT INTO traduceri VALUES ('ro', 'salut', 'Bună ziua'), ('en', 'salut', 'Hello');
SELECT * FROM traduceri WHERE limba = 'ro';
SELECT name, type, wr, strict FROM pragma_table_list WHERE name = 'traduceri';

Rezultat

╭───────┬───────┬───────────╮
│ limba │ cheie │   text    │
╞═══════╪═══════╪═══════════╡
│ ro    │ salut │ Bună ziua │
╰───────┴───────┴───────────╯
╭───────────┬───────┬────┬────────╮
│   name    │ type  │ wr │ strict │
╞═══════════╪═══════╪════╪════════╡
│ traduceri │ table │  1 │      1 │
╰───────────┴───────┴────┴────────╯

Greșeli frecvente

  • Creezi un tabel WITHOUT ROWID fără cheie primară. Primești eroarea PRIMARY KEY missing on table ....
  • Citești rowid dintr-un tabel WITHOUT ROWID. Coloana nu există și primești no such column: rowid.
  • Folosești WITHOUT ROWID pentru un tabel cu id INTEGER PRIMARY KEY simplu. Nu câștigi nimic: acolo cheia este deja rowid-ul.

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.
  • Tabele STRICT: Un tabel STRICT verifică tipul fiecărei valori la scriere și refuză, cu eroare, valorile care nu se potrivesc cu coloana.
  • CREATE INDEX: Creează un index pe una sau mai multe coloane, ca SQLite să găsească rândurile fără să citească tot tabelul.