Types de données
Indexation et optimisations
Contraintes étrangères
Modélisation forme normale
Et plus
Permet de stocker des données et de les retrouver facilement.
Les bases de données sont de différents types, certaines sont optimisées pour la rapidité, d'autres la flexibilité et certaines pour stocker des quantités de données impressionnantes.
Le serveur est un logiciel qui reste allumé de façon permanente sur un ordinateur et est utilisé pour stocker toutes les données des différentes bases de données.
On y configure des utilisateurs, rôles et permissions afin de contrôler l'accès aux données.
La base de données est une structure logique qui combine tables, trigger, vues et procédures stockées que l'utilisateur se servira pour stocker des données mais aussi pour les traiter.
Il est possible d'avoir plusieurs bases de données dans un serveur.
Les tables sont les endroits où sont stockées les données. Dans une table, vous trouverez des colonnes qui définissent les données qu'on peut entrer dans la table.
Chaque colonne peut recevoir de nombreuses configurations pour définir ce qui peut aller dedans.
Une rangée représente une entrée dans une table. Les rangées contiennent toujours toutes les données nécessaire pour satisfaire les contraintes des différentes colonnes.
Une contrainte est utilisées pour limiter les données que l'on peut entrer dans une colonne.
Il existe plusieurs types de contraintes en MySQL:
Nous étudierons ces concepts vers la fin du jour 2.
Une vue est l'équivalent d'une table mais utilise le langage SQL que nous verrons sous peu pour optimiser et transformer des données.
Un trigger est un bout de code qui réagit à des événements de la base de données comme l'ajout d'information dans une table.
Une procédure stockée est un bout de code qui exécute des fonctions complexe dans la base de données mais qui existe dans celle-ci au lieu de dans l'application.
On obtient des données en envoyant la commande
SELECT
au serveur de base de donnée.
Il faut lui dire ce que l'on souhaite obtenir:
Par exemple
SELECT * FROM ...
SELECT firstname FROM ...
Il faut aussi lui dire où aller chercher ces données:
Par exemple
SELECT * FROM employees
SELECT firstname FROM employees
employees
employee_id
lastname
department_id
date_of_birth
firstname
Obtenir les informations de la table employés:
On filtre les données en ajoutant la commande
WHERE
aux commandes SQL vues précédemment.
Il faut lui donner des conditions:
Par exemple
SELECT * FROM employees WHERE firstname = 'Mathieu'
SELECT * FROM employees WHERE department_id = 1
Il existe beaucoup d'opérateurs de conditions:
= | < | > |
<> | <= | >= |
Et plus encore!
La structure d'une expression est simple:
"Opérande gauche" "Opérateur" "Opérande droite"
Tout se lit facilement et doit répondre positivement:
Op gauche | Opérateur | Op droite |
---|---|---|
Le id de l'employé | égale | 1 |
Le nom de l'employé | égale | "Mathieu" |
employees
employee_id
lastname
department_id
date_of_birth
firstname
Obtenez, dans tous les exercices suivants:
Vous pouvez combiner des conditions ensemble à l'aide des opérateurs:
OR ou AND
Ainsi qu'avec les parenthèses comme dans les expressions d'algèbre en mathématiques.
Il existe beaucoup d'opérateurs de conditions:
() | and | or |
Et plus encore!
Obtenez, dans tous les exercices suivants:
Un opérateur permet de comparer des chaînes de texte de façon complexe:
LIKE
En utilisant une syntaxe particulière, vous pouvez rechercher des textes plus ou moins complexe:
SELECT * FROM employees WHERE firstname LIKE "%Math%"
Il existe beaucoup d'opérateurs de conditions:
like |
Et plus encore!
Obtenez, dans tous les exercices suivants:
Certains opérateurs facilitent l'écriture de conditions a valeurs multiple:
BETWEEN
IN
C'est opérateurs sont pratique pour simplifier :
SELECT * FROM employees WHERE firstname = "Mathieu" OR firstname = "Jean" OR firstname = "Valérie"
Il existe beaucoup d'opérateurs de conditions:
between | in |
Et plus encore!
Obtenez, dans tous les exercices suivants:
Il serait peu pratique d'avoir des données toujours dans un ordre inconsistant. Nous allons donc apprendre maintenant à utiliser le mot clef :
ORDER BY
Ce mot clef doit être ajouté à la fin de la requête pour spécifier comment trier les données.
La structure de cette portion est la suivante :
ORDER BY "nom d'un champ" "direction"
Le nom du champ est requis mais pas la direction. La direction est par défaut en ordre croissant. Donc:
1,2,3,4,5
Jean, Mathieu, Valérie
etc
Vous pouvez ajouter autant de critères de tri en les séparants par des virgules :
SELECT * FROM employees ORDER BY firstname
SELECT * FROM employees ORDER BY firstname, lastname
SELECT * FROM employees ORDER BY firstname, lastname, department_id
La direction se compose de 2 termes possible:
ASC ou DESC
Qui indiquent respectivement un tri ascendant et descendant.
Vous devez placer la direction après le nom du champ pour chaque champ à trier. Si omit, le champ sera trié ascendant.
employees
employee_id
lastname
department_id
date_of_birth
firstname
Obtenez, dans tous les exercices suivants:
Le champ sur lequel vous triez n'as pas besoin de faire parti du résultat. Par contre, ceci est valide seulement sous MySQL.
La majorité des langages de SQL requièrent que le nom (ou l'expression) qui sert à trier fasse partie des données!
Vous pouvez limiter la quantité de données retournée par le SQL en utilisant le mot clef suivant :
LIMIT quantité
La quantité doit toujours être un nombre!
Vous pouvez aussi changer les données limitées pour obtenir une tranche plus loin dans le résultat. Parfait pour paginer des résultats :
OFFSET quantité
La quantité doit toujours être un nombre!
Vous pouvez aussi utiliser une forme plus simple de LIMIT et OFFSET en utilisant :
LIMIT limite, offset
employees
employee_id
lastname
department_id
date_of_birth
firstname
Obtenir les informations de la table employés:
Jusqu'à présent, nous avons utilisé les nom des champs pour faire des sélections, conditions et tris. Vous pouvez par contre toujours utiliser des expressions à la place des noms des champs.
SELECT 1
SELECT 10 FROM employees
Ces instructions sont valide dans la plupart des bases de données!
Une expression est une série d'opérations logique ou mathématique. Quelques expressions des plus simples:
valeur
nom de champ
Mais vous pouvez créer des expressions plus complexes comme:
(valeur + valeur) * nom de champ
nom de champ - valeur
Une autre chose que vous pouvez faire est d'utiliser des fonctions. Une fonction est un bout de code qui exécute une opération complexe sur des données:
SUBSTRING(nom de champ, 3)
DAY(date_of_birth)
CURRENTDATE()
Ces fonctions ont toutes leur utilité et il en existe au dessus de 250 dans le langage SQL de MySQL. Nous allons en regarder quelques unes au cours de cette section.
Utiliser des expression dans la portion SELECT est très important. Elle permet de transformer les données brutes de vos tables en quelques chose de plus compréhensible.
SELECT CONCAT(firstname, ' ', lastname) AS fullname
FROM employees
Dans cette approche, vous collez les deux portions du nom d'un utilisateur ensemble dans une seule colonne de résultat.
Utiliser des expression dans la portion WHERE est déjà chose commune. En fait, chaque condition que vous avez fait jusqu'à présent est une expression.
SELECT * FROM employees WHERE employee_id = 1
SELECT * FROM employees WHERE (employee_id = 1) OR (employee_id = 2)
Ici, "employee_id = 1" est une expression.
Ici, "(employee_id = 1)" et "(employee_id = 2)" sont toutes les deux des expressions.
Pouvez-vous en identifier une 3e?
Apprenons de nouvelles fonctions de gestion de date.
Fonction | Utilité |
---|---|
DAY(date) | Retourne le jour du mois de la date |
MONTH(date) | Retourne le numéro 1-12 du mois de la date |
YEAR(date) | Retourne l'année à 4 chiffres de la date |
DAYOFYEAR(date) | Retourne le jour de l'année 1-366 |
MKDATE(year, days) | Retourne la date représenté par l'année "year" et le jour de l'année "days" |
employees
employee_id
lastname
department_id
date_of_birth
firstname
Obtenez, dans tous les exercices suivants:
Utiliser des expression dans la portion ORDER BY vous permet de trier de façon arbitraire.
Fonction | Utilité |
---|---|
SUBSTRING(texte, début, longueur) | Retourne une portion du texte |
RAND() | Retourne une valeur aléatoire |
Obtenez, dans tous les exercices suivants:
Certains mots clé servent à construire des résultats complexes sans toutefois êtres des fonctions:
CASE WHEN ... THEN ... ELSE ... END
En utilisant cette syntaxe particulière, vous pouvez obtenir des résultats différents selon certain cas.
SELECT CASE WHEN firstname = "Mathieu"
THEN "Mattew" ELSE firstname END AS firstname
FROM employees
sales
sale_id
employee_id
amount
date_of_sale
Obtenez, dans tous les exercices suivants:
Vous ne pouvez pas seulement utiliser une table pour générer vos données. La force principale d'une base de données relationnelle est justement de mettre les données en relation.
Pour y arriver, il faut utiliser les jointures:
LEFT JOIN, INNER JOIN, RIGHT JOIN, FULL OUTER JOIN
Voyons comment cela fonctionne!
Une sert à coller les données d'une table/résultat à une autre. Elle est accompagnée d'une ou plusieurs conditions.
SELECT *
FROM employees
JOIN sales ON sales.employee_id = employees.employee_id
Vous pouvez utiliser une jointure plusieurs fois pour augmenter les données retournées.
SELECT *
FROM employees
JOIN sales ON sales.employee_id = employees.employee_id
JOIN departments ON departments.department_id = employees.department_id
À chaque jointure, les différentes rangées de chaque tables sont inspectées et jointes ensemble. Le résultat est donc une multiplication de toutes les rangées de toutes les tables mais seulement pour les données qui sont valide.
Une version équivalente mais à proscrire est la suivante :
SELECT *
FROM employees, sales, departments
WHERE
sales.employee_id = employees.employee_id
AND departments.department_id = employees.department_id
Selon la complexité de la requête (ici ce ne serait pas le cas) le système pourrait dupliquer un montant impressionnant de rangées et ensuite filtrer les données ce qui peut rendre un serveur inacessible.
Il existe 4 types de jointures :
SELECT * FROM employees LEFT JOIN sales ON ...
La jointure left prends toute les lignes de la tables employees et y ajoute toutes les lignes de sales.
Si aucune ligne ne fonctionne dans la table sales, alors vous n'aurez que des lignes de la table employees.
Il existe 4 types de jointures :
SELECT * FROM employees JOIN sales ON ...
SELECT * FROM employees CROSS JOIN sales ON ...
La jointure cross (ou juste un join normal) prends toute les lignes de la tables employees et y ajoute toutes les lignes de sales.
Seulement les lignes qui concordent de chaque coté sont retournées. Donc si vous n'avez aucune ventes pour les employés retenus, vous n'aurez aucun résultat.
Il existe 4 types de jointures :
SELECT * FROM employees RIGHT JOIN sales ON ...
La jointure right prends toute les lignes de la tables sales et y ajoute toutes les lignes de employees.
Si aucune ligne ne fonctionne dans la table employees, alors vous n'aurez que des lignes de la table sales.
Il existe 4 types de jointures :
SELECT * FROM employees INNER JOIN sales ON ...
La jointure inner prends toute les lignes de la tables employees ou de la table sales.
Seulement les lignes qui concordent sont retournées jointes aux autres sauf si aucune lignes ne concordent. Alors, les lignes qui n'ont aucune concordances sont retournées avec des informations vides de l'autre coté.
employees
employee_id
lastname
department_id
date_of_birth
firstname
sales
sale_id
employee_id
amount
date_of_sale
departments
department_id
name
Lorsque vous utilisez une jointure de type left, right ou inner, vous obtiendrez parfois des informations NULL.
Cette information est importante dans le contexte des jointures et vous permet de trouver des trous ou problèmes d'intégrité.
SELECT * FROM sales LEFT JOIN departments ON sales.employee_id = departments.department_id
Ici, vous obtiendez forcément des NULLs car nous n'utilisons pas les bonnes clefs pour joindre les données.
En recherchant des valeur NULLs dans des jointures de type left ou right, vous pouvez trouver des informations manquantes :
SELECT * FROM employees LEFT JOIN sales
ON sales.employee_id = employees.employee_id
WHERE sales.employee_id IS NULL
Ici, on tente de trouver les employés qui n'ont pas de ventes.
Un regroupement permet de faire des calculs sur des ensembles de données. Pour ce faire, il faut ajouter l'instruction :
GROUP BY regroupement
Juste après les conditions WHERE.
SELECT employees.employee_id, firstname, lastname, SUM(amount)
FROM employees
LEFT JOIN sales ON sales.employee_id = employees.employee_id
WHERE firstname LIKE "%Math%"
GROUP BY employees.employee_id
Il existe quelques opérateurs de regroupement. Tous doivent êtres utilisés dans la section SELECT.
Opérateur | Utilité |
---|---|
COUNT(expr) | Compte le nombre d'expressions |
SUM(expr) | Additionne toutes les expressions |
AVG(expr) | Retourne la moyenne de toutes les expressions |
MIN(expr) | Retourne la valeur minimale de toutes les expressions |
MAX(expr) | Retourne la valeur maximale de toutes les expressions |
Les opérateurs de regroupement doivent être utilisés dans la section SELECT. Ils doivent être utilisé sur une expression. Ils sont donc une expression en soit.
SELECT COUNT(employee_id) FROM employees WHERE firstname LIKE "%Math%"
SELECT SUM(amount) FROM sales
SELECT MIN(amount), employees.firstname FROM sales JOIN employees USING(employee_id) GROUP BY employee_id
employees
employee_id
lastname
department_id
date_of_birth
firstname
sales
sale_id
employee_id
amount
date_of_sale
departments
department_id
name
Vous pouvez ajouter des conditions sur les valeurs regroupées. Si les expressions dans la section WHERE s'appliquent aux données retenues pour la section SELECT, alors la section HAVING contient les expression qui filtre les données finales regroupées.
GROUP BY ... HAVING ...
Vous ne pouvez pas utiliser HAVING sans GROUP BY.
Vous pouvez ajouter des données dans n'importe qu'elle table en utilisant la commande :
INSERT
Cette commande est très flexible, nous verrons différentes utilisations dans les prochaines diapositives.
Les insertions de base se font sous la forme suivante :
INSERT INTO table (column, column, ...)
VALUES (value, value, ...), (value, value, ...), ...
Cette version requiert le nom de chaque colonne qui recevra une valeur et dans la portion VALUES vous ajoutez chaque valeur dans le même ordre.
Les insertions peuvent remplacer des données si elles existent déjà :
REPLACE INTO table (column, column, ...)
VALUES (value, value, ...), (value, value, ...), ...
Cette version requiert qu'une des colonnes soit une clé de la table sinon ce sera toujours une insertion.
Si les valeurs données à REPLACE contiennent une clef et que la clef existe déjà, alors la rangée sera mise à jour.
La version REPLACE peut aussi s'écrire comme ceci:
INSERT INTO table (column, column, ...)
VALUES (value, value, ...), (value, value, ...), ...
ON DUPLICATE KEY UPDATE
column = VALUES(column), column = value, ...
Cette version est plus flexible que REPLACE car vous pouvez faire des mises à jour complètement différentes de l'insertion.
Une clef primaire est une colonne d'une table qui contient une information unique servant à retrouver une rangée.
Souvent, les clefs primaires sont des nombres, en séquence automatique, par exemple: 1, 2, 3, 4, 5, 6, 7. On les appellent des clefs de substitution.
Dans d'autres cas, les clefs primaires sont des valeurs dites naturelle soit, une information réelle comme un numéro de téléphone, une adresse courriel, etc
Lorsque vous insérez des données, vous pouvez omettre une clef primaire seulement si celle-ci est automatique comme dans le cas d'une clef de substitution.
INSERT INTO department (name) VALUES ("Nouveau départment")
Si vous n'avez pas de clef de substitution à séquence automatique, vous devez fournir une valeur.
departments
department_id
name
Insérez 3 nouveau départements en utilisant la méthode normale sans clef primaire :
INSERT [INTO] {tableName} (columnName, columnName, ...) VALUES (value, value, ...), (value, value, ...), ...
products
product_id
name
price
Insérez 3 nouveaux produits en utilisant la méthode REPLACE INTO avec les valeurs suivantes :
id | nom | prix |
---|---|---|
6 | Popcorn | 1.25 |
7 | Caramel en barre | 1 |
8 | Toaster | 25 |
REPLACE [INTO] {tableName} (columnName, columnName, ...) VALUES (value, value, ...), (value, value, ...), ...
Insérez 2 nouveaux produits en utilisant la méthode INSERT ON DUPLICATE avec les valeurs suivantes :
id | nom | prix |
---|---|---|
3 | Grilled cheese | 3 |
9 | Tournevis | 14 |
Important : Les nouveaux produits doivent augmenter le prix actuel de 1$ s'ils existent déjà. Ils ne doivent pas remplacer le nom ou le prix.
INSERT [INTO] {tableName} (columnName, columnName, ...) VALUES (value, value, ...), (value, value, ...), ...
ON DUPLICATE KEY UPDATE
column = column + value,
column = VALUES(column),
column = fixed_value, ...
Vous pouvez utiliser une dernière forme pour insérer des données soit la forme :
INSERT SELECT
Cette forme permet d'insérer le résultat d'une sélection. Très pratique pour générer des données!
Pour se faire, générez premièrement un résultat à l'aide d'une instruction SELECT. Lorsque vous êtes satisfait, vous pouvez ajouter en avant du SELECT la portion INSERT INTO ... (column, column, ...) :
INSERT INTO sales (employee_id, date_of_sale, amount)
SELECT employee_id, NOW(), FLOOR(RAND() * 1000)
FROM employees
Ceci ajoutera 1 vente à chaque employé en date actuelle avec une valeur au hasard entre 0$ et 1000$.
products
product_id
name
price
Présenter la méthode UPDATE :
employees
employee_id
lastname
department_id
date_of_birth
firstname
Présentation des mises à jour multi-tables:
employees
employee_id
lastname
department_id
date_of_birth
firstname
departments
department_id
name
Présenter les commandes de suppression :
departments
department_id
name
sale_items
sale_item_id
sale_id
qty
product_id
Pour ajouter ou supprimer des bases de données entières de votre serveur, utilisez :
DROP DATABASE 'nom de la bd'
CREATE DATABASE 'nom de la bd'
Vous pouvez ajouter un mot clé pour éviter les erreurs :
DROP DATABASE IF EXISTS 'nom de la bd'
CREATE DATABASE IF NOT EXISTS 'nom de la bd'
Pour ajouter des tables dans votre base de données :
CREATE TABLE [IF NOT EXISTS] {NOM DE TABLE} (
column1,
column2,
column3,
indexes and keys
) ENGINE=innodb;
La mention if not exists est optionnelle. Le nom de la table doit être composé de lettre, chiffres et barres de soulignement et ne peut pas commencer par un chiffre.
Vous devriez toujours nommer vos tables en mode "snake_case" soit aucune majuscule.
Les colonnes d'une table sont définies comme suit :
{NOM DE LA COLONNE} {TYPE ET LONGUEUR} {OPTIONS}
Par exemple :
sale_id INT UNSIGNED NOT NULL AUTO_INCREMENT,
employee_id INT UNSIGNED NOT NULL,
amount DECIMAL(8,2) NOT NULL,
confirmed TINYINT NOT NULL DEFAULT 1
Tout comme pour les tables, le nom de la colonne doit être composé de lettre, chiffres et barres de soulignement et ne peut pas commencer par un chiffre. Il existe un grand nombre de type de données et d'options que nous verrons sous peu.
Il existe beaucoup plus de type de données que ci-dessous mais ceci vous donne une bonne idée de ce que vous pouvez utiliser :
Type | Long? | Notes |
---|---|---|
Int, BigInt, TinyInt | Non | Nombres |
Char, VarChar | Oui | Chaines de texte |
Decimal | Oui, 2x | Pour les valeur monétaires |
Float, Double | Non | Pour les fractions |
Text, Blob | Non | Pour les long textes/Data |
Date, DateTime | Non | Pour les dates |
Il existe beaucoup de modificateurs et options pour les colonnes, en voici quelques un :
Modificateur | Notes |
---|---|
auto_increment | Rends une colonne auto séquencée, valide pour les types integer ou plus et doit être pour une clef primaire seulement. |
not null | Impossible d'insérer NULL |
default {val} | Valeur par défaut si non fournie |
unsigned | Force les nombres à être positifs |