À propos de ce code
Tôt ou tard, on est amené à se diriger vers l'utilisation d'une base de données pour son projet.
Que ce soit l'utilisation d'une base de données pour une application ou un site internet, le besoin pointe toujours le bout de son nez .
Ce tutoriel vise uniquement l'utilisation de SQLite dans un contexte de projet qui nécessite une gestion de données pour une application. Cela dit, il n'y a que peu de différence avec l'utilisation de MySQL, PostgreSQL... (mais je vous conseille de vous référer à la documentation sur http://gambasdoc.org pour plus d'informations à leur sujet) .
Ce tutoriel est découpé en quatre parties :
1- Explication sur le fonctionnement d'une BDD (=Base de données).
2- Mise en oeuvre avec Gambas.
3- Afficher les données.
4- Les erreurs que vous pouvez rencontrer.
Explication sur le fonctionnement d'une BDD
Une BDD vous permet de stocker un nombre impressionnant de données de façon structurée.
L'image la plus utilisée dans les tutoriels ou cours concernant les BDD est l'armoire. Pour comprendre comment fonctionne une BDD, vous imaginez simplement votre armoire, qui contient lui-même des tiroirs, qui contiennent eux-mêmes les données
. Sauf que vous êtes une personne organisée et vous décidez de coller une étiquette sur chaque tiroir (un pour les dossiers de la maison, un autre pour les comptes, un troisième pour votre collection de voitures, ...). Bien maintenant si on fait un petit transfert de vocabulaire, cela donne:
- Armoire =
Base de données- Tiroirs =
Tables- Dossiers =
donnéesOn va d'ailleurs même pousser le vice encore plus loin. Pour chaque voiture de votre collection, vous décidez d'indiquer le nom de la voiture, sa puissance, son prix.
Oui vous l'avez compris, ça ressemble dans votre tête à un bête tableau! Ce tableau n'est autre que la
Table en langage BDD. Et comme tout bon tableau qui se respecte, ces derniers ont des colonnes! En langage BDD ... ça s'appelle des
Champs (
Fields en anglais). Ce qui donne pour une table :
- Colonne =
Champ- ligne =
EntréeDonc pour conclure, une base de données n'est rien d'autre qu'une armoire qui a plusieurs tiroirs (=tableaux -> tables) qui contiennent les données.
En revanche, il faut savoir que chaque Champ de votre Table (oui désormais j'emploie le jargon!
) va contenir un type de données bien précis.
Admettons que vous ayez une Table que vous nommez
Personne, cette dernière pourrait contenir les données d'un groupe de personnes tel que leurs noms, leurs prénoms et leurs âges.
Nous reconnaissons rapidement ici qu'il s'agit des simples types de données comme
String ou
Integer en Gambas. Donc ma Table
Personne aura pour
Champs :
nom =
Stringprenom =
Stringage =
IntegerFacile n'est-ce pas?
Mais j'ai envie de corser un peu la chose. Chaque entrée nouvelle que vous allez effectués, doivent pouvoir être accessible si quelqu'un vous demande l'âge de Robert! On va donc instaurer un ID(=identifiant unique) à chaque nouvelle entrée. Et pour cela, on va tout bonnement rajouter un
Champ qui va contenir cet ID. Notre Table
Personne ressemblera donc à celle-ci:
id =
Serialnom =
Stringprenom =
Stringage =
IntegerVoilà qui est mieux. En revanche... quel est ce type "Serial" ?!
C'est simplement une valeur unique, qui est incrémentée
automatiquement lorsqu'on ajoute une nouvelle entrée à notre Table!
Oui parce que bon, vous pouvez gérer manuellement cette valeur, mais vous allez vite revenir à ce type croyez-moi
.
En d'autres termes, lors de vos manipulations sur la base de données, vous n'aurez pas à vous préoccuper de ce
Champ. Non me remerciez pas c'est normal...
Désormais, vous savez comment est constitué une base de données. Mais ce que vous savez pas, c'est qu'à lui seul, il utilise son propre langage pour communiquer avec vous! Et il porte le doux nom de SQL. Alors certains pourraient se poser cette question : "
Je ne comprends pas, c'est pas Gambas qui va gérer la base de données?! " .
Et bien si. Gambas va utiliser le langage SQL pour dialoguer avec votre base de données. Un langage qui utilise un langage, c'est pas magnifique?
Ce langage SQL n'est pas vraiment compliqué à comprendre. Il ressemble à de simples phrases(en anglais bien évidemment) qui donnent des ordres à SQLite, comme par exemple:
- Donne-moi tout le contenu de la base de données.
- Donne-moi les personnes qui s'appellent Benoît.
- Ajoute à la table cette charmante nouvelle cliente.
- Modifie l'identité de cette personne, il a changé de prénom!
- Donne-moi toutes les personnes qui ont entre 20 et 30 ans.
- Et j'en passe...
Avec notre cher langage de programmation qui est Gambas, on va se servir de ces résultats pour notre programme.
Bon, j'ai l'honneur de vous informer que vous êtes parés à manger de la crevette moussaillon
!!
C'est parti!
Mise en oeuvre avec Gambas
Commencez par créer un nouveau projet, en veillant à bien inclure les composants
gb.db et
gb.sqlite3.
Il faut savoir que pour utiliser une BDD, il faut se connecter à elle. Qui dit connexion, dit également mot de passe, login, port ... et la liste habituelle.
Sauf qu'ici, on utilise SQLite. Et ce dernier n'a pas vraiment la notion d'utilisateur et tout ce qui s'en suit. Souvenez-vous que dans notre exemple, nous utilisons SQLite afin de stocker des informations d'une application locale. (Oui parce qu'utiliser des fichiers pour stocker le nom, prénom et l'age de 200 personnes ça va 5 minutes
. D'autant plus qu'il faudrait coder un parser pour récupérer chaque données. Bref SQLite travaille très bien à ce poste!)
Comme je disais, c'est un peu différent avec lui. Vous avez l'habitude d'utiliser la propriété
.Host pour indiquer une adresse IP. Et bien ici on va s'en servir pour indiquer le chemin d'accès à votre BDD sur votre disque dur. La propriété
.Host va seulement contenir le chemin, pas le nom du fichier. Pour ce dernier, nous allons conjointement utiliser une propriété
.Name.
Vous l'avez deviné, si j'ai parlé de propriété, c'est qu'il y a un objet derrière tout ça
! Et cet objet va représenter notre connexion et notre base de données dans la foulée donc.
Et tant qu'on parle d'objets, autant vous dire directement que pour notre Table, on va utiliser aussi un objet!
Oh mais c'est pas tout. Vu qu'on va travailler avec ces tables, on va justement donner des ordres comme vu précédemment. Et je vous ai parlé de Résultat. Et bien il y aura aussi un objet résultat qui va contenir les informations sur les demandes qu'on a effectuées avec SQL. Je résume :
- 1 objet de type
Connection - 1 objet de type
Table- 1 objet de type
ResultIl nous suffit de 3 objets pour gérer notre base de données!
A partir de ce point, je vais vous expliquer l'ordre d'utilisation de ces objets:
- On crée tout d'abord un objet Connection et on lance la connexion avec la méthode
.Open. Mais avant de lancer la connexion, nous devons pré-configurer des infos tels que le type, l'hôte et le nom. Le type sert à indiquer quelles BDD on utilise. L'hôte est comme j'ai dis plus haut, et en dernier vous indiquez le nom de votre base de données.
Pour l'exemple, je me suis positionné dans mon home/ , et j'ai nommé ma BDD "MaBase.sq3" . A noter que l'extension est purement optionnel et vous pouvez la changer si vous le souhaitez (comme uneBase.sql ou encore uneBase.sqlite ... bref c'est à votre convenance.)
En regardant le code, je présume que vous vous dîtes, mais comment ça se fait que je fais appel à .Open alors que je n'ai pas renseigné la propriété .Name. Et bien si vous l'indiquez pas, Gambas utilisera un nom de fichier temporaire qui se trouvera dans /tmp. En lancant .Open j'obtiendrais une connexion donc, mais pas avec le nom que je voulais.
C'est la raison pour laquelle je teste derrière si mon fichier de BDD existe dans mon home/ et si ce n'est pas le cas, et bien je le crée.
"Mais... tu peux pas faire ça avant l'instruction .Open justement? Et puis à quoi ça sert désormais s'il utilise un fichier temporaire?" Bonne remarque, et tout arrive justement ici. Remarquez dans le code la méthode que j'utilise pour vérifier et créer mon fichier "MaBase.sq3". Ces dernières pour être utilisées doivent avoir une connexion. Donc j'ouvre une connexion temporairement afin de créer mon fichier "MaBase.sq3" et derrière je vais fermer la connexion, de sorte que je puisse relancer une connexion mais cette fois avec MON fichier en paramètre et non plus le temporaire. N'hésitez pas à relire lentement si ce passage vous obscure
.
Une fois ma connexion établie et mon fichier "MaBase.sq3" créé. Je vais désormais procéder un peu de la même manière. C'est-à-dire que je vais vérifier si ma table
Personne existe, et le cas échéant elle fera partie de ma BDD. Dans la foulée, je n'oublie pas de créer mes
champs en indiquant le type de chacun.
A noter ces deux instructions suivantes :
1
2
| $table.PrimaryKey = ["id"] $table.Update
|
La première définit la clé primaire.
La deuxième crée la Table.
Arrive ensuite le passage où je décide d'ajouter 30 entrées à ma Table. Et c'est là que l'objet Result rentre en jeu.
1
2
3
4
5
6
7
| FOR i = 1 TO 30 $result = $connexion.Create("Personne") $result!nom = tabNom[Int(Rnd(0, tabnom.Length))] $result!prenom = tabPrenom[Int(Rnd(0, tabPrenom.Length))] $result!age = Int(Rnd(1, 90)) $result.Update NEXT
|
La méthode .Create me crée une entrée pour la Table
Personne et me la renvoie dans notre objet Result (afin de la manipuler).
Alors pour chaque entrée j'affece un nom, un prénom et un age aléatoire (histoire de remplir notre Table tout de même
)
Et je valide mon entrée avec
.Update.
Rien de bien méchant à comprendre si ce n'est peu-être la syntaxe avec le point d'interrogation qui peut se montrer surprenante de prime abord. C'est l'équivalent de :
1
| $result["nom"] = "dupont"
|
Concernant ces 3 lignes, c'est un exemple pour l'ajout de 3 entrées dans la Table Personne pour ceux qui souhaitent savoir comment envoyer une requête SQL par Gambas.
1
2
3
| db.Exec("INSERT INTO Personne VALUES(NULL,'bourse','jean-baptiste',32)") db.Exec("INSERT INTO Personne VALUES(NULL,'jaures','jean',21)") db.Exec("INSERT INTO Personne VALUES(NULL,'zola','emile',23)")
|
Pour récupérer les données, c'est en dessous
.
Afficher les données
Pour afficher les données, j'ai décidé d'utiliser un
GridView dans ce tutoriel.
Cela dit, je vous donnerai un code indépendant du GridView avec une belle boucle
For Each.
Avant tout de chose, j'espère que vous êtes au point avec l'utilisation du GridView. Si ce n'est pas le cas, je vous recommande chaudement d'aller lire mon tutoriel à son sujet:
http://gambasforge.org/code-5-exemple-du-gridview.html Tout se passe dans cette portion de code :
1
2
3
4
5
6
7
8
| $tab = NEW STRING[$result.Count, 3] FOR i = 0 TO $result.Count - 1 $tab[i, 0] = $result!nom $tab[i, 1] = $result!prenom $tab[i, 2] = $result!age $result.MoveNext NEXT
|
Explication:
- Nous créons un tableau à deux dimensions dont le nombre de lignes est égal au nombre d'entrées dans notre Table.
- Pour remplir ce tableau, on utilise une boucle
For allant du début à la fin de notre Table. Remarquez ici le ' -1 '. En effet dans notre Table notre ID démarre à 1 et non à zéro comme nos tableaux en Gambas. Donc n'oubliez surtout pas de faire ce retrait sinon vous aurez une belle erreur précisant que vous êtes allés trop loin
- Ensuite, comme vous pouvez le remarquer, on remplit notre tableau ligne par ligne!
- Pour remplir une nouvelle ligne à notre tableau, nous devons passer à la prochaine entrée de notre Table, grâce à la méthode
.MoveNextEt voilà, il ne reste plus qu'à fournir ce tableau à notre GridView qui va se charger d'afficher pour vous les données à la bonne place:
1
2
3
4
5
| PUBLIC SUB GridView1_Data(Row AS INTEGER, Column AS INTEGER)
GridView1.Data.Text = $tab[row, Column]
END
|
Je vous ai dis en début de cette partie que je vous montrerai une autre façon d'afficher les résultats. La voici:
1
2
3
4
5
6
7
| $result = db.Exec("SELECT * FROM Personne") FOR EACH $result PRINT $result!nom PRINT $result!prenom PRINT $result!age NEXT
|
Très simple à comprendre. Pour chaque entrée on affiche ses données.
Les erreurs que vous pouvez rencontrer
Unable to locate database
Votre fichier de BDD est introuvable.
Vous avez mal renseigné les propriétés
.Host et
.Name de votre objet
Connection.
Connection already opened
Vous avez déjà une connexion avec le serveur. Deux raisons possibles :
- Vous avez lancé une seconde fois la méthode
.Open de votre objet
Connection dans votre code sans fermer la première.
- Vous tentez d'accéder aux méthodes de votre objet
Connection avant votre appel à la méthode
.Open.
Le dernier cas de figure arrive généralement lorsque vous tentez par exemple de vérifier la présence de votre fichier BDD avant l'appel
.Open afin de le créer.
Revoyez le code ci-dessous pour comprendre votre erreur.
Mes requêtes SQL à l'aide de DB.Exec() échouent!
Êtes-vous sur que votre BDD a bien créé vos tables?
C'est une erreur fréquente lorsqu'on ne pense pas à vérifier la présence de tables dans le fichier BDD.
Revoyez le code ci-dessous pour comprendre votre erreur.
No current connection
Cette erreur peut arriver lors de l'utilisation de
DB.Exec() .
Ca signifie que SQLite a détecté plusieurs connexions et vous devez sélectionner celle qui va exécuter la requête SQL.
Pour corriger le problème :
1
| DB.Current = $connexion
|
Avant les appels à
DB.Exec() .
Bon boulot.
Olivier