DECOMPOSITION SQL - ALGORITHME SIMPLE ET EFFICACE

cs_vladam Messages postés 216 Date d'inscription dimanche 13 janvier 2002 Statut Modérateur Dernière intervention 7 novembre 2009 - 21 oct. 2008 à 09:43
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009 - 30 oct. 2009 à 16:22
Cette discussion concerne un article du site. Pour la consulter dans son contexte d'origine, cliquez sur le lien ci-dessous.

https://codes-sources.commentcamarche.net/source/48263-decomposition-sql-algorithme-simple-et-efficace

cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
30 oct. 2009 à 16:22
@Yan35: Je précise bien dans le code que je m'intéresse uniquement aux syntaxes de la forme Transform ... select ... from ... where .... group by ... having ..., order by ... pivot ....
Le but n'est même pas de vérifier l'exactitude de la SQL, mais une décomposition dans le but de changer les paramètres des clauses.
Dans mon cas, j'ai un composant datagrid perso, qui permet d'afficher un recordset à partir de CommandText et de ConnectionString que j'utilise beaucoup pour afficher les tables filles, multi-requetage de liste, ...
Au lieu de charger toute la table et actualiser avec la méthode Filter qui rendrait le programme très lourd, j'ai besoin de passer à mon composant un critère externe. Mais les applications sont encore plus complexe, vu que je permet à chaque utilisateur d'avoir sa propre mise en forme de liste, disposition des colonnes et taille, c'est tout simple, je garde dans une table les valeurs de ColumnWithts, et la clause Select.

D'autre part la méthode Init permet de spécifier les délimiteurs de champs, par défaut c'est "[" et "]".

En déhors de l'aspect pratique de la source, l'algorithme utilisé est surtout le point important à assimiler.

A+
yan35 Messages postés 185 Date d'inscription dimanche 29 juin 2003 Statut Membre Dernière intervention 20 juin 2013
27 oct. 2009 à 02:22
Bonjour Asimengo et merci pour ce code.
Je viens de le tester car j'y trouve de l'intérêt notamment pour écrire plusieures requêtes qui se ressemblent et éviter de toutes les réécrire en assemblant les clauses similaires, par exemple la clause From qui peut être la même dans plusieurs recordsets qui eux se distingueraient par Select et Where, par exemple.
J'ai 2 remarques à faire : ton code ne fonctionne plus s'il y a des sous-requêtes inclues dans les différentes clauses ; tes séparateurs [ ] sont valables pour Access ou autres mais pas pour MySQL et sans doute d'autres SGBD.
Sinon je trouve dommage sur 284 téléchargements à cette date, personne ne t'a attribué de note.
Je mets 7/10 pour les remarques communiquées.
Cordialement
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
22 oct. 2008 à 14:25
Merci EBARTSOFT, venant de toi c'est un grand compliment.
cs_EBArtSoft Messages postés 4525 Date d'inscription dimanche 29 septembre 2002 Statut Modérateur Dernière intervention 22 avril 2019 9
22 oct. 2008 à 12:57
Je remercie asimengo pour perpetuer la tradition du VB6.
Et en plus c'est plutôt bien fait.

@+
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
22 oct. 2008 à 11:45
@Vladam: Je n'ai pas bien compris, en effet je ne cherches qu'à savoir plus si tu pouvais être plus explicite. Je profite également pour ajouter un autre intérêt de la decomposition SQL c'est de pouvoir ajouter/modifier des légendes ou les traduires dans une langue. Il suffira de rajouter des mots clés et après avoir identifier les captions, lire dans une table dictionnaire pour traduire en fonction de la langue choisie au démarrage de l'applis.

Je profite pour corriger un manquement dans la fonction TransformSQL
Remplacer "bParenthesisOpen As Boolean" par "lParenthesisOpen As Long"
et dans le corps de la procédure on aura plutôt
Select Case sCar
Case "(": lParenthesisOpen = lParenthesisOpen + 1
Case ")": lParenthesisOpen = lParenthesisOpen - 1
Case ",":
If (Not bNameBegin) And (lParenthesisOpen = 0) Then
...

NB :
Le but de cette source n'est pas de vérifier la validité d'une SQL mais de la decomposer en supposant qu'à l'origine elle est valide. Sa grande utilité est de permettre l'optimisation des resultats de recordset.
Pour mon utilisation j'ai 2 méthodes la méthodes Refresh qui va faire un .Filter et un .Sort sur les variables sFiltre et sSort et la méthode Requery qui va reécrer la SQL en incluant sFiltre et sSort dans la SQL.

C'est dommage de ne pas avoir des retours d'utilisation qui bien évidemment permettent de faire évoluer le code et surtout d'avoir les mises à jour sinon certaines mises à jour ne se voient pas reloader.
cs_vladam Messages postés 216 Date d'inscription dimanche 13 janvier 2002 Statut Modérateur Dernière intervention 7 novembre 2009
21 oct. 2008 à 14:24
en effet, c'est plus claire.
Je comprends mieux l'utilité de ton code.
Personnellement, j'aurais plutôt utilisé une architecture basée sur l'implémentation d'interce pour rester générique et adaptable, mais ta solution est défendable aussi.
cs_asimengo Messages postés 280 Date d'inscription jeudi 24 mars 2005 Statut Membre Dernière intervention 18 mars 2009
21 oct. 2008 à 11:48
@Vladam: C'est sûr tu n'as rien compris. Je t'explique.

Moi je travaille avec des composants independants, ce qui suppose qu'à la base il ne sait pas quel paramètre il recevra. Alors pour mon composant permettant d'afficher les données d'une base de données, il recoit en paramètres la SQL (CommandText) et la connectionString. Maintenant supposons que nous avons un combo dont la sélection entraine un filtre de la liste.
Solution evidente, tu me diras de mettre des indicateurs dans la SQL de la liste à afficher de facon à former facilement la SQL filtrée. MAis dans mon cas il s'agit d'un composant indépendant qui ne sait pas à priori le contenu de la SQL.
Autre méthode si la liste est dans un datagrid, il suffit de lier le datagrid.datasource au Recordset resultant de la commande et apres de faire un filter. Super ca marche mais lorsque la liste à afficher sans filtre contient 30 000 enregistrements alors on comprend vite qu'il y'a un problème.
Mon composant permet de jouer avec la SQL et la liste est optimale.
Il suffit pour moi de definir la methode Init pour passer la SQL, Criteria definir une condition et la méthode Requery et tout est propre et bien.

De même comme dans mon cas si tu dois permettre à l'utilisateur de choisir les champs visibles, definir son tri et definir ses filtres. A moins de connaitre explicitement la SQL ce n'est pas evident.
Eh bien j'ai egalement un composant qui recoit en parametres une SQL, pour t'afficher un form avec onglets (Colonnes, Tri, Fitre) libre à l'utilisateur de bidouiller après le composant peut renvoyer la SQL resultat ou tous les paramètres afin que le programmeur en fasse ce qu'il veut.

Ca devrait être déjà assez clair à ce niveau je crois.
cs_vladam Messages postés 216 Date d'inscription dimanche 13 janvier 2002 Statut Modérateur Dernière intervention 7 novembre 2009
21 oct. 2008 à 09:43
heu ..... mais ou est l'intérêt ?
ou je n'ai peut-être pas tout compris
Rejoignez-nous