Mise en place Connexion Création d`une base de données et
Transcription
Mise en place Connexion Création d`une base de données et
T-GSI Ch.4 Le Langage SQL – LDD, LCD Cet exercice guidé reprend le plan suivis lors de l’intervention de formation faite pour l’académie de Versailles. L’objectif principal visait en la présentation du langage SQL LDD, et en une initiation à la partie LCD. Tous les ordres SQL sont définis dans les autres chapitres de ce cours. Nous ne reviendrons donc pas sur la syntaxe. Olivier Mondet http://unidentified-one.net Mise en place MySQL doit être installé au préalable, soit seul, soit avec EasyPHP-ModGSI. Pour cela suivre les guides correspondants. Cet exercice utilise la version de MySQL installée avec EasyPHP-ModGSI. Nous utiliserons le client MySQL livré avec l’installation (dans EasyPHP1-8-ModGSI\mysql\bin) qui se nomme mysql (à ne pas confondre avec mysqld qui est le « logiciel » de base de données en luimême). Connexion La connexion à la base de données se fait par l’instruction mysql –u root –p puis en pressant la touche entrée. Le mot de passe demandé est root par défaut avec la version de MySQL fournie par EasyPHP-ModGSI. Voici la fenêtre de connexion : C:\Program Files\EasyPHP1-8-ModGSI\mysql\bin>mysql -u root -p Enter password: **** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 2 to server version: 5.0.18-max Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> Le prompt mysql> attend des ordres SQL de syntaxe correcte ou des commandes propres à MySQL. Création d’une base de données et création des tables : Nous allons créer la base de données des stagiaires gsi, où seront implémentées les relations suivantes : etablissement (nume, nome, ville) nume est la clé primaire stagiaire (nums, noms, prenoms, mails, nume) nums est la clé primaire, nume est la clé étrangère en référence à nume de la table etablissement Nous ne préciserons pas le moteur de base de données et utiliserons le moteur par défaut InnoDB de MySQL. Ce moteur remplace le moteur MyISAM plus ancien et ne respectant pas (entre autre) l’intégrité fonctionnelle. Se référer aux autres chapitres pour de plus amples explications. Ch.4 - Applications (exercice de découverte).doc page 1 / 9 om (2005-2006) mysql> CREATE DATABASE gsi; Query OK, 1 row affected (0.09 sec) mysql> USE gsi; Database changed mysql> CREATE TABLE etablissement -> ( -> nume INT NOT NULL, -> nome VARCHAR(30), -> ville VARCHAR(30), -> CONSTRAINT pk_etablissement PRIMARY KEY(nume) -> ); Query OK, 0 rows affected (0.20 sec) On aura noté que juste après avoir créé la base de données, on se connecte à celle-ci (avec USE). C’est dans la base de données gsi que nous allons créer les tables. mysql> CREATE TABLE stagiaire -> ( -> nums INT NOT NULL, -> noms VARCHAR(30), -> prenoms VARCHAR(30), -> mails VARCHAR(50), -> nume INT NOT NULL, -> CONSTRAINT pk_stagiaire PRIMARY KEY(nums), -> CONSTRAINT fk_stag_etab FOREIGN KEY(nume) REFERENCES etablissement(nume ) -> ); Query OK, 0 rows affected (0.16 sec) mysql> MySQL offre diverses possibilités de typage des champs : Types numériques exacts Types approchés Les entiers Dates Chaînes Chaînes de grande taille Enumérations NUMERIC, DECIMAL (DEC), INTEGER (INT)(4 octets) et SMALLINT FLOAT, REAL et DOUBLE PRECISION TINYINT (1 octet), SMALLINT (2 octets), MEDIUMINT (3 octets), INTEGER (INT)(4 octets), BIGINT (8 octets) DATE ('0000-00-00'), DATETIME ('0000-00-00 00:00:00') (attention les dates sont notées à l’anglaise AAAA-JJ-MM) CHAR (format nom compressé où 1caractère = 1octet), VARCHAR (format compressé, à choisir à partir de 5 à 10 caractères) BLOB, TEXT SET Les clauses CONSTRAINT permettent de déclarer les clés primaires et les clés étrangères. Le nommage pk_table ou fk_table1_table2 est un moyen signifiant de nommer les contraintes en fonction de leur rôle : pk_table est le nom de la contrainte qui déclare la clé primaire d’une table, fk_table1_table2 est le nom de la contrainte qui déclare la clé étrangère qui assure le l’intégrité référentielle entre la table n°1 et la table n°2. Les noms des contraintes doivent être uniques pour une base de données. On aura noté que tant qu’un point virgule ; n’est pas inséré (marquant la fin d’un ordre et donc le début de son interprétation par MySQL) le prompt passe de mysql> à ->. Se référer aux autres chapitres pour de plus amples explications. Ch.4 - Applications (exercice de découverte).doc page 2 / 9 om (2005-2006) Nous pouvons vérifier l’existence de la base de données et des tables. mysql> SHOW DATABASES; +--------------------+ | Database | +--------------------+ | information_schema | | cinema | | gsi | | mysql | | phpmyadmin | +--------------------+ 5 rows in set (0.00 sec) mysql> SHOW TABLES; +---------------+ | Tables_in_gsi | +---------------+ | etablissement | | stagiaire | +---------------+ 2 rows in set (0.00 sec) mysql> L’ordre SHOW TABLES implique d’être connecté à une base de données, car les tables affichées sont celle de la base de données active. Insertion des valeurs et violation de contraintes Nous allons entrer un premier enregistrement. mysql> INSERT INTO etablissement VALUES ('1','Geoffroy-Saint-Hilaire','ETAMPES') ; Query OK, 1 row affected (0.09 sec) mysql> Nous allons entrer un second enregistrement en tentant une violation de contrainte relative à la clé primaire. mysql> INSERT INTO etablissement VALUES ('1','Vilgenis','MASSY'); ERROR 1062 (23000): Duplicata du champ '1' pour la clef 1 mysql> On remarque que MySQL réagit et indique bien un problème sur la clé primaire avec un champ comportant un doublon. Problème qui devrait se régler avec une insertion correcte. mysql> INSERT INTO etablissement VALUES ('2','Vilgenis','MASSY'); Query OK, 1 row affected (0.03 sec) mysql> Nous allons insérer des valeurs dans la seconde table en respectant l’intégrité fonctionnelle relative au champ nume (l’établissement doit exister dans la table etablissement avant l’insertion). mysql> INSERT INTO stagiaire VALUES ('1','Georges','Dumont','georges.dumont@mail .fr','1'); Query OK, 1 row affected (0.06 sec) mysql> INSERT INTO stagiaire VALUES ('2','Bernardette','Martin','[email protected] r','1'); Query OK, 1 row affected (0.08 sec) mysql> Ch.4 - Applications (exercice de découverte).doc page 3 / 9 om (2005-2006) Nous allons tenter une violation de clé étrangère (intégrité fonctionnelle) en saisissant un code établissement n’existant pas dans la table etablissement. mysql> INSERT INTO stagiaire VALUES ('3','Yolande','Kraft','[email protected]' ,'3'); ERROR 1452 (23000): Cannot add or update a child row: a foreign key constraint f ails (`gsi/stagiaire`, CONSTRAINT `fk_stag_etab` FOREIGN KEY (`nume`) REFERENCES `etablissement` (`nume`)) mysql> L’intégrité référentielle est donc bien respectée. Si vous utilisez une version antérieure de MySQL ou si vos tables sont déclarées avec la mention type=MyISAM, vous serez surpris de constater que MySQL ne respecte pas l’intégrité référentielle. Autrement dit, l’insertion aurait été acceptée. Vous pouvez en faire le constat en réessayant cet exercice avec les tables déclarées de la façon suivante : CREATE TABLE etablissement ( nume INT NOT NULL, nome VARCHAR(30), ville VARCHAR(30), CONSTRAINT pk_etablissement PRIMARY KEY(nume) )type=MyISAM; CREATE TABLE stagiaire ( nums SMALLINT NOT NULL auto_increment, noms VARCHAR(30), prenoms VARCHAR(30), mails VARCHAR(50), nume INT NOT NULL, CONSTRAINT pk_stagiaire PRIMARY KEY(nums), CONSTRAINT fk_stag_etab FOREIGN KEY(nume) REFERENCES etablissement(nume) )type=MyISAM; Bien sur le moteur InnoDB semble plus performant si on s’attache à l’aspect « intégrité référentielle », cependant le moteur InnoDB est moins performant que le moteur MyISAM en termes de rapidité d’exécution. C’est pour cela que MySQL était souvent choisi pour les sites Web avec son moteur MyISAM. Vous pouvez en faire le constat en réessayant cet exercice avec les tables déclarées comme ci-dessus. Avec le moteur InnoDB il est impossible de supprimer un élément référencé. Pour terminer, on peut afficher le contenu de nos tables… mysql> SELECT * -> FROM etablissement; +------+------------------------+---------+ | nume | nome | ville | +------+------------------------+---------+ | 1 | Geoffroy-Saint-Hilaire | ETAMPES | | 2 | Vilgenis | MASSY | +------+------------------------+---------+ 2 rows in set (0.00 sec) mysql> SELECT * -> FROM stagiaire; +------+-------------+---------+------------------------+------+ | nums | noms | prenoms | mails | nume | +------+-------------+---------+------------------------+------+ | 1 | Georges | Dumont | [email protected] | 1 | | 2 | Bernardette | Martin | [email protected] | 1 | +------+-------------+---------+------------------------+------+ 2 rows in set (0.00 sec) mysql> Ch.4 - Applications (exercice de découverte).doc page 4 / 9 om (2005-2006) … ainsi que leur structure. mysql> DESCRIBE etablissement; +-------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +-------+-------------+------+-----+---------+-------+ | nume | int(11) | NO | PRI | | | | nome | varchar(30) | YES | | NULL | | | ville | varchar(30) | YES | | NULL | | +-------+-------------+------+-----+---------+-------+ 3 rows in set (0.05 sec) mysql> DESCRIBE stagiaire; +---------+-------------+------+-----+---------+-------+ | Field | Type | Null | Key | Default | Extra | +---------+-------------+------+-----+---------+-------+ | nums | int(11) | NO | PRI | | | | noms | varchar(30) | YES | | NULL | | | prenoms | varchar(30) | YES | | NULL | | | mails | varchar(50) | YES | | NULL | | | nume | int(11) | NO | MUL | | | +---------+-------------+------+-----+---------+-------+ 5 rows in set (0.05 sec) mysql> Mise à jour de la structure des tables Notre base de données prend en compte la discipline des enseignants participant au stage (CAPET). etablissement (nume, nome, ville) nume est la clé primaire discipline (numd, libd) numd est la clé primaire stagiaire (nums, noms, prenoms, mails, nume, numd) nums est la clé primaire, nume est la clé étrangère en référence à nume de la table etablissement numd est la clé étrangère en référence à numd de la table discipline Il faut donc ajouter une table, puis mettre à jour la structure de la table stagiaire en ajoutant le champ numd et l’intégrité référentielle. L’ajout de la table et l’insertion de valeurs. mysql> CREATE TABLE discipline -> ( -> numd CHAR(1) NOT NULL, -> libd VARCHAR(40), -> CONSTRAINT PK_discipline PRIMARY KEY(numd) -> ); Query OK, 0 rows affected (0.11 sec) mysql> INSERT INTO discipline VALUES ('B','Capet B'); Query OK, 1 row affected (0.05 sec) mysql> INSERT INTO discipline VALUES ('D','Capet D'); Query OK, 1 row affected (0.05 sec) mysql> Ch.4 - Applications (exercice de découverte).doc page 5 / 9 om (2005-2006) L’ajout du champ numd à la structure de la table stagiaire (ALTER) et la mise à jour (UPDATE) de la table (le stagiaire n°1 sera CAPET B, le stagiaire n°2 sera CAPET D). mysql> ALTER TABLE stagiaire -> ADD numd CHAR(1) NOT NULL; Query OK, 2 rows affected (0.36 sec) Enregistrements: 2 Doublons: 0 Avertissements: 0 mysql> UPDATE stagiaire -> SET numd = 'B' -> WHERE nums = '1'; Query OK, 1 row affected (0.06 sec) Enregistrements correspondants: 1 ModifiÚs: 1 Warnings: 0 mysql> UPDATE stagiaire -> SET numd = 'D' -> WHERE nums = '2'; Query OK, 1 row affected (0.05 sec) Enregistrements correspondants: 1 ModifiÚs: 1 Warnings: 0 mysql> L’ajout de la contrainte d’intégrité référentielle sur la clé étrangère. mysql> ALTER TABLE stagiaire -> ADD CONSTRAINT FK_disc_stag FOREIGN KEY(numd) REFERENCES discipline(numd ); Query OK, 2 rows affected (0.41 sec) Enregistrements: 2 Doublons: 0 Avertissements: 0 mysql> Notez que l’on ajoute cette contrainte après la mise à jour de la table stagiaire car sinon les champs numd seraient vides (NULL) et MySQL refuserait d’ajouter la contrainte sur des champs vides (c’est une violation de contrainte justement). Ce problème se pose uniquement parce que la table possède déjà des enregistrements. Modification de la structure d’une table (suite) et suppression d’un table Finalement nous ne voulons plus garder la discipline des stagiaires et donc revenir à notre base de données telle qu’elle était auparavant. Nous devons mettre à jour la structure de la table stagiaire et supprimer la contrainte d’intégrité référentielle, puis le champ numd. mysql> ALTER TABLE stagiaire -> DROP FOREIGN KEY FK_disc_stag; Query OK, 2 rows affected (0.25 sec) Enregistrements: 2 Doublons: 0 Avertissements: 0 mysql> ALTER TABLE stagiaire -> DROP numd; Query OK, 2 rows affected (0.24 sec) Enregistrements: 2 Doublons: 0 Avertissements: 0 mysql> Nous pouvons supprimer la table discipline. mysql> DROP TABLE discipline; Query OK, 0 rows affected (0.11 sec) mysql> La suppression des tables doit toujours se faire en tenant compte des contraintes d’intégrité référentielle. On doit toujours commencer par supprimer les tables comportant des clés étrangères puis les tables n’en comportant pas. Il s’agit de l’ordre exactement inverse de l’ordre de création des tables. Ch.4 - Applications (exercice de découverte).doc page 6 / 9 om (2005-2006) Création d’utilisateur et attribution de droits Sous MySQL la gestion des utilisateurs posait souvent des problèmes (avec les versions antérieures à la n°5). Il était fréquent d’entrer en ‘force’ les paramètres utilisateur pour qu’ils soient pris en compte. La version 5 de MySQL semble mieux intégrer la gestion des utilisateurs. Les droits (ou privilèges) que l’on peut accorder aux utilisateurs correspondent aux ordres que l’on veut leur laisser passe. Par exemple les privilèges sur les tables : SELECT, INSERT, UPDATE, DELETE, CREATE, DROP. Nous allons créer un utilisateur nommé bob dont le mot de passe sera 123456. mysql> CREATE USER 'bob' IDENTIFIED BY '123456'; Query OK, 0 rows affected (0.14 sec) mysql> Vous devriez pouvoir vous connecter avec ce compte (sinon reconnectez vous sous root et saisissez FLUSH PRIVILEGES pour forcer MySQL à recharger ses tables système). C:\Program Files\EasyPHP1-8-ModGSI\mysql\bin>mysql -u bob -p Enter password: ****** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 62 to server version: 5.0.18-max Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> L’ennui c’est que bob ne possède aucun privilège ! Il ne peut même pas se connecter à notre base gsi. mysql> USE gsi; ERROR 1044 (42000): AccÞs refusÚ pour l'utilisateur: 'bob'@'@%'. Base 'gsi' mysql> L’attribution des privilèges porte sur une base (ou toutes les bases) et sur des tables (ou toutes les tables). Nous allons simplement donner le privilège SELECT sur la table etablissement à bob. mysql> GRANT SELECT ON gsi.etablissement TO bob@localhost IDENTIFIED BY '123456' ; Query OK, 0 rows affected (0.03 sec) mysql> Après le privilège SELECT, nous avons précisés la base de données et la table, puis l’utilisateur et le domaine (localhost = le poste uniquement, % tous les postes). Ici bob ne pourra exercer ses droits qu’au niveau local uniquement. C:\Program Files\EasyPHP1-8-ModGSI\mysql\bin>mysql -u bob -p Enter password: ****** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 66 to server version: 5.0.18-max Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> USE gsi; Database changed mysql> SELECT * -> FROM etablissement; +------+------------------------+---------+ | nume | nome | ville | +------+------------------------+---------+ | 1 | Geoffroy-Saint-Hilaire | ETAMPES | | 2 | Vilgenis | MASSY | +------+------------------------+---------+ 2 rows in set (0.03 sec) mysql> SELECT * -> FROM stagiaire; ERROR 1142 (42000): La commande 'SELECT' est interdite Ó l'utilisateur: 'bob'@'@ localhost' sur la table 'stagiaire' Ch.4 - Applications (exercice de découverte).doc page 7 / 9 om (2005-2006) mysql> On aura vérifié que bob peut bien faire un SELECT sur la table etablissement et pas sur la table stagiaire. Vous aurez noté que lorsque nous avons attribué le privilège nous avons dû redonner le mot de passe de bob. Ce qui limite très fortement la portée de l’ordre CREATE USER. En effet, nous pouvons créer un utilisateur en même temps que nous lui accordons ses privilèges. mysql> GRANT SELECT ON gsi.* TO marc@'%' IDENTIFIED BY 'tomate34'; Query OK, 0 rows affected (0.05 sec) mysql> exit Bye C:\Program Files\EasyPHP1-8-ModGSI\mysql\bin>mysql -u marc -p Enter password: ******** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 68 to server version: 5.0.18-max Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> USE gsi; Database changed mysql> SELECT * -> FROM stagiaire; +------+-------------+---------+------------------------+------+ | nums | noms | prenoms | mails | nume | +------+-------------+---------+------------------------+------+ | 1 | Georges | Dumont | [email protected] | 1 | | 2 | Bernardette | Martin | [email protected] | 1 | +------+-------------+---------+------------------------+------+ 2 rows in set (0.03 sec) mysql> INSERT INTO stagiaire -> VALUES ('3','Henri','Grandin','[email protected]','2'); ERROR 1142 (42000): La commande 'INSERT' est interdite Ó l'utilisateur: 'marc'@' @localhost' sur la table 'stagiaire' mysql> Notre utilisateur marc a bien eu accès aux tables de la base gsi. Par contre il ne peut pas faire autre chose que des SELECT. Si nous voulons simplement changer le mot de passe de marc. mysql> SET PASSWORD FOR 'marc'@'%' = PASSWORD('nouveau_mot'); Query OK, 0 rows affected (0.00 sec) mysql> Si nous voulons supprimer les privilèges de marc. mysql> REVOKE SELECT ON gsi.* FROM 'marc'@'%'; Query OK, 0 rows affected (0.00 sec) mysql> Notre utilisateur ne pourra pas se connecter à la base gsi. Nous pouvons décider de le supprimer. mysql> DROP USER marc@'%'; Query OK, 0 rows affected (0.05 sec) mysql> L’utilisateur est définitivement supprimer et ne pourras plus se connecter à la base de données. Remarquez que nous avons précisé marc@'%' : avec les ordres CREATE USER et DROP USER vous n’êtes pas obligé de préciser '%', car par défaut, quand vous saisissez CREATE/DROP USER titi, l’utilisateur sera titi@'%'. Il n’y a que si vous voulez créer un utilisateur local titi@'locahost' ou pour une station particulière titi@'monposte' que vous devez ajouter cette mention : CREATE/DROP USER titi@'localhost'. Ch.4 - Applications (exercice de découverte).doc page 8 / 9 om (2005-2006) Création de vues Depuis la version 5, MySQL intègre la possibilité de créer des vues. Les vues permettent de projeter une image particulière d’une ou plusieurs tables. Par exemple une table où l’on masque certaines colonnes ou certaines lignes, ou bien des tables que l’on met en relation dans une vue. Prenons pour exemple la table stagiaire, à partir de laquelle nous voulons simplement établir la liste des membres avec leurs noms et leurs prénoms (on peut aisément imaginer que pour des raisons de confidentialité ou de vie privée des champs n’apparaissent plus). mysql> CREATE VIEW stage -> AS SELECT noms, prenoms -> FROM stagiaire; Query OK, 0 rows affected (0.05 sec) mysql> SELECT * -> FROM stage; +-------------+---------+ | noms | prenoms | +-------------+---------+ | Georges | Dumont | | Bernardette | Martin | +-------------+---------+ 2 rows in set (0.00 sec) mysql> Que faire avec cette vue ? Avec la partie précédente on peut très bien imaginer que cette liste épurée puisse être parcourue par un utilisateur créé pour cet effet. mysql> GRANT SELECT ON gsi.stage TO sophie@'%' IDENTIFIED BY 'fraise65'; Query OK, 0 rows affected (0.05 sec) mysql> exit Bye C:\Program Files\EasyPHP1-8-ModGSI\mysql\bin>mysql -u sophie -p Enter password: ******** Welcome to the MySQL monitor. Commands end with ; or \g. Your MySQL connection id is 91 to server version: 5.0.18-max Type 'help;' or '\h' for help. Type '\c' to clear the buffer. mysql> USE gsi; Database changed mysql> SELECT * -> FROM stage; +-------------+---------+ | noms | prenoms | +-------------+---------+ | Georges | Dumont | | Bernardette | Martin | +-------------+---------+ 2 rows in set (0.02 sec) mysql> Ch.4 - Applications (exercice de découverte).doc page 9 / 9 om (2005-2006)