CREATE TABLE en SQL : Types et Contraintes
Créer une table, choisir les bons types, PRIMARY KEY, FOREIGN KEY, NOT NULL, UNIQUE, CHECK et DEFAULT
Syntaxe CREATE TABLE
colonne1 type contraintes,
colonne2 type contraintes,
…
contraintes_de_table
);
— Exemple simple
CREATE TABLE clients (
id INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
age INT CHECK (age >= 0 AND age <= 150),
ville VARCHAR(100) DEFAULT ‘Paris’,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
AUTO_INCREMENT est la syntaxe MySQL. En PostgreSQL, utilise SERIAL ou GENERATED ALWAYS AS IDENTITY. En SQL Server, IDENTITY(1,1). En SQLite, INTEGER PRIMARY KEY suffit.
Types numériques
| Type | Taille | Plage | Usage |
|---|---|---|---|
| TINYINT | 1 octet | -128 à 127 | Booléens, petits compteurs |
| SMALLINT | 2 octets | -32 768 à 32 767 | Codes, petites quantités |
| INT / INTEGER | 4 octets | -2,1 milliards à 2,1 milliards | IDs, compteurs, quantités |
| BIGINT | 8 octets | ±9,2 × 10¹⁸ | IDs haute volumétrie, timestamps |
| DECIMAL(p,s) | Variable | Exact | Montants, prix (pas de perte) |
| FLOAT | 4 octets | Approx. 7 chiffres | Calculs scientifiques |
| DOUBLE | 8 octets | Approx. 15 chiffres | Calculs scientifiques précis |
prix DECIMAL(10,2) — 10 chiffres total, 2 après la virgule
— max : 99 999 999,99
— ID : INT ou BIGINT selon le volume
id BIGINT PRIMARY KEY AUTO_INCREMENT
⚠️ N’utilise jamais FLOAT ou DOUBLE pour les montants financiers. 0.1 + 0.2 ≠ 0.3 en virgule flottante. DECIMAL est exact — c’est le seul choix pour l’argent.
Types texte
| Type | Taille max | Usage |
|---|---|---|
| CHAR(n) | 255 caractères | Longueur fixe (codes pays, codes postaux) |
| VARCHAR(n) | 65 535 caractères (MySQL) | Longueur variable (noms, emails, URLs) |
| TEXT | 65 535 caractères | Textes longs (descriptions, commentaires) |
| MEDIUMTEXT | 16 Mo | Articles, contenu HTML |
| LONGTEXT | 4 Go | Très gros textes (rarement utilisé) |
| ENUM(‘a’,’b’,’c’) | — | Valeurs prédéfinies (statut, rôle) |
nom VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
code_postal CHAR(5), — toujours 5 caractères
bio TEXT,
statut ENUM(‘actif’,‘inactif’,‘suspendu’) DEFAULT ‘actif’,
Préfère VARCHAR dans la majorité des cas. CHAR est utile uniquement pour les colonnes de longueur fixe (codes ISO, hashes). TEXT ne peut pas avoir de valeur DEFAULT ni être utilisé comme index complet en MySQL.
Types date et autres
| Type | Format | Usage |
|---|---|---|
| DATE | YYYY-MM-DD | Dates sans heure (naissance, échéance) |
| TIME | HH:MM:SS | Heure seule |
| DATETIME | YYYY-MM-DD HH:MM:SS | Date + heure (sans fuseau) |
| TIMESTAMP | YYYY-MM-DD HH:MM:SS | Date + heure (avec fuseau UTC) |
| BOOLEAN | TRUE / FALSE | Drapeaux (est_actif, est_vérifié) |
| JSON | Texte JSON | Données semi-structurées (MySQL 5.7+, PG) |
| UUID | 128 bits | Identifiants distribués (PostgreSQL natif) |
date_naissance DATE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
— Booléens
est_actif BOOLEAN DEFAULT TRUE,
— JSON (MySQL 5.7+ / PostgreSQL)
metadata JSON,
TIMESTAMP stocke en UTC et convertit selon le fuseau du serveur. DATETIME stocke la valeur telle quelle. Pour les apps internationales, préfère TIMESTAMP (ou TIMESTAMPTZ en PostgreSQL).
Contraintes
| Contrainte | Rôle | Exemple |
|---|---|---|
| PRIMARY KEY | Identifiant unique de chaque ligne | id INT PRIMARY KEY |
| NOT NULL | Interdit les valeurs NULL | nom VARCHAR(100) NOT NULL |
| UNIQUE | Interdit les doublons | email VARCHAR(255) UNIQUE |
| DEFAULT | Valeur par défaut si non fournie | role VARCHAR(20) DEFAULT ‘user’ |
| CHECK | Validation sur les valeurs | CHECK (age >= 0) |
| FOREIGN KEY | Lien vers une autre table | FOREIGN KEY (client_id) REFERENCES clients(id) |
| AUTO_INCREMENT | Incrémentation automatique | id INT AUTO_INCREMENT |
CREATE TABLE inscriptions (
etudiant_id INT NOT NULL,
cours_id INT NOT NULL,
date_inscr DATE NOT NULL,
PRIMARY KEY (etudiant_id, cours_id), — clé primaire composite
UNIQUE (etudiant_id, cours_id) — un étudiant ne s’inscrit qu’une fois
);
FOREIGN KEY — clés étrangères
CREATE TABLE commandes (
id INT PRIMARY KEY AUTO_INCREMENT,
client_id INT NOT NULL,
produit VARCHAR(200) NOT NULL,
montant DECIMAL(10,2) NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (client_id) REFERENCES clients(id)
ON DELETE CASCADE — supprimer le client → supprime ses commandes
ON UPDATE CASCADE — modifier l’id client → met à jour ici
);
| Action ON DELETE / ON UPDATE | Comportement |
|---|---|
| CASCADE | Supprime / met à jour les lignes enfants automatiquement |
| SET NULL | Met la FK à NULL (la colonne ne doit pas être NOT NULL) |
| SET DEFAULT | Met la FK à sa valeur DEFAULT |
| RESTRICT | Empêche la suppression / modification du parent |
| NO ACTION | Comme RESTRICT (vérifie en fin de transaction) |
Règle courante : ON DELETE CASCADE pour les tables de détail (commandes d’un client supprimé). ON DELETE SET NULL quand la relation est optionnelle. ON DELETE RESTRICT pour les données critiques (empêcher les suppressions accidentelles).
ALTER TABLE — modifier une table
ALTER TABLE clients ADD COLUMN telephone VARCHAR(20);
— Modifier le type d’une colonne
ALTER TABLE clients MODIFY COLUMN nom VARCHAR(200) NOT NULL; — MySQL
ALTER TABLE clients ALTER COLUMN nom TYPE VARCHAR(200); — PostgreSQL
— Supprimer une colonne
ALTER TABLE clients DROP COLUMN telephone;
— Ajouter une contrainte
ALTER TABLE commandes
ADD CONSTRAINT fk_client
FOREIGN KEY (client_id) REFERENCES clients(id);
— Renommer une table
ALTER TABLE clients RENAME TO utilisateurs;
— Supprimer une table (⚠️ irréversible)
DROP TABLE clients; — erreur si la table n’existe pas
DROP TABLE IF EXISTS clients; — pas d’erreur
Exemple complet : e-commerce
id INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(100) NOT NULL,
email VARCHAR(255) UNIQUE NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE produits (
id INT PRIMARY KEY AUTO_INCREMENT,
nom VARCHAR(200) NOT NULL,
prix DECIMAL(10,2) NOT NULL CHECK (prix > 0),
stock INT NOT NULL DEFAULT 0 CHECK (stock >= 0),
categorie VARCHAR(100)
);
CREATE TABLE commandes (
id INT PRIMARY KEY AUTO_INCREMENT,
client_id INT NOT NULL,
statut ENUM(‘en_attente’,‘payee’,‘expediee’,‘livree’,‘annulee’)
DEFAULT ‘en_attente’,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (client_id) REFERENCES clients(id) ON DELETE CASCADE
);
CREATE TABLE lignes_commande (
id INT PRIMARY KEY AUTO_INCREMENT,
commande_id INT NOT NULL,
produit_id INT NOT NULL,
quantite INT NOT NULL CHECK (quantite > 0),
prix_unit DECIMAL(10,2) NOT NULL,
FOREIGN KEY (commande_id) REFERENCES commandes(id) ON DELETE CASCADE,
FOREIGN KEY (produit_id) REFERENCES produits(id) ON DELETE RESTRICT
);
Questions fréquentes
✏️ INSERT, UPDATE, DELETE
⚡ Les index SQL
🔗 Jointures SQL
🔢 Fonctions d’agrégation
📑 ORDER BY & LIMIT
🗄️ Cours SQL complet
🏠 Hub Programmation
CREATE TABLE en SQL — Types de données et contraintes
Référence : sql.sh CREATE TABLE
