Bonjour,
Quelqu'un a t-il dans ses cartons un code PL/SQL permettant de parser une requête SQL ?
c'est à dire d'analyser un ordre Select et d'en ressortir la liste des colonnes qui le constitue ?
Bonjour,
Quelqu'un a t-il dans ses cartons un code PL/SQL permettant de parser une requête SQL ?
c'est à dire d'analyser un ordre Select et d'en ressortir la liste des colonnes qui le constitue ?
Je comprends ce que tu veux dire mais je vois pas trop ce que cela devrait te resortir.
Tu veux un code PL/SQL qui quand tu lui donne un ordre select te resorte les colonnes utilisé dans la clause select????
Oui exactement. Et pour ce faire je ne peux pas tricher en créant une vue ou une table pour en extraire les colonnes....
Il me faut donc un analyseur qui sache se dépatouiller de trucs du genre :
Code : Sélectionner tout - Visualiser dans une fenêtre à part Select * from (select x "aliasx", y from .... ) ...
Et bien, pour ne rien te cacher, cela m'enlèverait un poteau télégraphique du pied !!!![]()
ouch... alors là c'est fort de fort... j'crois que je vais tenter aussi de relever le défis
aller hop... au boulot![]()
Merci pour ces chaleureux témoignages de trituration de matière grise les gars.
D'habitude je suis le premier à m'y coller, mais pour le coup, j'ai trop d'autres portions de code à décerveller en peu de temps...
tiens regarde avec ca...
Ca te renvoie une table pl/sql contenant les différentes colonnes (c un peu lent vu que je vais chercher dans all_tab_columns
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 FUNCTION parse_sql(p_requete VARCHAR2) RETURN owa_text.vc_arr IS v_mot owa_text.vc_arr; v_pos_espace NUMBER; v_cpt NUMBER := 1; v_requete VARCHAR2(32676) := p_requete; v_owner VARCHAR2(50); v_name VARCHAR2(50); CURSOR cur_col(p_name VARCHAR2) IS SELECT owner || '.' || column_name FROM all_tab_columns WHERE column_name = upper(p_name); CURSOR cur_col2(p_name VARCHAR2, p_owner VARCHAR2) IS SELECT owner || '.' || column_name FROM all_tab_columns WHERE column_name = upper(p_name) AND owner = upper(p_owner); v_colonne VARCHAR2(200); t_col owa_text.vc_arr; BEGIN -- On recherche le premier espace v_pos_espace := instr(v_requete, ' '); LOOP EXIT WHEN v_pos_espace = 0; --On extrait le premier mot v_mot(v_cpt) := REPLACE(substr(v_requete, 1, v_pos_espace), ' ', ''); v_cpt := v_cpt + 1; v_requete := substr(v_requete, v_pos_espace + 1); v_pos_espace := instr(v_requete, ' '); END LOOP; v_mot(v_cpt) := v_requete; v_cpt := 1; FOR i IN 1 .. v_mot.COUNT LOOP -- On ne tiens pas compte des mots clé standard IF lower(v_mot(i)) NOT IN ('select', 'from', 'where', 'group', 'by', 'order', 'having', '(', ')') THEN -- on vérifie si y a un point à l'interieur du mot IF instr(v_mot(i), '.') = 0 THEN OPEN cur_col(v_mot(i)); FETCH cur_col INTO v_colonne; CLOSE cur_col; ELSE v_owner := substr(v_mot(i), 1, instr(v_mot(i), '.')); v_name := substr(v_mot(i), instr(v_mot(i), '.') + 1); OPEN cur_col2(v_name, v_owner); FETCH cur_col2 INTO v_colonne; CLOSE cur_col2; END IF; --on enregistre le nom de la colonne IF v_colonne IS NOT NULL THEN t_col(v_cpt) := v_colonne; v_cpt := v_cpt + 1; v_colonne := NULL; END IF; END IF; END LOOP; return t_col; END;
Je peux compliquer apres en faisant une recherche sur les tables contenues dans la requete mais comme tu as pas précisé
Diantre, quelle vélocité !!
j'essaie le matos.
Le select dans les vues système implique que les bidouilles de type :
select col * 2 "comptage" ne passera pas ?
Alors sur ton exemple de requete il ne te retournera que le col
j'ai fait plus simple :
Voila comment j'ai trouvé
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 declare stmt VARCHAR2(2000); c number; d number; col_cnt integer; f boolean; rec_tab dbms_sql.desc_tab2; rec_desc dbms_sql.desc_rec2; col_num number; begin c := dbms_sql.open_cursor; stmt := 'select * from matable'; dbms_sql.parse(c,stmt, DBMS_SQL.NATIVE); d := dbms_sql.execute(c); dbms_sql.describe_columns2(c, col_cnt, rec_tab); /* * Following loop could simply be for j in 1..col_cnt loop. * Here we are simply illustrating some of the PL/SQL table * features. */ col_num := rec_tab.first; if (col_num is not null) then loop dbms_output.put_line('col_name = ' || rec_tab(col_num).col_name); col_num := rec_tab.next(col_num); exit when (col_num is null); end loop; end if; dbms_sql.close_cursor(c); end; /
http://download-west.oracle.com/docs/cd/B10501_01/appdev.920/a96612/d_sql.htm#1006465
A noter que describe_columns est buggé d'où l'utilisation de describe_columns2![]()
cela fonctionne parfaitement sur la requête de type :Envoyé par helyos
Je vais virer le nom du OWNER récupéré dans la collection et prendre en compte de préférence les alias s'ils sont indiqués dans la requête.
Code : Sélectionner tout - Visualiser dans une fenêtre à part select * from (select code from p_periodes where statut_stat=''O'' order by exercice_code desc, numero desc)
Super !! et merci
je m'en vais du même coup tester la propal d' orafrance.
si ma requête ne marche pas... bah j'aurais quand même appris un sacré truc avec DBMS_SQL
Et bravo à helyos qui décidemment est une star du PL/SQL![]()
LOL merci par contre la méthode d'orafrance sera plus performante sur une requete de type SELECT * sans clause where (vu que ca execute le code, plus besoin de regarder si c une colonne connue comme dans mon code)
Bravo à toi aussi orafrance
Ta requête fonctionne parfaitement, cher orafrance et de surcroit prend en compte les alias ! c'est du caviard !!!Envoyé par orafrance
Merci à vous deux, vous venez effectivement de m' enlever un poteau télégraphique du pied !!!
A charge de revanche.
Et bien c'est génial
Quand au poteau, attention où tu le mets![]()
Benff, cmouf'étais en train, chlourmpf, de finir ma bouchée, shlurpf, de caviar, groumpf.....
Partager