Faire des requêtes MySQL en Powershell

Si interroger ou écrire dans une base de données MySQL est trivial pour tout programmeur PHP qui se respecte, ça l’est beaucoup moins pour les aficionados de Powershell. Pourtant, ce n’est vraiment pas compliqué comme nous allons le voir…

Les bases

Qu’est-ce qu’une base de données me direz-vous ? Et bien c’est relativement simple : il s’agit d’un simple fichier (ou parfois de plusieurs fichiers) contenant… des données ! Si vous utilisez un tableur comme Excel, alors vous savez déjà à quoi ressemble une base de données :

Oui, ceci est une base de données. Incroyable, non ?

Comme vous le voyez, nous avons là un simple tableau (on parlera de table) à deux dimensions : le titre de chaque colonne correspondant au nom du champ (Nom, Prénom et Date de naissance) et pour chaque ligne, nous avons un enregistrement (le premier de notre tableau est donc un certain NEWTON, Isaac, né le 4 janvier 1643). Pour retrouver ces données en programmation, nous allons interroger la base de données en faisant une requête. Cette requête sera formulée (dans le cas de MySQL, mais aussi dans le cas d’autres logiciels de gestion de base de données) dans un langage nommé SQL, ou Structured Query Language. Ce langage est théoriquement normalisé par l’ISO (l’Organisation Internationale de Normalisation, dont le secrétariat est à Genève). Je dis bien théoriquement car dans la pratique, chaque éditeur de base de données a plus ou moins intégré à sa sauce la norme (qui a au passage évolué dans le temps), et du coup il n’y a pas UN langage SQL universel, mais PLUSIEURS dialectes, qui cela dit se ressemblent assez fortement. Mais il se peut qu’une requête qui fonctionne avec un logiciel X ne fonctionne pas exactement de la même façon avec un logiciel Y… cela dépasse de loin le cadre de ce billet cela dit.

Ainsi, nous avons une base de données que nous appellerons database, contenant une table nommée table (quelle originalité), elle-même composée de trois champs (écrits en anglais parce que ça évite les histoires d’accents et les espaces dans le nom des champs !) lastname, firstname et birthday. Cette table contient quatre enregistrements (les lignes), chacun lié à un personnage historique (si vous vous demandez qui est ce Nolan Bushnell, sachez qu’il s’agit du fondateur d’Atari). Le contenu de notre champ birthday sera toutefois stocké de manière un peu différente : le format que nous allons utiliser sera l’année, un tiret, le mois, un tiret puis le jour. C’est comme ça que les dates sont stockées par MySQL, ce qui n’est grave en soi, mais qui nécessite une petite conversion pour l’avoir au format “français”, c’est-à-dire JJ/MM/AAAA.

La même chose mais façon MySQL

Imaginons que nous voulons connaître la date de naissance – le champ birthday – de M. Tesla. Pour cela, nous allons donc nous connecter à la base de données database, puis gentiment demander à MySQL de nous donner cette date – qui se trouve dans la table table, ce qui revient à faire une requête en langage (My)SQL :

SELECT birthday FROM table WHERE lastname="TESLA"

Et celui-ci nous renverra :

1856-07-10

Libre à nous d’en faire ce que nous voulons, comme l’afficher par exemple. Même si le langage SQL est relativement simple à comprendre (les instructions sont en anglais, suffit de connaître quelques mots…), regardons de plus près la syntaxe :

  • SELECT : il s’agit d’une instruction de lecture (et seulement de lecture, on ne cherche pas à écrire dans la table). Nous demandons (gentiment) à MySQL de nous renvoyer une (ou plusieurs) données.
  • birthday : il s’agit là du nom du champ que nous désirons. Nous pourrions très demander la date de naissance ET le prénom, ce qui se traduirait par un
SELECT birthday, firstname

…ou carrément TOUS les champs :

SELECT *

Cela dit, quand vous en avez des dizaines, se restreindre ne fait pas de mal, car plus vous demandez de données, plus cela prend de temps et de mémoire.

  • FROM table : là nous indiquons que nous voulons des données présentes dans la table table. On pourrait très bien demander des données depuis une autre table, mais comme nous n’en avons qu’une dans notre base…
  • WHERE lastname=”TESLA” : là, nous indiquons une condition. Comme nous ne voulons que la date de naissance d’un type nommé TESLA (et seulement la sienne, les autres ne nous intéressent pas), nous exprimons cette conditions : le champ lastname (nom) doit être égal à la chaîne de caractère “TESLA”. Lors de l’exécution de la requête, MySQL va donc regarder le contenu de ce champ pour chaque enregistrement (avis aux puristes : je vulgarise, hein), jusqu’à ce qu’il trouve notre TESLA. Voilà ce qui se passe dans sa tête :

