Obligement - L'Amiga au maximum

Lundi 22 février 2021 - 19:02  

Translate

En De Nl Nl
Es Pt It Nl


Rubriques

 · Actualité (récente)
 · Actualité (archive)
 · Comparatifs
 · Dossiers
 · Entrevues
 · Matériel (tests)
 · Matériel (bidouilles)
 · Points de vue
 · En pratique
 · Programmation
 · Reportages
 · Quizz
 · Tests de jeux
 · Tests de logiciels
 · Tests de compilations
 · Trucs et astuces
 · Articles divers

 · Articles in english


Twitter

Suivez-nous sur Twitter




Liste des jeux Amiga

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z,
ALL


Trucs et astuces

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Glossaire

0, A, B, C, D, E, F,
G, H, I, J, K, L, M,
N, O, P, Q, R, S, T,
U, V, W, X, Y, Z


Galeries

 · Menu des galeries

 · BD d'Amiga Spécial
 · Caricatures Dudai
 · Caricatures Jet d'ail
 · Diagrammes de Jay Miner
 · Images insolites
 · Fin de jeux (de A à E)
 · Fin de Jeux (de F à O)
 · Fin de jeux (de P à Z)
 · Galerie de Mike Dafunk
 · Logos d'Obligement
 · Pubs pour matériels
 · Systèmes d'exploitation
 · Trombinoscope Alchimie 7
 · Vidéos


Téléchargement

 · Documents
 · Jeux
 · Logiciels
 · Magazines
 · Divers


Liens

 · Sites de téléchargements
 · Associations
 · Pages Personnelles
 · Matériel
 · Réparateurs
 · Revendeurs
 · Presse et médias
 · Programmation
 · Logiciels
 · Jeux
 · Scène démo
 · Divers


Partenaires

Annuaire Amiga

Amedia Computer

Relec

Hit Parade


A Propos

A propos d'Obligement

A Propos


Contact

David Brunet

Courriel

 


En pratique : Exploitation d'une base de données relationnelle avec SQLite sur MorphOS
(Tutoriel développé et écrit par Sébastien Jeudy - février 2021)


Présentation

SQLite est un système de gestion de bases de données relationnelles embarquées, libre et Open Source. Contrairement aux autres SGBDR, il n'est pas orienté "client-serveur", ses bases de données sont uniquement exploitées en local (idéal pour les logiciels devant embarquer la base de données, donc sans partage des données en réseau avec d'autres utilisateurs).

Pour cela, il est également ultra-léger (< 1 Mo).

SQLite

Autre intérêt : l'intégralité d'une base de données est stockée dans un fichier indépendant de la plate-forme. La gestion des droits d'accès et de modification des données se fait alors par le système de fichiers du système d'exploitation.

Intégré à de nombreux logiciels grand public, produits professionnels, bibliothèques standards, langages de programmation, systèmes embarqués, smartphones et tablettes, SQLite est au final le moteur de bases de données le plus utilisé au monde.

Une chance pour nous : la version AmigaOS/MorphOS (3.34.0 à ce jour) est aussi la dernière disponible, identique à la version Windows/Linux/macOS !

Étant spécialiste en bases de données et utilisateur de MorphOS, j'ai donc profité de la disponibilité de SQLite sur MorphOS pour approfondir ce SGBDR que je n'avais jamais utilisé.

L'objectif de ce tutoriel est de vous apporter un cas concret d'exploitation de base de données relationnelle avec SQLite, mais pas d'enseigner en détail le langage SQL ni l'implémentation de SQLite dans une application logicielle. Cependant, il est présenté de sorte que le novice peut tout de même s'y retrouver et en comprendre la finalité.

Enfin, l'environnement choisi est MorphOS mais l'utilisation de SQLite est logiquement la même sur AmigaOS ou tout autre système.

Pour découvrir davantage SQLite : fr.wikipedia.org/wiki/SQLite.
Site officiel : www.sqlite.org.

Téléchargement

L'archive de SQLite 3.34.0 (et suivantes) pour MorphOS est disponible sur www.morphos-storage.net/?find=sqlite.

Après avoir téléchargé l'archive, la désarchiver et copier son dossier à l'endroit souhaité sur disque.

Personnellement, j'ai renommé son dossier en "SQLite".

Utilisation en lignes de commandes avec l'outil SQLite nommé "sqlite3"

Ouvrir un terminal Shell, puis lancer l'outil SQLite - le tout en créant une nouvelle base de données - en tapant sur une seule ligne (avec un espace après "sqlite3" et attention à vos propres chemins) :

