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

Oracle Discussion :

Obtenir plusieurs valeurs d'une séquence en une seule requête


Sujet :

Oracle

  1. #1
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 143
    Par défaut Obtenir plusieurs valeurs d'une séquence en une seule requête
    Bonjour

    Je fais un algorithme avec une grande quantité d'inserts. A chaque itération j'exécute la requête suivante pour obtenir la clé primaire de mon enregistrement.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    select maSequence.nextVal from dual;
    Existe-t-il un moyen de récupérer un bloc de valeurs afin de ne pas avoir à exécuter cette requête à chaque boucle ? Cela économiserait un aller - retour à la base de données à chaque itération et améliorerait sans doute les performances.

    Merci d'avance pour vos réponses

  2. #2
    Expert confirmé
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 822
    Billets dans le blog
    1
    Par défaut
    Bonjour,
    Normalement, on ne devrait pas faire un aller-retour pour lire une sequence.
    Il suffit d'utiliser maSequence.NEXTVAL dans l'insert plutot que de faire un select from dual avant.
    Cordialement,
    Franck.

  3. #3
    Expert confirmé
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 822
    Billets dans le blog
    1
    Par défaut
    Sinon, pour répondre à
    Existe-t-il un moyen de récupérer un bloc de valeurs
    c'est assez simple: lorsque tu récupères la valeur n tu as 100 valeurs:
    n+0.00 , n+0.01 , n+0.02 , n+0.03 , ... , n+0.99
    un décimal de prends pas plus d'un entier
    Cordialement,
    Franck.

  4. #4
    Membre chevronné

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Par défaut
    Citation Envoyé par pachot Voir le message
    Sinon, pour répondre à

    c'est assez simple: lorsque tu récupères la valeur n tu as 100 valeurs:
    n+0.00 , n+0.01 , n+0.02 , n+0.03 , ... , n+0.99
    un décimal de prends pas plus d'un entier
    Cordialement,
    Franck.
    Mais dans ce cas, la séquence n'est pas incrémentée, ce qui peut être dangereux selon son utilisation.

  5. #5
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 143
    Par défaut
    Merci pour vos réponses.

    Utiliser le fait qu'un réel à 2 décimales ne prenne pas plus de place qu'un entier ne me plaît pas trop. La solution est techniquement bonne mais je ne trouve pas ça très joli. J'aimerais garder des nombres entier dans cette clé primaire.

    D'autre part, je ne peux pas utiliser la recherche de séquence directement dans mon INSERT sql. Cette séquence me sert pour valoriser la clé primaire de deux tables qui sont en relation 1-1. La seconde table a sa clé primaire qui est aussi une clé étrangère vers la clé primaire de la première table. Il me faut donc connaître la valeur de la séquence pour la spécifier dans le second insert.

    Enfin je réalise ces inserts en Java / JDBC en utilisant un PreparedStatement en batch afin de minimiser les aller retours à la base.

    Il n'y a que pour obtenir les séquences que je suis obligé de faire autant d'aller retour en base qu'il y a d'itérations dans mon algo.

    N'y a-t-il vraiment pas moyen de demander à la séquence Oracle une collection de valeurs transmises en bloc ?

    Merci encore

  6. #6
    Membre chevronné

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Par défaut
    Comme l'a dit Pachot dans son premier message, si vous utilisez la séquence directement, vous n'avez pas d'aller-retour supplémentaire:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    INSERT INTO ma_table (ID, NOM, ...) VALUES (sequence.nextval, le_nom, ...);

  7. #7
    Modérateur
    Avatar de Waldar
    Homme Profil pro
    Sr. Specialist Solutions Architect @Databricks
    Inscrit en
    Septembre 2008
    Messages
    8 454
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France, Val de Marne (Île de France)

    Informations professionnelles :
    Activité : Sr. Specialist Solutions Architect @Databricks
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2008
    Messages : 8 454
    Par défaut
    Il y a un mécanisme de cache avec les séquences, je ne sais pas si ça pourra vous aider.

  8. #8
    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 El Saigneur Voir le message
    ...
    D'autre part, je ne peux pas utiliser la recherche de séquence directement dans mon INSERT sql. Cette séquence me sert pour valoriser la clé primaire de deux tables qui sont en relation 1-1. La seconde table a sa clé primaire qui est aussi une clé étrangère vers la clé primaire de la première table. Il me faut donc connaître la valeur de la séquence pour la spécifier dans le second insert.
    ...
    Il y a deux solutions:
    1) utiliser returning
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    Insert Into ma_table(id,...) values (sequence.nextval, ...) Returning Id Into ...
    2) utiliser pour le deuxième insert la valeur courante de la séquence
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    Insert into ma_table1 values (sequence.nextval)
    insert into ma_table2 values (sequence.currval)

  9. #9
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 143
    Par défaut
    mnitu,

    Concernant la solution 1) :
    Suite à vos conseils sur un Post précédent sur ce forum (merci encore d'ailleurs), j'utilise un PreparedStatement JDBC en batch. Cette technique est très bien expliquée dans l'article que vous m'avez conseillé de lire. Effectivement les performances s'en trouvent nettement améliorées. Cependant en utilisant cette technique de batch, j'insère d'abord mes n lignes dans la table1 puis mes n lignes dans la table2. Quel serait le comportement de Returning id INTO dans ce cas où ma requête insère n lignes d'un coup (n = taille du batch) ? J'ai peur que cela me retourne une collection d'ids en vrac que je ne saurait pas réaffecter aux lignes du second insert en batch dans la table2.

    Concernant la solution 2)
    Utiliser maSequence.currval n'est-il pas problématique dans un contexte multithreads ? Mon application est une application Web. Plusieurs utilisateurs peuvent lancer l'algorithme en même temps. Dans ce contexte, la valeur retournée par maSequence.currval ne risque-t-elle pas d'être un id d'une ligne insérée par l'autre thread ? Et au-delà de ça, étant donné que j'insère en batch dans la première table, maSequence.currval ne me retournera pas ce qu'il faut pour mes inserts dans me second batch.

    Merci encore pour vos indications

    C'est dommage car le batch apporte vraiment un gain de performance. Le seul point qui prend vraiment du temps maintenant c'est cette obtention de valeurs de la séquence. Il semblerait donc qu'il n'y ait pas moyen d'obtenir en une seule requête plusieurs valeurs de la séquence. C'est dommage. Avez-vous d'autres idées ?

    Merci encore

  10. #10
    Membre chevronné

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Par défaut
    La seule solution que je vois, et qui colle exactement à l'esprit de votre demande, c'est une boucle PL/SQL qui récupère les numéros de séquences dans un tableau que vous utilisez ensuite.

    Schématiquement (il faut déclarer le tableau, gérer la taille...):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    FOR i in 1 .. n
    LOOP
       SELECT ma_sequence.NEXTVAL INTO mon_tableau(i) FROM DUAL;
    END LOOP;

  11. #11
    Expert confirmé
    Avatar de pachot
    Homme Profil pro
    Developer Advocate YugabyteDB
    Inscrit en
    Novembre 2007
    Messages
    1 822
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : Suisse

    Informations professionnelles :
    Activité : Developer Advocate YugabyteDB
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Novembre 2007
    Messages : 1 822
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par GoLDoZ Voir le message
    Mais dans ce cas, la séquence n'est pas incrémentée, ce qui peut être dangereux selon son utilisation.
    Si, elle est incrémentée. Chaque fois qu'elle est incrémentée de 1, on peut utiliser 100 valeurs décimales qu'on sera les seuls à utiliser.

    Citation Envoyé par El Saigneur Voir le message
    Utiliser le fait qu'un réel à 2 décimales ne prenne pas plus de place qu'un entier ne me plaît pas trop. La solution est techniquement bonne mais je ne trouve pas ça très joli. J'aimerais garder des nombres entier dans cette clé primaire.
    Alors tu peux créer ta sequence en 'increment by 100' et tu auras 100 entiers libres. Clependant, il n'y a vraiement pas beaucoup de différence entre un entier et un décimal car ils sont tous les 2 stockées en virgule flottante.

  12. #12
    Membre chevronné

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    507
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 507
    Par défaut
    Citation Envoyé par pachot Voir le message
    Si, elle est incrémentée. Chaque fois qu'elle est incrémentée de 1, on peut utiliser 100 valeurs décimales qu'on sera les seuls à utiliser.
    Oups! Exact.

  13. #13
    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 El Saigneur Voir le message
    mnitu,

    Concernant la solution 1) :
    Suite à vos conseils sur un Post précédent sur ce forum (merci encore d'ailleurs), j'utilise un PreparedStatement JDBC en batch. Cette technique est très bien expliquée dans l'article que vous m'avez conseillé de lire. Effectivement les performances s'en trouvent nettement améliorées. Cependant en utilisant cette technique de batch, j'insère d'abord mes n lignes dans la table1 puis mes n lignes dans la table2. Quel serait le comportement de Returning id INTO dans ce cas où ma requête insère n lignes d'un coup (n = taille du batch) ? J'ai peur que cela me retourne une collection d'ids en vrac que je ne saurait pas réaffecter aux lignes du second insert en batch dans la table2.

    Concernant la solution 2)
    Utiliser maSequence.currval n'est-il pas problématique dans un contexte multithreads ? Mon application est une application Web. Plusieurs utilisateurs peuvent lancer l'algorithme en même temps. Dans ce contexte, la valeur retournée par maSequence.currval ne risque-t-elle pas d'être un id d'une ligne insérée par l'autre thread ? Et au-delà de ça, étant donné que j'insère en batch dans la première table, maSequence.currval ne me retournera pas ce qu'il faut pour mes inserts dans me second batch.

    Merci encore pour vos indications

    C'est dommage car le batch apporte vraiment un gain de performance. Le seul point qui prend vraiment du temps maintenant c'est cette obtention de valeurs de la séquence. Il semblerait donc qu'il n'y ait pas moyen d'obtenir en une seule requête plusieurs valeurs de la séquence. C'est dommage. Avez-vous d'autres idées ?

    Merci encore
    1) Quand vous travaillez en batch vous préparez un tableau des valeurs pour l’insertion. Le Returning devrait vous retourner un tableau des id. Le premier Id corresponde à la première ligne insérée, le deuxième à la deuxième etc. Je pense donc que cette solution devrait aller, mais comme d’habitude un exemple de code pourrait aider à éviter des malentendus.

    2) Rien ne vaut plus qu’en petit test
    Session 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    mni@DEV>create sequence test_seq;
     
    Séquence créée.
     
    mni@DEV>select test_seq.nextval from dual;
     
       NEXTVAL
    ----------
             1
    Session 2
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    mni@DEV>select test_seq.nextval from dual;
     
       NEXTVAL
    ----------
             2
    Et on revient dans la sesion 1
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    mni@DEV>select test_seq.currval from dual;
     
       CURRVAL
    ----------
             1
    Si vous tenez vraiment d'obtenir dans un seule select N valeurs de la sequence, voilà une autre solution
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    1* select test_seq.nextval from dual, table(row_generator(1,5))
     
       NEXTVAL
    ----------
             3
             4
             5
             6
             7
    Ici row_generator tiens la place d'une table pivot qui permet de multiplier les nombre des enregistrements de la table qui est la source des données, dual dans ce cas. C'est une fonction pipelined mais cella n'a aucune importance; vous pouvez utiliser n'importe quelle autre table comme multiplicateur d'enregistrements.
    Petit remarque cette solutions c'est la même que le returning en fait

  14. #14
    Membre confirmé
    Profil pro
    Inscrit en
    Octobre 2003
    Messages
    143
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Octobre 2003
    Messages : 143
    Par défaut
    J'ai trouvé la solution il y a quelques mois et prends enfin le temps de la partager avec vous. Par exemple, pour récupérer 10000 valeurs de la séquence "maSequence" en une seule requête :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    select maSequence.nextval from dual connect by level <= 10000

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

Discussions similaires

  1. [Toutes versions] coller les données d'une plage d'une cellule dans une cellule d'une autre feuille[VBA]
    Par arthson dans le forum Macros et VBA Excel
    Réponses: 1
    Dernier message: 24/01/2012, 17h37
  2. Réponses: 7
    Dernier message: 25/03/2011, 10h52
  3. [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
  4. Réponses: 4
    Dernier message: 15/10/2009, 13h33
  5. [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

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