“Alors hmm… NEWTON, non c’est pas ça, EINSTEIN, ah bah non plus, TESLA… ah, TESLA, voilà, c’est lui. Regardons donc sa date de naissance : 1856-07-10. Hop, donnons-la à notre gentil utilisateur…”

Lire des données, c’est bien, mais nous pouvons aussi en ajouter à notre table :

INSERT INTO table VALUES ("LATEUR", "Dédé", "1876-01-21")

Je traduis : “Insère dans la table table les valeurs LATEUR, Dédé et 1876-01-21”, ce qui aura pour effet de rajouter un nouvel enregistrement, que nous retrouverons donc stocké comme ceci :

Je rejoins mon propre panthéon personnel, en toute modestie bien évidemment.

Oh mais quel étourdi je suis, je me suis trompé dans ma propre date de naissance ! Je ne suis évidemment pas né en 1876 (ce qui me ferait battre le record mondial de longévité humaine de Jeanne Calment), mais en 1976 (le premier qui fait un commentaire sur mon âge aura des problèmes, soyez-en sûr) ! Alors que faire ? Supprimer cet enregistrement et le recréer avec la bonne date ? Moui, on peut faire comme ça… Mais on peut tout aussi bien le mettre à jour, en une seule requête au lieu de deux (supprimer, recréer) :

UPDATE table SET birthday="1976-01-21" WHERE lastname="LATEUR"

En français : “Mets à jour, dans la table table, le champ birthday à la valeur “1976-01-21” pour l’enregistrement dont le champ lastname contient “LATEUR”, et rends ainsi justice à Mme Calment” (enfin cette dernière partie est sous-entendue, MySQL s’en tamponne complètement, il ne connaît absolument pas de Mme Calment).

Notre table ressemble désormais à ceci :

Ah je me sens plus jeune tout à coup !

Bon, c’est bien beau tout ça, mais le titre de l’article mentionne aussi Powershell, et jusqu’à présent nous n’avons parlé que de MySQL… Il est temps de remédier à tout ça.

Les ingrédients

Avant de nous lancer dans la programmation, il nous faut quelques éléments :

  • MySQL Server : euh ben oui, pour interroger une base MySQL, il faut MySQL, ça alors. Il convient donc de le télécharger et de l’installer (c’est vraiment très simple). Nous prendrons la community edition, qui a le mérite d’être gratuite (je rappelle à tout hasard qu’Oracle ayant racheté MySQL il y a quelques années, MySQL n’est PLUS un logiciel libre. Si cela vous pose un problème, vous pouvez très bien installer MariaDB à la place, c’est un fork libre, c’est compatible à quasiment 100% avec MySQL, et ça marche tout aussi bien).

Avis à la population : le lien ci-dessus pointe vers la version Windows de MySQL. Si vous utilisez Linux, vous pouvez aussi installer MySQL sur votre machine via l’installateur de packages de votre distribution, mais il vous faudra de toutes façons une machine Windows pour le connecteur .NET dont je parle ci-dessous. Au passage, il n’est absolument pas nécessaire d’avoir un compte Oracle pour télécharger les produits MySQL, il suffit de cliquer sur le lien “No thanks, just start my download”.

  • En option, MySQL Workbench, qui va nous permettre de manipuler MySQL via une interface graphique. Si vous avez déjà un serveur Apache avec l’extension PHP, vous pouvez évidemment utiliser phpMyAdmin à la place). Ou Toad si vous préférez. Enfin bref, un truc qui permette de créer la base, la table, et les enregistrements. Il y a le CLI de MySQL dans le pire des cas, mais alors débrouillez-vous.
  • Obligatoire, le connecteur .NET de MySQL. Ça, vous n’y couperez pas, car sans lui, point de salut, on ne peut pas faire communiquer Powershell et MySQL.
  • Et évidemment, Powershell. Si vous avez lui mes précédents billets sur Powershell, vous vous doutez que nous utiliserons aussi Powershell ISE pour écrire notre code.

