Langage SQL⚓︎
Contenus | Capacités Attendues |
Commentaires |
---|---|---|
Langage SQL : requêtes d’interrogation et de mise à jour d’une base de données. |
Identifier les composants d’une requête. Construire des requêtes d’interrogation à l’aide des clauses du langage SQL : SELECT, FROM, WHERE, JOIN. Construire des requêtes d’insertion et de mise à jour à l’aide de : UPDATE, INSERT, DELETE. |
On peut utiliser DISTINCT, ORDER BY ou les fonctions d’agrégation sans utiliser les clauses GROUP BY et HAVING. |
Histoire⚓︎
Développé par IBM dans les années \(1970\), le ou
, devient rapidement le standard des langages de bases de données relationnelles. Il permet les opérations usuelles (CRUD: insertion, lecture, mise à jour, suppression) sur les bases de données, avec un nombre minimaliste d'instructions, dont la syntaxe est (de plus) proche de la syntaxe anglaise.
Installation & Configuration⚓︎
Pour pouvoir utiliser le langage SQL, il faut avoir installé (et configuré... au moins un peu..):
- un serveur physique pour héberger les données
- un SGBD pour la manipuler :
- En lignes de commandes: Sqlite, MySQL, PostgreSQL, etc... sont des solutions possibles, Open Source et Gratuite,
- Interfaces Graphiques autorisant les requêtes SQL : PhpMyAdmin (en PHP, installé au-dessus du serveur Apache: WAMP/LAMP/MAMP), Sqlite Manager est un plugin Firefox pour SQLite
Requêtes SQL⚓︎
Requête
Une
Dans tout ce qui suit :
- On suppose que l'un des SGBD est installé (MySQL, MariaDB, PostgreSQL, SQLite, etc..) , et configuré.
- éventuellement (si besoin est) que le serveur/démon de bases de données ait été lancé sur la machine
- on va détailler quelques requêtes classiques
nous utiliserons MariaDB (i.e. MySQL)
Types de Données MySQL⚓︎
Les Types (de Données) suivants sont disponibles dans MySQL:
Numérique : Entiers⚓︎
Type | Nombre d'Octets | Minimum | Maximum |
---|---|---|---|
TINYINT |
1 | -128 | 127 |
SMALLINT |
2 | -32768 | 32767 |
MEDIUMINT |
3 | -8388608 | 8388607 |
INT |
4 | -2147483648 | 2147483647 |
BIGINT |
8 | -9223372036854775808 | 9223372036854775807 |
INT(x)
: permet de préciser le nombrex
de chiffres minimum à l'affichage d'une colonne de type INT (ou un de ses dérivés)ZEROFILL
, cumulé avecINT(x)
, ajoute autant de zéros à gauche que nécessaire, lors de l'affichage du nombre- L'attribut
UNSIGNED
permet de préciser que l'entier est non signé c'est à dire positif : Dans ce cas, la longueur de l'intervalle reste la même, mais les valeurs possibles sont décalées, le minimum valant 0. Ex:UNSIGNED TINYINT
s'étale de 0 à 255.
Numérique : Flottants⚓︎
Type | Syntaxe | Valeur Exacte vs Valeur Approchée |
---|---|---|
DECIMAL \(=\) NUMERIC |
DECIMAL(n,p) affiche le nombre avec n chiffres significatifs au maximumdont p sont après la virguleDECIMAL(n) = DECIMAL(n,0) |
stocké comme chaîne de caractère donc valeur exacte |
FLOAT |
FLOAT stocké sur \(4\) octetsFLOAT(n,p) comme DECIMAL |
stocké comme nombre donc valeur approchée |
REAL |
REAL |
^ |
DOUBLE |
DOUBLE : stocké sur \(8\) octets |
^ |
Chaînes de Caractères de Type Texte⚓︎
Type | Syntaxe | Taille Maximale | Stockage Mémoire |
---|---|---|---|
CHAR |
CHAR(x) contient jusqu'à x caractères |
\(255\) octets | taille fixe : stocké toujours exactement sur x caractères,quitte à compléter avec des espaces ( x entre \(1\) et \(255\)) |
VARCHAR |
VARCHAR(x) contient jusqu'à x caractères |
\(255\) octets | taille variable : (de \(0\)) jusqu'à x caractères ( x entre \(1\) et \(255\)) |
TINYTEXT |
TINYTEXT |
\(255\) octets | Longueur Chaîne\(+1\) octets |
TEXT |
TEXT |
\(2^{16}\) octets | Longueur Chaîne\(+2\) octets |
MEDIUMTEXT |
MEDIUMTEXT |
\(2^{24}\) octets | Longueur Chaîne\(+3\) octets |
LONGTEXT |
LONGTEXT |
\(2^{32}\) octets | Longueur Chaîne\(+4\) octets |
Chaînes de Caractères de Type Binaire⚓︎
De même que les chaînes de type texte, une chaîne binaire n'est rien d'autre qu'une suite de caractères.
Néanmoins, si les textes sont affectés par l'encodage et l'interclassement, ce n'est pas le cas des chaînes binaires. Une chaîne binaire n'est rien d'autre qu'une suite d'octets. Aucune interprétation n'est faite sur ces octets, en particulier :
- Une chaîne binaire traite directement l'octet, et pas le caractère que l'octet représente.
- Tous les caractères sont utilisables, y compris les fameux caractères de contrôle non affichables définis dans la table ASCII.
Type | Syntaxe | Taille Maximale | Stockage Mémoire |
---|---|---|---|
BINARY |
BINARY(x) contient jusqu'à x caractères binaires |
\(255\) octets | taille fixe : stocké toujours exactement sur x caractères binaires,quitte à compléter avec des espaces ( x entre \(1\) et \(255\)) |
VARBINARY |
VARBINARY(x) contient jusqu'à x caractères binaires |
\(255\) octets | taille variable : (de \(0\)) jusqu'à x caractères ( x entre \(1\) et \(255\)) |
TINYBLOB |
TINYBLOB |
\(255\) octets | Longueur Chaîne\(+1\) octets |
BLOB |
BLOB |
\(2^{16}\) octets | Longueur Chaîne\(+2\) octets |
MEDIUMBLOB |
MEDIUMBLOB |
\(2^{24}\) octets | Longueur Chaîne\(+3\) octets |
LONGBLOB |
LONGBLOB |
\(2^{32}\) octets | Longueur Chaîne\(+4\) octets |
SET et ENUM⚓︎
SET
et ENUM
permettent de définir un certain nombre de valeurs autorisées de type chaînes de caractères.
SET
et ENUM
sont des types spécifiques à MySQL : c'est donc une très mauvaise idée de les utiliser, sauf si vous êtes vraiement certain de ne jamais changer de SGBD.
SET("Fraises", "Framboises", "Mangue")
ENUM("Fraises", "Framboises", "Mangue")
Heures et Dates⚓︎
Type | Signification | Format | Exemples |
---|---|---|---|
DATE |
Sert à stocker une Date | Chaîne de caractères ou Nombre |
'AAAA-MM-JJ' 'AAMMJJ' 'AA/MM/JJ' 'AA+MM+JJ' 'AAAA%MM%JJ' AAAAMMJJ (Nombre)AAMMJJ (Nombre) |
TIME |
Sert à stocker une Heure | Chaîne de caractères ou Nombre |
'HH:MM:SS' 'HHH:MM:SS' 'MM+SS' 'J HH:MM:SS' 'HHMMSS' HHMMSS (Nombre) |
DATETIME |
Sert à stocker une Date et une Heure | Chaîne de caractères ou Nombre |
'AAAA-MM-JJ HH:MM:SS' 'AA*MM*JJ HH+MM+SS' AAAAMMJJHHMMSS (Nombre) |
YEAR |
Sert à stocker une Année | Chaîne de caractères ou Nombre sur \(1\) octet : entre \(1901\) et \(2155\) |
'YY' (Chaîne de Caractère) Ex : '00' \(=2000\) YY (Nombre) Ex : 00 \(=0000\) |
TIMESTAMP |
Nombre de Secondes écoulées depuis le \(1\)er Janvier \(1970\) \(0\) h \(0\) min \(0\) s (TUC) |
TIMESTAMP (Nombre) sur \(4\) octets :Date Maximale : \(19\) janvier \(2038\) à \(3\) h \(14\) min \(7\) s |
Si la date est \(2021-05-30\) \(19:25:00\) le nombre de secondes écoulées depuis \(1970\) est \(589067407500\) néanmoins le TIMESTAMP stocké n'est PAS \(589067407500\), mais bien \(20210530192500\) |
NULL
vs NOT NULL
⚓︎
De nombreux types de Données de MySQL :
- autorisent la valeur
NULL
\(=\) absence de valeur - Pire : En cas d'absence de valeur d'un champ/attribut lors de la création d'un nouvel l'enregistrement, le plus probable/fréquent est que ce soit la valeur
NULL
qui lui soit attribuée par défaut. Cela peut être ce que l'on souhaite, mais comment empêcher un champ/attribut de prendre la valeur NULL? en spécifiant, lors de la création de la table, que ce champ ne peut pas prendre la valeur NULL, en précisant que ce champ doit être :NOT NULL
AUTO_INCREMENT, PRIMARY KEY et FOREIGN KEY⚓︎
Déclaration/Statement | Signification |
---|---|
AUTO_INCREMENT |
incrémentation automatique du champ/attribut |
PRIMARY KEY |
Clé Primaire |
FOREIGN KEY [id_name] (nom_col,..) REFERENCES nom_table (nom_col,.. |
Clé Étrangère |
Voir des exemples de Syntaxe dans : Création de Tables
Gestion de Bases de Données⚓︎
SHOW DATABASES
: Affiche les Bases de Données⚓︎
> SHOW DATABASES;
+--------------------+
| Database |
+--------------------+
| information_schema |
| mysql |
| performance_schema |
| phpmyadmin |
+--------------------+
4 rows in set (0.001 sec)
CREATE DATABASE
: Crée une Base de Données⚓︎
Opération à Faire seulement la toute première fois :
# l option facultative IF NOT EXISTS (ne pas écrire les [])
# empêche l écrasement au cas où la base existerait déjà
> CREATE DATABASE name [IF NOT EXISTS];
Exp
# Crée une base de Donnée 'eleve'
> CREATE DATABASE eleve;
# ou bien
> CREATE DATABASE eleve IF NOT EXISTS;
Query OK, 1 row affected (0.000 sec)
> SHOW DATABASES;
USE
: Utiliser une Base de Données⚓︎
ATTENTION
il est OBLIGATOIRE de préciser quelle base de données on veut utiliser, grâce à l'instruction sql
USE
, c'est à dire sur quelle base de données on souhaite travailler.
> USE name;
Exp
MariaDB [(none)]> USE eleve;
Database changed
MariaDB [eleve]>
DROP DATABASE
: supprime une Base de Données⚓︎
# Supprime une base de Donnée 'eleve'
> DROP DATABASE eleve;
Query OK, 0 rows affected (0.004 sec)
> SHOW DATABASES;
Enfin, Recréez une Base de Données eleve
: > CREATE DATABASE eleve;
puis > USE eleve;
Gestion de Tables⚓︎
CREATE TABLE
: Création de Table.s⚓︎
# Options Facultatives entre [] : (ne pas écrire les []) IF NOT EXISTS ou
# ENGINE=INNODB qui définit le moteur sql choisi (par défaut : INNODB)
> CREATE TABLE name [IF NOT EXISTS] (
-> attribut1 type,
-> attribut2 type,
-> ...
-> ) [ENGINE=INNODB];
Créer les tables, dans le "bon" ordre, directement avec les clés (primaires et étrangères)
CREATE TABLE adresse (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
ville VARCHAR(20),
pays VARCHAR(20)
) ;
Query OK, 0 rows affected (0.021 sec)
CREATE TABLE utilisateur (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
nom VARCHAR(20),
prenom VARCHAR(20),
genre VARCHAR(20),
id_adresse INT UNSIGNED NOT NULL,
FOREIGN KEY (id_adresse) REFERENCES adresse (id)
) ;
Query OK, 0 rows affected (0.004 sec)
ou bien, Syntaxe Alternative :
Méthode 2 : Créer les tables dans un ordre quelconque, avec les clés primaires, puis déclarer les clés étrangères APRÈS COUP
CREATE TABLE utilisateur (
id INT UNSIGNED NOT NULL AUTO_INCREMENT,
nom VARCHAR(20),
prenom VARCHAR(20),
genre VARCHAR(20),
id_adresse INT UNSIGNED NOT NULL,
PRIMARY KEY (id)
) ;
Query OK, 0 rows affected (0.004 sec)
CREATE TABLE adresse (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
ville VARCHAR(20),
pays VARCHAR(20)
) ;
Query OK, 0 rows affected (0.019 sec)
Ajout des clés étrangères APRÈS COUP :
Modification de la table utilisateur
après sa création...
ALTER TABLE utilisateur
ADD FOREIGN KEY (id_adresse) REFERENCES adresse (id);
Query OK, 0 rows affected (0.040 sec)
Records: 0 Duplicates: 0 Warnings: 0
Cela a pour effet de créer :
-
une table
utilisateur
:- avec un champ/attribut
id
:- qui contient un nombre entier (
INT
) - positif (
UNSIGNED
), - n'autorisant PAS la valeur
NULL
pour le champid
, - dont la gestion des valeurs est automatique (
AUTO_INCREMENT
). on dira auto_incrémenté par la suite.. - qui est une clé primaire pour la table
utilisateur
(PRIMARY KEY
ouPRIMARY KEY (id)
)
- qui contient un nombre entier (
- un champ/attribut
nom
, Chaîne de caractères pouvant contenir un nombre variable de caractères : jusqu'à 20. - un champ/attribut
prenom
, Chaîne de caractères pouvant contenir un nombre variable de caractères : jusqu'à 20. - un champ/attribut
genre
, chaîne de caractères variable (jusqu'à 20). - un champ/attribut
id_adresse
, entier posifif non nul, qui est une clé étrangère qui référenceadresse(id)
- avec un champ/attribut
-
une table
adresse
:- avec un champ/attribut
id
entier, positif, non null, auto_incrémenté, clé primaire de la tableadresse
- un champ
ville
chaîne de caractères variables (jusqu'à 20) - un champ
pays
chaîne de caractères variables (jusqu'à 20)
- avec un champ/attribut
SHOW TABLES
: Affiche les Tables⚓︎
Vérifier que la/les tables ont bien été créées :
> SHOW TABLES;
+-----------------+
| Tables_in_eleve |
+-----------------+
| adresse |
| utilisateur |
+-----------------+
2 rows in set (0.001 sec)
DESCRIBE
: Décrit les champs/attributs et les Types d'une Table⚓︎
Décrit/Affiche le schéma de la structure d'une table.
> DESCRIBE nom_table;
Exp
MariaDB [eleve]> DESCRIBE utilisateur;
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| nom | varchar(20) | YES | | NULL | |
| prenom | varchar(20) | YES | | NULL | |
| genre | varchar(20) | YES | | NULL | |
| id_adresse | int(10) unsigned | NO | MUL | NULL | |
+------------+------------------+------+-----+---------+----------------+
5 rows in set (0.001 sec)
DROP TABLE
: Suppression de Table⚓︎
> DROP TABLE nom_table;
Exp
MariaDB [eleve]> SHOW TABLES;
+-----------------+
| Tables_in_eleve |
+-----------------+
| adresse |
| utilisateur |
+-----------------+
2 rows in set (0.001 sec)
MariaDB [eleve]> DROP TABLE adresse;
ERROR 1451 (23000): Cannot delete or update a parent row: a foreign key constraint fails
MariaDB [eleve]> DROP TABLE utilisateur;
Query OK, 0 rows affected (0.015 sec)
MariaDB [eleve]> SHOW TABLES;
+-----------------+
| Tables_in_eleve |
+-----------------+
| adresse |
+-----------------+
1 row in set (0.001 sec)
RECRÉÉZ LA TABLE
utilisateur
AVEC SA CLÉ ÉTRANGÈRE (vous pouvez copier-coller la définition plus haut)
ALTER TABLE
: Modification de Table⚓︎
Voici comme modifier une Table :
Ajout de champ/attribut/colonne⚓︎
> ALTER TABLE nom_table
-> ADD nom_colonne type_donnees;
Ajoute un champ age
de type INT
à la table utilisateur
:
> ALTER TABLE utilisateur
-> ADD age INT NOT NULL;
Query OK, 0 rows affected (0.079 sec)
Records: 0 Duplicates: 0 Warnings: 0
Suppression de champ/attribut/colonne⚓︎
> ALTER TABLE nom_table
-> DROP [COLUMN] nom_colonne;
Supprime le champ/attribut/colonne age
dans la table utilisateur
:
> ALTER TABLE utilisateur
-> DROP age;
Modifier la structure d'un champ/attribut/colonne⚓︎
> ALTER TABLE nom_table
-> MODIFY nom_colonne type_donnees;
Exp
Modifie le champ age
en un nouveau type FLOAT
dans la table utilisateur
:
> ALTER TABLE utilisateur
-> MODIFY age FLOAT;
Query OK, 0 rows affected (0.006 sec)
Records: 0 Duplicates: 0 Warnings: 0
Renommer un champ/attribut/colonne⚓︎
> ALTER TABLE nom_table
-> CHANGE OLD_nom_colonne NEW_nom_colonne NEW_type_donnees;
Exp
Renomme le champ ville
en departement
avec le type VARCHAR(30)
dans la table utilisateur
:
> ALTER TABLE utilisateur
-> CHANGE age experience INT;
Query OK, 0 rows affected (0.079 sec)
Records: 0 Duplicates: 0 Warnings: 0
Ex
renommer la colonne
experience
en age
, entier non nul.
Résumé Final⚓︎
> DESCRIBE utilisateur;
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| nom | varchar(20) | YES | | NULL | |
| prenom | varchar(20) | YES | | NULL | |
| genre | varchar(20) | YES | | NULL | |
| id_adresse | int(10) unsigned | NO | MUL | NULL | |
| age | int(11) | NO | | NULL | |
+------------+------------------+------+-----+---------+----------------+
6 rows in set (0.001 sec)
> DESCRIBE adresse;
+-------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| ville | varchar(20) | YES | | NULL | |
| pays | varchar(20) | YES | | NULL | |
+-------+------------------+------+-----+---------+----------------+
3 rows in set (0.001 sec)
CRUD d'enregistrements de Tables⚓︎
INSERT INTO ... VALUES ...
: Insertion/Création d'enregistrements dans une Table⚓︎
> INSERT INTO nom_table (col1, col2,...)
-> VALUES (valeur1, valeur2,...);
Ajout d'Enregistrements Un par un⚓︎
> INSERT INTO adresse (ville, pays)
-> VALUES ('Marseille', 'France');
Query OK, 1 row affected (0.002 sec)
Ajout de Plusieurs Enregistrements en un seul coup⚓︎
> INSERT INTO adresse (ville, pays)
-> VALUES ('Toulouse', 'France'),
-> ('Bordeaux', 'France');
Query OK, 2 rows affected (0.004 sec)
Records: 2 Duplicates: 0 Warnings: 0
Pour la suite, afin de travailler avec des tables un peu renseignées, en plus des enregistrements précédents, copiez-coller les enregistrements suivants :
INSERT INTO adresse (ville, pays)
VALUES ('Paris', 'France'),
('Strasbourg', 'France'),
('Brest', 'France'),
('Lyon', 'France'),
('Granada', 'Espagne'),
('Madrid', 'Espagne'),
('Sevilla', 'Espagne'),
('Valencia', 'Espagne'),
('Oxford', 'UK'),
('Cambridge', 'UK'),
('London', 'UK');
Query OK, 11 rows affected (0.014 sec)
Records: 11 Duplicates: 0 Warnings: 0
INSERT INTO utilisateur (nom, prenom, genre, id_adresse, age)
VALUES ('Dupont', 'Gaelle', 'Femme', 1, 27),
('Dupond', 'Jean', 'Homme', 3, 24),
('Durand', 'Laura', 'Femme', 2, 28),
('Dufour', 'Sarah', 'Femme', 4, 18),
('Dumiel', 'Paul', 'Homme', 5, 19),
('Durmont', 'Karl', 'Homme', 12, 25),
('Doe', 'John', 'Homme', 13, 29),
('Dorne', 'Jane', 'Femme', 14, 29),
('Sanchez', 'Maria', 'Homme', 9, 23),
('Martinez', 'Juan', 'Homme', 8, 22),
('Santamaria', 'Alvaro', 'Homme', 10, 26),
('Santiago', 'Marta', 'Homme', 11, 20);
Query OK, 12 rows affected (0.001 sec)
Records: 12 Duplicates: 0 Warnings: 0
SELECT
: Sélection/Lecture/Affichage d'Attributs d'une Table⚓︎
SELECT
est une , ou
permettant de sélectionner / afficher certains enregistrements d'une table vérifant optionnellement certains critères conditionnels.
SELECT : Syntaxe Générale
SELECT [DISTINCT] {expr1_selection, expr2_selection,...}
FROM nom_table
[ WHERE condition_recherche ]
[ GROUP BY {nom_col | expr | position} [ASC | DESC] ]
[ HAVING condition ]
[ ORDER BY {nom_col | expr_tri | position} [ASC | DESC] ]
[ LIMIT n ]
La syntaxe générale dispose d'options appelées des clauses:
CLAUSE
Une
SELECT ... FROM ...⚓︎
SELECT * FROM nom_table
: La TOUS
les attributs pour tous les enregistrements de la Table utilisateur
> SELECT * FROM utilisateur;
+----+------------+--------+-------+------------+-----+
| id | nom | prenom | genre | id_adresse | age |
+----+------------+--------+-------+------------+-----+
| 1 | Dupont | Gaelle | Femme | 1 | 27 |
| 2 | Dupond | Jean | Homme | 3 | 24 |
| 3 | Durand | Laura | Femme | 2 | 28 |
| 4 | Dufour | Sarah | Femme | 4 | 18 |
| 5 | Dumiel | Paul | Homme | 5 | 19 |
| 6 | Durmont | Karl | Homme | 12 | 25 |
| 7 | Doe | John | Homme | 13 | 29 |
| 8 | Dorne | Jane | Femme | 14 | 29 |
| 9 | Sanchez | Maria | Homme | 9 | 23 |
| 10 | Martinez | Juan | Homme | 8 | 22 |
| 11 | Santamaria | Alvaro | Homme | 10 | 26 |
| 12 | Santiago | Marta | Homme | 11 | 20 |
+----+------------+--------+-------+------------+-----+
12 rows in set (0.001 sec)
> SELECT * FROM adresse;
+----+------------+---------+
| id | ville | pays |
+----+------------+---------+
| 1 | Marseille | France |
| 2 | Toulouse | France |
| 3 | Bordeaux | France |
| 4 | Paris | France |
| 5 | Strasbourg | France |
| 6 | Brest | France |
| 7 | Lyon | France |
| 8 | Granada | Espagne |
| 9 | Madrid | Espagne |
| 10 | Sevilla | Espagne |
| 11 | Valencia | Espagne |
| 12 | Oxford | UK |
| 13 | Cambridge | UK |
| 14 | London | UK |
+----+------------+---------+
14 rows in set (0.001 sec)
SELECT .., .., ..⚓︎
SELECT attribut1, attribut2, ...
: Exemple: sélectionner/afficher UNIQUEMENT les attributs prenom
et age
pour tous les enregistrements de la Table utilisateur
> SELECT prenom, age FROM utilisateur;
+--------+-----+
| prenom | age |
+--------+-----+
| Gaelle | 27 |
| Jean | 24 |
| Laura | 28 |
| Sarah | 18 |
| Paul | 19 |
| Karl | 25 |
| John | 29 |
| Jane | 29 |
| Maria | 23 |
| Juan | 22 |
| Alvaro | 26 |
| Marta | 20 |
+--------+-----+
12 rows in set (0.001 sec)
SELECT .. AS .. (,.. AS ..)⚓︎
SELECT attribut1 AS a1, attribut2 AS a2 ...
: Renommage des Champs/attributs (en tant que autre chose que leur nom original) :
- lors de l'affichage
- comme variable dans la suite de la requête
Exemple: afficher id_adresse
en tant que identifiant
:
> SELECT id_adresse AS identifiant FROM utilisateur;
+-------------+
| identifiant |
+-------------+
| 1 |
| 2 |
| 3 |
| 4 |
| 5 |
| 8 |
| 9 |
| 10 |
| 11 |
| 12 |
| 13 |
| 14 |
+-------------+
12 rows in set (0.001 sec)
SELECT DISTINCT⚓︎
SELECT DISTINCT
: la genre
SANS DOUBLONS de tous les enregistrements de la Table utilisateur
> SELECT DISTINCT genre FROM utilisateur;
+-------+
| genre |
+-------+
| Femme |
| Homme |
+-------+
2 rows in set (0.001 sec)
WHERE⚓︎
WHERE condition
: La
> SELECT * FROM utilisateur WHERE id=8;
+----+-------+--------+-------+------------+-----+
| id | nom | prenom | genre | id_adresse | age |
+----+-------+--------+-------+------------+-----+
| 8 | Dorne | Jane | Femme | 14 | 29 |
+----+-------+--------+-------+------------+-----+
1 row in set (0.001 sec)
Les conditions
peuvent utiliser des opérateurs logiques :
Opérateur | Signification | Exemple |
---|---|---|
AND |
ET | SELECT nom_colonnes FROM nom_table WHERE condition1 AND condition2 |
OR |
OU | SELECT nom_colonnes FROM nom_table WHERE condition1 OR condition2 |
IN |
APPARTIENT À | SELECT nom_colonne FROM nom_table WHERE nom_colonne IN (valeur1, valeur2, ..) |
BETWEEN |
EST COMPRIS ENTRE | SELECT nom_colonne FROM nom_table WHERE nom_colonne BETWEEN 'valeur1' AND 'valeur2' |
LIKE |
suit le modèle.. | SELECT nom_colonne FROM nom_table WHERE nom_colonne LIKE modèle
|
ORDER BY⚓︎
ORDER BY
: La
Exemple : ordonner selon un attribut, le jeu de résultats d'une sélection de tous les enregistrements de la Table utilisateur
> SELECT * FROM utilisateur ORDER BY prenom;
+----+------------+--------+-------+------------+-----+
| id | nom | prenom | genre | id_adresse | age |
+----+------------+--------+-------+------------+-----+
| 11 | Santamaria | Alvaro | Homme | 10 | 26 |
| 1 | Dupont | Gaelle | Femme | 1 | 27 |
| 8 | Dorne | Jane | Femme | 14 | 29 |
| 2 | Dupond | Jean | Homme | 3 | 24 |
| 7 | Doe | John | Homme | 13 | 29 |
| 10 | Martinez | Juan | Homme | 8 | 22 |
| 6 | Durmont | Karl | Homme | 12 | 25 |
| 3 | Durand | Laura | Femme | 2 | 28 |
| 9 | Sanchez | Maria | Homme | 9 | 23 |
| 12 | Santiago | Marta | Homme | 11 | 20 |
| 5 | Dumiel | Paul | Homme | 5 | 19 |
| 4 | Dufour | Sarah | Femme | 4 | 18 |
+----+------------+--------+-------+------------+-----+
12 rows in set (0.001 sec)
LIMIT⚓︎
LIMIT n
: La n
premiers résultats.
Exemple: Limiter aux n
premiers résultats d'une sélection de TOUS les attributs pour tous les enregistrements de la Table utilisateur
> SELECT * FROM utilisateur LIMIT 1;
+----+--------+--------+-------+------------+-----+
| id | nom | prenom | genre | id_adresse | age |
+----+--------+--------+-------+------------+-----+
| 1 | Dupont | Gaelle | Femme | 1 | 27 |
+----+--------+--------+-------+------------+-----+
1 row in set (0.000 sec)
GROUP BY⚓︎
GROUP BY
(HORS-PROGRAMME) : La
Exemple : compter le nombre d'enregistrements par genre
dans la Table utilisateur
> SELECT genre, count(*) AS quantite FROM utilisateur GROUP BY genre;
+-------+----------+
| genre | quantite |
+-------+----------+
| Femme | 4 |
| Homme | 8 |
+-------+----------+
2 rows in set (0.001 sec)
HAVING (HORS-PROGRAMME)⚓︎
HAVING
(HORS-PROGRAMME) : La
Exemple : compter le nombre d'enregistrements par genre
dans la Table utilisateur
vérifiant la condition age>25
> SELECT genre, count(*) AS quantite FROM utilisateur GROUP BY genre, age HAVING age>25;
ou bien
> SELECT genre, count(*) AS quantite FROM utilisateur WHERE age>25 GROUP BY genre;
+-------+----------+
| genre | quantite |
+-------+----------+
| Femme | 3 |
| Homme | 2 |
+-------+----------+
2 rows in set (0.001 sec)
UPDATE .. SET ..
: Modification d'un Enregistrement d'une Table⚓︎
UPDATE ... SET ...
: mettre à jour l' attribut nom
de la Table utilisateur
vérifiant une certaine condition (avec WHERE condition
)
Changer un seul attribut d'un enregistrement⚓︎
> UPDATE utilisateur SET nom='Dupond' WHERE id=1;
Query OK, 1 row affected (0.004 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Changer plusieurs attributs d'un enregistrement⚓︎
> UPDATE utilisateur SET nom='Durand', prenom='Laurene' WHERE id=1;
Query OK, 1 row affected (0.008 sec)
Rows matched: 1 Changed: 1 Warnings: 0
vérifier la dernière modification:
> SELECT * FROM utilisateur;
+----+------------+--------+-------+------------+-----+
| id | nom | prenom | genre | id_adresse | age |
+----+------------+--------+-------+------------+-----+
| 1 | Dupond | Gaelle | Femme | 1 | 27 |
| 2 | Dupond | Jean | Homme | 3 | 24 |
| 3 | Durand | Laura | Femme | 2 | 28 |
| 4 | Dufour | Sarah | Femme | 4 | 18 |
| 5 | Dumiel | Paul | Homme | 5 | 19 |
| 6 | Durmont | Karl | Homme | 12 | 25 |
| 7 | Doe | John | Homme | 13 | 29 |
| 8 | Dorne | Jane | Femme | 14 | 29 |
| 9 | Sanchez | Maria | Homme | 9 | 23 |
| 10 | Martinez | Juan | Homme | 8 | 22 |
| 11 | Santamaria | Alvaro | Homme | 10 | 26 |
| 12 | Santiago | Marta | Homme | 11 | 20 |
+----+------------+--------+-------+------------+-----+
12 rows in set (0.000 sec)
DELETE FROM
: Supprimer un enregistrement d'une Table⚓︎
> DELETE FROM utilisateur WHERE id=1;
Query OK, 1 row affected (0.008 sec)
vérifier la bonne suppression:
> SELECT * from utilisateur;
+----+------------+--------+-------+------------+-----+
| id | nom | prenom | genre | id_adresse | age |
+----+------------+--------+-------+------------+-----+
| 2 | Dupond | Jean | Homme | 3 | 24 |
| 3 | Durand | Laura | Femme | 2 | 28 |
| 4 | Dufour | Sarah | Femme | 4 | 18 |
| 5 | Dumiel | Paul | Homme | 5 | 19 |
| 6 | Durmont | Karl | Homme | 12 | 25 |
| 7 | Doe | John | Homme | 13 | 29 |
| 8 | Dorne | Jane | Femme | 14 | 29 |
| 9 | Sanchez | Maria | Homme | 9 | 23 |
| 10 | Martinez | Juan | Homme | 8 | 22 |
| 11 | Santamaria | Alvaro | Homme | 10 | 26 |
| 12 | Santiago | Marta | Homme | 11 | 20 |
+----+------------+--------+-------+------------+-----+
11 rows in set (0.001 sec)
Jointures⚓︎
Comme déjà expliqué, il existe trois types des jointures:
- INNER pour Jointure Interne
- OUTER pour Jointure Externe
- CROSS pour Produit Cartésien
Le principe des jointures entre deux tables, est basé sur une (ou des) conditions ON ..
devant être vérifiées par un (ou plusieurs) attributs de l'une des tables comparés avec un (ou des) attributs de l'autre table. Classiquement, mais non obligatoirement, il s'agit de faire correspondre un attribut de l'un (une clé primaire), avec l'attribut correspondant de l'autre table (une clé étrangère).
On souhaite retrouver les résultats de la partie théorique.
C'est pourquoi, dans cette partie, on définira les table1
et table2
suivantes (encore dans la base de données eleve
)
CREATE TABLE table2 (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
nom_ville VARCHAR(20));
CREATE TABLE table1 (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_ville INT UNSIGNED NOT NULL,
FOREIGN KEY (id_ville) REFERENCES table2 (id),
nom VARCHAR(20),
prenom VARCHAR(20));
INSERT INTO table2 (nom_ville)
VALUES ('Marseille'), ('Toulouse'), ('Bordeaux');
INSERT INTO table1 (id_ville, nom, prenom) VALUES (3, 'Dupont','Gaelle'), (3, 'Dutronc','Jacques'), (1, 'Dupond','Jean'), (3, 'Durand','Laura'), (1, 'Dufour','Sarah'), (1, 'Dumiel','Paul'), (3, 'Dumont','Karl');
SET FOREIGN_KEY_CHECKS=0;
UPDATE table1 SET id_ville=4 WHERE id=2;
SELECT * FROM table1;
+----+----------+---------+---------+
| id | id_ville | nom | prenom |
+----+----------+---------+---------+
| 1 | 3 | Dupont | Gaelle |
| 2 | 4 | Dutronc | Jacques |
| 3 | 1 | Dupond | Jean |
| 4 | 3 | Durand | Laura |
| 5 | 1 | Dufour | Sarah |
| 6 | 1 | Dumiel | Paul |
| 7 | 3 | Dumont | Karl |
+----+----------+---------+---------+
7 rows in set (0.001 sec)
SELECT * FROM table2;
+----+-----------+
| id | nom_ville |
+----+-----------+
| 1 | Marseille |
| 2 | Toulouse |
| 3 | Bordeaux |
+----+-----------+
3 rows in set (0.001 sec)
INNER JOIN
: Jointure Interne⚓︎
La ON
..) dans la table de droite (table2). Aucune ligne du résultat d'une jointure interne ne contient de NULL.
SELECT colonne1, colonne2, ..
FROM table1
JOIN table2 ON table1.id = table2.fk_id
Syntaxe Alternative :
SELECT colonne1, colonne2, ..
FROM table1
INNER JOIN table2 ON table1.id = table2.fk_id
Syntaxe Alternative :
SELECT *
FROM table1
INNER JOIN table2
WHERE table1.id = table2.fk_id
le mot
INNER
est facultatif dans MariaDB :
INNER JOIN
ou JOIN
sont donc synonymes
Cette requête joint les deux tables table1
et table2
et on choisit un critère de sélection avec le ON condition
Exp
SELECT *
FROM table1
INNER JOIN table2
ON table1.id_ville=table2.id;
+----+----------+--------+--------+----+-----------+
| id | id_ville | nom | prenom | id | nom_ville |
+----+----------+--------+--------+----+-----------+
| 1 | 3 | Dupont | Gaelle | 3 | Bordeaux |
| 3 | 1 | Dupond | Jean | 1 | Marseille |
| 4 | 3 | Durand | Laura | 3 | Bordeaux |
| 5 | 1 | Dufour | Sarah | 1 | Marseille |
| 6 | 1 | Dumiel | Paul | 1 | Marseille |
| 7 | 3 | Dumont | Karl | 3 | Bordeaux |
+----+----------+--------+--------+----+-----------+
6 rows in set (0.001 sec)
On retrouve bien le résultat théorique
LEFT OUTER JOIN
: Jointure Externe Gauche⚓︎
La Dans une jointure (externe) gauche, les lignes de la table de droite sans correspondance vaudront toutes NULL.
SELECT colonne1, colonne2, ..
FROM ma_table1
LEFT JOIN table2 ON table1.id = table2.fk_id
Syntaxe Alternative :
SELECT colonne1, colonne2, ..
FROM ma_table1
LEFT OUTER JOIN table2 ON table1.id = table2.fk_id
Au moins l'un des mots
LEFT
(ou RIGHT
) est requis/obligatoire avec un OUTER JOIN
. Autrement dit : OUTER JOIN
tout seul, n'est pas compris par MariaDB.
Cette requête joint les deux tables table1
et table2
et on choisit un critère de sélection avec le ON condition
Jointure Externe Gauche
SELECT *
FROM table1
LEFT OUTER JOIN table2
ON table1.id_ville=table2.id;
+----+----------+---------+---------+------+-----------+
| id | id_ville | nom | prenom | id | nom_ville |
+----+----------+---------+---------+------+-----------+
| 1 | 3 | Dupont | Gaelle | 3 | Bordeaux |
| 2 | 4 | Dutronc | Jacques | NULL | NULL |
| 3 | 1 | Dupond | Jean | 1 | Marseille |
| 4 | 3 | Durand | Laura | 3 | Bordeaux |
| 5 | 1 | Dufour | Sarah | 1 | Marseille |
| 6 | 1 | Dumiel | Paul | 1 | Marseille |
| 7 | 3 | Dumont | Karl | 3 | Bordeaux |
+----+----------+---------+---------+------+-----------+
7 rows in set (0.001 sec)
On retrouve bien le résultat théorique
RIGHT OUTER JOIN
: Jointure Externe Droite⚓︎
La Dans une jointure (externe) droite, les lignes de la table de gauche sans correspondance vaudront toutes NULL.
SELECT colonne1, colonne2, ..
FROM ma_table1
RIGHT JOIN table2 ON table1.id = table2.fk_id
Syntaxe Alternative :
SELECT colonne1, colonne2, ..
FROM ma_table1
RIGHT OUTER JOIN table2 ON table1.id = table2.fk_id
Jointure Externe Droite
SELECT *
FROM table1
RIGHT OUTER JOIN table2
ON table1.id_ville=table2.id;
+------+----------+--------+--------+----+-----------+
| id | id_ville | nom | prenom | id | nom_ville |
+------+----------+--------+--------+----+-----------+
| 3 | 1 | Dupond | Jean | 1 | Marseille |
| 5 | 1 | Dufour | Sarah | 1 | Marseille |
| 6 | 1 | Dumiel | Paul | 1 | Marseille |
| NULL | NULL | NULL | NULL | 2 | Toulouse |
| 1 | 3 | Dupont | Gaelle | 3 | Bordeaux |
| 4 | 3 | Durand | Laura | 3 | Bordeaux |
| 7 | 3 | Dumont | Karl | 3 | Bordeaux |
+------+----------+--------+--------+----+-----------+
7 rows in set (0.001 sec)
On retrouve bien le résultat théorique
CROSS JOIN
: Produit Cartésien⚓︎
La syntaxe pour un produit cartésien est :
> SELECT attribut1, ...
FROM table1
CROSS JOIN table2
ON table1.attribut1 = table2.attribut2;
le mot
INNER
est facultatif dans MariaDB :
INNER JOIN
ou JOIN
sont synonymes
Cette requête joint les deux tables table1
et table2
et on choisit un critère de sélection avec le ON condition
Exp
SELECT *
FROM table1
CROSS JOIN table2;
+----+----------+---------+---------+----+-----------+
| id | id_ville | nom | prenom | id | nom_ville |
+----+----------+---------+---------+----+-----------+
| 1 | 3 | Dupont | Gaelle | 1 | Marseille |
| 1 | 3 | Dupont | Gaelle | 2 | Toulouse |
| 1 | 3 | Dupont | Gaelle | 3 | Bordeaux |
| 2 | 4 | Dutronc | Jacques | 1 | Marseille |
| 2 | 4 | Dutronc | Jacques | 2 | Toulouse |
| 2 | 4 | Dutronc | Jacques | 3 | Bordeaux |
| 3 | 1 | Dupond | Jean | 1 | Marseille |
| 3 | 1 | Dupond | Jean | 2 | Toulouse |
| 3 | 1 | Dupond | Jean | 3 | Bordeaux |
| 4 | 3 | Durand | Laura | 1 | Marseille |
| 4 | 3 | Durand | Laura | 2 | Toulouse |
| 4 | 3 | Durand | Laura | 3 | Bordeaux |
| 5 | 1 | Dufour | Sarah | 1 | Marseille |
| 5 | 1 | Dufour | Sarah | 2 | Toulouse |
| 5 | 1 | Dufour | Sarah | 3 | Bordeaux |
| 6 | 1 | Dumiel | Paul | 1 | Marseille |
| 6 | 1 | Dumiel | Paul | 2 | Toulouse |
| 6 | 1 | Dumiel | Paul | 3 | Bordeaux |
| 7 | 3 | Dumont | Karl | 1 | Marseille |
| 7 | 3 | Dumont | Karl | 2 | Toulouse |
| 7 | 3 | Dumont | Karl | 3 | Bordeaux |
+----+----------+---------+---------+----+-----------+
21 rows in set (0.001 sec)
On retrouve bien les résultats théoriques
Opérations d'Agrégation⚓︎
Dans cette partie, on travaille sur une table commande
définie comme ceci, et on y insère les enregistrements suivants :
CREATE TABLE commande (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
id_client INT UNSIGNED NOT NULL,
id_article INT UNSIGNED NOT NULL,
prix FLOAT UNSIGNED NOT NULL,
quantite INT UNSIGNED NOT NULL);
+------------+------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------------+------+-----+---------+----------------+
| id | int(10) unsigned | NO | PRI | NULL | auto_increment |
| id_client | int(10) unsigned | NO | | NULL | |
| id_article | int(10) unsigned | NO | | NULL | |
| prix | float unsigned | NO | | NULL | |
| quantite | int(10) unsigned | NO | | NULL | |
+------------+------------------+------+-----+---------+----------------+
5 rows in set (0.001 sec)
INSERT INTO commande (id_client, id_article, prix, quantite)
VALUES (1, 1000, 20, 1),
(2, 1010, 30, 1),
(3, 1020, 35.2, 1),
(4, 1030, 54.87, 1),
(5, 1040, 18.1, 3),
(6, 1050, 32.7, 2);
+----+-----------+------------+-------+----------+
| id | id_client | id_article | prix | quantite |
+----+-----------+------------+-------+----------+
| 1 | 1 | 1000 | 20 | 1 |
| 2 | 2 | 1010 | 30 | 1 |
| 3 | 3 | 1020 | 35.2 | 1 |
| 4 | 4 | 1030 | 54.87 | 1 |
| 5 | 5 | 1040 | 18.1 | 3 |
| 6 | 6 | 1050 | 32.7 | 2 |
+----+-----------+------------+-------+----------+
Il est possible d'agréger les résultats, i.e. intuitivement de les compacter ensemble d'une certaine manière. Il existe plusieurs opérations spécifiques.
SUM
: Somme de toutes les valeurs d'un attribut⚓︎
SELECT SUM(prix) AS Total FROM commande;
+-------------------+
| Total |
+-------------------+
| 190.8700008392334 |
+-------------------+
1 row in set (0.001 sec)
SELECT ROUND(SUM(prix),2) AS Total FROM commande;
+--------+
| Total |
+--------+
| 190.87 |
+--------+
1 row in set (0.001 sec)
COUNT
: Comptage⚓︎
SELECT COUNT(*) AS quantite FROM commande WHERE prix<34;
+----------+
| quantite |
+----------+
| 4 |
+----------+
1 row in set (0.000 sec)
AVG
: AVeraGe = Moyenne⚓︎
SELECT AVG(prix) AS 'prix moyen' FROM commande;
+------------------+
| prix moyen |
+------------------+
| 31.8116668065389 |
+------------------+
1 row in set (0.001 sec)
MIN
et MAX
: Minimum et Maximum⚓︎
SELECT MIN(prix) AS minimum FROM commande;
+---------+
| minimum |
+---------+
| 18.1 |
+---------+
1 row in set (0.001 sec)
SELECT MAX(prix) AS maximum FROM commande;
+---------+
| maximum |
+---------+
| 54.87 |
+---------+
1 row in set (0.001 sec)