Possibilité d'écrire une requête d'un Recordset

Molenn Messages postés 797 Date d'inscription mardi 7 juin 2005 Statut Membre Dernière intervention 23 février 2011 - 20 nov. 2006 à 12:21
Molenn Messages postés 797 Date d'inscription mardi 7 juin 2005 Statut Membre Dernière intervention 23 février 2011 - 20 nov. 2006 à 15:44
Bonjour,

J'ai un petit soucis d'optimisation d'une requête SQL, et je me dis que vous auriez peut être une idée à me proposer. Je n'ai pas trouvé mon bonheur dans le moteur de recherche, si sur les quelques sites WEb qui jusque là, m'avaient bien aidé à apprendre le SQL et le VBScript donc ...
Je vous expose vite fait mon cas :

Ce que je fais actuellement :
J'interroge une base de donnée située sur un réseau d'entreprise via un VBScript de cette forme :


Set objDBConnection = WScript.CreateObject("ADODB.Connection")
Set RS = WScript.CreateObject("ADODB.Recordset")
objDBConnection.open Blablablabla ...
SQL = "SELECT * FROM ... blablabla"
RS.open SQL,objDBConnection,1,1

Tout cela fonctionne nickel, mon soucis, c'est que entre la création de la requête et l'ouverture du recorset, pour me remonter une 20aine d'enregistrements, il se passe déjà 20 sec, ce qui est énorme pour une base de données ou tout le monde tape déjà allègrement, occasionnant sur l'appli en dépendant des temps de réponse pourris. Et comme mon script est appelé à tourner souvent.
Si je réduis mes critères de sélection, j'arrive à descendre à 3-4 s ce qui est déjà plus acceptable, mais j'ai 450 enregistrements.

Ma question :
Dans une requête faite sous ACCESS par exemple, je sais que je peux faire un SELECT * From Nom de table ou Nom de requête.
Est-ce que je peux en VBScript faire une interrogation d'un recordset ?

Je m'explique, si je crée un premier recordset "global" qui me remonte les 450 enregistrements "globaux", est-ce que je peux ouvrir un 2nd recorset avec une requête SQL qui va prendre pour table de données cette fois le contenu de mon 1er recordset ?

Est-ce que je suis sur une bonne piste ? Je suppose qu'une fois mon 1er recordset ouvert, les enregistrements sont chargés dans la mémoire de mon PC en local, donc, si je viens interroger ce recordset, je ne vais plus taper dans la base de données SQL Server sur le réseau ? Parce que ce n'est pas le temps de réponse à proprement parler qui me pose soucis, c'est le fait que ça vienne ralentir une base de données déjà "à risque" dans la boîte.

