Utilisation de mysql avec excel en mode shell, sans driver odbc sous xp

Contenu du snippet

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.

A voir également

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.