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 :

Un tableau pour la clause IN ? [11g]


Sujet :

PL/SQL Oracle

  1. #1
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut Un tableau pour la clause IN ?


    J'ai cette procédure:
    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
       PROCEDURE proc_liste_pratiques_epandages (
          p_campagne       IN     VARCHAR2,
          p_liste_champs   IN     ?,
          p_cur               OUT r_cursor)
       IS
       BEGIN
          OPEN p_cur FOR
               SELECT DISTINCT
                      champ.id_champ,
                      lot_boue.dp,
                      lot_boue.dr,
                      champ.num_sdea AS num_sdea_champ,
                      liste_parcelles.id_parcelle AS id_parcelle,
                      liste_parcelles.num_sdea AS num_sdea_parcelle,
                      champ.ilot_num_pac AS num_ilot,
                      champ.cad_lieu_dit AS lieu_dit,
                      com.nom AS commune,
                      exploit.id_exploitation,
                      exploit.nom_exploitation,
                      champ.champ_surf_declaree AS surface_totale,
                      DECODE (liste_parcelles.num_sdea,
                              '', '',
                              liste_parcelles.surface)
                         AS surface_parcelle,
                      DECODE (liste_parcelles.num_sdea,
                              '', champ.champ_surf_epandable,
                              liste_parcelles.surface)
                         AS surface_epandable,
                      DECODE (liste_parcelles.num_sdea,
                              '', champ.champ_surf_epandable,
                              liste_parcelles.surface)
                         AS surface_a_epandre,
                      type_cultures.id_culture_avant,
                      type_cultures.lib_culture_avant,
                      type_cultures.id_culture_intermediaire,
                      type_cultures.lib_culture_intermediaire,
                      type_cultures.id_culture_apres,
                      type_cultures.lib_culture_apres
                 FROM t_champs champ,
                      t_exploitations exploit,
                      v_communes com,
                      epf.lpe lot_boue,
                      t_campagnes_epandages camp,
                      (  SELECT DISTINCT id_parcelle,
                                         id_champ,
                                         surface,
                                         num_sdea
                           FROM t_parcelles_culturales
                       ORDER BY id_champ, num_sdea) liste_parcelles,
                      (  SELECT DISTINCT
                                pc.id_parcelle,
                                pc.id_champ,
                                pc.dte_fin,
                                pc.avant AS id_culture_avant,
                                tc_avant.lib AS lib_culture_avant,
                                pc.intermediaire AS id_culture_intermediaire,
                                tc_cipan.lib AS lib_culture_intermediaire,
                                pc.apres AS id_culture_apres,
                                tc_apres.lib AS lib_culture_apres
                           FROM t_parcelles_culturales pc,
                                t_type_culture tc_avant,
                                t_type_culture tc_cipan,
                                t_type_culture tc_apres
                          WHERE     tc_avant.id_culture = pc.avant
                                AND tc_cipan.id_culture = pc.intermediaire
                                AND tc_apres.id_culture = pc.apres
                                AND pc.dte_fin IS NULL
                       ORDER BY id_champ, id_parcelle) type_cultures
                WHERE     champ.id_champ IN (p_liste_champs) /* Ici passage de la liste des champs ! */
                      AND camp.id_campagne = p_campagne
                      AND lot_boue.id = camp.lot_boues
                      AND champ.id_exploitation = exploit.id_exploitation
                      AND com.id = champ.idtcom
                      AND liste_parcelles.id_champ(+) = champ.id_champ
                      AND type_cultures.id_parcelle(+) =
                             liste_parcelles.id_parcelle
             ORDER BY id_champ, num_sdea_champ, num_sdea_parcelle;
       END;
    Dans celle-ci, je voudrais passer un tableau de chaînes (les identifiants sont en varchar2) seulement, je ne vois pas trop comment faire ! Tout ce que j'ai trouvé implique de créer un type hors procédure mais qui demande alors de fixer la taille du tableau. J'ignore cependant la taille qu'aura cette liste. La procédure est appelée depuis une application web faite en ASP.Net/VB.Net.

    Comment puis-je faire s'il vous plaît ?


    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  2. #2
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    J'ai testé ceci:
    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
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
       PROCEDURE proc_liste_pratiques_epandages (
          p_campagne       IN     VARCHAR2,
          p_liste_champs   IN     VARCHAR2,
          p_cur               OUT r_cursor)
       IS
          TYPE tab_liste_champs IS TABLE OF t_champs.id_champ%TYPE;
     
          CURSOR r_liste_champs
          IS
             WITH t AS (SELECT p_liste_champs c FROM DUAL)
             SELECT EXTRACTVALUE (COLUMN_VALUE, '/x') AS id_champ
               FROM t,
                    TABLE (
                       XMLSEQUENCE (
                          EXTRACT (
                             XMLTYPE (
                                   '<list><x>'
                                || REPLACE (c, '|', '</x><x>')
                                || '</x></list>'),
                             '/list/x')));
     
          v_liste_champs   tab_liste_champs;
          v_row            t_champs.id_champ%TYPE;
          i                NUMBER := 0;
       BEGIN
          /* Remplissage d'un tableau avec la liste des champs passés en paramètre */
          OPEN r_liste_champs;
     
          LOOP
             FETCH r_liste_champs INTO v_row;
     
             v_liste_champs.EXTEND;
             v_liste_champs (i) := v_row;
             i := i + 1;
          END LOOP;
     
          CLOSE r_liste_champs;
     
          /* Fin remplissage */
     
     
          OPEN p_cur FOR
               SELECT DISTINCT
                      champ.id_champ,
                      lot_boue.dp,
                      lot_boue.dr,
                      champ.num_sdea AS num_sdea_champ,
                      liste_parcelles.id_parcelle AS id_parcelle,
                      liste_parcelles.num_sdea AS num_sdea_parcelle,
                      champ.ilot_num_pac AS num_ilot,
                      champ.cad_lieu_dit AS lieu_dit,
                      com.nom AS commune,
                      exploit.id_exploitation,
                      exploit.nom_exploitation,
                      champ.champ_surf_declaree AS surface_totale,
                      DECODE (liste_parcelles.num_sdea,
                              '', '',
                              liste_parcelles.surface)
                         AS surface_parcelle,
                      DECODE (liste_parcelles.num_sdea,
                              '', champ.champ_surf_epandable,
                              liste_parcelles.surface)
                         AS surface_epandable,
                      DECODE (liste_parcelles.num_sdea,
                              '', champ.champ_surf_epandable,
                              liste_parcelles.surface)
                         AS surface_a_epandre,
                      type_cultures.id_culture_avant,
                      type_cultures.lib_culture_avant,
                      type_cultures.id_culture_intermediaire,
                      type_cultures.lib_culture_intermediaire,
                      type_cultures.id_culture_apres,
                      type_cultures.lib_culture_apres
                 FROM t_champs champ,
                      t_exploitations exploit,
                      v_communes com,
                      epf.lpe lot_boue,
                      t_campagnes_epandages camp,
                      (  SELECT DISTINCT id_parcelle,
                                         id_champ,
                                         surface,
                                         num_sdea
                           FROM t_parcelles_culturales
                       ORDER BY id_champ, num_sdea) liste_parcelles,
                      (  SELECT DISTINCT
                                pc.id_parcelle,
                                pc.id_champ,
                                pc.dte_fin,
                                pc.avant AS id_culture_avant,
                                tc_avant.lib AS lib_culture_avant,
                                pc.intermediaire AS id_culture_intermediaire,
                                tc_cipan.lib AS lib_culture_intermediaire,
                                pc.apres AS id_culture_apres,
                                tc_apres.lib AS lib_culture_apres
                           FROM t_parcelles_culturales pc,
                                t_type_culture tc_avant,
                                t_type_culture tc_cipan,
                                t_type_culture tc_apres
                          WHERE     tc_avant.id_culture = pc.avant
                                AND tc_cipan.id_culture = pc.intermediaire
                                AND tc_apres.id_culture = pc.apres
                                AND pc.dte_fin IS NULL
                       ORDER BY id_champ, id_parcelle) type_cultures
                WHERE     champ.id_champ IN (v_liste_champs)
                      AND camp.id_campagne = p_campagne
                      AND lot_boue.id = camp.lot_boues
                      AND champ.id_exploitation = exploit.id_exploitation
                      AND com.id = champ.idtcom
                      AND liste_parcelles.id_champ(+) = champ.id_champ
                      AND type_cultures.id_parcelle(+) =
                             liste_parcelles.id_parcelle
             ORDER BY id_champ, num_sdea_champ, num_sdea_parcelle;
       END;
    Mais j'ai cette erreur
    [Warning] ORA-24344: opération réussie avec erreur de compilation
    406/42 PLS-00642: types de collecte locale interdite dans les instructions SQL
    (2: 0): Warning: compiled but with compilation errors
    On dirait que la base n'aime pas trop
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  3. #3
    McM
    McM est déconnecté
    Expert éminent

    Homme Profil pro
    Développeur Oracle
    Inscrit en
    Juillet 2003
    Messages
    4 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Développeur Oracle

    Informations forums :
    Inscription : Juillet 2003
    Messages : 4 580
    Points : 7 740
    Points
    7 740
    Billets dans le blog
    4
    Par défaut
    Il y a une façon que j'ai l'habitude de coder (j'ai pas retrouvé mes posts sur ce forum où je l'ai donné).
    Peut être que ça ne t'ira pas si tu as un tableau important.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    WHERE INSTR(';'||liste_param ||';',  ';'|| colonne ||';') > 0
    Avec liste_param = 'valeur1;valeur2;valeur3'

    Quelques inconvénients :
    1/ séparateur interdit dans les valeurs
    2/ pas d'utilisation index


    Sinon, pour faire des jointures directement avec un tableau, il faut passer par des type record et une selection from table(...). Exemple
    More Code : More Bugs. Less Code : Less Bugs
    Mon Blog PL/Sql : Fichier Zip / Image BMP / Lire sqliteDB / QRCode et Images PNG ou BMP

  4. #4
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Je reste perplexe
    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

  5. #5
    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 un type collection de type table imbriquée (nested table) pour le paramètre de la procédure ou construisez votre requête dynamiquement (peu recommandé).

  6. #6
    Expert confirmé
    Profil pro
    Inscrit en
    Août 2008
    Messages
    2 947
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Août 2008
    Messages : 2 947
    Points : 5 846
    Points
    5 846
    Par défaut
    Je ne comprends pas, vous avez déjà :
    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
    SQL> WITH t AS (SELECT 'a|b|c' c FROM DUAL)
      2           SELECT EXTRACTVALUE (COLUMN_VALUE, '/x') AS id_champ
      3             FROM t,
      4                  TABLE (
      5                     XMLSEQUENCE (
      6                        EXTRACT (
      7                           XMLTYPE (
      8                                 '<list><x>'
      9                              || REPLACE (c, '|', '</x><x>')
     10                              || '</x></list>'),
     11                           '/list/x')));
     
    ID_CHAMP
    --------------------------------------------------------------------------------
    a
    b
    c
     
    SQL>
    Du coup je ne vois pas l'intérêt de mettre le résultat dans une collection, il suffit d'utiliser le résultat directement dans la requête, non ?
    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
      WITH t AS (SELECT p_liste_champs c FROM DUAL),
           v_liste_champs as (
    SELECT EXTRACTVALUE (COLUMN_VALUE, '/x') AS id_champ
      FROM t,
           TABLE (
                  XMLSEQUENCE (
                          EXTRACT (
                             XMLTYPE (
                                   '<list><x>'
                                || REPLACE (c, '|', '</x><x>')
                                || '</x></list>'),
                             '/list/x')))
    )
    SELECT DISTINCT champ.id_champ,
           lot_boue.dp,
    ...
      WHERE champ.id_champ IN (select id_champ from v_liste_champs)
    ...

  7. #7
    Rédacteur
    Avatar de Franck.H
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Janvier 2004
    Messages
    6 951
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : France, Haut Rhin (Alsace)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : Service public

    Informations forums :
    Inscription : Janvier 2004
    Messages : 6 951
    Points : 12 462
    Points
    12 462
    Par défaut
    Oui c'est vrai, je suis aller sur quelque chose de plus compliqué


    Mon Site
    Ma bibliothèque de gestion des chaînes de caractères en C

    L'imagination est plus importante que le savoir. A. Einstein

    Je ne répond à aucune question technique par MP, merci d'avance !

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

Discussions similaires

  1. Problème de tableau pour un exercice en C++
    Par tigresses57 dans le forum C++
    Réponses: 14
    Dernier message: 05/03/2006, 23h27
  2. [HTML] Tableau pour l'enregistrement des données
    Par ghyosmik dans le forum Balisage (X)HTML et validation W3C
    Réponses: 13
    Dernier message: 01/11/2005, 15h28
  3. TABLEAU pour video
    Par kevinf dans le forum Balisage (X)HTML et validation W3C
    Réponses: 4
    Dernier message: 11/10/2005, 19h29
  4. Problème tableau pour une requête
    Par LE NEINDRE dans le forum Langage
    Réponses: 2
    Dernier message: 07/10/2005, 20h21
  5. [VB.NET] Quel objet tableau pour une recherche indexée ???
    Par Kitano dans le forum Windows Forms
    Réponses: 7
    Dernier message: 02/09/2004, 09h38

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