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

PL/SQL Oracle Discussion :

PL/SQL et boucle infinie


Sujet :

PL/SQL Oracle

  1. #1
    Membre à l'essai
    Inscrit en
    Juillet 2005
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 32
    Points : 22
    Points
    22
    Par défaut PL/SQL et boucle infinie
    Bonjour,

    Je dois faire un programme en PL/SQL qui doit insérer dans une table des données générées aléatoirement.

    Voici ma précédure actuelle:
    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
     
    PROCEDURE insert_orga (
    		nb_jud_cat IN NUMBER(4,0),
    		nb_orga_type IN NUMBER(4,0)
    	) IS
    		siret NUMBER(14,0);
    		jud_cat_id NUMBER(4,0);
    		orga_type_id NUMBER(4,0);
    	BEGIN
     
    			SELECT trunc(dbms_random.value(10000000000000,99999999999999)) INTO siret FROM DUAL;
     
    			SELECT trunc(dbms_random.value(1,nb_jud_cat)) INTO jud_cat_id FROM DUAL;
     
     
    			SELECT trunc(dbms_random.value(1,nb_orga_type)) INTO orga_type_id FROM DUAL;
     
    			INSERT INTO organization (orga_id, orga_type_id, judicial_category_id, siret, name, name_complement) 
    			VALUES (SEQ_ORGANIZATION.NEXTVAL,orga_type_id, jud_cat_id  ,siret,'nom','complenom');
     
    		COMMIT;
    	END insert_orga;
    A cause de contraintes d'unicité sur le champ siret je vais devoir faire une boucle qui réessaye d'insérer une nouvelle ligne en cas d'échec.

    Mais que se passe-t-il dans le cas ou je fais une boucle infinie? Le script s'arrete-t-il au bout d'un certain temps?

    Y a t-il un "processus" qu'il faut killer?

  2. #2
    Membre éprouvé Avatar de Yorglaa
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    845
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2004
    Messages : 845
    Points : 931
    Points
    931
    Par défaut
    Salut,
    je voudrais être sûr de comprendre :
    est-ce que SEUL le champ siret doit être contrôlé ?
    ou tous les champs que tu génère via dbms_ramdom...
    si c'est les 3, est-ce que CHAQUE no généré doit être unique ou juste la combinaison des 3 doit être unique ?

    PS peux-tu éditer ton premier post en utilisant les balises CODE stp...ce serait plus lisible.

  3. #3
    Membre à l'essai
    Inscrit en
    Juillet 2005
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    Oui seul le champ siret doit être unique.

    La clef primaire est orga_id, mais je le génére avec une sequence.

    Les autres champs ne doivent pas être nuls c'est tout.

    Si je veux générer exactement x enregistrements, il est possible (quoi que trés improbable) que je génère un numéro siret qui existe déja.

    C'est ce cas que je veux traiter.

  4. #4
    Membre éprouvé Avatar de Yorglaa
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    845
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2004
    Messages : 845
    Points : 931
    Points
    931
    Par défaut
    en gros le principe auquel je pense est de faire une procédure récursive (qui s'appelle elle-même)...

    Voici ta procédure, avec le test d'unicité sur le No Siret uniquement... si tu veux contrôler les trois no ou la combinaison, tu n'as plus qu'a adapter le Select du contrôle d'unicité.
    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
    40
    41
    PROCEDURE insert_orga (
                            nb_jud_cat IN NUMBER(4,0),
                            nb_orga_type IN NUMBER(4,0)
                          ) 
    IS
        nSiret          NUMBER(14,0);
        jud_cat_id      NUMBER(4,0);
        orga_type_id    NUMBER(4,0);
     
        nTest           Number ;
    BEGIN
     
        -- génération des No 
        SELECT trunc(dbms_random.value(10000000000000,99999999999999)) INTO siret FROM DUAL;
        SELECT trunc(dbms_random.value(1,nb_jud_cat)) INTO jud_cat_id FROM DUAL;
        SELECT trunc(dbms_random.value(1,nb_orga_type)) INTO orga_type_id FROM DUAL;
     
        -- TEST unicité 
        Select
                orga_id
        Into    nTest
        From    Organization
        Where   siret = nSiret ;
     
        -- on a trouvé UNE ligne, on lève l'erreur comme si on en avait trouvé plusieures 
        Raise Too_Many_Rows ;
     
        Exception
        When Too_Many_Rows -- on traite l'erreur, qu'on aie trouvé une ou plusieurs lignes 
        Then
            -- la procédure se relance elle-même et va donc générer d'autres no aléatoires 
            insert_orga(nb_jud_cat, nb_orga_type); 
     
        When No_Data_Found -- cette erreur sera levée si le test d'unicité ne ramène rien... c'est ce qu'on veut ! 
        Then
            INSERT INTO organization (orga_id, orga_type_id, judicial_category_id, siret, name, name_complement) 
            VALUES (SEQ_ORGANIZATION.NEXTVAL,orga_type_id, jud_cat_id ,nSiret,'nom','complenom');
     
        COMMIT;
     
    END insert_orga;
    PS1 j'ai modifié le nom de ta variable siret en nSiret... ça ne marche pas d'avoir une variable du même nom qu'une colonne de la table cible !

    PS2 j'ai fait ce code en vitesse, à la louche !! je te laisse le vérifier !

  5. #5
    Rédacteur

    Homme Profil pro
    Développeur et DBA Oracle
    Inscrit en
    Octobre 2006
    Messages
    878
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Algérie

    Informations professionnelles :
    Activité : Développeur et DBA Oracle

    Informations forums :
    Inscription : Octobre 2006
    Messages : 878
    Points : 1 197
    Points
    1 197
    Par défaut
    salut,

    On peut faire plus simple

    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
     
    PROCEDURE insert_orga (
                            nb_jud_cat IN NUMBER(4,0),
                            nb_orga_type IN NUMBER(4,0)
                          ) 
    IS
        nSiret          NUMBER(14,0);
        jud_cat_id      NUMBER(4,0);
        orga_type_id    NUMBER(4,0);
     
        nTest           Number ;
    BEGIN
     
        -- génération des No 
        SELECT trunc(dbms_random.value(10000000000000,99999999999999)) INTO siret FROM DUAL;
        SELECT trunc(dbms_random.value(1,nb_jud_cat)) INTO jud_cat_id FROM DUAL;
        SELECT trunc(dbms_random.value(1,nb_orga_type)) INTO orga_type_id FROM DUAL;
     
        -- TEST unicité 
        INSERT INTO organization (orga_id, orga_type_id, judicial_category_id, siret, name, name_complement) 
            VALUES (SEQ_ORGANIZATION.NEXTVAL,orga_type_id, jud_cat_id ,nSiret,'nom','complenom');
       COMMIT;
     
    Exception
        When dup_val_on_index -- on traite l'erreur, qu'on aie trouvé une ou plusieurs lignes 
        Then
            -- la procédure se relance elle-même et va donc générer d'autres no aléatoires 
            insert_orga(nb_jud_cat, nb_orga_type); 
    when others then 
         dbms_output.put_line(sqlcode||' - '||sqlerrm);
    END insert_orga;

  6. #6
    Membre éprouvé Avatar de Yorglaa
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    845
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2004
    Messages : 845
    Points : 931
    Points
    931
    Par défaut
    bien vu !!

    la seul effet de bord potentiel sera d'avoir éventuellement plus de "trous" dans la clef primaire, la séquence.nextval étant dans ce cas utilisée à chaque essais...

    mais il est vrai que la plupart du temps c'est sans importance !

  7. #7
    Membre à l'essai
    Inscrit en
    Juillet 2005
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    hum effectivement je n'avais pas pensé à utiliser cette méthode. J

    Mais en fait ça revient à utiliser une boucle while.

    Que se passe-t-il dans le cas d'une procédure récursive qui boucle à l'infini?

    (ou d'une boucle while infinie?)

  8. #8
    Membre éprouvé Avatar de Yorglaa
    Profil pro
    Inscrit en
    Janvier 2004
    Messages
    845
    Détails du profil
    Informations personnelles :
    Âge : 53
    Localisation : Suisse

    Informations forums :
    Inscription : Janvier 2004
    Messages : 845
    Points : 931
    Points
    931
    Par défaut
    ben tu as un process qui tourne en permanence jusqu'au prochain shutdown de ta base...

    qui, d'ailleurs, devra être un shutdown immediate ou abort selon ce qui est fait dans la procédure qui tourne à l'infini (transaction débutée ou non).

    à moin encore que le process de ta session infinie soit killé manuellement...

  9. #9
    Membre à l'essai
    Inscrit en
    Juillet 2005
    Messages
    32
    Détails du profil
    Informations forums :
    Inscription : Juillet 2005
    Messages : 32
    Points : 22
    Points
    22
    Par défaut
    Merci pour toutes ces précisions.

    J'ai testé le code de slim11, il y avait juste une petite erreur (fort ompréhensible)
    Il fallait remplacer dup_val_index par dup_val_on_index...

    Pour ceux que ça intéresse j'ai cherché de la doc sur comment killer une session oracle on peut le faire grace à ces requetes:

    SELECT s.sid,
    s.serial#,
    s.osuser,
    s.program
    FROM v$session s;

    ALTER SYSTEM KILL SESSION 'sid,serial#';

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [T-SQL]Curseur et boucle infinie
    Par Mathusalem dans le forum Sybase
    Réponses: 10
    Dernier message: 02/02/2007, 13h49
  2. symptome de la boucle infinie dans une requete
    Par ouam81 dans le forum Langage SQL
    Réponses: 8
    Dernier message: 27/05/2005, 12h10
  3. Réponses: 15
    Dernier message: 24/05/2005, 08h34
  4. [Socket] Pb de boucle infinie
    Par Myogtha dans le forum Entrée/Sortie
    Réponses: 12
    Dernier message: 10/06/2004, 14h10
  5. [C#] Comment eviter les boucles infinies ?
    Par Thomas Lebrun dans le forum C#
    Réponses: 12
    Dernier message: 09/06/2004, 00h04

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