Work:Applications/SQLite/build-ppc-morphos/bin/sqlite3 Work:Developpement/SQLite/BDD/Bibliotheque

Sachant que chez moi l'outil "sqlite3" est dans "Work:Applications/SQLite/build-ppc-morphos/bin/" et que le fichier de la base de données créée s'appellera "Bibliotheque" dans "Work:Developpement/SQLite/BDD/".

Une autre solution serait de copier "sqlite3" dans "C:", ce qui donnerait :

sqlite3 Work:Developpement/SQLite/BDD/Bibliotheque

Puis dans l'outil SQLite, saisir l'ensemble des commandes suivantes (après l'invite de commande "sqlite> "), dans l'ordre précisé afin de suivre correctement ce tutoriel - pas à pas - jusqu'au bout.

Commandes internes de base

Voir l'ensemble des commandes internes intégrées à l'outil SQLite (le point en préfixe est obligatoire pour les commandes internes) :

.help

Pour quitter l'outil SQLite :

.quit

Pour retourner dans SQLite et dans la base de données "Bibliotheque", retaper (chez moi) :

Work:Applications/SQLite/build-ppc-morphos/bin/sqlite3 Work:Developpement/SQLite/BDD/Bibliotheque

Ou avec "sqlite3" dans "C:" :

sqlite3 Work:Developpement/SQLite/BDD/Bibliotheque

Dans SQLite, vérifier les bases de données utilisées :

.databases

Création de tables et clés primaires/clés étrangères

Créer la nouvelle table "Auteurs" dans la base de données "Bibliotheque" (le point-virgule en fin d'instruction est obligatoire pour les requêtes SQL) :

create table Auteurs(IdAuteur integer primary key not null, Nom varchar(30) not null,
Prenom varchar(30) not null, DateNaissance date, DateDeces date);

Précision SQLite : avec ce genre de "primary key" sur une seule colonne de type entier (integer), sa valeur sera automatiquement incrémentée au fur et à mesure des insertions de lignes dans la table.

Autre rappel : la clé primaire permet d'éviter les doublons de lignes dans la table mais aussi d'identifier une ligne de façon unique.

Créer la nouvelle table "Livres" dans la base de données "Bibliotheque" :

create table Livres(IdLivre integer primary key not null, Titre varchar(100) not null,
IdAuteur integer not null, Parution year(4) not null, NbPages integer, constraint fk_auteurs
foreign key (IdAuteur) references Auteurs(IdAuteur));

Précision SQLite : la contrainte "foreign key" permet de relier la table "Livres" à la table "Auteurs" via les colonnes respectives "IdAuteur", celle-ci ne pouvant pas être rajoutée ultérieurement avec un "alter table" (comme dans d'autres SGBDR).

Autre rappel : une clé étrangère permet de contrôler que les données d'une (ou plusieurs) colonne(s) de table correspondent bien aux données de la clé primaire d'une autre table (de référence). Ici, chaque livre de la table "Livres" doit être affecté à un auteur existant dans la table "Auteurs".

Activer le contrôle des clés étrangères (sinon inactif) :

pragma foreign_keys = on;

Attention : à réactiver à chaque nouvelle utilisation de la base de données (accès à SQLite) !

Vérifier les tables créées (dans la base de données courante "Bibliotheque") :

.tables

Revoir le schéma ("create table") des tables existantes :

.schema Auteurs

.schema Livres

Insertion de données

Insérer des lignes de données dans la table "Auteurs" :

insert into Auteurs (Nom, Prenom) values ('Verne', 'Jules');
insert into Auteurs (Nom, Prenom) values ('Stevenson', 'Robert Louis');
insert into Auteurs (Nom, Prenom) values ('De Saint-Exupéry', 'Antoine');

Interroger toute la table "Auteurs" :

select * from Auteurs;

Résultat :

1|Verne|Jules||
2|Stevenson|Robert Louis||
3|De Saint-Exupéry|Antoine||

Rappel : une "*" affiche toutes les colonnes et un "select" sans condition "where" retourne toutes les lignes.

Insérer des lignes de données dans la table "Livres" :

insert into Livres (Titre, IdAuteur, Parution) values ('Le Tour du Monde en 80 Jours', 1, 1872);
insert into Livres (Titre, IdAuteur, Parution) values ('De la Terre à la Lune', 1, 1865);
insert into Livres (Titre, IdAuteur, Parution) values ('Autour de la Lune', 1, 1870);
insert into Livres (Titre, IdAuteur, Parution) values ('L''Ile au Trésor', 2, 1883);
insert into Livres (Titre, IdAuteur, Parution) values ('L''Etrange Cas du Docteur Jekyll et de M. Hyde', 2, 1886);
insert into Livres (Titre, IdAuteur, Parution) values ('Vol de Nuit', 3, 1931);
insert into Livres (Titre, IdAuteur, Parution) values ('Le Petit Prince', 3, 1943);
insert into Livres (Titre, IdAuteur, Parution) values ('Terre des Hommes', 3, 1939);

Interroger toute la table "Livres" :

select * from Livres;

Résultat :

1|Le Tour du Monde en 80 Jours|1|1872|
2|De la Terre à la Lune|1|1865|
3|Autour de la Lune|1|1870|
4|L'Ile au Trésor|2|1883|
5|L'Etrange Cas du Docteur Jekyll et de M. Hyde|2|1886|
6|Vol de Nuit|3|1931|
7|Le Petit Prince|3|1943|
8|Terre des Hommes|3|1939|

Interrogation de tables avec tri

Avec tri selon la colonne "Parution" :

select * from Livres order by Parution asc;

Résultat :

2|De la Terre à la Lune|1|1865|
3|Autour de la Lune|1|1870|
1|Le Tour du Monde en 80 Jours|1|1872|
4|L'Ile au Trésor|2|1883|
5|L'Etrange Cas du Docteur Jekyll et de M. Hyde|2|1886|
6|Vol de Nuit|3|1931|
8|Terre des Hommes|3|1939|
7|Le Petit Prince|3|1943|

Précision : "asc" pour ascendant et "desc" pour descendant.

Nombre de lignes des tables

Afficher le nombre de lignes des tables :

select count(*) from Auteurs;

select count(*) from Livres;

Contrôle des clés étrangères

Essayer d'insérer un livre dont l'auteur n'existe pas (violation de clé étrangère) :

insert into Livres (Titre, IdAuteur, Parution) values ('Le Vieil Homme et la Mer', 4, 1952);

Résultat :

Error: FOREIGN KEY constraint failed

Essayer de supprimer un auteur affecté à des livres (violation de clé étrangère) :

delete from Auteurs where IdAuteur = 1;

Résultat :

Error: FOREIGN KEY constraint failed

Interrogation de tables avec jointure

Interroger plusieurs tables reliées avec jointure (liaison entre clé étrangère et clé primaire, en général mais pas obligatoirement) :

select Titre, Prenom, Nom, Parution from Livres L join Auteurs A on L.IdAuteur = A.IdAuteur;

Résultat (liste des livres avec leur auteur et leur date de parution) :

Le Tour du Monde en 80 Jours|Jules|Verne|1872
De la Terre à la Lune|Jules|Verne|1865
Autour de la Lune|Jules|Verne|1870
L'Ile au Trésor|Robert Louis|Stevenson|1883
L'Etrange Cas du Docteur Jekyll et de M. Hyde|Robert Louis|Stevenson|1886
Vol de Nuit|Antoine|De Saint-Exupéry|1931
Le Petit Prince|Antoine|De Saint-Exupéry|1943
Terre des Hommes|Antoine|De Saint-Exupéry|1939

Création et utilisation de vues

Créer la nouvelle vue "LivresAuteurs" (table image résultant d'un "select" interrogeant une ou plusieurs tables) :

create view LivresAuteurs as select Titre, Prenom, Nom,
Parution from Livres L join Auteurs A on L.IdAuteur = A.IdAuteur;

Résultat :

.tables

.schema LivresAuteurs

Rappel : une fois créée, une vue s'utilise comme une table mais sans contenir de données.

Exemple d'utilisation de la vue "LivresAuteurs" :

select * from LivresAuteurs order by Parution asc;

Résultat :

De la Terre à la Lune|Jules|Verne|1865
Autour de la Lune|Jules|Verne|1870
Le Tour du Monde en 80 Jours|Jules|Verne|1872
L'Ile au Trésor|Robert Louis|Stevenson|1883
L'Etrange Cas du Docteur Jekyll et de M. Hyde|Robert Louis|Stevenson|1886
Vol de Nuit|Antoine|De Saint-Exupéry|1931
Terre des Hommes|Antoine|De Saint-Exupéry|1939
Le Petit Prince|Antoine|De Saint-Exupéry|1943

Rappel : une vue allège les syntaxes et optimise les traitements des requêtes SQL complexes.

Autre exemple d'utilisation de la vue "LivresAuteurs" :

select * from LivresAuteurs where Nom = 'Verne' or Nom like '%saint%' order by Parution desc;

Résultat :

Le Petit Prince|Antoine|De Saint-Exupéry|1943
Terre des Hommes|Antoine|De Saint-Exupéry|1939
Vol de Nuit|Antoine|De Saint-Exupéry|1931
Le Tour du Monde en 80 Jours|Jules|Verne|1872
Autour de la Lune|Jules|Verne|1870
De la Terre à la Lune|Jules|Verne|1865

Interrogation de tables avec regroupement

Afficher le nombre de livres par auteur (avec regroupement par nom) :

select count(*), Nom from LivresAuteurs group by Nom;

Résultat :

3|De Saint-Exupéry
2|Stevenson
3|Verne

Attention, pas la même chose que :

select count(*), Nom from LivresAuteurs;

(résultat erroné ou ambigu)

Autre exemple de regroupement (avec condition "having") :

select count(*), Nom from LivresAuteurs group by Nom having count(*) >= 3;

Résultat :

3|De Saint-Exupéry
3|Verne

Avec alias "as Total" pour "count(*)" :

select count(*) as Total, Nom from LivresAuteurs group by Nom having Total >= 3;

Même résultat :

3|De Saint-Exupéry
3|Verne

Interrogation de tables avec union de sélections

Afficher le résultat de plusieurs "select" à la suite (union de sélections) :

select Prenom, Nom from Auteurs union all select Titre, Parution from Livres;

Résultat :

Jules|Verne
Robert Louis|Stevenson
Antoine|De Saint-Exupéry
Le Tour du Monde en 80 Jours|1872
De la Terre à la Lune|1865
Autour de la Lune|1870
L'Ile au Trésor|1883
L'Etrange Cas du Docteur Jekyll et de M. Hyde|1886
Vol de Nuit|1931
Le Petit Prince|1943
Terre des Hommes|1939

Précisions : les "select" doivent retourner le même nombre de colonnes. "all" conserve les lignes en doublon.

Utilisation de fonctions d'agrégat

Utiliser des fonctions d'agrégat (retournent une valeur unique à partir d'un ensemble de valeurs) :

Pour rappel :

select Parution from Livres;

Comptage :

select count(Parution) from Livres;

Minimum :

select min(Parution) from Livres;

Maximum :

select max(Parution) from Livres;

Somme :

select sum(Parution) from Livres;

Moyenne :

select avg(Parution) from Livres;

Précisions : les fonctions d'agrégat ne tiennent pas compte des valeurs vides (null), sauf le count(*). "count", "min" et "max" fonctionnent également sur les valeurs alphanumériques (textes).

Modification de données

Modifier un enregistrement dans une table :

update Auteurs set DateNaissance = '1828-02-08', DateDeces = '1905-03-24' where IdAuteur = 1;

Vérifier :

select * from Auteurs where IdAuteur = 1;

Résultat :

1|Verne|Jules|1828-02-08|1905-03-24

Attention : un "update" sans condition "where" modifie toutes les lignes de la table !

Valeurs vide et non vide

Rechercher des valeurs de colonne à vide (null) ou non vide (not null) :

select * from Auteurs where DateNaissance is null;

select * from Auteurs where DateNaissance is not null;

Suppression de données

Supprimer un enregistrement dans une table :

delete from Livres where IdLivre = 8;

Vérifier :

select * from Livres;

Résultat :

1|Le Tour du Monde en 80 Jours|1|1872|
2|De la Terre à la Lune|1|1865|
3|Autour de la Lune|1|1870|
4|L'Ile au Trésor|2|1883|
5|L'Etrange Cas du Docteur Jekyll et de M. Hyde|2|1886|
6|Vol de Nuit|3|1931|
7|Le Petit Prince|3|1943|

Attention : un "delete" sans condition "where" supprime toutes les lignes de la table !

Utilisation de transactions

Utiliser une transaction (pour éventuellement annuler les modifications avec un "rollback;") :

Démarrer la transaction :

begin;

Effectuer des modifications, par exemple vider la table "Livres" :

delete from Livres;

select * from Livres;

Annuler les modifications (et quitter la transaction) :

rollback;

Vérifier :

select * from Livres;

Résultat :

1|Le Tour du Monde en 80 Jours|1|1872|
2|De la Terre à la Lune|1|1865|
3|Autour de la Lune|1|1870|
4|L'Ile au Trésor|2|1883|
5|L'Etrange Cas du Docteur Jekyll et de M. Hyde|2|1886|
6|Vol de Nuit|3|1931|
7|Le Petit Prince|3|1943|

Précision : un "commit;" à la place du "rollback;" aurait enregistré les modifications (et quitté la transaction).

Création et utilisation de triggers

Créer un trigger/déclencheur sur la table "Auteurs" (programme s'exécutant automatiquement lorsqu'un évènement insert/update/delete survient sur la table associée) :

create trigger suppr_auteur_et_livres before delete on Auteurs begin delete from Livres where Livres.IdAuteur = old.IdAuteur; end;

Résultat :

.schema Auteurs

Précision : "old" fait référence à la table "Auteurs" avant suppression ("before delete").

Exemple d'utilisation du trigger "suppr_auteur_et_livres" (lorsqu'un auteur est supprimé dans la table "Auteurs", ses livres sont aussi automatiquement supprimés dans la table "Livres") :

delete from Auteurs where IdAuteur = 2;

Résultats :

select * from Auteurs;

1|Verne|Jules|1828-02-08|1905-03-24
3|De Saint-Exupéry|Antoine||

select * from Livres;

1|Le Tour du Monde en 80 Jours|1|1872|
2|De la Terre à la Lune|1|1865|
3|Autour de la Lune|1|1870|
6|Vol de Nuit|3|1931|
7|Le Petit Prince|3|1943|

Exportation et importation de données

Exporter toutes les données de la table "Livres" dans le fichier "RAM:Livres.csv" :

.once RAM:Livres.csv

select * from Livres;

Vérifier (en utilisant la commande interne ".system" d'appel de commandes système depuis SQLite) :

.system dir RAM:

.system type RAM:Livres.csv

Résultat :

1|Le Tour du Monde en 80 Jours|1|1872|
2|De la Terre à la Lune|1|1865|
3|Autour de la Lune|1|1870|
6|Vol de Nuit|3|1931|
7|Le Petit Prince|3|1943|

Réimporter toutes les données du fichier "RAM:Livres.csv" dans la table "Livres" (à vider au préalable) :

delete from Livres;

select * from Livres;

.import RAM:Livres.csv Livres

select * from Livres;

Résultat :

1|Le Tour du Monde en 80 Jours|1|1872|
2|De la Terre à la Lune|1|1865|
3|Autour de la Lune|1|1870|
6|Vol de Nuit|3|1931|
7|Le Petit Prince|3|1943|

Sauvegarde et restauration de bases de données (et destruction de tables/vues/triggers)

Faire la sauvegarde complète (backup) de la base de données "Bibliotheque" dans le fichier "RAM:Bibliotheque.bak" :

.backup RAM:Bibliotheque.bak

Vérifier :

.system dir RAM:

.system type RAM:Bibliotheque.bak

Précision SQLite : cette sauvegarde (et sa restauration) peut être également réalisée en copiant simplement le fichier sur disque de la base de données.

Détruire les trigger, vue et tables créés :

drop trigger suppr_auteur_et_livres;

drop view LivresAuteurs;

drop table Livres;

drop table Auteurs;

Vérifier :

.tables

Faire la restauration complète (restore) de la base de données "Bibliotheque" depuis le fichier "RAM:Bibliotheque.bak" :

.restore RAM:Bibliotheque.bak

Vérifier :

.tables

.schema Auteurs

.schema Livres

.schema LivresAuteurs

select * from Auteurs;

select * from Livres;

select * from LivresAuteurs;

Sauvegarde SQL de bases de données

Faire la sauvegarde SQL complète (dump) de la base de données "Bibliotheque" dans le fichier "RAM:Bibliotheque.sql" (notamment pour une migration vers un autre SGBDR) :

.output RAM:Bibliotheque.sql

.dump

.quit

Vérifier (dans le terminal Shell) :

dir RAM:

type RAM:Bibliotheque.sql

Le mot de la fin

Vous voilà venu à bout de ce tutoriel qui vous a introduit l'essentiel des fonctionnalités d'exploitation d'une base de données relationnelle avec SQLite. Un SGBDR digne de ce nom, qui dispose d'un langage SQL riche et relativement standard. En définitive une excellente solution pour gérer les données dans le développement de vos logiciels sur MorphOS (et AmigaOS) !


[Retour en haut] / [Retour aux articles]


Soutenez le travail d'Obligement