Vous ne trouvez pas de réponse à votre problème ? Alors posez la question dans le forum. Souvenez-vous qu'il n'y a jamais de question bête, mais rester dans l'ignorance parce que l'on n'ose pas poser une question, ça c'est une erreur !

DECOMPOSITION SQL - ALGORITHME SIMPLE ET EFFICACE


Description

Cliquez pour voir la capture en taille normale
Une DLL qui permet de décomposer un texte SQL ou de jouer avec et d'avoir la décomposition de chaque Clause.

Pour mon utilisation perso je n'ai pas vraiment besoin de scruter le contenu de la clause From, raison pour laquelle la méthode utilisée pour le traitement de la clause From a des manquements et des limites. J'en ai plus besoin pour mon contrôle qui permet de visualiser des recordsets par passage des paramètres de CommandText et ConnectionString et Criteria.
De ce fait au lieu de Charger la Commande et après faire un .Filter=..., qui n'est pas optimisé je charge directement la commande ajustée sur les bons enregistrements.
Le problème également est que je dois compter les enregistrements, .MoveLast aprés .MoveFirst, il vaut mieux dans tous les cas avoir moins d'enregistrements à parcourir.

En réalité

J'ai ajouté à la propriété get SQL la possibilité de rajouter des valeurs dans les clauses WHERE, HAVING et ORDER BY de la SQL initiale.La propriété Let SQL permet de passer des paramètres jouant également sur les clauses citées plus haut.
On peut reinitialiser les critères et le tri.

L'algorithme utilisé est assez simple, le texte est préformaté en un passage de la chaine SQL et après la lecture devient aisé. Le principe de cette algorithme peut être réutilisé dans bien des cas.

Comme dab, vos commentaires seraient les bienvenus afin que je puisse optimiser le code.

 

Source

  • 'méthode Init de la Classe
  • Public Function Init(ByVal psSQL As String, _
  • Optional ByVal psLeftNameSeparator As String, _
  • Optional ByVal psRightNameSeparator As String, _
  • Optional ByVal psTextIdentificator As String)
  • If psLeftNameSeparator <> vbNullString Then msLeftNameSeparator = psLeftNameSeparator
  • If psRightNameSeparator <> vbNullString Then msRightNameSeparator = psRightNameSeparator
  • If psTextIdentificator <> vbNullString Then msTextIdentificator = psTextIdentificator
  • msSQL = TransformSQL(psSQL)
  • 'Pour mes besoins actuels, je ne joue qu'avec les instructions de la forme
  • ' SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
  • ' au mieux avec TRANSFORM ... SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... PIVOT ...
  • Call ExtraitVariable("PIVOT", msPivot)
  • Call ExtraitVariable("ORDER BY", msOrderBy)
  • Call ExtraitVariable("HAVING", msHaving)
  • Call ExtraitVariable("GROUP BY", msGroupBy)
  • Call ExtraitVariable("WHERE", msWhere)
  • Call ExtraitVariable("FROM", msFrom)
  • Call ExtraitVariable("SELECT", msSelect)
  • Call ExtraitVariable("TRANSFORM", msTransform)
  • End Function
  • 'Propriétés de la classe
  • Public Property Get SQL(Optional ByVal psWhereCriteria As String, _
  • Optional ByVal psHavingCriteria As String, _
  • Optional ByVal psSort As String) As String
  • Public Property Let SQL(Optional ByVal psWhereCriteria As String, _
  • Optional ByVal psHavingCriteria As String, _
  • Optional ByVal psSort As String, ByVal psSQL As String)
  • Public Property Get SQLTransform(Optional ByRef psField As String, Optional ByRef psCaption As String) As String
  • Public Property Get SQLSelect(Optional ByRef psPredicate As String, Optional ByRef paFields As Variant, Optional ByRef paCaptions As Variant) As String
  • 'Propriété Get SQLFrom
  • 'paTables est un tableau des tables utilisées dans la SQL
  • 'paRelationShips est un tableau des relations
  • 'L'algorithme utilisée pour pour cette proprité a des limites certes mais permet de retrouver nos petits dans bien des cas
  • Public Property Get SQLFrom(Optional ByRef paTables As Variant, Optional ByRef paRelationShips As Variant) As String
  • Public Property Get SQLWhere() As String
  • Public Property Let SQLWhere(ByVal psSQLWhere As String)
  • Public Property Get SQLGroupBy(Optional ByRef paFields As Variant) As String
  • Public Property Get SQLHaving() As String
  • Public Property Let SQLHaving(ByVal psSQLHaving As String)
  • Public Property Get SQLOrderBy(Optional ByRef paFields As Variant) As String
  • Public Function ClearOrderBy()
  • Public Property Get SQLPivot(Optional ByRef psField As String, Optional ByRef paColumnsNames As Variant) As String