Bref, prenez-le temps d’installer tout ça. Si vous avez des soucis, n’hésitez pas à me poser une question dans les commentaires, je tâcherai d’y répondre.

Avec l’installer, on installe tout d’un coup, et hop !

Pour faire simple, gardez toutes les options par défaut. Mais mettez un mot de passe suffisamment fort pour le compte root, car cela ouvre un port TCP (le 3306, par défaut) sur votre machine, et ce n’est jamais bon de laisser des bases de données traîner sans un minimum de protection… au passage, le script Powershell contiendra aussi le mot de passe du compte root en clair, alors évitez de le faire traîner si vous travaillez sur un serveur de production…

Créons notre base

Une fois tout ce bazar installé, nous allons rapidement créer notre base de données. Pour cela, nous allons utiliser MySQL Workbench. Connectez-vous à votre instance (locale, si tout est sur la même machine), en indiquant le mot de passe du compte root. Ensuite, cliquez sur la quatrième icône (qui permet de créer un nouveau schema, autrement dit une base de données), et indiquez comme nom database. Vous pouvez l’appeler comme bon vous semble, mais ne mettez pas d’espace dans le nom (ou remplacez l’espace par l’underscore _ ).

Faisons dans le simple.

Cliquez ensuite sur le bouton Apply : un petit assistant se lance (vous indiquant au passage la requête qu’il compte exécuter pour créer ce nouveau schema). Cliquez là encore sur le bouton Apply et terminez. La base est désormais créée, mais elle est vide. Il nous faut donc créer une table (nommée table, ou ce que voulez, encore une fois sans espace…) en cliquant sur la cinquième icône (assurez-vous de bien être sur le schéma database comme indiqué, si vous avez déjà d’autres schémas dans cette instance), et les champs contenus dans cette table (lastname, firstname et birthday), en précisant leur type (respectivement, VARCHAR(20), VARCHAR(20) et DATE). Il suffit de cliquer sur la ligne vide sous “Column name” pour ajouter un champ. Cochez les cases PK (Primary Key) et NN (Not Null) pour le champ lastname : cela a un rapport avec l’index de la base de données, mais je n’en parlerai pas ici.

Au final, vous devez obtenir ceci :

Faites exactement comme moi, ne vous posez pas de question…

Là encore, cliquez sur le bouton Apply. Le petit assistant se lance de nouveau, cliquez sur Apply et terminez. La table est créée. Il ne reste plus qu’à la remplir. Dans l’arborescence en base à gauche de MySQL Workbench, développez le schéma database, puis Tables et cliquez sur table. Entrez ensuite la requête suivante dans l’onglet Query 1 tout en haut :

INSERT INTO `table` VALUES ('NEWTON', 'Isaac', '1643-01-04')

Cliquez enfin sur l’icône représentant un éclair pour exécuter la requête.

Là aussi, faites exactement ce que je vous dis, sinon…

