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 :

SELECT FOR UPDATE SKIP LOCKED ORA-02014


Sujet :

PL/SQL Oracle

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 155
    Par défaut SELECT FOR UPDATE SKIP LOCKED ORA-02014
    Bonjour,
    Je suis en Oracle 11g.
    J'utilise une table UTILISATEUR_ORA comme pool de connexion (couple login/mot de passe).
    Un webservice devrait appeler la fonction ci dessous afin de retourner l'id d'une seule ligne de cette table telle que la ligne soit la plus ancienne (attr UTO_DATE_SATUT) et dans l’état 'LIBRE' (attr UTO_STA). ou -1 si il n'y a plus de ligne correspondante (plus de place [pour le moment]dans le pool de connexion)


    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
    42
    43
    44
    45
    46
    47
    48
    49
    50
     
    -- -------------------------------------------------------------
    -- Tentative de revervation d'un couple login/mot de passe dans le pool (UTILISATEUR_ORA)
    -- -------------------------------------------------------------
    FUNCTION Reserve_UOC(p_id_java IN NUMBER)
    RETURN NUMBER IS 
    PRAGMA AUTONOMOUS_TRANSACTION;
    --Retour -1 en cas d'erreur sinon la clé de la table UTO_SEQ
    -- compte INTEGER;
    v_retour NUMBER(38,0);
    v_session_id NUMBER;
    v_UOC_trouve BOOLEAN;
    v_UOC_dispo UTILISATEUR_ORA%ROWTYPE;
     
    CURSOR CUR_UOC_LIBRE_PLUS_VIEUX IS
    select * 
    from (
    SELECT * FROM  UTILISATEUR_ORA 
    WHERE UTO_STA='LIBRE' 
    ORDER BY UTO_DATE_STATUT ASC) where rownum=1
    FOR UPDATE SKIP LOCKED;
     
    BEGIN
      v_UOC_trouve:=FALSE;
      v_retour:=-1;
    	/* On recupere l'identificateur de session */
    	SELECT USERENV('SESSIONID') INTO v_session_id FROM dual;
    	/* On scanne tous les tuples en etat LIBRE du plus ancien au plus recent */
    	OPEN CUR_UOC_LIBRE_PLUS_VIEUX;
    	LOOP
    		FETCH CUR_UOC_LIBRE_PLUS_VIEUX INTO v_UOC_dispo;
    		EXIT WHEN v_UOC_trouve=TRUE OR CUR_UOC_LIBRE_PLUS_VIEUX%NOTFOUND;
    		--DBMS_OUTPUT.PUT_LINE('Nombre Ligne Utilisateur_ORA dispo:*'||CUR_UOC_LIBRE_PLUS_VIEUX%ROWCOUNT || '*.');
    		--DBMS_OUTPUT.PUT_LINE('Utilisateur trouvé:*'||v_UOC_dispo.UTO_USR_GPL||'*');
    		v_UOC_trouve:=TRUE;
        UPDATE UTILISATEUR_ORA 
        SET UTO_STA='RESERVE', UTO_DATE_STATUT=SYSDATE, UTO_ID_ORA=v_session_id, UTO_ID_THREAD=p_id_java
    		WHERE CURRENT OF CUR_UOC_LIBRE_PLUS_VIEUX;
    		v_retour:=v_UOC_dispo.UTO_SEQ;
    	END LOOP;	
    	CLOSE CUR_UOC_LIBRE_PLUS_VIEUX;
     
    	IF v_UOC_trouve=FALSE THEN
    		COMMIT;
        RETURN -1;
       ELSE 
        COMMIT;
        RETURN v_retour;
    	END IF;
    END Reserve_UOC;
    Après tentative de test de la requête du curseur (qui doit me ramener l'id de cette fameuse ligne [+ ancienne et statut libre]), j'obtiens l'erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    ORA-02014: SELECT FOR UPDATE depuis vue imposs. avec fonctions DISTINCT, GROUP BY, etc
    02014. 00000 -  "cannot select FOR UPDATE from view with DISTINCT, GROUP BY, etc."
    Erreur à la ligne 2, colonne 6
    Qu'ai - je fais pour mériter cela ?

    Et surtout comment obtenir un curseur qui ne fetch qu'une seule ligne selon les conditions : la plus ancienne et le statut à LIBRE ?
    Car FOR UPDATE SKIP LOCKED devrait ne me retourner qu'une ligne non verrouillée ET correspondant à mes conditions citées ci-dessus, non ?

    Merci pour votre aide

  2. #2
    Expert confirmé 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
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
     
     UPDATE UTILISATEUR_ORA 
        SET UTO_STA='RESERVE', 
            UTO_DATE_STATUT=SYSDATE, 
            UTO_ID_ORA=USERENV('SESSIONID'), 
            UTO_ID_THREAD=p_id_java
      WHERE UTO_STA='LIBRE' 
        And <condition_enregistrement_unique>
      Returning UTO_SEQ Into l_retour;
    --
      If SQL%NOTFOUND Then
        l_retour = -1;
      End IF;
    Mettez à la place de <condition_enregistrement_unique> vos critères qui permetront d'identifier un unique enregistrement.

  3. #3
    Membre confirmé
    Profil pro
    Inscrit en
    Janvier 2008
    Messages
    155
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2008
    Messages : 155
    Par défaut
    Bonjour mnitu et merci pour votre réponse,
    Mais n'y aura - t il pas de problèmes de 'lost_update' si plusieurs threads fonds appelle à la fonction Reserve_UOC dans un même laps de temps ?

    En fait, en parallele de cette fonction j'ai un trigger on logon database qui fait un update sur UTILISATEUR_ORA (et crée un job pour modifier le mot de passe aleatoire) tel que :
    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
     
      v_ddl_cmd:='ALTER USER '||v_username||' IDENTIFIED BY '||v_new_passwd||'';
      /* Synchrone */  
      sys.DBMS_SCHEDULER.CREATE_JOB (
       job_name           =>  'job_trg_log_on',
       job_type           =>  'PLSQL_BLOCK',
       job_action         =>  'BEGIN PKG_OTP.execute_alter_user(''' || v_ddl_cmd || '''); END;',
       start_date         =>  null,
       repeat_interval    =>  null,
       auto_drop          =>  TRUE,
       enabled            =>  TRUE,
       comments           =>  'trg_log_on job');
      sys.DBMS_SCHEDULER.RUN_JOB (
       'job_trg_log_on',
       TRUE);-- use_current_session TRUE => synchrone 
       -- SELECT job_name, LOG_DATE, operation, status FROM USER_SCHEDULER_JOB_LOG;
       -- "REASON="manual slave run"
       -- is not an error message - it just says that this run was run manually in a foreground session and not in the background by a job slave (which is the normal case).
     
     L_Requete:='UPDATE UTILISATEUR_ORA SET UTO_PWD_GPL=:a, UTO_DATE_STATUT=:b, UTO_STA=:c WHERE UTO_USR_GPL=:d';
     Execute immediate L_Requete using v_new_passwd, v_date_connexion, 'LIBRE', v_username;
     
      COMMIT;

  4. #4
    Expert confirmé 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
    Par défaut
    Citation Envoyé par Moostiq Voir le message
    Bonjour mnitu et merci pour votre réponse,
    Mais n'y aura - t il pas de problèmes de 'lost_update' si plusieurs threads fonds appelle à la fonction Reserve_UOC dans un même laps de temps ?
    ...
    Il peut y avoir un update restart mais pas de lost update.

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

Discussions similaires

  1. Select for update nowait skip locked en oracle 11
    Par bruno270579 dans le forum SQL
    Réponses: 2
    Dernier message: 29/06/2012, 08h12
  2. JDBC Locking row : SELECT FOR UPDATE
    Par relbeghdadi dans le forum JDBC
    Réponses: 3
    Dernier message: 14/01/2011, 11h35
  3. ORA-02014: SELECT FOR UPDATE.
    Par tommey dans le forum PL/SQL
    Réponses: 5
    Dernier message: 28/04/2010, 14h51
  4. select for update LOCK 3 10gR2
    Par petitfrere dans le forum Oracle
    Réponses: 1
    Dernier message: 01/12/2006, 18h52
  5. [Verrou] SELECT FOR UPDATE
    Par e1lauren dans le forum PostgreSQL
    Réponses: 10
    Dernier message: 13/10/2005, 17h06

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