'méthode Init de la Classe
Public Function Init(ByVal psSQL As String, _
    Optional ByVal psLeftNameSeparator As String, _
    Optional ByVal psRightNameSeparator As String, _
    Optional ByVal psTextIdentificator As String)

    If psLeftNameSeparator <> vbNullString Then msLeftNameSeparator = psLeftNameSeparator
    If psRightNameSeparator <> vbNullString Then msRightNameSeparator = psRightNameSeparator
    If psTextIdentificator <> vbNullString Then msTextIdentificator = psTextIdentificator
    
    msSQL = TransformSQL(psSQL)
    
    'Pour mes besoins actuels, je ne joue qu'avec les instructions de la forme
    ' SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ...
    ' au mieux avec TRANSFORM ... SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY ... PIVOT ...

    
    Call ExtraitVariable("PIVOT", msPivot)
    Call ExtraitVariable("ORDER BY", msOrderBy)
    Call ExtraitVariable("HAVING", msHaving)
    Call ExtraitVariable("GROUP BY", msGroupBy)
    Call ExtraitVariable("WHERE", msWhere)
    Call ExtraitVariable("FROM", msFrom)
    Call ExtraitVariable("SELECT", msSelect)
    Call ExtraitVariable("TRANSFORM", msTransform)
    
End Function

'Propriétés de la classe
Public Property Get SQL(Optional ByVal psWhereCriteria As String, _
    Optional ByVal psHavingCriteria As String, _
    Optional ByVal psSort As String) As String

Public Property Let SQL(Optional ByVal psWhereCriteria As String, _
    Optional ByVal psHavingCriteria As String, _
    Optional ByVal psSort As String, ByVal psSQL As String)

Public Property Get SQLTransform(Optional ByRef psField As String, Optional ByRef psCaption As String) As String

Public Property Get SQLSelect(Optional ByRef psPredicate As String, Optional ByRef paFields As Variant, Optional ByRef paCaptions As Variant) As String

'Propriété Get SQLFrom
'paTables est un tableau des tables utilisées dans la SQL
'paRelationShips est un tableau des relations
'L'algorithme utilisée pour pour cette proprité a des limites certes mais permet de retrouver nos petits dans bien des cas
Public Property Get SQLFrom(Optional ByRef paTables As Variant, Optional ByRef paRelationShips As Variant) As String

Public Property Get SQLWhere() As String

Public Property Let SQLWhere(ByVal psSQLWhere As String)

Public Property Get SQLGroupBy(Optional ByRef paFields As Variant) As String

Public Property Get SQLHaving() As String

Public Property Let SQLHaving(ByVal psSQLHaving As String)

Public Property Get SQLOrderBy(Optional ByRef paFields As Variant) As String

Public Function ClearOrderBy()

Public Property Get SQLPivot(Optional ByRef psField As String, Optional ByRef paColumnsNames As Variant) As String

Conclusion

Pour aider cette DLL à retrouver les noms de tables dans la clause From, il vaudrait mieux que les tables dans la clause From soient des crochets ([...])

