Si l'instruction SELECT INTO ne renvoie pas au moins une ligne, ORA-01403 est levée.
Pour tous les autres SGBD, je sais que c'est normal sur un SELECT. Seul Oracle traite un SELECT INTO comme ceci.
CREATE OR REPLACE PROCEDURE no_data_proc IS
dummy dual.dummy%TYPE;
BEGIN
BEGIN
SELECT dummy
INTO dummy
FROM dual
WHERE dummy = 'Y';
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('Why is this needed?');
END;
END no_data_proc;
Pourquoi?
À mon avis, vous n'avez pas vraiment besoin de cette exception. C'est trop de frais généraux. Parfois, c'est pratique mais vous devez écrire un bloc BEGIN, EXCEPTION, WHEN, END complet.
Y a-t-il des raisons essentielles que je ne vois pas?
Le bloc d'exception n'est pas nécessaire , vous pouvez l'utiliser ou non, selon le contexte.
Ici, vous ignorez activement l'exception (la procédure retournera avec succès) mais la plupart du temps si vous effectuez un SELECT INTO, vous voulez qu'il --- échec s'il ne retourne pas de ligne, pensez à:
PROCEDURE update_employee_salary (p_empno) IS
l_salary NUMBER;
BEGIN
SELECT sal INTO l_salary FROM emp WHERE empno = p_empno FOR UPDATE;
/* do something with emp data */
END;
Ici, je veux que ma fonction échoue si elle est appelée avec un empno
qui n'existe pas dans la table EMP. Je peux intercepter l'exception pour déclencher un message d'erreur significatif (avec raise_application_error
) mais la plupart du temps je suis content de l'ORA-01403.
En général, les seules exceptions que vous devez intercepter sont les exceptions attendues (c'est-à-dire que cela ne devrait pas être la norme pour intercepter toutes les ORA-01403, ou toutes les exceptions d'ailleurs).
Mais nous devons encore répondre à la question "pourquoi une exception est-elle levée dans le cas où un SELECT n'a pas de données à récupérer".
Je crois que cela se fait parce que c'est une situation courante qui pourrait autrement être négligée. Écrire du code comme s'il s'attendait toujours à trouver des données est une chose courante à faire, et si nous étions censés effectuer des vérifications d'erreurs telles que
SELECT <something...>
IF SQLCODE = 100 THEN -- No data found
<no-data handler>
END IF
il est probable à mon humble avis que la vérification de SQLCODE = 100 soit sautée fréquemment. Une exception ayant soulevé des béliers, vous avez directement remarqué que A) une condition importante (aucune donnée trouvée) s'est produite, et B) AUCUNE INDEMNITÉ N'A ÉTÉ FAITE POUR CELA. IMO ayant le moteur PL/SQL lever une exception est mieux que d'avoir le programme continuer joyeusement sur son chemin en supposant que les données ont été récupérées alors qu'en fait ce n'était pas le cas, ce qui peut conduire à toutes sortes de problèmes autres que joyeux.
Partagez et profitez.
Vous pouvez essayer d'utiliser MIN pour éviter d'utiliser la clause EXCEPTION.
SELECT MIN(dummy)
INTO dummy
FROM dual
WHERE dummy = 'Y';
alors la variable fictive sera NULL
Parce que vous faites SELECT INTO qui nécessite exactement une ligne (plus de lignes seraient également une erreur).
Si vous pouvez avoir une ou aucune ligne, vous pouvez utiliser un curseur.
Ce n'est pas le travail de la base de données de décider pour vous qu'une ligne manquante n'est pas une erreur, et définissez simplement la valeur sur null.
Vous pouvez également utiliser les fonctions sql MAX ou MIN . Si aucune ligne n'est renvoyée, ces fonctions renverront un NULL .
Par exemple: Sélectionnez MAX (column1) Dans la variable From Table Where Column1 = 'Value';
La fonction MAX renverra la valeur maximale ou si aucune ligne n'est renvoyée, elle renverra NULL.
Parce que ce que le moteur PL/SQL doit faire n'est pas clair - doit-il quitter le bloc? Doit-il continuer avec NULL dans la variable? Que se passe-t-il si dans le bloc suivant vous essayez d'insérer cela dans une colonne NOT NULL, comment doit-il signaler l'emplacement de l'erreur? En faire une exception vous oblige à être explicite à ce sujet.
La fonction MAX fonctionne, elle ne génère pas d'erreur ORA-014 fonctionne lorsque NULL est renvoyé en sélectionnant INTO