Méthode simple qui consiste à lancer un shell (commande dos) puis à suivre le processus Windows jusqu'à ce qu'il se termine. La requête SQL contenu dans le Shell créée un fichier CSV comportant le résultat de la requête. Si c'est un requête "action", par exemple "Indexation", elle ne retourne rien. C'est très rapide, j'importe et indexe 10 millions de lignes de 50 caractères en 2 champs en moins de 20 min (1 GO de mémoire, travail en mode local). Chaque requête simple sur la base indéxée met ensuite moins de 35 s pour sortir un résultat!
Notez que l'on peut lancer le service Mysql, mais qu'il peut se trouver dans un état ni démarré ni arrèté. Il peut être en Pending par exemple. Il faut alors un timer pour tester son état. Si rien n'y fait, une seule solution existe à ma connaissance : killer le processus Mysql. C'est assez rare.
On peut le faire avec le gestionnaire de tàche.
Source / Exemple :
Declare Function OpenProcess Lib "kernel32" _
(ByVal dwDesiredAccess As Long, _
ByVal bInheritHandle As Long, _
ByVal dwProcessId As Long) As Long
Declare Function GetExitCodeProcess Lib "kernel32" _
(ByVal hProcess As Long, _
lpExitCode As Long) As Long
Public Const PROCESS_QUERY_INFORMATION = &H400
Public Const STILL_ACTIVE = &H103
Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Sub ShellAndWait(ByVal Pathname As String, Optional windowstate)
'Attention : Code très sensible
'Code permettant de suivre un processus windows pour savoir s'il est terminé
'Comme les requètes SQL sont lancés en mode batch, il faut savoir quand les requêtes se terminent
Dim hProg As Long
Dim hProcess As Long
Dim ExitCode As Long
'Renseigne le paramètre optionel et execute le programme
If IsMissing(windowstate) Then windowstate = 2
hProg = Shell(Pathname, windowstate)
'hProg est le process ID sous Win32.
'Pour obtenir le handle:
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, False, hProg)
Do
'Récupération de la variable Exitcode
GetExitCodeProcess hProcess, ExitCode
'Le sleep permet d'obtimiser la CPU
DoEvents: Sleep 100
'On boucle tant que le processus tourne
Loop While ExitCode = STILL_ACTIVE
End Sub
Function ServiceWinD(ByVal Pathname As String, ByVal ServiceName As String, ByVal MarcheArret As String)
'Code permettant de lancer un service Windows (par exemple le serveur Mysql)
Dim hProg As Long, Délais As Double
Dim Computer, ServiceSet, Service
Computer = "."
'Renseigne le paramètre optionel et execute le programme
hProg = Shell(Pathname, 2)
Délais = Time 'Timer qui permet de tout killer si le service ne se lance vraiment pas
'Récupère la liste des services actifs plusieurs fois car il y a un délais de mise à jour
LectureService:
Set ServiceSet = GetObject("winmgmts:{impersonationLevel=impersonate}!//" & _
Computer & "/root/cimv2").InstancesOf("Win32_Service")
'Test si le lancement est bon et récupère le premier élément
i = 1
For Each Service In ServiceSet
Temp = Service.displayname
Exit For
Next
Do
For Each Service In ServiceSet
If Temp = Service.displayname And i <> 1 Then
GoTo LectureService 'force à recharger la lecture des services
End If
i = i + 1 'Sert à sortir de la boucle quand on a lu tous les services une fois
'Mise en majuscule des noms pour comparer 2 chaines
'Le nom du service peut se trouver dans plusieurs champs
If StrConv(Service.displayname, vbUpperCase) = StrConv(ServiceName, vbUpperCase) And Service.State = MarcheArret Then Exit Do
If StrConv(Service.Description, vbUpperCase) = StrConv(ServiceName, vbUpperCase) And Service.State = MarcheArret Then Exit Do
If StrConv(Service.Name, vbUpperCase) = StrConv(ServiceName, vbUpperCase) And Service.State = MarcheArret Then Exit Do
If StrConv(Service.Name, vbUpperCase) = StrConv(ServiceName, vbUpperCase) Then
tt = 1
End If
'Service.DisplayName
'Service.Pathname
'Service.Description
'Service.StartMode
'Service.State
'Service.StartName
'Service.Name
'Service.Caption
'Exemple :
'MySQL;"P:\Program Files\Mysql\bin\mysqld-nt" --defaults-file="P:\Program Files\Mysql\my.ini" MySQL;;Manual;Running;LocalSystem;MySQL;MySQL
Next
If Time - CDate(Délais) > 0.0051 Then Délais = -1: Exit Do
Loop
Set ServiceSet = Nothing
If Délais = -1 Then
réponse = MsgBox("Impossible de lancer le serveur " & ServiceName, vbCritical, "Arrêt de la macro")
'Arrêt de la macro car la base Mysql est obligatoire
End
End If
End Function
Function NomfichierExport() As String
'Permet de définir un nom de fichier unique pour exporter les résultats SQL sous format csv
NomfichierExport = Format(Date, "yyyymmdd") & Hour(Time) & Minute(Time) & Second(Time) & ".csv"
End Function
Function Create_Table()
'Code présent uniquement pour définir le format de la table initiale, cas d'intallation
SQL = SQl_Connect & "create table HLRV (HLR char(11), Imsis char(15));"
Create_Table = SQL & SQL_Base
End Function
Function Import_Table(ByVal Nom_Fichier As String) As String
'Importe les données
SQL = SQl_Connect & "LOAD DATA LOCAL INFILE "
SQL = SQL & "'" & Nom_Fichier & "' INTO TABLE hlrv" & SQl_Fields_Terminated & SQl_Line_Terminated
SQL = SQL & " (IMSIS, HLR)"
Import_Table = SQL & SQL_Base
End Function
Function Purge_Table(ByVal Nom_Table As String) As String
'Purge une table proprement
SQL = SQl_Connect & "truncate " & Nom_Table
Purge_Table = SQL & SQL_Base
End Function
Function Index_Table(ByVal Nom_Table As String, ByVal Nom_Index As String) As String
'Index une table selon le nom du champ indiqué
SQL = SQl_Connect & "alter table " & Nom_Table & " add index (" & Nom_Index & ")"
Index_Table = SQL & SQL_Base
End Function
Function Purge_Index(ByVal Nom_Table As String, ByVal Nom_Index As String) As String
'Index une table selon le nom du champ indiqué
SQL = SQl_Connect & "alter table " & Nom_Table & " DROP index (" & Nom_Index & ")"
Index_Table = SQL & SQL_Base
End Function
'Définition des constantes locales de Mysql
Private Const SQl_Répertoire = "P:\Program Files\Mysql\bin\"
Private Const SQl_Connect = SQl_Répertoire & "mysql.exe -u NomUtilisateur -pPassWord --execute=" & """"
Private Const SQL_Base = """" & " NomdelaBase"
'Pour les exports c'est le caractère "A" qui sépare les champs
'permet d'identifier un fichier natif d'un export de la base Mysql
'Pour les imports c'est le caractère "F" qui sépare les champs
Private Const SQl_Fields_Terminated = " FIELDS TERMINATED BY 'A'"
Private SQL As String
Function SQL_1(ByVal champs As Double, ByVal table As Double) As String
'Liste l'ensemble des données d'un champs sur une table
SQL = SQl_Connect & "select champs1 "
SQL = SQL & "INTO OUTFILE '" & Fichier_resultat & "'" & SQl_Fields_Terminated
SQL = SQL & " from " & table & "where champ1 like '" & champs & "%'
SQL_1 = SQL & SQL_Base
End Function
sub toto
'Lance le serveur Mysql-----------------------/
réponse = ServiceWinD("NET START MYSQL", "Mysql", "Running")
'---------------------------------------------/
SQL_Texte = Purge_Table("toto")
ShellAndWait (SQL_Texte)
SQL_Texte = Purge_Index("toto", "titi")
ShellAndWait (SQL_Texte)
SQL_Texte = SQL_1("Données1", "données2")
ShellAndWait (SQL_Texte)
'Il ne reste plus qu'à lire les résultat dans le fichier Csv
lngCanal_Lect = FreeFile
' On ouvre le fichier en lecture
Open "P:\Program Files\Mysql\data\range\" & Fichier_resultat For Input As #lngCanal_Lect
'Lecture de l'unique ligne (format Unix) => il faut donc transformer la ligne en plusieurs lignes
Do While Not EOF(lngCanal_Lect)
Line Input #lngCanal_Lect, TextLine
If TextLine <> Empty Then
'Séparation des champs comportant un saut de ligne (Chr(10))
SplitToto() = Split(TextLine, Chr(10))
'------------ je coupe
end if
loop
'Arrète le serveur Mysql-----------------------/
réponse = ServiceWinD("NET STOP MYSQL", "Mysql", "Stopped")
'---------------------------------------------/
end sub
Conclusion :
Avec Excel et Mysql, on peut tout faire sans driver juste en contrôlant les processus Windows.
Vous n'êtes pas encore membre ?
inscrivez-vous, c'est gratuit et ça prend moins d'une minute !
Les membres obtiennent plus de réponses que les utilisateurs anonymes.
Le fait d'être membre vous permet d'avoir un suivi détaillé de vos demandes et codes sources.
Le fait d'être membre vous permet d'avoir des options supplémentaires.