Précédent   Forum des professionnels en informatique > Bases de données > Oracle > SQL
SQL Forum d'entraide sur le SQL pour Oracle
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 17/03/2008, 12h30   #1
Membre chevronné
 
Avatar de randriano
 
Homme Rija Randriano
Inscription : janvier 2007
Messages : 984
Détails du profil
Informations personnelles :
Nom : Homme Rija Randriano
Localisation : Madagascar

Informations forums :
Inscription : janvier 2007
Messages : 984
Points : 729
Points : 729
Par défaut Gérer un select into avec aucune valeur trouvée

Bonjour,

Faudrait que je m'y fasse au fait que sous Oracle, un "select field into" avec aucune donnée trouvée génère une exception NO_DATA_FOUND contrairement à SQL Server où on aurait juste un retour NULL !!
Comment éviter cette exception alors ?
Je me propose de faire un "select count(field)" et ne faire le "select field into" que si le comptage supérieur à 0:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
SELECT count(SC.Name) INTO v_CountClassName FROM TClasses SC, TEntity OE,   TCategories OC 
WHERE OE.IDCa = OC.ID AND 
OC.IDClass = SC.ID AND 
OE.ID = v_ID;
 
 
IF v_CountClassName = 0 then
   v_ClassName := NULL;
else
   SELECT SC.Name INTO v_ClassName  FROM TClasses SC, TEntity OE,   TCategories OC 
   WHERE OE.IDCa = OC.ID AND 
   OC.IDClass = SC.ID AND 
   OE.ID = v_ID; 
end IF;
Est-ce que cette technique est bonne ou y a-t-il une autre technique ?
__________________
randriano.dvp.com
randriano est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 12h40   #2
Membre éprouvé
 
Avatar de miloux32
 
Inscription : juillet 2003
Messages : 538
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 538
Points : 473
Points : 473
Si tu es dans une procédure , pourquoi ne pas pas faire un bloc d'exeption WHEN_NO_DATA_FOUND ?

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
DECLARE
 
BEGIN
 
 
SELECT SC.Name INTO v_ClassName  FROM TClasses SC, TEntity OE,   TCategories OC 
   WHERE OE.IDCa = OC.ID AND 
   OC.IDClass = SC.ID AND 
   OE.ID = v_ID; 
EXCEPTION
   When NO_DATA_FOUND then
         -- Ne rien faire
END ;
__________________
C'est pas parce que ca marche que c'est bon!!
Pensez au bouton "Résolu"
Je ne réponds pas en privé aux questions
miloux32 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 13h12   #3
Membre chevronné
 
Avatar de randriano
 
Homme Rija Randriano
Inscription : janvier 2007
Messages : 984
Détails du profil
Informations personnelles :
Nom : Homme Rija Randriano
Localisation : Madagascar

Informations forums :
Inscription : janvier 2007
Messages : 984
Points : 729
Points : 729
En effet, je l'utilise dans une procédure mais je ne veux pas considérer le fait qu'il n'y a pas de donnée trouvée comme une erreur, il y a d'autres instructions qui suivent le SELECT !! Sous Access et Sql Server, c'est pas un problème donc je veux faire pareil
Il semble aussi qu'un select brut c-à-d pas dans une procédure génère aussi une exception quand il n'y a pas de donnée trouvée ??
__________________
randriano.dvp.com
randriano est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 13h24   #4
Membre éprouvé
 
Avatar de miloux32
 
Inscription : juillet 2003
Messages : 538
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 538
Points : 473
Points : 473
Citation:
Envoyé par randriano Voir le message
En effet, je l'utilise dans une procédure mais je ne veux pas considérer le fait qu'il n'y a pas de donnée trouvée comme une erreur, il y a d'autres instructions qui suivent le SELECT !! Sous Access et Sql Server, c'est pas un problème donc je veux faire pareil
Il semble aussi qu'un select brut c-à-d pas dans une procédure génère aussi une exception quand il n'y a pas de donnée trouvée ??
Ben c'est tout l'astuce du code que je t'ai donné !