J'espère avoir des avis qui me permettront de voir les manquements et surtout de l'optimiser.

ASIMENGO
 

Fichier Zip

Pour les "Membres Club", vous pouvez télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip

Commentaires et avis

signaler à un administrateur
Commentaire de vladam le 21/10/2008 09:43:09 administrateur CS

heu ..... mais ou est l'intérêt ?
ou je n'ai peut-être pas tout compris

signaler à un administrateur
Commentaire de asimengo le 21/10/2008 11:48:16

@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.

signaler à un administrateur
Commentaire de vladam le 21/10/2008 14:24:45 administrateur CS

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.

signaler à un administrateur
Commentaire de asimengo le 22/10/2008 11:45:04

@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.

signaler à un administrateur
Commentaire de EBArtSoft le 22/10/2008 12:57:05 administrateur CS

Je remercie asimengo pour perpetuer la tradition du VB6.
Et en plus c'est plutôt bien fait.

@+

signaler à un administrateur
Commentaire de asimengo le 22/10/2008 14:25:33

Merci EBARTSOFT, venant de toi c'est un grand compliment.

Ajouter un commentaire

Discussions en rapport avec ce code source dans le forum

Algorithme de compression LZW [ par PhiPhi ] Je recherche un algorithme de compression LZW pour une application non commerciale, si possible disponible en vb5.0 ou vb6.0 avec le code source.code connexion ODBC [ par nds ] Je voudrais appeler un etat crystal report7 (.rpt) à partir d'un controle activeX "CrystalReport" dans VB et pouvoir modifier le requete SQL qui alime Probleme requete SQL [ par steph ] Bonjour à touscomment faire dans une requete SQL pour sélectionner des enregistrements avec une clause WHERE faisant référence à une TEXTBOX du formul Connection SQL et RDO [ par Linda ] Bonjour !Voici mon problème.Dans SQL Server j'ai créé un role d'application.Je voudrais connecter mon application à ce rôle comment dois-je faire ?Mer combo sous access [ par presseb ] J'ai un probleme sous un formulaire access un combo fait appel a un champs d'une base de données SQLQuand je supprime a l'aide d'une requete sql des c Requete SQL [ par funtay ] bonjour, j'ai un problème de syntaxe dans une requete SQL.En fait ,j'ai une date de début (c'est un maskedbox( txt_datedeb)) et une date de fin (c'est Commande SQL LIKE avec Access [ par Valere ] Dans un script ASP j'interroge une base access avec une requete de type select * from MaTable Where MonChamp Like 't*' et je me retrouve avec un recor Compter les enregistrements d'une requete SQL [ par JCLK ] Je travaille habituellement avec ColdFusion, et j'ai du mal a transformer mes programmes en ASP.Je voudrais compter les enregistrements d'une requete ASP, SQL et champ DATE [ par idev ] En ASP avec une base Access, la requete suivante ne fonctionne pas. Erreur de syntaxe. Tout essayer mais je ne trouve pas la bonne syntaxe.SQL = "INSE Insérer un gif dans une base SQL [ par Sabrina ] J'utilise ASP pour afficher des gifs pomper sur une base SQL7, et j'aimerais insérer avec VB mes gifs dans cette base via ODBC ...Merci ...


Nos sponsors

Sondage...

CalendriCode

Juillet 2009
LMMJVSD
  12345
6789101112
13141516171819
20212223242526
2728293031  

Consulter la suite du CalendriCode

Comparez les prix Nouvelle version

Photothèque Nouveau !



Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés
Temps d'éxécution de la page : 0,593 sec

Google Coop CodeS-SourceS Google Coop CodeS-SourceS


Certaines images présentes sur le site (notament certains avatars) sont issues des collections IconShock, donc si vous souhaitez utiliser ces icons vous devez les acheter, ne les copiez pas et ne utilisez pas dans vos sites et applications sans les avoir commandé.