Attention lorsque vous indiquez le nom de la table dans la requête : il veut absolument que ce nom soit entouré de carrets ` et non d’apostrophes ‘. Pour obtenir un carret, vous devez appuyez sur les touches AltGr et 7 de votre clavier. Pour entourer les valeurs, vous pouvez mettre au choix des apostrophes ou des guillemets.

Une fois la requête exécutée, les données sont inscrites dans la table. Pour vérifier que c’est bien le cas, faites un clic droit sur la table table dans l’arborescence, et sélectionnez la première entrée du menu contextuel (“Select rows – limit 1000”). Si tout va bien, vous devriez obtenir le résultat suivant :

Youpi, ça marche !

Je vous laisse ajouter les données pour Einstein, Tesla et Bushnell, en reprenant la seconde illustration de l’article…

Passons à Powershell

Maintenant que nous avons un serveur MySQL, une base de données, une table et des enregistrements, il est temps de se mettre à coder en Powershell. Lancez Powershell ISE.

Comme je l’ai écrit plus haut, il va d’abord falloir se connecter au serveur MySQL. Pour ce faire, il faut absolument le connecteur .NET de MySQL, et donc le charger dans l’environnement Powershell.

$mysqlnet=[Reflection.Assembly]::LoadWithPartialName("MySql.Data")
if(-not $mysqlnet)
{
    Write-Error "Ouhlala, problème !"
    Exit
}

Nous chargeons donc l’assembly (en gros, une DLL) nommée MySql.Data (le connecteur .NET), et en cas d’échec, nous affichons un message d’erreur. Pas la peine d’aller plus loin si cela arrive.

Dans le cas où le connecteur est chargé, nous allons pouvoir (tenter de) nous connecter à MySQL. Pour cela, il faut indiquer quelques paramètres que j’ai mis en variables. Les commentaires sont je pense assez explicites :

# Paramètres de connexion à la base MySQL
$dbuser = "root" # le nom d'utilisateur (root)
$dbpwd = "password" # son mot de passe (cet exemple est très mauvais)
$dbname = "database" # nom de la base de données database
$dbhost = "localhost" # nom d'hôte ou adresse IP du serveur
$dbport = 3306 # port TCP MySQL (3306 par défaut)

Ces variables nous servirons à créer une chaîne de connexion, que nous utiliserons ensuite :

$connectionString = "server=$dbhost;port=$dbport;uid=$dbuser;pwd=$dbpwd;database=$dbname" # chaîne de connexion à la base MySQL

Je passe par des variables intermédiaires uniquement parce que je trouve ça plus pratique, vous pouvez très bien créer la chaîne de connexion directement avec les bonnes valeurs. Mais c’est à mon avis moins lisible.

Pour la suite, j’utilise des fonctions que j’ai créé pour me faciliter la vie. Mais faisons dans le simple, et voyons comment procéder de manière basique. Tout d’abord, il faut ouvrir la connexion. Nous créons donc un nouvel objet nommé $conn, de type MySql.Data.MySqlClient.MySqlConnection, auquel nous passons notre variable $connectionString :

$conn = New-Object MySql.Data.MySqlClient.MySqlConnection($connectionString) 

Comme tout objet, celui-ci possède des propriétés et des méthodes. Nous allons faire appel à l’une d’elle pour ouvrir (Open) la connexion :

$conn.Open()

Bon, dans un monde idéal, je ferai de la gestion d’erreur pour éviter les ennuis. Mais comme nous ne sommes pas dans un monde idéal, partons du principe que tout fonctionne de manière parfaite. Notre connexion est ouverte. Reste maintenant à faire des requêtes, nous sommes là pour ça après tout…

Sauf qu’il y a un hic. Les requêtes de lecture (comme SELECT) ne doivent pas être appelées de la même façon que les requêtes d’écriture ou de mise à jour (INSERT, UPDATE). Sans compter qu’il y a d’autres types de requêtes que je n’évoquerai pas ici. Personnellement, je me suis concocté une fonction de lecture et une autre d’écriture, mais chaque chose en son temps. Commençons par la plus simple des requêtes, la lecture (car lire est plus simple qu’écrire, en informatique comme ailleurs).

$query="SELECT * FROM ``table``"

Une simple variable ($query) contenant ma requête, qui elle-même est la plus simple qui soit (je veux TOUS les enregistrements de la table table). Enfin simple, simple… vous voyez aussi bien que moi les double carrets qui entourent “table”… Alors visiblement MySQL 5.7 a décidé d’être pénible avec ces histoires de carret (jusqu’à présent, je n’en mettais jamais dans mes requêtes). Il en veut autour du nom de la table, sinon il boude et déclenche une erreur de syntaxe. Sauf qu’en Powershell, le carret est utilisé pour indiquer des caractères spéciaux dans une chaîne (par exemple, “`r`n” permet de sauter une ligne). Il faut donc en mettre deux d’affilée pour indiquer que le caractère spécial dans la chaîne est un… carret !

L’étape suivante consiste à créer trois objets dans cet ordre précis : une commande, une adaptateur et enfin, un jeu de données. Je passe sur ce à quoi ils servent, ce n’est pas très important, l’essentiel est de les créer dans le bon ordre.

$MysqlCmd = New-Object MySql.Data.MySqlClient.MySqlCommand($query, $conn)    # Créer la commande SQL en indiquant la requête et la connexion
$DataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter($MysqlCmd) # Créer l'adaptateur depuis la commande
$DataSet = New-Object System.Data.DataSet                                    # Créer le jeu de données

Ce jeu de données $DataSet nécessite d’être rempli (avec le résultat de la requête), mais tel quel il ne nous serait pas très utile car Powershell ne sait pas ce qu’est un jeu de données. Par contre, si on en fait un tableau, là tout de suite pour lui ce sera plus clair. Grâce à la méthode Fill() de l’objet $DataAdapter (qui remplira $DataSet), nous pouvons justement indiquer un nom de tableau :

$DataAdapter.Fill($DataSet, "data")   # Remplir le jeu de données $dataset et le mettre dans un tableau nommé "data"      

En réalité, ce tableau sera le contenu de la propriété indexée Tables de $DataSet. On pourra donc y accéder comme ceci :

$dataSet.Tables["data"] 

Et magie de l’informatique, cette ligne inscrit ceci dans la console Powershell :

lastname firstname birthday           
-------- --------- --------           
NEWTON   Isaac     04/01/1643 00:00:00

Oui, je n’ai pour l’instant qu’Isaac Newton dans ma table. Évidemment, si vous avez ajouté Einstein, Tesla et Bushnell, vous les verrez aussi.

Notez que la date est affichée sous la forme JJ/MM/AAAA HH:MM:SS. C’est le format utilisé par les options régionales de mon Windows, Powershell a automatiquement fait la conversion. Par contre je vous le dit tout de suite, il ne sait pas convertir une date de son format à celui de MySQL (AAAA-MM-JJ), il faudra la faire “manuellement”.

Pour faire les choses proprement, nous allons supprimer de la mémoire la commande $MysqlCmd et fermer la connexion $conn :

$MysqlCmd.Dispose()
$conn.Close()

Un truc à savoir : si vous ne fermez pas la connexion, elle reste ouverte. Mais si vous exécutez la même requête de lecture en ayant entre temps ajouté des enregistrements, et bien vous ne les verrez pas. Le jeu de données n’est pas à jour…

Une autre chose me chagrine : taper $dataSet.Tables[“data”] ne fait que retourner tout le jeu de donnée, on ne peut pas isoler un enregistrement (une ligne) en particulier, et cela va vite poser un souci. Et puis au niveau code, ça fait beaucoup de caractères pour pas grand chose. Donc tout d’abord, mettons ce jeu de données dans une variable $res, on ira plus vite par la suite :

$res=$dataSet.Tables["data"]

Pour la beauté du geste, tapez cette commande dans la console de Powershell :

$res | gm

(je rappelle à tout hasard que gm est l’alias de la commande Get-Member de Powershell, qui permet de lister les propriétés et méthodes d’un objet). Alléluia, il y a tout un tas de méthodes et de propriétés dites-donc :

PS C:\WINDOWS\system32> $res | gm


   TypeName : System.Data.DataRow

Name              MemberType            Definition                                                                                                           
----              ----------            ----------                                                                                                           
AcceptChanges     Method                void AcceptChanges()                                                                                                 
BeginEdit         Method                void BeginEdit()                                                                                                     
CancelEdit        Method                void CancelEdit()                                                                                                    
ClearErrors       Method                void ClearErrors()                                                                                                   
Delete            Method                void Delete()                                                                                                        
EndEdit           Method                void EndEdit()                                                                                                       
Equals            Method                bool Equals(System.Object obj)                                                                                       
GetChildRows      Method                System.Data.DataRow[] GetChildRows(string relationName), System.Data.DataRow[] GetChildRows(string relationName, S...
GetColumnError    Method                string GetColumnError(int columnIndex), string GetColumnError(string columnName), string GetColumnError(System.Dat...
GetColumnsInError Method                System.Data.DataColumn[] GetColumnsInError()                                                                         
GetHashCode       Method                int GetHashCode()                                                                                                    
GetParentRow      Method                System.Data.DataRow GetParentRow(string relationName), System.Data.DataRow GetParentRow(string relationName, Syste...
GetParentRows     Method                System.Data.DataRow[] GetParentRows(string relationName), System.Data.DataRow[] GetParentRows(string relationName,...
GetType           Method                type GetType()                                                                                                       
HasVersion        Method                bool HasVersion(System.Data.DataRowVersion version)                                                                  
IsNull            Method                bool IsNull(int columnIndex), bool IsNull(string columnName), bool IsNull(System.Data.DataColumn column), bool IsN...
RejectChanges     Method                void RejectChanges()                                                                                                 
SetAdded          Method                void SetAdded()                                                                                                      
SetColumnError    Method                void SetColumnError(int columnIndex, string error), void SetColumnError(string columnName, string error), void Set...
SetModified       Method                void SetModified()                                                                                                   
SetParentRow      Method                void SetParentRow(System.Data.DataRow parentRow), void SetParentRow(System.Data.DataRow parentRow, System.Data.Dat...
ToString          Method                string ToString()                                                                                                    
Item              ParameterizedProperty System.Object Item(int columnIndex) {get;set;}, System.Object Item(string columnName) {get;set;}, System.Object It...
birthday          Property              datetime birthday {get;set;}                                                                                         
firstname         Property              string firstname {get;set;}                                                                                          
lastname          Property              string lastname {get;set;}

…et comme vous le voyez, nos champs lastname, firstname et birthday sont JUSTEMENT des propriétés de notre jeu de données, comme c’est pratique. Et comme nous avons pris soin de copier notre jeu de données dans l’objet (ou variable) $res, cela veut dire que nous allons pouvoir y accéder bien plus simplement :

$res.birthday

Sauf que… oui, pour un résultat unique, ça va marcher, mais si on en a plusieurs ? Powershell va tous les sortir, ça va être un de ces bazars… Et bien il suffit d’indiquer le numéro d’index de l’enregistrement souhaité, et hop, le tour est joué !

$res.birthday[0] #pour le premier enregistrement
$res.birthday[1] # pour le second, etc...

Notez que Powershell nous fait encore un gag dont il a le secret avec les dates : en effet, sur ma machine, pour $res.birthday[0] il me sort ceci :

vendredi 14 mars 1879 00:00:00

Et si je veux un résultat sous la format 14/03/1879, c’est simple : s’agissant d’une propriété de type date, je peux la formatter comme je veux, par exemple en faisant :

$res.birthday[0].ToString("dd/MM/yyyy")

Il y a plusieurs méthodes pour ce faire, mais celle-ci est simple et rapide.

Si vous utilisez une boucle type foreach pour lire (et traiter) tous les résultats, nul besoin de préciser l’index de l’enregistrement. Par exemple, devinez ce que va afficher le bout de code ci-dessous :

foreach($gugusse in $res) # pour chaque enregistrement du tableau $res...
{
    Write-Host "$($gugusse.firstname) $($gugusse.lastname) est né le $($gugusse.birthday.ToString("dd/MM/yyyy")) !"
}

Si vous avez répondu quelque chose comme ceci, vous avez gagné :

Albert EINSTEIN est né le 14/03/1879 !
Isaac NEWTON est né le 04/01/1643 !

N’oubliez pas d’entourer avec $() les $objet.propriété dans une chaîne, sinon ça risque de poser un petit souci d’affichage…

Bien, nous avons vu comment lire une base de données MySQL, mais il reste encore à écrire dedans, et comme je l’ai dit plus haut, ça ne se fait pas tout à fait de la même façon. On va évidemment créer une requête, créer aussi une commande mais ici pas de jeu de données à créer puisqu’on ne lit pas. Il faut par contre préciser dans la propriété CommandText de la commande notre requête, puis l’exécuter, et récupérer le résultat (c’est toujours bien de savoir si une requête s’est correctement exécutée…).

$query="INSERT INTO ``table`` VALUES ('LATEUR', 'Dédé', '1876-01-21')"
$MysqlCmd = New-Object MySql.Data.MySqlClient.MySqlCommand($query, $conn) # Créer la commande SQL
$MysqlCmd.CommandText = $query  # On met la requête dans la propriété CommandText de la commande
$RowsInserted = $MysqlCmd.ExecuteNonQuery() # On exécute la commande

Si tout va bien, $RowsInserted doit contenir le nombre d’enregistrements que nous voulions ajouter (ici, en l’occurence, un seul enregistrement donc $RowsInserted doit être égal à 1). Pour tester ça :

  if ($RowsInserted) 
  { 
     $RowsInserted
  } 
  else 
  { 
    Write-Error "Ouhlalalala quelque chose a foiré !"
  }

Si vous avez eu la bonne idée (pas comme moi dans cet article) de mettre un champ d’ID unique avant le champ lastname, vous pouvez obtenir le dernier ID ajouté en regardant la propriété LastInsertedId de la commande $MysqlCmd :

$MysqlCmd.LastInsertedId

Mais dans le cas présent, l’ID retourné sera systématiquement 0, ce qui ne nous sert pas à grand chose.

Comme vous l’avez vu, je me suis encore planté dans ma propre date de naissance. Pour corriger tout ça, je dois donc faire un UPDATE de mon enregistrement. Je n’ai qu’à modifier la requête $query, et l’exécuter exactement comme une requête INSERT :

$query="UPDATE ``table`` SET birthday='1976-01-21' WHERE lastname='LATEUR'"
$MysqlCmd = New-Object MySql.Data.MySqlClient.MySqlCommand($query, $conn) # Créer la commande SQL
$MysqlCmd.CommandText = $query  # On met la requête dans la propriété CommandText de la commande
$RowsInserted = $MysqlCmd.ExecuteNonQuery() # On exécute la commande

N’oubliez pas ensuite, une fois que vous n’avez plus besoin d’une commande, de faire un Dispose(), puis pour finir, de fermer la connexion ($conn.Close()).

The end

Voilà, vous savez désormais lire et écrire dans une base MySQL ! Sur ces bonnes paroles, portez-vous bien et so long, and thanks for all the fish* !

Bonus

En cadeau bonus, le script complet de l’article :

$mysqlnet=[Reflection.Assembly]::LoadWithPartialName("MySql.Data")
if(-not $mysqlnet)
{
    Write-Error "Ouhlala, problème !"
    Exit
}

# Paramètres de connexion à la base MySQL
$dbuser = "root" # le nom d'utilisateur (root)
$dbpwd = "password" # son mot de passe (cet exemple est très mauvais)
$dbname = "database" # nom de la base de données database
$dbhost = "localhost" # nom d'hôte ou adresse IP du serveur
$dbport = 3306 # port TCP MySQL (3306 par défaut)

$ConnectionString = "server=$dbhost;port=$dbport;uid=$dbuser;pwd=$dbpwd;database=$dbname" # chaîne de connexion à la base MySQL
$conn = New-Object MySql.Data.MySqlClient.MySqlConnection($connectionString) 
$conn.Open()

$query="SELECT * FROM ``table``;"

$MysqlCmd = New-Object MySql.Data.MySqlClient.MySqlCommand($query, $conn)    # Créer la commande SQL
$DataAdapter = New-Object MySql.Data.MySqlClient.MySqlDataAdapter($MysqlCmd) # Créer l'adaptateur depuis la commande
$DataSet = New-Object System.Data.DataSet                                    # Créer le jeu de données
$dataAdapter.Fill($dataSet, "data")                                          # Remplir le jeu de données $dataset et le mettre dans un tableau nommé "data"            

$res=$dataSet.Tables["data"] 

foreach($gugusse in $res)
{
    Write-Host "$($gugusse.firstname) $($gugusse.lastname) est né le $($gugusse.birthday.ToString("dd/MM/yyyy")) !"
}

$query="INSERT INTO ``table`` VALUES ('LATIR', 'Doudou', '1876-01-21')"
$MysqlCmd = New-Object MySql.Data.MySqlClient.MySqlCommand($query, $conn) # Créer la commande SQL
$MysqlCmd.CommandText = $query  # On met la requête dans la propriété CommandText de la commande
$RowsInserted = $MysqlCmd.ExecuteNonQuery() # On exécute la commande

if ($RowsInserted) 
{ 
    Write-Host "Nombre d'enregistrement ajoutés : $RowsInserted"
    Write-Host "Dernier ID ajouté : $($MysqlCmd.LastInsertedId)"
} 
else 
{ 
    Write-Error "Ouhlalalala quelque chose a foiré !"
} 
$MysqlCmd.Dispose() # On supprime la commande quand on n'en a plus besoin, pas avant !

$query="UPDATE ``table`` SET birthday='1976-01-21' WHERE lastname='LATEUR'"
$MysqlCmd = New-Object MySql.Data.MySqlClient.MySqlCommand($query, $conn) # Créer la commande SQL
$MysqlCmd.CommandText = $query  # On met la requête dans la propriété CommandText de la commande
$RowsInserted = $MysqlCmd.ExecuteNonQuery() # On exécute la commande

$MysqlCmd.Dispose() # On supprime la commande quand on n'en a plus besoin, pas avant !

$conn.Close() # On ferme la connexion

* Et pour comprendre le jeu de mots, lisez ceci

 

1 commentaire

Répondre à Anne Onyme Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.