💾 Qu'est-ce qu'une Base de Données ?
📖 Définition
Une Base de Données (Database, DB) est une collection systématiquement structurée de données. Un SGBD (Système de Gestion de Base de Données, DBMS) est le logiciel qui crée, gère et accède aux bases de données. Les bases de données permettent le stockage et la récupération efficace des données, permettant à plusieurs utilisateurs d'accéder de manière sécurisée et simultanée.
🎯 Comprendre avec l'Analogie
Système de Bibliothèque
Pensez à une base de données comme une bibliothèque :
- Base de Données : La bibliothèque entière
- Table : Chaque section (fiction, science, histoire, etc.)
- Ligne (Row) : Livre individuel
- Colonne (Column) : Attributs du livre (titre, auteur, année de publication, etc.)
- Clé Primaire (Primary Key) : Numéro unique du livre
- SGBD : Bibliothécaire et système de gestion
Bibliothèque (Base de Données)
├─ Section Fiction (Table)
│ ├─ Livre 1: Harry Potter, J.K. Rowling, 1997
│ ├─ Livre 2: Le Seigneur des Anneaux, Tolkien, 1954
│ └─ Livre 3: Le Petit Prince, Saint-Exupéry, 1943
├─ Section Science (Table)
│ ├─ Livre 1: Cosmos, Carl Sagan, 1980
│ └─ Livre 2: Le Gène Égoïste, Richard Dawkins, 1976
└─ Registre d'Emprunts (Table)
├─ Enregistrement 1: Membre123, Harry Potter, 2024-01-15
└─ Enregistrement 2: Membre456, Cosmos, 2024-01-20
⚙️ Fonctionnement
1. Structure de Base de Données
Base de Données (Database)
└─ Table
├─ Ligne (Row/Record) - Élément de données individuel
│ └─ Exemple : Informations d'un utilisateur
└─ Colonne (Column/Field) - Attributs de données
└─ Exemple : Nom, email, âge
2. Exemple de Base de Données Relationnelle
-- Table users
users
┌────┬────────┬──────────────────┬─────┐
│ id │ name │ email │ age │
├────┼────────┼───── ─────────────┼─────┤
│ 1 │ Jean │ jean@mail.com │ 25 │
│ 2 │ Marie │ marie@mail.com │ 30 │
│ 3 │ Pierre │ pierre@mail.com │ 28 │
└────┴────────┴──────────────────┴─────┘
-- Table orders
orders
┌──── ┬─────────┬─────────────┬───────┐
│ id │ user_id │ product │ price │
├────┼─────────┼─────────────┼───────┤
│ 1 │ 1 │ Ordinateur │ 1500 │
│ 2 │ 1 │ Souris │ 30 │
│ 3 │ 2 │ Clavier │ 80 │
└────┴─────────┴─────────────┴───────┘
↑
└─ Clé étrangère : Référence id dans table users
3. Opérations CRUD
CRUD sont les 4 opérations de base de données :
C - Create (Créer) : Ajouter nouvelles données
R - Read (Lire) : Consulter données
U - Update (Mettre à jour) : Modifier données existantes
D - Delete (Supprimer) : Enlever données
💡 Exemples Réels
CRUD avec SQL
-- CREATE (Créer) : Créer table
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
age INT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- CREATE (Créer) : Ajouter données
INSERT INTO users (name, email, age)
VALUES ('Jean', 'jean@mail.com', 25);
INSERT INTO users (name, email, age)
VALUES
('Marie', 'marie@mail.com', 30),
('Pierre', 'pierre@mail.com', 28);
-- READ (Lire) : Consulter tous les utilisateurs
SELECT * FROM users;
-- READ (Lire) : Consultation conditionnelle
SELECT name, email FROM users
WHERE age >= 28;
-- READ (Lire) : Consultation triée
SELECT * FROM users
ORDER BY age DESC;
-- READ (Lire) : Recherche
SELECT * FROM users
WHERE name LIKE 'Jean%';
-- UPDATE (Mettre à jour) : Modifier données
UPDATE users
SET age = 26
WHERE name = 'Jean';
-- UPDATE (Mettre à jour) : Modifier plusieurs champs
UPDATE users
SET email = 'new@mail.com', age = 31
WHERE id = 2;
-- DELETE (Supprimer) : Enlever données
DELETE FROM users
WHERE id = 3;
-- DELETE (Supprimer) : Suppression conditionnelle
DELETE FROM users
WHERE age < 20;
Utilisation de Base de Données en Node.js
const mysql = require('mysql2/promise');
// Connexion base de données
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'myapp',
waitForConnections: true,
connectionLimit: 10
});
// CREATE - Ajouter utilisateur
async function createUser(name, email, age) {
const [result] = await pool.execute(
'INSERT INTO users (name, email, age) VALUES (?, ?, ?)',
[name, email, age]
);
console.log('ID créé:', result.insertId);
return result.insertId;
}
// READ - Obtenir tous les utilisateurs
async function getAllUsers() {
const [rows] = await pool.execute('SELECT * FROM users');
return rows;
}
// READ - Obtenir utilisateur spécifique
async function getUserById(id) {
const [rows] = await pool.execute(
'SELECT * FROM users WHERE id = ?',
[id]
);
return rows[0];
}
// UPDATE - Mettre à jour informations utilisateur
async function updateUser(id, name, email, age) {
const [result] = await pool.execute(
'UPDATE users SET name = ?, email = ?, age = ? WHERE id = ?',
[name, email, age, id]
);
console.log('Lignes mises à jour:', result.affectedRows);
return result.affectedRows;
}
// DELETE - Supprimer utilisateur
async function deleteUser(id) {
const [result] = await pool.execute(
'DELETE FROM users WHERE id = ?',
[id]
);
console.log('Lignes supprimées:', result.affectedRows);
return result.affectedRows;
}
// Exemple d'utilisation
async function main() {
try {
// Créer
const userId = await createUser('Jean', 'jean@mail.com', 25);
// Consulter
const users = await getAllUsers();
console.log('Tous les utilisateurs:', users);
// Consulter utilisateur spécifique
const user = await getUserById(userId);
console.log('Utilisateur spécifique:', user);
// Mettre à jour
await updateUser(userId, 'Jean', 'new@mail.com', 26);
// Supprimer
await deleteUser(userId);
} catch (error) {
console.error('Erreur:', error);
}
}
main();
Utilisation d'ORM (Sequelize)
const { Sequelize, DataTypes } = require('sequelize');
// Connexion base de données
const sequelize = new Sequelize('myapp', 'root', 'password', {
host: 'localhost',
dialect: 'mysql'
});
// Définition de modèle (structure de table)
const User = sequelize.define('User', {
name: {
type: DataTypes.STRING(50),
allowNull: false
},
email: {
type: DataTypes.STRING(100),
allowNull: false,
unique: true
},
age: {
type: DataTypes.INTEGER
}
});
// Opérations CRUD (Sans SQL, uniquement JavaScript !)
async function ormExample() {
// CREATE - Créer
const user = await User.create({
name: 'Jean',
email: 'jean@mail.com',
age: 25
});
console.log('Créé:', user.toJSON());
// READ - Consulter
const allUsers = await User.findAll();
console.log('Tous les utilisateurs:', allUsers);
// READ - Consultation conditionnelle
const youngUsers = await User.findAll({
where: { age: { [Sequelize.Op.gte]: 20 } },
order: [['age', 'DESC']]
});
// READ - Consulter un
const oneUser = await User.findOne({
where: { email: 'jean@mail.com' }
});
// UPDATE - Mettre à jour
await User.update(
{ age: 26 },
{ where: { name: 'Jean' } }
);
// DELETE - Supprimer
await User.destroy({
where: { id: 1 }
});
}
Configuration de Relation (JOIN)
// Configuration de relation entre utilisateur et commandes
const User = sequelize.define('User', {
name: DataTypes.STRING,
email: DataTypes.STRING
});
const Order = sequelize.define('Order', {
product: DataTypes.STRING,
price: DataTypes.DECIMAL(10, 2)
});
// Définition de relation : Un utilisateur peut avoir plusieurs commandes
User.hasMany(Order);
Order.belongsTo(User);
// Requête JOIN
async function getUserWithOrders(userId) {
const userWithOrders = await User.findOne({
where: { id: userId },
include: Order // JOIN
});
console.log(userWithOrders.toJSON());
// {
// id: 1,
// name: 'Jean',
// email: 'jean@mail.com',
// Orders: [
// { product: 'Ordinateur', price: 1500 },
// { product: 'Souris', price: 30 }
// ]
// }
}
🤔 Questions Fréquentes
Q1. Pourquoi utiliser des bases de données ?
R: Nombreux avantages par rapport aux systèmes de fichiers :
❌ Système de Fichiers (ex : users.txt)
├─ Duplication de données possible
├─ Problèmes d'accès concurrent
├─ Sauvegarde/récupération difficile
├─ Vulnérabilités de sécurité
└─ Recherches lentes
✅ Base de Données
├─ Intégrité des données garantie
├─ Contrôle de concurrence (plusieurs utilisateurs)
├─ Sauvegarde/récupération automatisée
├─ Gestion des permissions d'accès
├─ Recherches rapides (index)
└─ Support des transactions
Q2. Quelle base de données choisir ?
R: Dépend des exigences du projet :
// Bases de Données Relationnelles (SQL)
MySQL / PostgreSQL / SQLite
├─ Avantages : Structure de données précise, transactions
├─ Inconvénients : Faible flexibilité, évolutivité limitée
└─ Adapté : Finance, e-commerce, gestion des utilisateurs
// Bases de Données Non-Relationnelles (NoSQL)
MongoDB / Redis / Cassandra
├─ Avantages : Schéma flexible, mise à l'échelle horizontale
├─ Inconvénients : Traitement difficile des relations complexes
└─ Adapté : Médias sociaux, analyse en temps réel, mise en cache
Q3. Qu'est-ce qu'un Index ?
R: Une structure de données qui accélère la récupération des données :
-- Sans index
SELECT * FROM users WHERE email = 'test@mail.com';
-- → Vérifier 1M de lignes (lent)
-- Créer index
CREATE INDEX idx_email ON users(email);
-- Avec index
SELECT * FROM users WHERE email = 'test@mail.com';
-- → Trouver directement via index (rapide!)
-- Inconvénient : Écritures plus lentes (l'index doit être mis à jour)
Analogie : Comme la table des matières ou l'index d'un livre, permet de trouver rapidement ce que vous cherchez.
Q4. Qu'est-ce qu'une Transaction ?
R: Regrouper plusieurs opérations comme une seule unité :
// Exemple de virement bancaire
async function transferMoney(fromId, toId, amount) {
const connection = await pool.getConnection();
try {
// Démarrer transaction
await connection.beginTransaction();
// 1. Diminuer le solde de l'expéditeur
await connection.execute(
'UPDATE accounts SET balance = balance - ? WHERE id = ?',
[amount, fromId]
);
// 2. Augmenter le solde du destinataire
await connection.execute(
'UPDATE accounts SET balance = balance + ? WHERE id = ?',
[amount, toId]
);
// Tout succès → Confirmer
await connection.commit();
console.log('Virement terminé !');
} catch (error) {
// Erreur → Tout annuler
await connection.rollback();
console.log('Virement échoué, annulé');
throw error;
} finally {
connection.release();
}
}
// Principes ACID
// Atomicity (Atomicité): Tout ou rien
// Consistency (Cohérence): Pas de violation des règles
// Isolation (Isolation): Indépendance entre transactions
// Durability (Durabilité): Stockage permanent après achèvement
Q5. Qu'est-ce que SQL Injection ?
R: Une attaque qui injecte du code SQL malveillant :
// ❌ Code dangereux (vulnérable à SQL Injection)
const email = req.body.email; // "admin@mail.com' OR '1'='1"
const query = `SELECT * FROM users WHERE email = '${email}'`;
// Exécute: SELECT * FROM users WHERE email = 'admin@mail.com' OR '1'='1'
// → Toutes les informations utilisateur fuites !
// ✅ Code sécurisé (Prepared Statement)
const [rows] = await pool.execute(
'SELECT * FROM users WHERE email = ?',
[email] // Automatiquement échappé
);
// Utilisation d'ORM (défense automatique)
const user = await User.findOne({
where: { email: email } // Sécurisé
});
🎓 Prochaines Étapes
Après avoir compris les bases de données, apprenez :
- SQL vs NoSQL - Guide de sélection de base de données
- Qu'est-ce que Node.js ? - Développement backend
- Qu'est-ce qu'une API ? - Connexion entre base de données et frontend
Mise en Pratique
# Installation et exécution de MySQL
brew install mysql # macOS
sudo apt install mysql # Linux
# Connexion base de données
mysql -u root -p
# Créer base de données
CREATE DATABASE myapp;
USE myapp;
# Créer table et ajouter données
CREATE TABLE users (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
email VARCHAR(100)
);
INSERT INTO users (name, email) VALUES ('Jean', 'test@mail.com');
SELECT * FROM users;
🎬 Résumé
Les bases de données sont le cœur de toutes les applications :
- Base de Données : Collection de données structurée
- CRUD : Create, Read, Update, Delete - opérations de base
- Table : Organise les données en lignes et colonnes
- Relation : Connexions entre tables (JOIN)
- Transaction : Traitement sécurisé des données
Bien comprendre les bases de données permet de construire des applications stables et évolutives ! 💾✨