Si vous voyez d'autres possibilités, n'hésitez pas, mais je me doute que sans ma requête, vous ne pourrez pas m'en dire grand chose . J'ai plein de OR dans mes critères, et je n'ai pas de moyens de m'en passer (Les OR concerne des champs différents, pas seulement le contenu d'un seul champ).

D'avance merci

Molenn

2 réponses

cs_skweeky Messages postés 259 Date d'inscription mercredi 3 mai 2006 Statut Membre Dernière intervention 11 janvier 2010 8
20 nov. 2006 à 13:41
Bonjour,

Pour la première question, est ce l'on peut utiliser les données d'un RecordSet dans un second la réponse est oui, mais avec plus ou moins de facilité avec ADO... en recherchant sur Internet "Disconnected Recordset" "adLockBatchOptimistic" je pense qu'il facilement possible de trouver la méthode pour le faire (on déconnecte le RecordSet 1 ou le clone, etc.)

Pour les problèmes de performance il manque des éléments, il y 3 paramètres à prendre en compte :
CursorType = adOpenForwardOnly
LockType = adLockReadOnly ou adLockBatchOptimistic (pour le cas du RS déconnecté)
CursorLocation = adUseClient

Qui sont 3 propriétés d'un RecordSet on fonction de la valeur des 3, l'emplacement des données peut changer... la manière d'interroger les données elle aussi, etc... Dans ce cas vous avez renseigné 1 et 1 ce qui correspond à KeySet et ReadOnly (le 3ème je ne sais pas)... Ce n'est pas la meilleure méthode d'accès le mieux étant ce que je mets ci dessus pour l'accès en lecrture seule. Pour des accès nécessitant des modification c'est un peu plus compliqué, l'aide sur ADO montre des exemples...

Cordialement,

Christian Robert - Winwise
http://blogs.developpeur.org/christian/
MCT - Database Development / Database Administration
0
Molenn Messages postés 797 Date d'inscription mardi 7 juin 2005 Statut Membre Dernière intervention 23 février 2011 7
20 nov. 2006 à 15:44
D'abord, merci pour la réponse ... Je viens de passer une bonne heure à fouiller le net, et j'ai appris des tas de trucs , mais je ne vois pas comment l'appliquer à mon cas.

Effectivement, la possibilité de travailler avec un recordset déconnecté pourrait être intéressante pour moi, mais ce n'est pas le noeud de mon pb. En effet, que mon objet Recordset soit connecté ou non, je ne peux pas l'interroger pour créer un nouveau recordset.

Je suis ensuite parti sur les objets QueryDef (on peut créer des QueryDef temporaire) et TableDef (mais là, inutilisable : j ene veux surtout pas créer de nouvelles tables dans la base).

La méthode GetRow pourrait m'intéresser, je créer mon recordset et je sors tous les enregistrements dans un tableau qui est en quelque sorte, l'image à plat de mon recordset, et donc, quelque part, la "mini" base de données sur laquelle je veux travailler. Mais je ne vois pas comment faire l'équivalent de ma requête dedans, sauf à créer des boucles contrôlant chaque enregistrement du tableau. Mais bon, 5 boucles imbriquées pour vérifier un tableau qui fait 500 lignes sur 37 colonnes, je ne suis pas fan ^^

Je vais essayer d'illustrer plus précisément ce que je veux faire.

Table Clients
Ville      Dpt      Region                  Profession
Rennes   35      Bretagne               Artisan
Lorient   56      Bretagne               Ouvrier
Paris      75      Ile de France         Artisan
Nantes   44      Pays de la Loire      Artisan

Ma requête telle qu'elle est faite actuellement, correspondrait à :
Set objDBConnection = WScript.CreateObject("ADODB.Connection")
Set RS = WScript.CreateObject("ADODB.Recordset")
objDBConnection.open Blablablabla ...SQL "SELECT * FROM Clients WHERE ((Region 'Bretagne) OR (Dpt ='44') AND (Profession = 'Artisan'))"
RS.open SQL,objDBConnection,1,1

Ce qui fait donc que j'ai crée un recordset RS, qui contient les infos suivantes :
Rennes   35      Bretagne               Artisan
Nantes   44      Pays de la Loire      Artisan
C'est cette requête qui me prend 20 secondes.

Voici ce que j'aimerai réussir à faire :
Set objDBConnection = WScript.CreateObject("ADODB.Connection")
Set RS = WScript.CreateObject("ADODB.Recordset")
objDBConnection.open Blablablabla ...SQL "SELECT * FROM Clients WHERE (Profession 'Artisan')"
RS.open SQL,objDBConnection,1,1
Le Recordset RS crée contient
Rennes   35      Bretagne               Artisan
Paris      75      Ile de France         Artisan
Nantes   44      Pays de la Loire      Artisan
Cette requête ne me prend que 3-4 secondes (ce qui est acceptable cette fois).

A ce niveau, je pourrais couper la connection pour être sûr de ne plus toucher à ma base de données, et je voudrais pouvoir ouvrir un recordset du type : SQL "SELECT * FROM RS WHERE ((Region 'Bretagne) OR (Dpt ='44'))"
RSBis.open SQL,objDBConnection,1,1
Là, à la rigueur, que ça prenne 10, 15 ou même 20 secondes, ça n'a aucune importance puisque je suis en local sur mon poste.

Crée un QueryDef me semblait une piste intéressante, pour remplacer mon RS. Mais si j'ai bien compris, un QueryDef, c'est juste une requête donc, les enregistrements ne sont pas inclus et si je l'interroge, en fait, je vais recrée ma requête entière et donc, je n'aurais rien gagné.

Je ne sais pas si je suis très clair en fait, je m'en rends compte
Sinon, et bien, il me restera la solution d'extraire ma requête initiale dans un fichier Excel ou une Base ACCESS et refaire tous mes tris derrière, mais je voudrais limiter au maximum les manips.

Merci.

Molenn
0
Rejoignez-nous