Dans une requête, si les noms de colonnes ne sont pas ambiguës, il n’est pas nécessaire de rajouter devant un champ le nom de la table.
Mais ce n’est pas “propre”, c’est difficile à relire, donc si il y a des jointures au minimum préfixer le nom des champs par de simple alias pour savoir à quelle table appartient chaque champ.
C’est la jointure par défaut celle que vous devez maîtriser parfaitement
Il existe 2 manières de réaliser (écrire) une jointure interne :
SELECT <fields>
FROM TableA
INNER] JOIN TableB ON TableA.PrimaryKey = TableB.ForeignKey; [
SELECT <fields>
FROM TableA , TableB
WHERE TableA.PrimaryKey = TableB.ForeignKey;
La première méthode d’écrire une jointure avec “INNER JOIN” est recommandée bien que un peu plus difficile à écrire au début, elle est plus normalisée plus rapide pour les moteurs de SGBDR. C’est cette méthode que vous devez privilégier.
Si les clés dans les tables portent le même nom, avec le mot clé NATURAL, il est possible de définir la jointure sans utiliser le mot clé “ON” (à titre d’information, éviter cette notation).
SELECT <fields>
FROM TableA
NATURAL JOIN TableB;
Les Différents types de jointures :
Créer les 2 tables ci dessous :
DROP TABLE IF EXISTS TD_EMPLOYE,TD_DEPARTEMENT;
CREATE TABLE TD_DEPARTEMENT (
INT,
idDept VARCHAR(255),
nom VARCHAR(255),
lieu PRIMARY KEY(idDept)
);
INSERT INTO TD_DEPARTEMENT (idDept,nom,lieu) VALUES (10,"recherche","Besançon");
INSERT INTO TD_DEPARTEMENT (idDept,nom,lieu) VALUES (20,"vente","Montbéliard");
INSERT INTO TD_DEPARTEMENT (idDept,nom,lieu) VALUES (30,"direction","Belfort");
INSERT INTO TD_DEPARTEMENT (idDept,nom,lieu) VALUES (40,"fabrication","Sochaux");
CREATE TABLE TD_EMPLOYE (
INT,
idEmploye VARCHAR(255),
nom VARCHAR(255),
fonction INT,
idResponsable date,
date_embauche NUMERIC(8,2),
salaire NUMERIC(8,2),
prime INT,
departement_id PRIMARY KEY(idEmploye)
);INSERT INTO TD_EMPLOYE(nom,idEmploye,fonction,idResponsable,date_embauche,salaire,prime,departement_id) VALUES
'MARTIN',16712,'directeur',25717,'2000-05-23',8000,NULL,30);
(INSERT INTO TD_EMPLOYE(nom,idEmploye,fonction,idResponsable,date_embauche,salaire,prime,departement_id) VALUES
'DUPONT',17574,'administratif',16712,'2005-05-03',1800,NULL,30),
('DUPOND',26691,'commercial',27047,'1998-04-04',5000,500,20),
('LAMBERT',25012,'administratif',27047,'2001-03-14',NULL,2400,20),
('JOUBERT',25717,'president',NULL,'1992-08-10',10000,NULL,30),
('LEBRETON',16034,'commercial',27047,'2001-06-01',3000,0,20),
('MARTIN',17147,'commercial',27047,'2005-05-03',4000,500,20),
('PAQUEL',27546,'commercial',27047,'1993-09-03',4400,1000,20),
('LEFEBVRE',25935,'commercial',27047,'1994-01-11',4700,400,20),
('GARDARIN',15155,'ingenieur',24533,'1995-03-22',4800,NULL,10),
('SIMON',26834,'ingenieur',24533,'1998-10-04',4000,NULL,10),
('DELOBEL',16278,'ingenieur',24533,'2004-11-16',4200,NULL,10),
('ADIBA',25067,'ingenieur',24533,'1997-10-05',6000,NULL,10),
('CODD',24533,'directeur',25717,'1985-11-12',11000,NULL,10),
('LAMERE',27047,'directeur',25717,'1999-09-07',9000,NULL,20),
('BALIN',17232,'administratif',24533,'1997-10-03',2700,NULL,10),
('BARA',24831,'administratif',16712,'1998-11-10',3000,NULL,30),
('toto','00001','livreur de pizzas',NULL,NULL,NULL,NULL,NULL); (
EXERCICES : les différents cas vont être présentés à l’aide d’exemples
Dans les 2 requêtes, le résultat sera trié selon l’ordre lexicographique sur le nom de département puis le nom d’employé
+----------+---------------+----------------+
| nom | fonction | nomDepartement |
+----------+---------------+----------------+
| BARA | administratif | direction |
| DUPONT | administratif | direction |
| JOUBERT | president | direction |
| MARTIN | directeur | direction |
| ADIBA | ingenieur | recherche |
| BALIN | administratif | recherche |
| CODD | directeur | recherche |
| DELOBEL | ingenieur | recherche |
| GARDARIN | ingenieur | recherche |
| SIMON | ingenieur | recherche |
| DUPOND | commercial | vente |
| LAMBERT | administratif | vente |
| LAMERE | directeur | vente |
| LEBRETON | commercial | vente |
| LEFEBVRE | commercial | vente |
| MARTIN | commercial | vente |
| PAQUEL | commercial | vente |
+----------+---------------+----------------+
Utiliser dans la suite le mot clé JOIN pour vos jointures
R3 : refaire la même chose avec une jointure externe à droite et à gauche
Quelle est la différence avec le résultat précédent ?
R4 : afficher le nombre d’employés par département
+----------------+----------------+
| NombreEmployes | nomDepartement |
+----------------+----------------+
| 4 | direction |
| 6 | recherche |
| 7 | vente |
+----------------+----------------+
+----------------+----------------+--------------+
| NombreEmployes | nomDepartement | lieu |
+----------------+----------------+--------------+
| 4 | direction | Belfort |
| 6 | recherche | Besançon |
| 7 | vente | Montbéliard |
+----------------+----------------+--------------+
ONLY_FULL_GROUP_BY
; Regarder la valeur de la variable @@sql_mode
; ajouter puis retirer le mode ONLY_FULL_GROUP_BY
SELECT @@sql_mode ;
-- ajouter le mode
SET sql_mode=(SELECT CONCAT(@@sql_mode,',ONLY_FULL_GROUP_BY'));
-- supprimer le mode
SET sql_mode=(SELECT REPLACE(@@sql_mode, 'ONLY_FULL_GROUP_BY', ''));
ne pas faire SET sql_mode = '';
; conséquence => https://dev.mysql.com/doc/refman/8.0/en/sql-mode.html
voir config sql_mode
+---------------+-------------+
| NombreEmploye | nom |
+---------------+-------------+
| 4 | direction |
| 0 | fabrication |
| 6 | recherche |
| 7 | vente |
+---------------+-------------+
+-------------+
| nom |
+-------------+
| fabrication |
+-------------+
+---------------+-------------+
| NombreEmploye | nom |
+---------------+-------------+
| 0 | fabrication |
+---------------+-------------+
le résultat sera trié selon l’ordre lexicographique sur la fonction du responsable puis le nom du responsable puis la fonction de l’employé puis le nom de l’employé
+----------+---------------+----------------+---------------------+
| nom | fonction | nomResponsable | FonctionResponsable |
+----------+---------------+----------------+---------------------+
| BALIN | administratif | CODD | directeur |
| ADIBA | ingenieur | CODD | directeur |
| DELOBEL | ingenieur | CODD | directeur |
| GARDARIN | ingenieur | CODD | directeur |
| SIMON | ingenieur | CODD | directeur |
| LAMBERT | administratif | LAMERE | directeur |
| DUPOND | commercial | LAMERE | directeur |
| LEBRETON | commercial | LAMERE | directeur |
| LEFEBVRE | commercial | LAMERE | directeur |
| MARTIN | commercial | LAMERE | directeur |
| PAQUEL | commercial | LAMERE | directeur |
| BARA | administratif | MARTIN | directeur |
| DUPONT | administratif | MARTIN | directeur |
| CODD | directeur | JOUBERT | president |
| LAMERE | directeur | JOUBERT | president |
| MARTIN | directeur | JOUBERT | president |
+----------+---------------+----------------+---------------------+
+--------+-----------+----------------+---------------------+
| nom | fonction | nomResponsable | FonctionResponsable |
+--------+-----------+----------------+---------------------+
| MARTIN | directeur | JOUBERT | president |
| CODD | directeur | JOUBERT | president |
| LAMERE | directeur | JOUBERT | president |
+--------+-----------+----------------+---------------------+
+----------+------------+----------+
| nom | fonction | salaire |
+----------+------------+----------+
| GARDARIN | ingenieur | 4800.00 |
| DELOBEL | ingenieur | 4200.00 |
| MARTIN | directeur | 8000.00 |
| CODD | directeur | 11000.00 |
| ADIBA | ingenieur | 6000.00 |
| JOUBERT | president | 10000.00 |
| LEFEBVRE | commercial | 4700.00 |
| DUPOND | commercial | 5000.00 |
| LAMERE | directeur | 9000.00 |
| PAQUEL | commercial | 4400.00 |
+----------+------------+----------+
Une caractéristique puissante de SQL est la possibilité qu’un critère de recherche employé dans une clause WHERE (expression à droite d’un opérateur de comparaison) soit lui-même le résultat d’un SELECT ; c’est ce qu’on appelle une sous-interrogation.
https://dev.mysql.com/doc/refman/5.7/en/any-in-some-subqueries.html
Remarque : Tout ces cas ne sont pas à connaître par cœur mais l’objectif est de vous montrer la complexité possible de certaines requêtes faites avec un SELECT
R10 : Quels sont les employés ayant la même fonction que “codd” ?
+--------+-----------+----------+---------------+
| nom | fonction | salaire | idResponsable |
+--------+-----------+----------+---------------+
| MARTIN | directeur | 8000.00 | 25717 |
| CODD | directeur | 11000.00 | 25717 |
| LAMERE | directeur | 9000.00 | 25717 |
+--------+-----------+----------+---------------+
R11 : Liste des employés gagnant plus que la moyenne des salaires.
+---------+-----------+----------+
| nom | fonction | salaire |
+---------+-----------+----------+
| MARTIN | directeur | 8000.00 |
| CODD | directeur | 11000.00 |
| ADIBA | ingenieur | 6000.00 |
| JOUBERT | president | 10000.00 |
| LAMERE | directeur | 9000.00 |
+---------+-----------+----------+
Remarques :
+---------+-----------+----------+
| nom | fonction | salaire |
+---------+-----------+----------+
| CODD | directeur | 11000.00 |
| JOUBERT | president | 10000.00 |
+---------+-----------+----------+
+--------------+
| min(salaire) |
+--------------+
| 3000.00 |
+--------------+
+----------+------------+----------+
| nom | fonction | salaire |
+----------+------------+----------+
| GARDARIN | ingenieur | 4800.00 |
| DELOBEL | ingenieur | 4200.00 |
| MARTIN | directeur | 8000.00 |
| MARTIN | commercial | 4000.00 |
| CODD | directeur | 11000.00 |
| ADIBA | ingenieur | 6000.00 |
| JOUBERT | president | 10000.00 |
| LEFEBVRE | commercial | 4700.00 |
| DUPOND | commercial | 5000.00 |
| SIMON | ingenieur | 4000.00 |
| LAMERE | directeur | 9000.00 |
| PAQUEL | commercial | 4400.00 |
+----------+------------+----------+
Il est possible de comparer le résultat d’un SELECT ramenant plusieurs colonnes à une liste de colonnes. La liste de colonnes figurera entre parenthèses à gauche de l’opérateur de comparaison.
+--------+-----------+----------+---------------+
| nom | fonction | salaire | idResponsable |
+--------+-----------+----------+---------------+
| MARTIN | directeur | 8000.00 | 25717 |
| CODD | directeur | 11000.00 | 25717 |
| LAMERE | directeur | 9000.00 | 25717 |
+--------+-----------+----------+---------------+
Dans les exemples précédents, la sous-interrogation était évaluée d’abord, puis le résultat pouvait être utilisé pour exécuter l’interrogation principale.
SQL sait également traiter une sous-interrogation faisant référence à une colonne de la table de l’interrogation principale.
Le traitement dans ce cas est plus complexe car il faut évaluer la sous-interrogation pour chaque ligne de l’interrogation principale.
+--------+
| nom |
+--------+
| CODD |
| LAMERE |
+--------+
L’opérateur EXISTS permet de construire un prédicat vrai si la sous-interrogation qui suit ramène au moins une ligne.
+----------+-----------+---------------+---------------+----------------+
| nom | idEmploye | fonction | date_embauche | departement_id |
+----------+-----------+---------------+---------------+----------------+
| LEBRETON | 16034 | commercial | 2001-06-01 | 20 |
| MARTIN | 16712 | directeur | 2000-05-23 | 30 |
| MARTIN | 17147 | commercial | 2005-05-03 | 20 |
| DUPONT | 17574 | administratif | 2005-05-03 | 30 |
| BARA | 24831 | administratif | 1998-11-10 | 30 |
| LAMBERT | 25012 | administratif | 2001-03-14 | 20 |
| JOUBERT | 25717 | president | 1992-08-10 | 30 |
| LEFEBVRE | 25935 | commercial | 1994-01-11 | 20 |
| DUPOND | 26691 | commercial | 1998-04-04 | 20 |
| LAMERE | 27047 | directeur | 1999-09-07 | 20 |
| PAQUEL | 27546 | commercial | 1993-09-03 | 20 |
+----------+-----------+---------------+---------------+----------------+
Un SELECT peut comporter plusieurs sous-interrogations, soit imbriquées, soit au même niveau dans différents prédicats combinés par des AND ou des OR.
+-------+---------------+----------------+
| nom | fonction | departement_id |
+-------+---------------+----------------+
| BALIN | administratif | 10 |
| CODD | directeur | 10 |
+-------+---------------+----------------+
DROP TABLE IF EXISTS TD_CLIENT1,TD_CLIENT2;
CREATE TABLE TD_CLIENT1 (
varchar(30)
nom
);INSERT INTO TD_CLIENT1 VALUES ('nom1');
INSERT INTO TD_CLIENT1 VALUES ('nom2');
INSERT INTO TD_CLIENT1 VALUES ('nom3');
CREATE TABLE TD_CLIENT2 (
varchar(30)
nom
);INSERT INTO TD_CLIENT2 VALUES ('nom1');
INSERT INTO TD_CLIENT2 VALUES ('nom2');
INSERT INTO TD_CLIENT2 VALUES ('nom10');
INSERT INTO TD_CLIENT2 VALUES ('nom11');
SELECT nom FROM TD_CLIENT1;
SELECT nom FROM TD_CLIENT2;
SELECT nom FROM TD_CLIENT1
UNION
SELECT nom FROM TD_CLIENT2;
SELECT nom FROM TD_CLIENT1
UNION ALL
SELECT nom FROM TD_CLIENT2;
-- ==> ne fonctionne pas sur MYSQL mais sur ORACLE
SELECT nom FROM TD_CLIENT1
INTERSECT
SELECT nom FROM TD_CLIENT2; -- (nom1 et nom2)
-- utiliser IN sur MYSQL
SELECT nom FROM TD_CLIENT1
WHERE nom IN
SELECT nom FROM TD_CLIENT2); (
-- ==> ne fonctionne pas sur MYSQL mais sur ORACLE
SELECT nom FROM TD_CLIENT1
EXCEPT
SELECT nom FROM TD_CLIENT2; -- (nom3)
-- utiliser NOT IN sur MYSQL
SELECT nom FROM TD_CLIENT1
WHERE nom NOT IN
SELECT nom FROM TD_CLIENT2); (
+-------------+--------+----------+-------------------+----------------+
| nom | idDept | nom | fonction | departement_id |
+-------------+--------+----------+-------------------+----------------+
| recherche | 10 | GARDARIN | ingenieur | 10 |
....
| direction | 30 | JOUBERT | president | 30 |
| fabrication | 40 | NULL | NULL | NULL |
| NULL | NULL | toto | livreur de pizzas | NULL |
+-------------+--------+----------+-------------------+----------------+
19 rows in set (0.01 sec)
Structure de données qui reprend la liste ordonnée des valeurs auxquelles il se rapporte. (exemple de définition)
Lorsque vous créez un index sur une table, MySQL stocke cet index sous forme d’une structure particulière, contenant les valeurs des colonnes impliquées dans l’index.
Création d’un index sur MySql
CREATE TABLE nom_table (
colonne1 description_colonne1,
[colonne2 description_colonne2,
colonne3 description_colonne3,...,]
PRIMARY KEY (colonne_clé_primaire)],
[INDEX|KEY} [nom_index] (colonne1_index [, colonne2_index, ...]],
[{UNIQUE [INDEX|KEY] [nom_index] (colonne1_index [, colonne2_index, ...]]
[ );
exemple :
CREATE TABLE TD_EMPLOYE;
SHOW ALTER TABLE TD_EMPLOYE ADD INDEX `departement_nom_index` (`nom`);
ALTER TABLE TD_EMPLOYE ADD INDEX `employe_date_embauche_index` (`date_embauche`);
CREATE TABLE TD_EMPLOYE;
SHOW INDEX FROM TD_EMPLOYE \G SHOW
EXPLAIN SELECT TD_EMPLOYE.nom FROM TD_EMPLOYE WHERE fonction LIKE 'd%' AND date_embauche >='1985-11-12' \G
EXPLAIN
SELECT DISTINCT E1.nom
FROM TD_EMPLOYE E1, TD_DEPARTEMENT D1, TD_EMPLOYE E2, TD_DEPARTEMENT D2
WHERE E1.departement_id=D1.idDept
AND E2.departement_id=D2.idDept
AND D1.nom='vente'
AND D2.nom='direction'
AND E1.date_embauche=E2.date_embauche
\G
réflexion sur l’optimisation des requêtes
SHOW PROCESSLIST;-- ouvrir 2 terminaux connectés à mysql
SET profiling = 1;
--exécuter une requête
PROFILE; SHOW
GLOBAL STATUS like "%used_connections";
SHOW global status like 'opened_tables';
show SELECT @@table_open_cache;
SELECT @@max_connections;
optimisation du code sur www.altidev.com/livres.php un article
Les vues permettent d’assurer l’objectif d’indépendance logique. Grâce à elles, chaque utilisateur pourra avoir sa vision propre des données.
On a vu que le résultat d’un SELECT est lui-même une table.
Une telle table, qui n’existe pas dans la base mais est créée dynamiquement lors de l’exécution du SELECT, peut être vue comme une table réelle par les utilisateurs. Pour cela, il suffit de cataloguer le SELECT en tant que vue.
Les utilisateurs pourront consulter la base, ou modifier la base (avec certaines restrictions) à travers la vue, c’est-à-dire manipuler la table résultat du SELECT comme si c’était une table réelle.
La commande CREATE VIEW permet de créer une vue en spécifiant le SELECT constituant la définition de la vue :
CREATE VIEW nom_vue [(nom_col1,...)]
AS SELECT ...
[WITH CHECK OPTION] ;
La spécification des noms de colonnes de la vue est facultative. Par défaut, les noms des colonnes de la vue sont les mêmes que les noms des colonnes résultat du SELECT (si certaines colonnes résultat du SELECT sont des expressions, il faut renommer ces colonnes dans le SELECT, ou spécifier les noms de colonne de la vue).
Une fois créée, une vue s’utilise comme une table. Il n’y a pas de duplication des informations mais stockage de la définition de la vue.
Exemple : Création d’une vue constituant une restriction de la table TD_EMPLOYE aux employés du département 10.
CREATE VIEW v_emp10 AS
SELECT *
FROM TD_EMPLOYE
WHERE departement_id = 10 ;
CREATE VIEW v_emp10co AS
SELECT *
FROM TD_EMPLOYE
WHERE departement_id = 10
WITH CHECK OPTION ;
-- pour les visualiser
SHOW TABLES;
Le CHECK OPTION permet de vérifier que la mise à jour ou l’insertion faite à travers la vue ne produisent que des lignes qui font partie de la sélection de la vue.
Ainsi donc, si la vue v_emp10co a été créée avec CHECK OPTION, on ne pourra à travers cette vue ni modifier, ni insérer des employés ne faisant pas partie du département 10.
Exemple : Modification des salaires du département 10 à travers la vue v_emp10.
SELECT * FROM v_emp10;
UPDATE v_emp10 SET salaire = salaire * 1.1;
SELECT * FROM TD_EMPLOYE;
Toutes les lignes de la table TD_EMPLOYE, telles que le contenu de la colonne departement_id est égal à 10 seront modifiées.
SELECT * FROM v_emp10;
UPDATE v_emp10 SET departement_id=20 where idEmploye=15155;
SELECT * FROM v_emp10;
UPDATE v_emp10 SET departement_id=10 where idEmploye=15155;
SELECT * FROM v_emp10;
-- on ne retrouve plus l'employe GARDARIN !
SELECT * FROM v_emp10co;
UPDATE v_emp10co SET departement_id=20 where idEmploye=26834;
SELECT * FROM v_emp10co;
UPDATE v_emp10co SET departement_id=10 where idEmploye=26834;
Une vue peut être détruite par la commande :
DROP VIEW nom_vue;
On peut renommer une vue par la commande :
RENAME ancien_nom TO nouveau_nom;
DROP VIEW v_emp10,v_emp10co;
http://polymorphe.free.fr/cours/bd/sql/sql_avance/poly_39.html
https://perso.liris.cnrs.fr/fabien.duchateau/BDW1/
Pour aller plus loin
+---------+----------+
| nom | salaire |
+---------+----------+
| MARTIN | 8000.00 |
| CODD | 11000.00 |
| JOUBERT | 10000.00 |
| LAMERE | 9000.00 |
+---------+----------+
+-------+-----------+---------------+
| nom | nom | fonction |
+-------+-----------+---------------+
| BALIN | recherche | administratif |
| CODD | recherche | directeur |
+-------+-----------+---------------+
+--------+
| nom |
+--------+
| MARTIN |
+--------+
+---------+
| nom |
+---------+
| CODD |
| JOUBERT |
+---------+
+----------+---------------+---------+---------------+
| nom | date_embauche | nom | date_embauche |
+----------+---------------+---------+---------------+
| CODD | 1985-11-12 | JOUBERT | 1992-08-10 |
| BARA | 1998-11-10 | MARTIN | 2000-05-23 |
| LEFEBVRE | 1994-01-11 | LAMERE | 1999-09-07 |
| DUPOND | 1998-04-04 | LAMERE | 1999-09-07 |
| PAQUEL | 1993-09-03 | LAMERE | 1999-09-07 |
+----------+---------------+---------+---------------+
+---------+----------+
| nom | salaire |
+---------+----------+
| CODD | 11000.00 |
| JOUBERT | 10000.00 |
| LAMERE | 9000.00 |
+---------+----------+
+--------------+-------------------+--------------+
| AVG(salaire) | fonction | min(salaire) |
+--------------+-------------------+--------------+
| 2500.000000 | administratif | 1800.00 |
| 4220.000000 | commercial | 3000.00 |
| 9333.333333 | directeur | 8000.00 |
| 4750.000000 | ingenieur | 4000.00 |
| NULL | livreur de pizzas | NULL |
| 10000.000000 | president | 10000.00 |
+--------------+-------------------+--------------+
R26 : Donner les emplois ayant le salaire moyen le plus bas; donnez aussi leur salaire moyen.