PRAGMA foreign_keys în SQLite

PRAGMA și configurare SQLite 3.6.19

Pornește verificarea cheilor străine. În SQLite este oprită implicit și trebuie pornită la fiecare conexiune.

Sintaxă
PRAGMA foreign_keys;          -- 0 sau 1
PRAGMA foreign_keys = ON;     -- sau OFF
PRAGMA foreign_key_check [(tabel)];

Ce face PRAGMA foreign_keys

SQLite înțelege REFERENCES și FOREIGN KEY, dar, din motive de compatibilitate, implicit nu le verifică: poți insera o comandă pentru un client care nu există. Verificarea pornește cu PRAGMA foreign_keys = ON.

Setarea nu se salvează în fișierul bazei: este valabilă doar pentru conexiunea curentă. Aplicația trebuie să o ruleze după fiecare deschidere a bazei. Nu are efect dacă o rulezi în interiorul unei tranzacții deschise.

Cu verificarea pornită funcționează și acțiunile ON DELETE CASCADE, ON DELETE SET NULL și ON UPDATE CASCADE. PRAGMA foreign_key_check listează rândurile care încalcă cheile străine, de exemplu cele inserate înainte de pornirea verificării.

Parametri

Parametru Descriere
ON / OFF Pornește sau oprește verificarea pentru conexiunea curentă (implicit OFF).
foreign_key_check(tabel) Afișează rândurile cu chei străine fără pereche: tabel, rowid, tabelul părinte, numărul cheii.

Exemple

Exemplele de pe această pagină pornesc de la datele de mai jos. Rulează mai întâi acest cod, apoi exemplul.

CREATE TABLE clienti (id INTEGER PRIMARY KEY, nume TEXT);
CREATE TABLE comenzi (
  id INTEGER PRIMARY KEY,
  client_id INTEGER REFERENCES clienti (id) ON DELETE CASCADE,
  total INTEGER
);
INSERT INTO clienti VALUES (1, 'Ana'), (2, 'Mihai');
INSERT INTO comenzi VALUES (10, 1, 250), (11, 1, 90), (12, 2, 120);

Exemplul 1: Implicit, cheile străine nu sunt verificate

Verificarea este oprită (0), așa că o comandă pentru clientul 99, care nu există, este acceptată. foreign_key_check găsește apoi rândul orfan.

PRAGMA foreign_keys;
INSERT INTO comenzi VALUES (13, 99, 50);
PRAGMA foreign_key_check;

Rezultat

╭──────────────╮
│ foreign_keys │
╞══════════════╡
│            0 │
╰──────────────╯
╭─────────┬───────┬─────────┬──────╮
│  table  │ rowid │ parent  │ fkid │
╞═════════╪═══════╪═════════╪══════╡
│ comenzi │    13 │ clienti │    0 │
╰─────────┴───────┴─────────┴──────╯

Exemplul 2: Cu verificarea pornită

După PRAGMA foreign_keys = ON, aceeași inserare este refuzată.

PRAGMA foreign_keys = ON;
INSERT INTO comenzi VALUES (13, 99, 50);

Rezultat (eroare)

Error near line 2: FOREIGN KEY constraint failed

Exemplul 3: ON DELETE CASCADE

Cu verificarea pornită, ștergerea Anei șterge automat și cele două comenzi ale ei. Fără PRAGMA foreign_keys = ON, comenzile ar rămâne în tabel.

PRAGMA foreign_keys = ON;
DELETE FROM clienti WHERE nume = 'Ana';
SELECT * FROM comenzi ORDER BY id;

Rezultat

╭────┬───────────┬───────╮
│ id │ client_id │ total │
╞════╪═══════════╪═══════╡
│ 12 │         2 │   120 │
╰────┴───────────┴───────╯

Greșeli frecvente

  • Pornești foreign_keys o singură dată, în utilitarul sqlite3, și te aștepți să fie activ și în aplicație. Fiecare conexiune pornește cu verificarea oprită.
  • Rulezi PRAGMA foreign_keys = ON după BEGIN. În interiorul unei tranzacții pragma nu are efect; rulează-o imediat după deschiderea conexiunii.
  • Declari client_id INTEGER REFERENCES clienti, dar clienti.id nu este cheie primară sau UNIQUE. Coloana părinte trebuie să fie unică, altfel primești foreign key mismatch.

Comenzi înrudite

  • CREATE TABLE: Creează un tabel nou. În SQLite tipul coloanei este opțional și doar sugerează cum se salvează valorile.
  • BEGIN, COMMIT, ROLLBACK: Grupează mai multe modificări într-o tranzacție: fie se salvează toate cu COMMIT, fie niciuna cu ROLLBACK.
  • PRAGMA integrity_check: Verifică dacă fișierul bazei de date este întreg: paginile, indexurile și constrângerile. Răspunde „ok” dacă totul e în regulă.
  • CREATE TRIGGER: Rulează automat instrucțiuni SQL când un rând este inserat, modificat sau șters: jurnal de modificări, validări, câmpuri calculate.