ORA-02291 « parent key not found » : causes et solutions

ORA-02291 « parent key not found » : pourquoi votre clé étrangère échoue et comment la corriger (ordre d'insertion, FK nullable, DEFERRABLE).

Illustration de l'erreur Oracle ORA-02291

ORA-02291 « integrity constraint violated – parent key not found » signifie que vous insérez (ou modifiez) une ligne dont la clé étrangère pointe vers un parent qui n’existe pas. Exemple type : une commande pour un client_id absent de la table clients. Voici comment identifier la relation en cause et les bonnes solutions.

Publicité

Le message

ORA-02291: integrity constraint (MONSCHEMA.FK_CMD_CLIENT) violated - parent key not found
ORA-02291: violation de contrainte d'intégrité - clé parent introuvable

Oracle nomme la contrainte (FK_CMD_CLIENT) : c’est une clé étrangère. La valeur que vous insérez dans la colonne enfant n’a pas de correspondance dans la table parent.

Étape 1 — Identifier la relation (enfant → parent)

SELECT a.table_name        AS table_enfant,
       a.column_name       AS colonne_fk,
       c_pk.table_name     AS table_parent,
       pk.column_name      AS colonne_parent
FROM   user_constraints   c
JOIN   user_cons_columns  a     ON a.constraint_name  = c.constraint_name
JOIN   user_constraints   c_pk  ON c_pk.constraint_name = c.r_constraint_name
JOIN   user_cons_columns  pk    ON pk.constraint_name = c_pk.constraint_name
WHERE  c.constraint_name = 'FK_CMD_CLIENT';

Vous savez maintenant : commandes.client_id doit exister dans clients.id. (Rappel : notre guide des contraintes Oracle.)

Étape 2 — Vérifier que le parent existe

-- la valeur insérée existe-t-elle côté parent ?
SELECT * FROM clients WHERE id = 4242;
-- (aucune ligne → c'est la cause)

Étape 3 — Choisir la solution adaptée

Solution 1 : créer le parent d’abord (ordre d’insertion)

Dans une relation, on insère toujours le parent avant l’enfant :

INSERT INTO clients (id, nom) VALUES (4242, 'Durand');   -- parent d'abord
INSERT INTO commandes (id, client_id, total) VALUES (1, 4242, 99);  -- puis enfant

Solution 2 : corriger la valeur de la clé étrangère

Souvent, le client_id est simplement faux (mauvais ID, valeur d’un autre environnement). Reliez la commande au bon client existant.

Solution 3 : autoriser l’absence de parent → clé étrangère NULL

Si « pas de parent » est un cas métier valide (commande sans client attribué), la colonne enfant peut être NULL : une FK n’est pas vérifiée quand la valeur est NULL.

INSERT INTO commandes (id, client_id, total) VALUES (1, NULL, 99);  -- ✅ accepté
-- (à condition que la colonne client_id soit nullable)

Le piège de l’ordre lors d’un chargement de masse

En insérant des milliers de lignes via plusieurs tables, l’ordre casse facilement. Deux options :

  • Charger dans le bon ordre (toutes les tables parents, puis les enfants).
  • Différer la vérification avec une contrainte DEFERRABLE, validée seulement au COMMIT :
-- à la création de la contrainte
ALTER TABLE commandes ADD CONSTRAINT fk_cmd_client
  FOREIGN KEY (client_id) REFERENCES clients(id) DEFERRABLE INITIALLY DEFERRED;

-- dans la transaction
INSERT INTO commandes ...;   -- ordre quelconque
INSERT INTO clients   ...;
COMMIT;                      -- la cohérence est vérifiée ici

Cas particulier — ORA-02291 sur un UPDATE

Modifier client_id vers une valeur inexistante déclenche la même erreur. Vérifiez la valeur cible avant l’UPDATE (voir UPDATE en SQL Oracle).

FAQ

Quelle différence avec ORA-02292 ?

ORA-02291 : l’enfant référence un parent absent (à l’INSERT/UPDATE de l’enfant). ORA-02292 : on tente de supprimer un parent encore référencé par des enfants (« child record found »).

Comment trouver toutes les clés étrangères d’une table ?

SELECT constraint_name, r_constraint_name FROM user_constraints WHERE table_name='COMMANDES' AND constraint_type='R';

Mettre la FK en NULL est-il une bonne idée ?

Seulement si « sans parent » a un sens métier. Sinon, corrigez la donnée : neutraliser la contrainte masquerait une incohérence réelle.

Publicité

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Publicité