Apres le select et avant le bloc "EXCEPTION" tu peux mettre le traitement que tu veux ( qui ne se déclenchera donc pas quand il y'a pas de données)
__________________
C'est pas parce que ca marche que c'est bon!!
Pensez au bouton "Résolu"
Je ne réponds pas en privé aux questions
miloux32 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 15h08   #5
Membre chevronné
 
Avatar de randriano
 
Homme Rija Randriano
Inscription : janvier 2007
Messages : 984
Détails du profil
Informations personnelles :
Nom : Homme Rija Randriano
Localisation : Madagascar

Informations forums :
Inscription : janvier 2007
Messages : 984
Points : 729
Points : 729
Les codes qui suivent le select doivent être après lui car ils vont utiliser les enregistrements resultants. C'est pour ça que je fais ce "select count" pour affecter une chaine vide au résultat si no data found
__________________
randriano.dvp.com
randriano est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 15h43   #6
Membre éprouvé
 
Avatar de miloux32
 
Inscription : juillet 2003
Messages : 538
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 538
Points : 473
Points : 473
Je redonne mon explication car a priori tu n'as pas compris ....

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
DECLARE
BEGIN
SELECT SC.Name INTO v_ClassName  FROM TClasses SC, TEntity OE,   TCategories OC 
   WHERE OE.IDCa = OC.ID AND 
   OC.IDClass = SC.ID AND 
   OE.ID = v_ID; 

ECRIRE ICI TON TRAITEMENT

EXCEPTION
   When NO_DATA_FOUND then
         -- TON TRAITEMENT DANS LE CAS OU PAS DE DONNEES
END ;
Le traitement sera donc le suivant :
Si ton "select ...into" se passe correctement , la partie du traitement que tu auras ecrit se fera.
Sinon => l'execution de ton traitement sautera il fera ce que tu as ecrit dans le "WHEN NO_DATA_FOUND"

Ca revient à ce que tu as fait mais en plus propre, sans la requete de count en plus et te permettant de bien gerer l'exception comme tu le veux .
__________________
C'est pas parce que ca marche que c'est bon!!
Pensez au bouton "Résolu"
Je ne réponds pas en privé aux questions
miloux32 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 16h03   #7
Nouveau Membre du Club
 
Inscription : novembre 2006
Messages : 113
Détails du profil
Informations forums :
Inscription : novembre 2006
Messages : 113
Points : 32
Points : 32
Bonjour,

je pense qu'une instruction NVL peut te régler le problème
donc tu vas mettre :
Code :
1
2
3
 
 
SELECT nvl(ton_champ,0) INTO var frop TABLE
Bonne journée
fatati est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 16h33   #8
Expert Confirmé
 
Homme
Chef de projet en SSII
Inscription : janvier 2004
Messages : 2 866
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Chef de projet en SSII
Secteur : Conseil

Informations forums :
Inscription : janvier 2004
Messages : 2 866
Points : 3 448
Points : 3 448
Un petit exemple pour illustrer ce que t'a expliqué miloux32 :
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
SQL> declare
  2    v_res number(1);
  3  begin
  4    dbms_output.put_line ('Avant le select');
  5    begin
  6      SELECT 1 INTO v_res FROM dual WHERE 1 = 1;
  7      dbms_output.put_line ('Apres le select');
  8    exception
  9       when no_data_found then
 10          dbms_output.put_line ('Aucune donnee');
 11    end;
 12    dbms_output.put_line ('Fin du traitement');
 13  end;
 14  /
Avant le SELECT
Apres le SELECT
Fin du traitement
 
Procédure PL/SQL terminée avec succès.
 
SQL> declare
  2    v_res number(1);
  3  begin
  4    dbms_output.put_line ('Avant le select');
  5    begin
  6      SELECT 1 INTO v_res FROM dual WHERE 1 = 0;
  7      dbms_output.put_line ('Apres le select');
  8    exception
  9       when no_data_found then
 10          dbms_output.put_line ('Aucune donnee');
 11    end;
 12    dbms_output.put_line ('Fin du traitement');
 13  end;
 14  /
Avant le SELECT
Aucune donnee
Fin du traitement
 
Procédure PL/SQL terminée avec succès.
Après à toi de placer le code où tu souhaites en fonction de ce que tu veux faire.

NB : le count(*) est à proscrire pour des raisons de performance.
__________________
Un problème sans solution est un problème mal posé

Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.
plaineR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 16h44   #9
Membre éprouvé
 
Avatar de miloux32
 
Inscription : juillet 2003
Messages : 538
Détails du profil
Informations forums :
Inscription : juillet 2003
Messages : 538
Points : 473
Points : 473
Citation:
Envoyé par fatati Voir le message
Bonjour,

je pense qu'une instruction NVL peut te régler le problème
donc tu vas mettre :
Code :
1
2
3
 
 
SELECT nvl(ton_champ,0) INTO var frop TABLE
Bonne journée
et dans le cas ou la valeur vaut vraiment 0 ?
et pourquoi faire un traitement sur une variable qui n'existe pas ?
Et ca ne resoud pas le problème ,je crois... je ne suis pas sur qu'un nvl retourne une valeur quand la requete ne ramene rien ...

exempl simple :

Code :
SELECT nvl(1,2) FROM dual WHERE 1=2
Code :
1
2
Résultat : 
no rows returned ...
__________________
C'est pas parce que ca marche que c'est bon!!
Pensez au bouton "Résolu"
Je ne réponds pas en privé aux questions
miloux32 est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 16h52   #10
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 319
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 319
Points : 5 837
Points : 5 837
Bon si tu y tiens vraiment
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
declare
  l_ind_trouve number(1);
Begin
  SELECT *
    INTO l_ind_trouve
  FROM (  
    SELECT 1
      FROM dual
     WHERE EXISTS (SELECT NULL
                     FROM  scott.emp e
                    WHERE e.empno = '7369'
                  )
    Union ALL             
    SELECT 0
      FROM dual
     WHERE NOT EXISTS (SELECT NULL
                     FROM  scott.emp e
                    WHERE e.empno = '7369'
                  )
       );
  dbms_output.put_line(to_char(l_ind_trouve));
end;
/
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 17h11   #11
Expert Confirmé
 
Homme
Chef de projet en SSII
Inscription : janvier 2004
Messages : 2 866
Détails du profil
Informations personnelles :
Sexe : Homme
Localisation : France, Loire Atlantique (Pays de la Loire)

Informations professionnelles :
Activité : Chef de projet en SSII
Secteur : Conseil

Informations forums :
Inscription : janvier 2004
Messages : 2 866
Points : 3 448
Points : 3 448
Citation:
Envoyé par mnitu Voir le message
Bon si tu y tiens vraiment
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
 
declare
  l_ind_trouve number(1);
Begin
  SELECT *
    INTO l_ind_trouve
  FROM (  
    SELECT 1
      FROM dual
     WHERE EXISTS (SELECT NULL
                     FROM  scott.emp e
                    WHERE e.empno = '7369'
                  )
    Union ALL             
    SELECT 0
      FROM dual
     WHERE NOT EXISTS (SELECT NULL
                     FROM  scott.emp e
                    WHERE e.empno = '7369'
                  )
       );
  dbms_output.put_line(to_char(l_ind_trouve));
end;
/
Pour faire simple quand on peut faire compliqué
En plus les perf
__________________
Un problème sans solution est un problème mal posé

Merci de poser vos questions sur le forum, je ne réponds pas aux questions posées par MP.
plaineR est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 17/03/2008, 17h15   #12
Rédacteur/Modérateur
 
Avatar de Vincent Rogier
 
vincent rogier
Inscription : juillet 2007
Messages : 2 355
Détails du profil
Informations personnelles :
Nom : vincent rogier
Âge : 34

Informations forums :
Inscription : juillet 2007
Messages : 2 355
Points : 3 108
Points : 3 108
La solution de miloux32 EST la façon la plus simple et la plus performante.

Je ne vois pas du tout pourquoi tu ne veux pas la mettre en œuvre !
__________________
Vincent Rogier.

Rubrique ORACLE : Accueil - Forum - Tutoriels - FAQ - Livres - Blog

Vous voulez contribuer à la rubrique Oracle ? Contactez la rubrique !

OCILIB (C Driver for Oracle)

Librairie C Open Source multi-plateformes pour accéder et manipuler des bases de données Oracle
Vincent Rogier est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2008, 06h41   #13
Membre chevronné
 
Avatar de randriano
 
Homme Rija Randriano
Inscription : janvier 2007
Messages : 984
Détails du profil
Informations personnelles :
Nom : Homme Rija Randriano
Localisation : Madagascar

Informations forums :
Inscription : janvier 2007
Messages : 984
Points : 729
Points : 729
Désolé pour le retard de ma réponse mais j'ai étudié la proposition de miloux32!
Le catch d'exception n'est-il pas unique pour chaque couple begin-end car en fait, si j'utilises un catch exception pour le SELECT INTO où vais-je placer le catch exception général ??
Mon soucis avec votre méthode c'est que la longueur du code va doubler car je devrais tout copier le code après SELECT dans le "When NO_DATA_FOUND then" pour le cas où aucune réponse !
En fait, un select hors procédure crée-t-il une exception ?
__________________
randriano.dvp.com
randriano est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2008, 09h08   #14
Membre éclairé
 
Inscription : août 2005
Messages : 316
Détails du profil
Informations personnelles :
Âge : 41

Informations forums :
Inscription : août 2005
Messages : 316
Points : 342
Points : 342
j'ai lu en biais les reponse , mais il me semble qu'il ne faut pas recopier tout
le code dans l'exception, il suffit de refaire un bloc begin end pour le select

Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
 
begin
--traitement avant
 
    begin
 
       SELECT SC.Name INTO v_ClassName  FROM TClasses SC, TEntity OE,    TCategories OC 
       WHERE OE.IDCa = OC.ID AND 
       OC.IDClass = SC.ID AND 
       OE.ID = v_ID; 
    exception
         when no_data_found then
                   v_ClassName := NULL;
      end;
 
--traitement apres avec test de v_classname
end;
c.langlet est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2008, 09h22   #15
Expert Confirmé Sénior


 
Avatar de laurentschneider
 
Homme Laurent Schneider
Administrateur de base de données
Inscription : décembre 2005
Messages : 2 927
Détails du profil
Informations personnelles :
Nom : Homme Laurent Schneider
Localisation : Suisse

Informations professionnelles :
Activité : Administrateur de base de données
Secteur : Finance

Informations forums :
Inscription : décembre 2005
Messages : 2 927
Points : 4 549
Points : 4 549
éventuellement

Code :
1
2
3
4
SELECT (SELECT SC.Name  FROM TClasses SC, TEntity OE,   TCategories OC 
   WHERE OE.IDCa = OC.ID AND 
   OC.IDClass = SC.ID AND 
   OE.ID = v_ID) INTO v_ClassName FROM dual;
__________________
Mon blog : laurentschneider.com
Mon livre : Advanced Oracle SQL Programming
laurentschneider est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2008, 11h20   #16
Membre chevronné
 
Avatar de randriano
 
Homme Rija Randriano
Inscription : janvier 2007
Messages : 984
Détails du profil
Informations personnelles :
Nom : Homme Rija Randriano
Localisation : Madagascar

Informations forums :
Inscription : janvier 2007
Messages : 984
Points : 729
Points : 729
J'avais pensé à votre code c.langlet, donc si ça marche et ça marche, c'est la solution.
Pour votre code laurentschneider, c'est un autre moyen de faire comme sous Access, retourner une chaine vide lorsqu'aucun objet n'est trouvé. C'est aussi une autre solution !!!
__________________
randriano.dvp.com
randriano est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2008, 13h24   #17
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 319
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 319
Points : 5 837
Points : 5 837
Citation:
Envoyé par plaineR Voir le message
Pour faire simple quand on peut faire compliqué
En plus les perf
J'avais jamais penser à l'utiliser ! Mais si c'était tellement important de faire comme le SQL Server ...
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 18/03/2008, 20h53   #18
Expert Confirmé Sénior
 
Avatar de mnitu
 
Homme Marius Nitu
Ingénieur développement logiciels
Inscription : octobre 2007
Messages : 3 319
Détails du profil
Informations personnelles :
Nom : Homme Marius Nitu
Localisation : France, Marne (Champagne Ardenne)

Informations professionnelles :
Activité : Ingénieur développement logiciels
Secteur : High Tech - Éditeur de logiciels

Informations forums :
Inscription : octobre 2007
Messages : 3 319
Points : 5 837
Points : 5 837
Il existe toujours une autre technique pour éviter l'exception No_DATA_FOUND qui consiste toute simplement à remplacer le SELECT ... INTO ... FROM par un curseur explicite
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
 
  Cursor crs IS 
    SELECT ... 
      FROM ... 
     WHERE ..
  l_var crs%RowType;
Begin
  Open crs;
  Fetch crs INTO l_var;
  IF crs%NOTFOUND THEN
    -- Traitement à faire quand le curseur ne ramène rien
  End IF;
  Close crs;
End;
Il y avait une époque ou on disait que c'était plus performant d'utiliser le curseur explicite (c'est un mythe).

A partir de cette idée il est possible d'utiliser la variante suivante:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
 
Declare
  l_ename scott.emp.ename%Type;
Begin
  FOR crs IN (SELECT ename 
                FROM scott.emp
               WHERE empno = 7369)
  Loop
    l_ename := crs.ename;
  End Loop;
  dbms_output.put_line('Name = '||l_ename);
End;
/
que je dois avouer que j'hésiterais avant de l'employer. Et dans le même contexte il pourrait être intéressant d'examiner aussi:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
 
Declare
  Type refcursor IS ref cursor;
  Cursor crs IS 
    SELECT cursor(SELECT ename 
                    FROM scott.emp 
                   WHERE empno = 73691)
      FROM dual;
  --
  l_crs refcursor;
  l_ename scott.emp.ename%Type;  
Begin
  Open crs;
  Fetch crs INTO l_crs;
  Fetch l_crs INTO l_ename;
  IF l_crs%NotFound Then
    l_ename := NULL;
  End IF;
  Close crs;
  dbms_output.put_line('Name = '||l_ename);
End;
/
mnitu est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 19/03/2008, 19h58   #19
Membre chevronné
 
Avatar de randriano
 
Homme Rija Randriano
Inscription : janvier 2007
Messages : 984
Détails du profil
Informations personnelles :
Nom : Homme Rija Randriano
Localisation : Madagascar

Informations forums :
Inscription : janvier 2007
Messages : 984
Points : 729
Points : 729
merci mnitu pour cette autre technique qu'est l'emploi de curseur explicite, c'est vraiment un autre moyen de contourner le traitement de l'exception no_data_found
__________________
randriano.dvp.com
randriano est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 09h01.


 
 
 
 
Partenaires

Hébergement Web