IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

SQL Oracle Discussion :

Gérer un select into avec aucune valeur trouvée


Sujet :

SQL Oracle

  1. #1
    Membre expérimenté
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 219
    Points : 1 438
    Points
    1 438
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 ?

  2. #2
    Membre confirmé Avatar de miloux32
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    545
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 545
    Points : 565
    Points
    565
    Par défaut
    Si tu es dans une procédure , pourquoi ne pas pas faire un bloc d'exeption WHEN_NO_DATA_FOUND ?

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 ;

  3. #3
    Membre expérimenté
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 219
    Points : 1 438
    Points
    1 438
    Par défaut
    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 ??

  4. #4
    Membre confirmé Avatar de miloux32
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    545
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 545
    Points : 565
    Points
    565
    Par défaut
    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)

  5. #5
    Membre expérimenté
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 219
    Points : 1 438
    Points
    1 438
    Par défaut
    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

  6. #6
    Membre confirmé Avatar de miloux32
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    545
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 545
    Points : 565
    Points
    565
    Par défaut
    Je redonne mon explication car a priori tu n'as pas compris ....

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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 .

  7. #7
    Membre du Club
    Inscrit en
    Novembre 2006
    Messages
    113
    Détails du profil
    Informations forums :
    Inscription : Novembre 2006
    Messages : 113
    Points : 65
    Points
    65
    Par défaut
    Bonjour,

    je pense qu'une instruction NVL peut te régler le problème
    donc tu vas mettre :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
     
    select nvl(ton_champ,0) into var frop table
    Bonne journée

  8. #8
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    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 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Un petit exemple pour illustrer ce que t'a expliqué miloux32 :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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.

  9. #9
    Membre confirmé Avatar de miloux32
    Profil pro
    Inscrit en
    Juillet 2003
    Messages
    545
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juillet 2003
    Messages : 545
    Points : 565
    Points
    565
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    select nvl(1,2) from dual where 1=2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    Résultat : 
    no rows returned ...

  10. #10
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    Bon si tu y tiens vraiment
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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;
    /

  11. #11
    Membre expert

    Homme Profil pro
    Chef de projet en SSII
    Inscrit en
    Janvier 2004
    Messages
    2 862
    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 862
    Points : 3 609
    Points
    3 609
    Par défaut
    Citation Envoyé par mnitu Voir le message
    Bon si tu y tiens vraiment
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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

  12. #12
    Rédacteur
    Avatar de Vincent Rogier
    Profil pro
    Inscrit en
    Juillet 2007
    Messages
    2 373
    Détails du profil
    Informations personnelles :
    Âge : 46
    Localisation : France

    Informations forums :
    Inscription : Juillet 2007
    Messages : 2 373
    Points : 5 306
    Points
    5 306
    Par défaut
    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 !

  13. #13
    Membre expérimenté
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 219
    Points : 1 438
    Points
    1 438
    Par défaut
    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 ?

  14. #14
    Membre averti
    Profil pro
    Inscrit en
    Août 2005
    Messages
    316
    Détails du profil
    Informations personnelles :
    Âge : 54
    Localisation : France

    Informations forums :
    Inscription : Août 2005
    Messages : 316
    Points : 388
    Points
    388
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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;

  15. #15
    Expert confirmé
    Avatar de laurentschneider
    Homme Profil pro
    Administrateur de base de données
    Inscrit en
    Décembre 2005
    Messages
    2 944
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

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

    Informations forums :
    Inscription : Décembre 2005
    Messages : 2 944
    Points : 4 926
    Points
    4 926
    Par défaut
    éventuellement

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    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;

  16. #16
    Membre expérimenté
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 219
    Points : 1 438
    Points
    1 438
    Par défaut
    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 !!!

  17. #17
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    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 ...

  18. #18
    Expert éminent sénior Avatar de mnitu
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2007
    Messages
    5 611
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    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 : 5 611
    Points : 11 252
    Points
    11 252
    Par défaut
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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 : Sélectionner tout - Visualiser dans une fenêtre à part
    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;
    /

  19. #19
    Membre expérimenté
    Avatar de randriano
    Homme Profil pro
    Inscrit en
    Janvier 2007
    Messages
    1 219
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Madagascar

    Informations forums :
    Inscription : Janvier 2007
    Messages : 1 219
    Points : 1 438
    Points
    1 438
    Par défaut
    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

Discussions similaires

  1. [MySQL-5.5] Export texte avec SELECT INTO OUTFILE et valeurs nulles
    Par guen dans le forum MySQL
    Réponses: 3
    Dernier message: 05/01/2015, 14h02
  2. Retourner NULL si aucune valeur trouvée
    Par Micke7 dans le forum Langage SQL
    Réponses: 5
    Dernier message: 05/03/2009, 13h50
  3. Select into avec "Identity"
    Par Crotte dans le forum MS SQL Server
    Réponses: 3
    Dernier message: 21/03/2007, 11h14
  4. [PL/SQL] SELECT INTO avec type TABLE
    Par Kaejar dans le forum Oracle
    Réponses: 13
    Dernier message: 06/07/2006, 16h17
  5. INSERT INTO avec une valeur numéroauto
    Par priest69 dans le forum Requêtes et SQL.
    Réponses: 12
    Dernier message: 08/11/2005, 15h39

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo