ORA-00001 « unique constraint violated » : cause et solutions

ORA-00001 « unique constraint violated » : identifier le doublon et le traiter (MERGE, séquence, exception PL/SQL), avec exemples SQL Oracle.

Illustration de l'erreur Oracle ORA-00001

ORA-00001 « unique constraint violated » signifie que votre INSERT (ou UPDATE) essaie d’écrire une valeur qui existe déjà dans une colonne protégée par une contrainte UNIQUE ou une clé primaire. Voici comment identifier la contrainte en cause, retrouver le doublon, et les 4 stratégies pour traiter le problème proprement.

Publicité

🧪 Envie de pratiquer ? Exécutez les exemples de cet article dans notre SQL Playground gratuit — aucun logiciel à installer.

Le message

ORA-00001: unique constraint (MONSCHEMA.PK_CLIENTS) violated
ORA-00001: violation de contrainte unique (MONSCHEMA.PK_CLIENTS)

Bonne nouvelle : Oracle vous donne le nom exact de la contrainte violée. Toute la résolution part de là.

Étape 1 — Identifier la contrainte et ses colonnes

SELECT c.table_name, cc.column_name
FROM   user_constraints c
JOIN   user_cons_columns cc ON cc.constraint_name = c.constraint_name
WHERE  c.constraint_name = 'PK_CLIENTS';

Vous savez maintenant quelle(s) colonne(s) doivent être uniques. (Rappel : notre guide des contraintes Oracle.)

Étape 2 — Trouver la valeur en double

-- quelle valeur essaie d'entrer en double ?
SELECT email, COUNT(*)
FROM   clients
GROUP  BY email
HAVING COUNT(*) > 1;

Étape 3 — Choisir la bonne stratégie (4 cas)

Cas 1 : la ligne existe déjà → faire un « upsert » avec MERGE

MERGE INTO clients c
USING (SELECT 'a.dupont@mail.fr' email, 'Dupont' nom FROM dual) src
ON    (c.email = src.email)
WHEN MATCHED THEN UPDATE SET c.nom = src.nom
WHEN NOT MATCHED THEN INSERT (email, nom) VALUES (src.email, src.nom);

C’est LA solution propre pour les chargements répétés — détails dans notre tutoriel MERGE Oracle.

Cas 2 : ignorer silencieusement les doublons (chargement de masse)

INSERT /*+ IGNORE_ROW_ON_DUPKEY_INDEX(clients, pk_clients) */
INTO clients (id, email) SELECT id, email FROM staging_clients;

Le hint IGNORE_ROW_ON_DUPKEY_INDEX saute les lignes en double au lieu d’échouer. Autre option en masse : DBMS_ERRLOG + LOG ERRORS REJECT LIMIT UNLIMITED pour router les rejets vers une table d’erreurs.

Cas 3 : l’ID vient d’une séquence désynchronisée

Classique après un import : la séquence génère des IDs déjà pris.

SELECT MAX(id) FROM clients;            -- ex. 50230
SELECT seq_clients.NEXTVAL FROM dual;   -- ex. 48000 → en retard !

-- resynchroniser (Oracle 12c+)
ALTER SEQUENCE seq_clients RESTART START WITH 50231;

Mieux : utilisez une colonne GENERATED AS IDENTITY qui évite ce décalage.

Cas 4 : en PL/SQL, gérer l’exception dédiée

BEGIN
  INSERT INTO clients (email, nom) VALUES (p_email, p_nom);
EXCEPTION
  WHEN DUP_VAL_ON_INDEX THEN
    UPDATE clients SET nom = p_nom WHERE email = p_email;
END;

Et si la contrainte ne devrait PAS exister ?

Parfois la contrainte unique est une erreur de conception (ex. unicité sur le nom). On la supprime — en conscience :

ALTER TABLE clients DROP CONSTRAINT uq_clients_nom;

⚠️ Ne supprimez jamais une clé primaire pour « faire passer » un insert : le doublon se paiera très cher plus tard.

FAQ

Comment savoir quelle valeur exacte a déclenché l’erreur ?

Oracle ne la donne pas dans le message. Reproduisez avec la requête GROUP BY … HAVING COUNT(*)>1 ci-dessus, ou loggez la ligne dans votre traitement (LOG ERRORS).

ORA-00001 sur un UPDATE, c’est possible ?

Oui : si l’UPDATE modifie la colonne unique vers une valeur déjà existante (UPDATE clients SET email='x@y.fr' alors que x@y.fr existe).

Quelle différence avec ORA-02291 ?

ORA-00001 = doublon sur une contrainte unique. ORA-02291 = clé étrangère qui pointe vers un parent inexistant.

Un nouveau tutoriel SQL par semaine

Nous ne spammons pas ! Consultez notre politique de confidentialité pour plus d’informations.

Publicité

Laisser un commentaire

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

Publicité