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 :

Visibilité entre une transaction et une fonction stockée


Sujet :

PL/SQL Oracle

  1. #1
    Membre régulier Avatar de hamster
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 137
    Points : 123
    Points
    123
    Par défaut Visibilité entre une transaction et une fonction stockée
    Bonjour,

    voilà le contexte de mon problème :
    J'ai une table T dans laquelle je stocke un nom et un code. Le code est une clef unique, calculée grâce à une fonction qui est appelée dans un trigger à l'insertion.
    La méthode de calcul de ce code est la suivante : on prend les quatre premiers caractères alphabétiques du nom, auxquels on ajoute une séquence de 4 chiffres. Par exemple :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into T (nom) values ('Maison');
    va valoriser le champ code avec MAIS0001.
    Pour le calcul de la séquence numérique, on recherche la valeur max de SUBSTR(T.nom,5,4) et on y ajoute 1.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    insert into T (nom) values ('Maisonnette');
    va valoriser le champ code avec MAIS0002.

    En revanche, si j'exécute les deux instructions dans la même transaction (sans commit),
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    insert into T (nom) values ('Chateau');
    insert into T (nom) values ('Chaton');
    et bien la deuxième instruction sera rejetée au motif que la règle d'unicité du champ code a été violée. Dans ma transaction même sans faire de commit, j'ai bien la visibilité de la première instruction. Si j'insère un select entre les deux, je verrai que le premier enregistrement a bien été créé (même s'il n'a pas encore été commité) ce qui ne semble pas être le cas de la fonction, qui elle ne le voit pas encore. Du coup elle considère que l'enregistrement 'Chateau' n'existe pas et essaie de valoriser T.code à CHAT0001 pour les deux lignes.

    Mon besoin est d'insérer un très grand nombre d'enregistrements (potentiellement quelques centaines de milliers) et je me vois mal fixer ma fréquence de commit à 1.

    Est-ce que vous savez comment je pourrais faire pour que ma fonction puisse "voir" que le premier enregistrement a déjà été créé, et ainsi le prendre en compte pour le calcul du T.code de l'enregistrement suivant ?

    Merci pour toutes vos suggestions !

  2. #2
    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
    Utilisez une séquence à la place du calcul du max sur la table (personnellement je ne utiliserait jamais de telles artifices pour le calcul d'une valeur de clé primaire).
    En général la solution avec le max sur la table est une catastrophe.

  3. #3
    Membre régulier Avatar de hamster
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 137
    Points : 123
    Points
    123
    Par défaut
    Malheureusement l'utilisation de la séquence ne fonctionne pas ici. Le risque de colision avec un code déjà existant n'est pas nul. La table contient actuellement plus d'un million d'enregistrements, qui ont déjà tous un code unique. Si j'initialise à partir de maintenant une séquence, qui plus est la même pour tous les quadruplets de caractères possibles, je suis quasiment certain de retomber sur un code déjà existant.

  4. #4
    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 hamster Voir le message
    Malheureusement l'utilisation de la séquence ne fonctionne pas ici. Le risque de colision avec un code déjà existant n'est pas nul. La table contient actuellement plus d'un million d'enregistrements, qui ont déjà tous un code unique. Si j'initialise à partir de maintenant une séquence, qui plus est la même pour tous les quadruplets de caractères possibles, je suis quasiment certain de retomber sur un code déjà existant.
    Franchement je n'ai pas pensé qu'en plus c'est du vrai .
    Le vrai problème n’est pas le trigger mais l’insertion concurrente.
    N’est-il pas envisageable d’ajouter une clé primaire ersatz (en anglais surogate primary key) donc un id_entite ?

  5. #5
    Membre régulier Avatar de hamster
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 137
    Points : 123
    Points
    123
    Par défaut
    Je ne saisi pas très bien ta proposition de clé primaire ersatz. Est-ce que tu peux m'en dire un peu plus ?

  6. #6
    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
    Ajoute d'un colonne id_entite dans la table qui peut être valorisé pour les enregistrements existente avec des valeurs numériques (1, 2, 3, ... 1 000 000)et qui ensuite sera alimenté par une séquence et abandon de la clé primaire actuelle (celle avec max sur la table). Est-ce possible ?

  7. #7
    Candidat au Club
    Inscrit en
    Avril 2007
    Messages
    5
    Détails du profil
    Informations forums :
    Inscription : Avril 2007
    Messages : 5
    Points : 3
    Points
    3
    Par défaut
    Non je ne peux pas abandonner la clé contenue dans code, car elle est propagée vers d'autres applications. Donc si je mélange des codes pour les enregistrements existants avec des séquences pour les nouveaux enregistrements, je me retrouve avec un problème de cohérence.

  8. #8
    Membre régulier Avatar de hamster
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 137
    Points : 123
    Points
    123
    Par défaut
    Désolé, c'est bien moi qui ai tapé la réponse précédente, mais j'ai été connecté automatiquement avec un autre nom d'user.

  9. #9
    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
    Peut-être en passant par une table temporaire dans laquelle tu stockes les codes insérés.
    Donc dans ton trigger tu lis d'abord ta table temporaire, si tu ne trouves rien tu récupères la valeur de ta fonction.
    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.

  10. #10
    Membre régulier Avatar de hamster
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 137
    Points : 123
    Points
    123
    Par défaut
    Et ça fonctionnerait même si les insertions dans la table temporaire ne sont pas committées à chaque nouvel enregistrements ?

  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
    Oui, puisque tu ne passes plus par une fonction autonome pour lire les valeurs insérées dans la session courante.

    Fonction autonome = session différente = tu ne vois pas ce qui se passe dans la session courante tant que cela n'a pas été committé.
    Les fonctions autonomes sont donc à utiliser avec la plus grande vigilence.
    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.

  12. #12
    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
    Par table temporaire j'entends GLOBAL TEMPORARY TABLE
    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.

  13. #13
    Membre régulier Avatar de hamster
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 137
    Points : 123
    Points
    123
    Par défaut
    Oui, ça a l'air très intéressant comme idée !

    Il faut juste que je détermine à quel niveau positionner cette table, afin d'être sûr que les insertions ou les updates seront toujours visibles par la fonction stockée qui génère les champs codes.

    je vais creuser ce point. Merci plaineR

  14. #14
    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
    Je ferai qlq chose comme cela :
    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
    create or replace trigger ....
    declare
       maseq number;
    begin
       -- lecture table temporaire
       select max(...) into maseq 
       from maTableTemp 
       where code = substr(...);
       -- enreg non trouve, recup seq via fonction
       if maseq is null then
         maseq = maFct;
       end if;
       -- valeur de mon code
       :new.code = ...;
       -- insertion dans ma table temp
       insert into maTableTemp (...) values (....);
    end;
    /
    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.

  15. #15
    Membre régulier Avatar de hamster
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 137
    Points : 123
    Points
    123
    Par défaut
    C'est une possibilité.

    Je pensais plutôt charger complètement ma table temporaire au début du traitement, puis faire les recherches uniquement sur cette table. Si la valeur existe, j'incrémente, sinon je l'ajoute à la table temporaire.

  16. #16
    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 hamster Voir le message
    C'est une possibilité.

    Je pensais plutôt charger complètement ma table temporaire au début du traitement, puis faire les recherches uniquement sur cette table. Si la valeur existe, j'incrémente, sinon je l'ajoute à la table temporaire.
    Attention aux 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.

  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
    Comme je l'ai déjà dit le vrai problème dans cette génération des valeurs uniques est lié à l'accès concurrent de la table, plus précis les insertions et non rien à voir avec les triggers, les global temporary tables, les transactions autonomes ou autres usines à gaz construites sur ces notions.

    Je m'explique: sauf le cas où l'insert dans cette table se fait uniquement par un traitement batch

    • a un instant T un utilisateur insère la valeur 'Maison'. A ce moment on va aller lire la table TAB pour calculer le MAX de la valeur pour le code 'MAIS'. Supposons que la valeur est N. Il génère la clé MAISN et il l'insère dans la table TAB. Il n'a pas encore fait le commit.
    • à peu près à ce même instant T un autre utilisateur insère la valeur 'Maisonnette'. Dans ce cas aussi on va aller lire la table TAB et calculer le MAX de la valeur pour le code 'MAIS'. La valeur sera la même: N parce que Oracle garanti le niveau d'isolation READ COMMITED par défaut et donc la clé généré sera 'MAISN': un doublon.

    Pour résoudre ce problème il faut garantir que la lecture du MAX se fait seulement après la validation de la première insertion de où l'exception des insertions via programme batch.

    Les solutions
    • Dans le cas d'un batch nul besoin de lire le Max pour chaque enregistrement il suffit de gérer un sort de tableau des clés de genre ((MAIS, 0001), (CHAT, 2000), etc) dans le programme.
    • Dans le cas des accès concurrentes on peut passer par une table de compteurs (code, valeur)
      ex:
      CODE VALEUR
      MAIS, 0001
      CHAT, 2000
      et à chaque génération d'une clé verrouiller la table des compteurs pour le code concerné, lire la valeur, l'incrémenter, la remettre à jour dans la table des compteurs.

    Mais cette solution a la propriété de poser des problèmes si le nombre des utilisateurs simultanée est important.

  18. #18
    Membre régulier Avatar de hamster
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 137
    Points : 123
    Points
    123
    Par défaut
    @ mnitu > Les insertions se feront uniquement par batch (un seul batch à la fois) et jamais par IHM.

    @ plaineR > bonne remarque ! Je vais également étudier les volumes d'enregistrements à insérer. Il est sans doute inutile de charger à chaque lancement du batch l'ensemble des données dans la table temporaire, pour insérer quelques dizaines d'enregistrements. De ce fait, ta solution (d'abord chercher dans la table temporaire, puis dans la table principale) est sans doute plus performante, puisque pour n insertions on aura au pire 2n accès à la table principale et 2n accès à la table temporaire (que ce soit en lecture ou en écriture).

  19. #19
    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 hamster Voir le message
    @ mnitu > Les insertions se feront uniquement par batch (un seul batch à la fois) et jamais par IHM.
    ...
    Donc nul besoin d'un trigger ou du Select Max de la table.

  20. #20
    Membre régulier Avatar de hamster
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    137
    Détails du profil
    Informations personnelles :
    Âge : 40
    Localisation : France, Rhône (Rhône Alpes)

    Informations forums :
    Inscription : Octobre 2003
    Messages : 137
    Points : 123
    Points
    123
    Par défaut
    Et pourquoi exactement ?

+ Répondre à la discussion
Cette discussion est résolue.
Page 1 sur 2 12 DernièreDernière

Discussions similaires

  1. Réponses: 7
    Dernier message: 25/03/2011, 10h52
  2. [XL-2002] Macro de comparaison d'une cellule d'une feuille avec une cellule d'une autre feuille.
    Par steelydan dans le forum Macros et VBA Excel
    Réponses: 6
    Dernier message: 08/09/2010, 12h59
  3. Réponses: 4
    Dernier message: 15/10/2009, 13h33
  4. [XL-2007] Afficher une checkbox dans une feuille si une checkbox d'une autre feuille est cochée
    Par JessieCoutas dans le forum Macros et VBA Excel
    Réponses: 3
    Dernier message: 18/08/2009, 13h35
  5. Recherche une valeur d'une cellule dans une colonne d'une autre feuille
    Par kourria dans le forum Macros et VBA Excel
    Réponses: 8
    Dernier message: 21/06/2007, 13h48

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