Vous êtes sur la page 1sur 130

1 - Introduction à SQL

Le sigle SQL signifie "Structured Query Language", soit en français "Langage de recherche
structuré". SQL est un langage de gestion des bases de données relationnelles.

Dernière normalisation sql ansi en SQL99 (sql3)

Malgré la normalisation ISO, l'implémentation du SQL par les différents éditeurs de SGBD
comporte des différences plus ou moins importante concernant :
Les détails de la syntaxe
L’écriture des commandes 
Le fonctionnement exact des commandes 
L'implémentation de nouveaux types de données (images, animations, vidéos, liens
hypertexte, champs binaire)

C'est un langage complet, qui permet de créer des BDD, des tables, de saisir des données et de
les corriger, de créer des vues, des index et des états (parfois baptisés "rapports", par
francisation de l'anglais "reports") pour Access.

Cas concret :
1 : Stocker des fiches élèves
2 : Stocker le profil des élèves (par ex: age formation caractère …)
3 : Stocker des notes
4 : Rechercher les élèves qui ont eu 20/20, malléable, 20 ans pour une nouvelle
formation

le langage SQL interroge des bases de données relationnelles, le modèle utilisé est un modèle
client/serveur

1
Quelques noms :
Oracle, Microsoft, Informix, Sybase, IBM
MySQL, PostgresSQL, SAP

Les bases contiennent des tables qui contiennent des champs de données.

2 : Mode d’emploi

Se connecter à la base

CONNECT user@database

Traitement des requêtes

Se déconnecter de la base

DISCONNECT and EXIT

3 : Les requêtes 


catégories
· DDL (Data Definition Language)
· DML (Data Manipulation Language)
· DQL (Data Query Language)0
· DCL (Data Control Language)
· DAC (Data administration commands)
· TCC (Transactional control commands)

DDL
· CREATE TABLE

· ALTER TABLE

· DROP TABLE

· CREATE INDEX

· ALTER INDEX

· DROP INDEX

· CREATE VIEW

· DROP VIEW

2
DML
· INSERT

· UPDATE

· DELETE
DQL
· SELECT
DCL
· ALTER PASSWORD

· GRANT

· REVOKE

· CREATE SYNONYM
DAC
· START AUDIT

· STOP AUDIT

TCC
· COMMIT Sauvegarde des transactions des bases de données
· ROLLBACK Défaire les transactions de données
· SAVEPOINT Création des points dans des groupes de transaction pour faire du
ROLLBACK

· SET TRANSACTION Nomme une transaction

3
Les types de champs
(mysql)
§ Numérique
· BIT[(M) M va de 1(défaut) à 64 (synonyme de
TINYINT(1))
· TINYINT[(M)] [UNSIGNED] [ZEROFILL] (de -127 à 128
ou non signé de 0 à 255)
· BOOL, BOOLEAN (zéro=faux synonyme de TINYINT(1))
· SMALLINT [(M)] [UNSIGNED] [ZEROFILL] (de 32767 à
32768 , non signé 0 à 65535)
· MEDIUMINT[(M)] [UNSIGNED] [ZEROFILL] (de -8388608 à
8388607. Non signé de 0 à 16777215).
· INT[(M)] [UNSIGNED] [ZEROFILL] (de -2147483648 à
2147483647, non signé 0 à 4294967295).
· INTEGER[(M)] [UNSIGNED] [ZEROFILL] = INT
· BIGINT[(M)] [UNSIGNED] [ZEROFILL] (de
-9223372036854775808 à 9223372036854775807, non signé
de 0 à 18446744073709551615).Attention aux opérations sur
64 bits
· FLOAT[(M,D)] [UNSIGNED] [ZEROFILL] (-
3.402823466E+38 à -1.175494351E-38 , 0 ,
1.175494351E-38 à 3.402823466E+38) IEEE Std
M est le nombre total de décimale et D le nombre de
décimale après la virgule.Si M ou D ne sont pas spécifiés
les limites sont celle du matériel. Si unsigned les valeurs
négatives sont interdites. Attention les calculs internes sont en
double précision
· DOUBLE[(M,D)] [UNSIGNED] [ZEROFILL] (-
1.7976931348623157E+308 à -2.2250738585072014E-308, 0,
2.2250738585072014E-308 à 1.7976931348623157E+308)
IEEE Std (idem M D et unsigned FLOAT)
· DOUBLE PRECISION[(M,D)] [UNSIGNED] [ZEROFILL], =
DOUBLE
· REAL[(M,D)] [UNSIGNED] [ZEROFILL] = DOUBLE
o Attention à l’option REAL_AS_FLOAT !
· FLOAT(p) [UNSIGNED] [ZEROFILL]

Un FLOAT. p représente la précision en bits, mais MySQL utilise seulement celle-ci pour
déterminer le type FLOAT ou DOUBLE. Si p est entre 0 et 24, =FLOAT sans M ou D . Si p
est entre 25 et 53 = DOUBLE sans M ou D . FLOAT(p) est nécessaire pour la compatibilité
d’ODBC.

· DECIMAL[(M[,D])] [UNSIGNED] [ZEROFILL]


o Suivant les versions de mysql
§ >V5.0.3 M,D M<=65 et 0<=D<3=0
·

TINYINT = 1 octet
SMALLINT = 2 octets
MEDIUMINT = 3 octets

4
INTEGER = 4 octets
BIGINT = 8 octets

§ Date DATE
· Format 'YYYY-MM-DD'
§ Heure TIME
· De '-838:59:59' à '838:59:59'
· Format édition 'HH:MM:SS'

§ Date et heure DATETIME


· Format ‘YYYY-MM-DD HH:MM:SS’
§ Date TIMESTAMP[(M)]
· Temps écoulé depuis le 1970-01-01 00:00:00
Si ce champ n’est pas rempli ou s’il est NULL alors il contiendra
lors de l’enregistrement la valeur lors de l’écriture de la base
Format édition YYYY-MM-DD HH:MM:SS
§ Année YEAR [(2|4)]
· De 1901 à 2155 et 0000.
· De 70 à 69 (soit 1970 à 2069)
· Format édition YYYY
§ Chaîne de caractère
· CHAR et VARCHAR
Différence de stockage et de taille
Char de 0 à 255 caractères
VARCHAR dans MySQL 5.0 est déterminé par la taille des
colonnes et le jeux de caractère utilise. Le maximum au total est
de 65,532 octets.
Le stockage dans la base est fixe avec du type CHAR et variable
( Longueur +1 ) avec du VARCHAR.
· BINARY et VARBINARY
Idem que ci-dessus mais on stocke des valeurs binaires et non
ascii. Les tris sont donc différents.
Ex si <MySQL 5.0.15 le séparateur était l’espace et après c’est
0x00.
Ex : BINARY(3) :
>MySQL5.0.15 la valeur ‘a ’donne ‘a \0’ quand inséré et
‘a\0 ‘ deviendra ‘a \0\0’.Les deux type de valeurs insérées ne
change pas lors d’un SELECT
<MySQL5.0.15 la valeur ‘a ’donne ‘a ’(deux espaces)
quand inséré et ‘a‘ lors d’un SELECT. 'a\0' deviendra'a\0 '
lors de l’insertion et 'a\0' lors d’un SELECT.

· BLOB et TEXT
o TINYBLOB, BLOB, MEDIUMBLOB, et LONGBLOB
o TINYTEXT, TEXT, MEDIUMTEXT, et LONGTEXT
Même limite et même taille de stockage.
La différence se situe dans les comparaisons
Blob=binaire et Text :basé sur une table de
caractère. Pas de valeur par défaut !
§ Le type énumération ENUM
· Maximum de 65536 éléments
Si la valeur n’est pas reconnue comme étant connue, elle est quand
même insérée avec la valeur index 0

5
§ Le type ensemble SET
· 64 valeurs maximum
· A chaque valeur est associé un bit

6
Place occupée par les données

Type de champs Place occupée en octet


TINYINT 1
SMALLINT 2
MEDIUMINT 3
INT, INTEGER 4
BIGINT 8
FLOAT (p) 4 octets si 0 <= p <= 24, 8 octets si 25 <= p <=
53
FLOAT 4
DOUBLE [PRECISION], item REAL 8
DECIMAL(M,D), NUMERIC(M,D) Variable
BIT(M) A peu près (M+7)/8 octets
DATE 3
DATETIME 8
TIMESTAMP 4
TIME 3
YEAR 1
CHAR(M) 0 <= M <= 255
VARCHAR(M) L+1 octets, L <= M and 0 <= M <= 65535. Et 0
<= M <= 255 avant MySQL 5.0.3.
BINARY(M) 0 <= M <= 255
VARBINARY(M) L+1 octets, et L <= M and 0 <= M <= 255
TINYBLOB, TINYTEXT L+1 octets , et L < 28
BLOB, TEXT L+2 octets, et L < 216
MEDIUMBLOB, MEDIUMTEXT L+3 octets, et L < 224
LONGBLOB, LONGTEXT L+4 octets, et L < 232
ENUM('value1','value2',...) 1 ou 2 octets (cela dépend, du nombre
d’énumération) max 65535
SET('value1','value2',...) 1, 2, 4 ou 8 octets (cela dépend, de la longueur
de chaque valeur ) max 64

7
Les fonctions et leur syntaxe

Créer une table

Pour créer une base de donnée


CREATE {DATABASE | SCHEMA} [IF NOT EXISTS] db_name
[create_specification [, create_specification] ...]

Create_specification:
[DEFAULT] CHARACTER SET charset_name
| [DEFAULT] COLLATE collation_name

Le plus simple :
CREATE DATABASE `essai` ;

Et le plus compliqué  avec un CHARACTER SET spécifique lié a

Exercice (création d’une table à votre nom )


1 : phonétique (type latin)
2 : idéogramme (japon par ex , 2 syllabaries: Hiragana et Katakana : codage sur plus
d’un octet)
3 : ponctuation, caractère de contrôle, nombre, symbole
4 : sens de l’écriture

Différent type de table de caractère cf annexe

Lors de la création d’une base, on peut définir des contraintes d’intégrité encodé de la manière
suivante par exemple sous Oracle :
CREATE TABLE nom_table (
nom_col_1 type_1,
nom_col_2 type_2,
...
nom_col_n type_n
CONSTRAINT [nom_contrainte_1] contrainte_1,
CONSTRAINT [nom_contrainte_2] contrainte_2,
...
CONSTRAINT [nom_contrainte_m] contrainte_m
);

Ou bien
CREATE TABLE nom_table (
nom_col_1 type_1 CONSTRAINT [nom_contrainte_1_1] contrainte_1_1
CONSTRAINT [nom_contrainte_1_2] contrainte_1_2
...
CONSTRAINT [nom_contrainte_1_m] contrainte_1_m,
nom_col_2 type_2 CONSTRAINT [nom_contrainte_2_1] contrainte_2_1
CONSTRAINT [nom_contrainte_2_2] contrainte_2_2
...
CONSTRAINT [nom_contrainte_2_p] contrainte_2_p,
...
nom_col_n type_n CONSTRAINT [nom_contrainte_n_1] contrainte_n_1
CONSTRAINT [nom_contrainte_n_2] contrainte_n_2

8
...
CONSTRAINT [nom_contrainte_n_q] contrainte_n_q
);

Les contraintes différentes que l'on peut déclarer sont les suivantes :
NOT NULL
La colonne ne peut pas contenir de valeurs NULL.
UNIQUE
Chaque ligne de la table doit avoir une valeur différente ou NULL pour cette (ou ces)
colonne.
PRIMARY KEY
Chaque ligne de la table doit avoir une valeur différente pour cette (ou ces) colonne.
les valeurs NULL sont rejetées.
FOREIGN KEY
Cette colonne fait référence à une colonne clé d'une autre table.
CHECK
Permet de spécifier les valeurs acceptables pour une colonne.

Mais sous mysql des différences apparaissent

Par exemple avec le moteur de base de donnée « innodb »

CREATE TABLE product (category INT NOT NULL, id INT NOT NULL,
price DECIMAL,
PRIMARY KEY(category, id)) ENGINE=INNODB;

CREATE TABLE customer (id INT NOT NULL,


PRIMARY KEY (id)) ENGINE=INNODB;

CREATE TABLE product_order (no INT NOT NULL AUTO_INCREMENT,


product_category INT NOT NULL,
product_id INT NOT NULL,
customer_id INT NOT NULL,
PRIMARY KEY(no),
INDEX (product_category, product_id),
FOREIGN KEY (product_category, product_id)
REFERENCES product(category, id)
ON UPDATE CASCADE ON DELETE RESTRICT,
INDEX (customer_id),
FOREIGN KEY (customer_id)
REFERENCES customer(id)) ENGINE=INNODB;

L’utilisation d’ « InnoDB » permet d’ajouter des clefs de contrainte étrangères à une


table via la commande ALTER TABLE:

ALTER TABLE yourtablename


ADD [CONSTRAINT symbol] FOREIGN KEY [id] (index_col_name, ...)
REFERENCES tbl_name (index_col_name, ...)
[ON DELETE {RESTRICT | CASCADE | SET NULL | NO ACTION}]
[ON UPDATE {RESTRICT | CASCADE | SET NULL | NO ACTION}]

9
Interrogation d’une base

La commande SELECT constitue, à elle seule, le langage permettant d'interroger une base de
données. Elle permet :

* de sélectionner certaines colonnes d'une table : c'est l'opération de projection ;


* de sélectionner certaines lignes d'une table en fonction de leur contenu : c'est l'opération
de restriction ;
* de combiner des informations venant de plusieurs tables : ce sont les opérations de
jointure, union, intersection,différence relationnelle ;
* de combiner entre elles ces différentes opérations.

Une interrogation, on parle plutôt de requête, est une combinaison d'opérations portant sur des
tables (relations) et dont le résultat est lui-même une table dont l'existence est éphémère (le
temps de la requête).

SELECT nom_col1, nom_col2, ...


FROM nom_table ;

1
Opérateur:
Les relations prioritaires entre opérateur sont effectuées dans cet ordre du moins important ou
plus important.

:=
||, OR, XOR
&&, AND
NOT
BETWEEN, CASE, WHEN, THEN, ELSE
=, <=>, >=, >, <=, <, <>, !=, IS, LIKE, REGEXP, IN
|
&
<<, >>
-, +
*, /, DIV, %, MOD
^
- (unary minus), ~ (unary bit inversion)
!
BINARY, COLLATE

Les parenthèses
La commande SELECT 1+2*3 ; donne le résultat 7 alors que SELECT (1+2)*3;
donne 9
Exemple :
select `type` from mytable where type = '2' AND pc1 = 'B38' OR type = '2' AND pc1 = 'B30'
OR type = '2' AND pc1 = 'B31' OR type = '2' AND pc1 = 'B14' OR type = '2' AND pc1 =
'B47' OR type = '2' AND pc1 = 'B48' OR type = '2' AND pc1 = 'B45';

est la même chose que :

select `type` from mytable where type = '2' AND (pc1 = 'B38' OR pc1 = 'B30' OR pc1 = 'B31'
OR pc1 = 'B14' OR pc1 = 'B47' OR pc1 = 'B48' OR pc1 = 'B45');

et en plus court :

select `type` from mytable where type = '2' AND pc1 in


('B38','B30','B31','B14','B47','B48','B45');

1
Fonctions et opérateurs de comparaison.

Le résultat d’une fonction de comparaison est soit


1 TRUE
0 FALSE
NULL
A part pour LEAST() et GREATEST()

Ces fonctions opèrent sur des nombres ou sur des chaînes de caractères.
Si un des arguments est NULL alors le résultat est toujours NULL à part pour la commande
NULL-safe : <=>
Si les deux arguments sont des chaînes de caractères alors la comparaison se fera en mode
chaîne de caractères. De même s’il s’agit de deux valeurs numériques, elles seront traitées
comme telles.
Par contre dans le cas ou l’on compare une valeur hexadécimale à une valeur autre qu’un
chiffre, elle sera traitée comme une chaîne binaire.
Dans le cas d’une valeur DATE ou TIME ou similaire comparé à une constante, cette valeur
sera converti en interne en TIMESTAMP.
Dans tous les autres cas ; la comparaison se fait en mode « reél » (REAL /FLOAT ….)
Par défaut les comparaisons de chaîne de caractères sont insensibles à la case.et elles utilisentl
la page de code par défaut.
Pour convertir des valeurs en chaîne et vice-versa, il faut utiliser les fonctions CAST ou
CONVERT.

Ex :
mysql> SELECT 1 > '6x';
-> 0
mysql> SELECT 7 > '6x';
-> 1
mysql> SELECT 0 > 'x6';
-> 0
mysql> SELECT 0 = 'x6';
-> 1

Note : quand vous comparez une chaîne de caractère à un nombre mysql ne peut pas l’index
de cette colonne pour retrouver rapidement une valeur par ex :
SELECT * FROM tbl_name WHERE str_col=1;
Ou str_col est une chaîne indexée, le résultat peut être erroné car '1', ' 1', '1a', ... peuvent
être compris comme un 1

Egal =
mysql> SELECT 1 = 0;
-> 0
mysql> SELECT '0' = 0;
-> 1
mysql> SELECT '0.0' = 0;
-> 1
mysql> SELECT '0.01' = 0;
-> 0
mysql> SELECT '.01' = 0.01;
-> 1

1
Egal tolérant au NULL <=>
Idem égalsauf qu’il retourne un 1 si deux opérandes sont NULL ou 0 si une des deux sont
NULL
mysql> SELECT 1 <=> 1, NULL <=> NULL, 1 <=> NULL;
-> 1, 1, 0
mysql> SELECT 1 = 1, NULL = NULL, 1 = NULL;
-> 1, NULL, NULL

Différent <>, !=
mysql> SELECT '.01' <> '0.01';
-> 1
mysql> SELECT .01 <> '0.01';
-> 0
mysql> SELECT 'zapp' <> 'zappp';
-> 1

Inférieur Supérieur …ou égal <= => > <


mysql> SELECT 0.1 <= 2;
-> 1
mysql> SELECT 2 < 2;
-> 0
mysql> SELECT 2 >= 2;
-> 1
mysql> SELECT 2 > 2;
-> 0

Test avec une valeur booléenne IS ou IS NOT


mysql> SELECT 1 IS TRUE, 0 IS FALSE, NULL IS UNKNOWN;
-> 1, 1, 1
mysql> SELECT 1 IS NOT UNKNOWN, 0 IS NOT UNKNOWN, NULL IS NOT UNKNOWN;
-> 1, 1, 0
Pour permettre une utilisation avec des logiciels utilisant l’ODBC
Si auto_col est de type AUTO_INCREMENT, SELECT * FROM tbl_name WHERE
auto_col IS NULL donne la dernière saisie.
Pour les champs DATE/DATETIME avec un type NOT NULL, pour retrouver les
dates « 0000-00-00 » on utilise :
SELECT * FROM tbl_name WHERE date_column IS NULL

Expression d’ensemble expr BETWEEN min AND max


mysql> SELECT 1 BETWEEN 2 AND 3;
-> 0
mysql> SELECT 'b' BETWEEN 'a' AND 'c';
-> 1
mysql> SELECT 2 BETWEEN 2 AND '3';
-> 1
mysql> SELECT 2 BETWEEN 2 AND 'x-3';
-> 0
expr NOT BETWEEN min AND max = NOT (expr BETWEEN min AND max

Recherche d’une valeur non nulle d’une liste COALESCE(value,...)


mysql> SELECT COALESCE(NULL,1);
-> 1
mysql> SELECT COALESCE(NULL,NULL,NULL);
-> NULL

1
Recherche d’une valeur la plus grande GREATEST(value1,value2,...)
mysql> SELECT GREATEST(2,0);
-> 2
mysql> SELECT GREATEST(34.0,3.0,5.0,767.0);
-> 767.0
mysql> SELECT GREATEST('B','A','C');
-> 'C'
Recherche d’une valeur la plus petite LEAST(value1,value2,...)
mysql> SELECT LEAST(2,0);
-> 0
mysql> SELECT LEAST(34.0,3.0,5.0,767.0);
-> 3.0
mysql> SELECT LEAST('B','A','C');
-> 'A'

Recherche d’une valeur appartenant à une liste expr IN (value,...)

mysql> SELECT 2 IN (0,3,5,'wefwf');


-> 0
mysql> SELECT 'wefwf' IN (0,3,5,'wefwf');
-> 1

expr NOT IN (value,...) = NOT (expr IN (value,...)).

Recherche d’une valeur NULL ISNULL(expr)


mysql> SELECT ISNULL(1+1);
-> 0
mysql> SELECT ISNULL(1/0);
-> 1
Recherche d’une place dans un intervalle INTERVAL(VALEUR,N1,N2,N3,...)
L’ensemble doit être un ensemble déjà classé. Il retourne la valeur 0 si
VALEUR < N sinon donne sa place dans l’ensemble. Toutes les valeurs sont
traitées comme des entiers.
mysql> SELECT INTERVAL(23, 1, 15, 17, 30, 44, 200);
-> 3
mysql> SELECT INTERVAL(10, 1, 10, 100, 1000);
-> 2
mysql> SELECT INTERVAL(22, 23, 30, 44, 200);
-> 0

1
Opérateur logique
NOT AND ( && ) OR ( || ) XOR
mysql> SELECT NOT 10;
-> 0
mysql> SELECT NOT 0;
-> 1
mysql> SELECT NOT NULL;
-> NULL
mysql> SELECT ! (1+1);
-> 0
mysql> SELECT ! 1+1;
-> 1

mysql> SELECT 1 && 1;


-> 1
mysql> SELECT 1 && 0;
-> 0
mysql> SELECT 1 && NULL;
-> NULL
mysql> SELECT 0 && NULL;
-> 0
mysql> SELECT NULL && 0;
-> 0
mysql> SELECT 1 || 1;
-> 1
mysql> SELECT 1 || 0;
-> 1
mysql> SELECT 0 || 0;
-> 0
mysql> SELECT 0 || NULL;
-> NULL
mysql> SELECT 1 || NULL;

-> 1
mysql> SELECT 1 XOR 1;
-> 0
mysql> SELECT 1 XOR 0;
-> 1
mysql> SELECT 1 XOR NULL;
-> NULL
mysql> SELECT 1 XOR 1 XOR 1;
-> 1

1
Pour cet exercice, vous devrez me donner les requetes sql qui correspondent aux demandes.

Voici une liste de données que vous devrez saisir.

nom maitre especes sexe naissance mort


Fluffy Harold chat f 1993-02-04
Claws Gwen chat m 1994-03-17
Buffy Harold chien f 1989-05-13
Fang Benny chien m 1990-08-27
Bowser Diane chien m 1998-08-31 1995-07-29
Chirpy Gwen oiseau f 1998-09-11
Whistler Gwen oiseau 1997-12-09
Slim Benny serpent m 1996-04-29

Vous devrez créer la table animaux, proprietaire, parametre


Voici le descriptif de la table animaux
nom, id_proprietaire,id_espece, sexe (m ou f)
id_proprietaire est une clé étrangère sur la table proprietaire
id_espece est une clé étrangère sur la table parametre

Voici le descriptif de la table proprietaire


Nom, prenom, rue, id_ville
id_ville est une cle étrangère sur la table commune

Voici le descriptif de la TABLE `communes`


(
`insee` int(5) NOT NULL,
`ville` varchar(40) character set ascii NOT NULL,
`code postal` int(5) NOT NULL,
`rattachement` int(5) NOT NULL,
`id` int(11) NOT NULL auto_increment,
PRIMARY KEY (`id`)
) DEFAULT CHARSET=latin1;

Cette table commune est accèssible et sur la quelle vous n'avez le droit que de lire (ex
SELECT).

Il faut aussi créer une table evenement qui va se composer comme suit:

id: l'index ou clef primaire...


id_annimaux : pointe sur le champ id la table annimaux
date : pour stocker la date de l'évement
commentaire:
id_parametre: un index sur la table paramètre

Table parametre
id: index...
texte : prévoir un champ d'au moins 50caractères

1
Le remplir avec:
id texte
1 Naissance
2 Mort
3 Maladie
4 Visite médicale
5 Vaccin
......
100 Chien
101 Chat
102 Oiseau
103 Serpent

Etablir une requete qui génère l'affichage du début en fonction de vos tables.

1
Les caractères passe-partout dans les requêtes

MySQL fournit le standard SQL des recherches de modèles, basé sur une extension des
expressions régulières similaires à celles utilisées par les utilitaires Unix comme vi, grep, et
sed.
La recherche de modèles SQL vous permet d'utiliser le caractère ‘_’ pour trouver n'importe
quel caractère et le caractère ‘%’ pour trouver un nombre arbitraire de caractères (y compris
aucun caractère). Dans MySQL, la recherche de modèles est sensible à la casse par défaut.
Quelques exemples vous sont présentés ici.
Notez que vous n'utilisez ni = ni <> lorsque vous utilisez la recherche de modèles SQL ;
utilisez les opérateurs de comparaison LIKE ou NOT LIKE à la place.
Pour trouver les noms commençant par la lettre ‘b’:
mysql> SELECT * FROM animal WHERE nom LIKE "b%";
+--------+--------+--------+------+------------+------------+
| nom | maitre | espece | sexe | naissance | mort |
+--------+--------+--------+------+------------+------------+
| Buffy | Harold | chien | f | 1989-05-13 | NULL |
| Bowser | Diane | chien | m | 1989-08-31 | 1995-07-29 |
+--------+--------+--------+------+------------+------------+

Pour trouver les noms finissant par ‘fy’ :


mysql> SELECT * FROM animal WHERE nom LIKE "%fy";
+--------+--------+---------+------+------------+-------+
| nom | maitre | espece | sexe | naissance | mort |
+--------+--------+---------+------+------------+-------+
| Fluffy | Harold | chat | f | 1993-02-04 | NULL |
| Buffy | Harold | chien | f | 1989-05-13 | NULL |
+--------+--------+---------+------+------------+-------+

Pour trouver les noms contenant le caractères ‘w’ :


mysql> SELECT * FROM animal WHERE nom LIKE "%w%";
+----------+--------+---------+------+------------+------------+
| nom | maitre | espece | sexe | naissance | mort |
+----------+--------+---------+------+------------+------------+
| Claws | Gwen | chat | m | 1994-03-17 | NULL |
| Bowser | Diane | chien | m | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen | oiseaux | NULL | 1997-12-09 | NULL |
+----------+--------+---------+------+------------+------------+

Pour trouver les noms contenant exactement 5 caractères, utilisez le caractère de recherche
‘_’ :
mysql> SELECT * FROM animal WHERE nom LIKE "_____";
+-------+--------+--------+------+------------+------+
| nom | maitre | espece | sexe | naissance | mort |
+-------+--------+--------+------+------------+------+
| Claws | Gwen | chat | m | 1994-03-17 | NULL |
| Buffy | Harold | chien | f | 1989-05-13 | NULL |
+-------+--------+--------+------+------------+------+

L'autre type de recherche de modèles fourni par MySQL utilise les expressions régulières
étendues. Lorsque vous testez une recherche avec ce type de modèle, utilisez les opérateurs
REGEXP et NOT REGEXP (ou RLIKE et NOT RLIKE qui sont des synonymes).

1
Quelques caractéristiques des expressions régulières étendues sont :
l Le caractère ‘.’ trouve n'importe quel caractère.
l Une classe de caractères ‘[...]’ trouve n'importe quel caractère contenu entre les
crochets. Par exemple, la classe de caractères ‘[abc]’ trouve le caractère ‘a’, ‘b’, ou
‘c’. Pour définir un intervalle de caractères, utilisez un trait d'union. La classe de
caractères ‘[a-z]’ trouvera n'importe quel caractère minuscule, tout comme la classe
‘[0-9]’ trouvera n'importe quel nombre.
l Le caractère ‘*’ trouvera aucune ou plus d'instances du caractère qui le précède. Par
exemple, ‘x*’ trouvera n'importe quel nombre de fois le caractère ‘x’, ‘[0-9]*’
trouvera n'importe quel nombre et ‘.*’ trouvera n'importe quel nombre de fois
n'importe quel caractère.
l Le modèle est trouvé s'il se produit n'importe où dans la valeur testée. (Les modèles
SQL ne sont trouvés que s'ils sont présents en valeur entière.)
l Pour ancrer un modèle de sorte qu'il soit trouvé au début ou à la fin de valeur testée,
utilisez ‘^’ au début ou bien ‘$’ à la fin du modèle.
Pour démontrer comment les expressions régulières fonctionnent, les requêtes LIKE vues
précédemment ont été réécrites pour utiliser REGEXP.
Pour trouver les noms qui commencent par la lettre ‘b’, utilisez ‘^’ pour trouver le début du
nom :
mysql> SELECT * FROM animal WHERE nom REGEXP "^b";
+--------+--------+--------+------+------------+------------+
| nom | maitre | espece | sexe | naissance | mort |
+--------+--------+--------+------+------------+------------+
| Buffy | Harold | chien | f | 1989-05-13 | NULL |
| Bowser | Diane | chien | m | 1989-08-31 | 1995-07-29 |
+--------+--------+--------+------+------------+------------+

Avant la version 3.23.4 de MySQL, REGEXP était sensible à la casse, et la requête précédente
ne retournait aucune ligne. Pour trouver la lettre ‘b’ minuscule ou majuscule, utilisez cette
requête à la place :
mysql> SELECT * FROM animal WHERE nom REGEXP "^[bB]";

Depuis MySQL 3.23.4, pour forcer REGEXP à être sensible à la casse, utilisez le mot-clé
BINARY pour faire de la chaîne, une chaîne binaire. Cette requête trouvera uniquement la
lettre minuscule ‘b’ au début du nom :
mysql> SELECT * FROM animal WHERE nom REGEXP BINARY "^b";

Pour trouver les noms finissant par ‘fy’, utilisez ‘$’ pour trouver la fin du nom :
mysql> SELECT * FROM animal WHERE nom REGEXP "fy$";
+---------+--------+--------+-------+------------+------+
| nom | maitre | espece | sexe | naissance | mort |
+---------+--------+--------+-------+------------+------+
| Fluffy | Harold | chat | f | 1993-02-04 | NULL |
| Buffy | Harold | chien | f | 1989-05-13 | NULL |
+---------+--------+--------+-------+------------+------+

Pour trouver les noms contenant la lettre ‘w’ minuscule ou majuscule, utilisez la requête
suivante :

1
mysql> SELECT * FROM animal WHERE nom REGEXP "w";
+----------+--------+---------+------+------------+------------+
| nom | maitre | espece | sexe | naissance | mort |
+----------+--------+---------+------+------------+------------+
| Claws | Gwen | chat | m | 1994-03-17 | NULL |
| Bowser | Diane | chien | m | 1989-08-31 | 1995-07-29 |
| Whistler | Gwen | oiseaux | NULL | 1997-12-09 | NULL |
+----------+--------+---------+------+------------+------------+

Parce qu'une expression régulière est trouvée si le modèle se trouve n'importe où dans la
valeur, il n'est pas nécessaire dans la requête précédente de mettre un joker de chaque côté du
modèle recherché pour trouver la valeur entière comme cela aurait été le cas en utilisant les
modèles de recherche SQL.
Pour trouver les noms contenant exactement 5 caractères, utilisez ‘^’ et ‘$’ pour trouver le
début et la fin du nom, et 5 instances de ‘.’ au milieu :
mysql> SELECT * FROM animal WHERE nom REGEXP "^.....$";
+-------+--------+--------+------+------------+------+
| nom | maitre | espece | sexe | naissance | mort |
+-------+--------+--------+------+------------+------+
| Claws | Gwen | chat | m | 1994-03-17 | NULL |
| Buffy | Harold | chien | f | 1989-05-13 | NULL |
+-------+--------+--------+------+------------+------+

Vous pouvez aussi écrire la requête suivante en utilisant l'opérateur ‘{n}’ ``répéter-n-fois'' :
mysql> SELECT * FROM animal WHERE nom REGEXP "^.{5}$";
+-------+--------+--------+------+------------+------+
| nom | maitre | espece | sexe | naissance | mort |
+-------+--------+--------+------+------------+------+
| Claws | Gwen | chat | m | 1994-03-17 | NULL |
| Buffy | Harold | chien | f | 1989-05-13 | NULL |
+-------+--------+--------+------+------------+------+

Compter les lignes

Les bases de données sont souvent employées pour répondre à la question : ``Combien de fois
un certain type de données se trouve dans la table ?'' Par exemple, vous aimeriez savoir
combien d'animaux vous avez, ou bien combien d'animaux chaque propriétaire possède, ou
encore savoir différentes choses concernant vos animaux.
Savoir combien vous avez d'animaux revient à se poser la question : ``Combien de lignes y a-
t-il dans la table animal ?'' parce qu'il y a un enregistrement par animal. La fonction
COUNT() compte le nombre de résultats non NULL, donc, la requête pour compter les
animaux ressemble à ceci :
mysql> SELECT COUNT(*) FROM animal;
+----------+
| COUNT(*) |
+----------+
| 9 |
+----------+

Vous pouvez trouver également les noms des propriétaires des animaux. Vous pouvez utiliser
COUNT() si vous voulez trouver combien d'animaux possède chaque propriétaire :

2
mysql> SELECT maitre, COUNT(*) FROM animal GROUP BY maitre;
+--------+----------+
| maitre | COUNT(*) |
+--------+----------+
| Benny | 2 |
| Diane | 2 |
| Gwen | 3 |
| Harold | 2 |
+--------+----------+

Notez l'utilisation de la clause GROUP BY pour grouper tous les enregistrements par
propriétaire. Sans cela, vous auriez le message d'erreur suivant :
mysql> SELECT maitre, COUNT(maitre) FROM animal;
ERROR 1140 at line 1: Mixing of GROUP columns (MIN(),MAX(),COUNT()...)
with no GROUP columns is illegal if there is no GROUP BY clause

COUNT() et GROUP BY sont utiles pour caractériser vos données de diverses fa¸ons. Les
exemples suivants montrent différentes manières pour obtenir des statistiques sur les animaux.
Nombre d'animaux par espèce :
mysql> SELECT espece, COUNT(*) FROM animal GROUP BY espece;
+---------+----------+
| espece | COUNT(*) |
+---------+----------+
| oiseau | 2 |
| chat | 2 |
| chien | 3 |
| hamster | 1 |
| serpent | 1 |
+---------+----------+

Nombre d'animaux par sexe :


mysql> SELECT sexe, COUNT(*) FROM animal GROUP BY sexe;
+------+----------+
| sexe | COUNT(*) |
+------+----------+
| NULL | 1 |
| f | 4 |
| m | 4 |
+------+----------+

(Dans ce résultat, NULL indique les sexes inconnus.)


Nombre d'animaux par espèce et sexe :
mysql> SELECT espece, sexe, COUNT(*) FROM animal GROUP BY espece, sexe;
+---------+------+----------+
| espece | sexe | COUNT(*) |
+---------+------+----------+
| oiseau | NULL | 1 |
| oiseau | f | 1 |
| chat | f | 1 |
| chat | m | 1 |
| chien | f | 1 |
| chien | m | 2 |
| hamster | f | 1 |
| serpent | m | 1 |
+---------+------+----------+

2
Vous n'avez pas besoin de rechercher une table entière quand vous employez COUNT(). Par
exemple, la requête précédente, si vous voulez trouver uniquement les chiens et les chats,
ressemble à cela :
mysql> SELECT espece, sexe, COUNT(*) FROM animal
-> WHERE espece = "chien" OR espece = "chat"
-> GROUP BY espece, sexe;
+---------+------+----------+
| espece | sexe | COUNT(*) |
+---------+------+----------+
| chat | f | 1 |
| chat | m | 1 |
| chien | f | 1 |
| chien | m | 2 |
+---------+------+----------+

Ou bien, si vous voulez trouver le nombre d'animaux par sexe, uniquement pour les animaux
dont le sexe est connu :
mysql> SELECT espece, sexe, COUNT(*) FROM animal
-> WHERE sexe IS NOT NULL
-> GROUP BY espece, sexe;
+---------+------+----------+
| espece | sexe | COUNT(*) |
+---------+------+----------+
| oiseau | f | 1 |
| chat | f | 1 |
| chat | m | 1 |
| chien | f | 1 |
| chien | m | 2 |
| hamster | f | 1 |
| serpent | m | 1 |
+---------+------+----------+

La table animal garde les enregistrements de vos animaux. Si vous voulez enregistrer
d'autres informations concernant vos animaux, comme les événements de leurs vies, les
visites chez le vétérinaire, ou encore lorsqu'ils ont mis bas, vous avez besoin d'une autre table.
De quoi a besoin cette table ? Elle doit :
l Contenir le nom de l'animal pour savoir à quel animal cet événement se rattache.
l Une date pour savoir quand a eu lieu l'événement.
l Un champ qui décrit l'événement.
l Un champ de type événement, si vous voulez être capable de cataloguer les
événements.
En prenant cela en considération, le code CREATE TABLE pour la table evenement doit
ressembler à ceci :
mysql> CREATE TABLE evenement (nom VARCHAR(20), date DATE,
-> type VARCHAR(15), remarque VARCHAR(255));

Tout comme la table animal, il est facile d'enregistrer les enregistrements initiaux en créant
un fichier texte délimité par des tabulations, contenant l'information :
nom date Type remarque
Fluffy 1995-05-15 mise bas 4 chatons, 3 femelles, 1 mâles
Buffy 1993-06-23 mise bas 5 chiots, 2 femelles, 3 mâles

2
Buffy 1994-06-19 mise bas 3 chiots, 3 femelles
Chirpy 1999-03-21 vétérinaire Redresser le bec
Slim 1997-08-03 vétérinaire Cotes cassées
Bowser 1991-10-12 chenil  
Fang 1991-10-12 chenil  
Don d'un nouvel objet de
Fang 1998-08-28 anniversaire
mastication
Claws 1998-03-17 anniversaireDon d'un nouveau collier anti-puces
Whistler 1998-12-09 anniversairePremier anniversaire
Chargez ces enregistrements comme cela :
mysql> LOAD DATA LOCAL INFILE "evenement.txt" INTO TABLE evenement;

En se basant sur ce que vous avez appris des requêtes effectuées sur la table animal, vous
devriez être capable de faire des recherches sur les enregistrements de la table evenement ;
le principe est le même. Quand devez-vous vous demander si la table evenement est seule
suffisante pour répondre à votre question ?
Supposez que vous voulez trouver l'âge de chaque animal lorsqu'il a mis bas. La table
evenement indique quand cela s'est produit, mais pour le calcul de l'âge de la mère, vous
avez besoin de sa date de naissance. Parce que ces informations sont stockées dans la table
animal, vous avez besoin des deux tables pour cette requête :
mysql> SELECT animal.nom,
-> (TO_DAYS(date) - TO_DAYS(naissance))/365 AS age,
-> remarque
-> FROM animal, evenement
-> WHERE animal.nom = evenement.nom AND type = "mise bas";
+--------+------+--------------------------------+
| nom | age | remarque |
+--------+------+--------------------------------+
| Fluffy | 2.27 | 4 chatons, 3 femelles, 1 mâle |
| Buffy | 4.12 | 5 chiots, 2 femelles, 3 mâles |
| Buffy | 5.10 | 3 chiots, 3 femelles |
+--------+------+--------------------------------+

Il y a plusieurs choses à noter concernant cette requête :


l La clause FROM liste les deux tables parce que la requête a besoin d'informations
contenues dans ces deux tables.
l Lorsque vous combinez (joignez) des informations provenant de plusieurs tables, vous
devez spécifier quels enregistrements d'une table peuvent être associés à quels
enregistrements des autres tables. C'est aisé parce qu'elles ont toutes les deux une
colonne nom. La requête utilise la clause WHERE pour faire correspondre les
enregistrements des deux tables sur les valeurs de la colonne nom.
l Parce que la colonne nom apparaît dans les deux tables, vous devez être explicite
concernant la table que vous utilisez lorsque vous vous référez à cette colonne. C'est
fait en faisant précéder le nom de la colonne par le nom de la table.

2
Vous n'avez pas besoin de deux tables différentes pour effectuer une jointure. Quelques fois,
c'est plus facile de joindre une table sur elle-même, si vous voulez comparer des
enregistrements dans une table avec d'autres enregistrements de la même table. Par exemple,
pour trouver des paires multiples parmi vos animaux, vous pouvez joindre la table animal
sur elle-même pour trouver les paires mâles / femelles par rapport à l'espèce :
mysql> SELECT p1.nom, p1.sexe, p2.nom, p2.sexe, p1.espece
-> FROM animal AS p1, animal AS p2
-> WHERE p1.espece = p2.espece AND p1.sexe = "f" AND p2.sexe = "m";
+--------+------+--------+------+---------+
| nom | sexe | nom | sexe | espece |
+--------+------+--------+------+---------+
| Fluffy | f | Claws | m | chat |
| Buffy | f | Fang | m | chien |
| Buffy | f | Bowser | m | chien |
+--------+------+--------+------+---------+

Dans cette requête, nous avons spécifié des alias pour les noms de tables dans l'ordre de
référence des colonnes et ainsi maintenir directement à quelle instance de la table chaque
colonne est associée.

3.4. Obtenir des informations à propos des bases de données et


des tables
Que faire si vous oubliez le nom d'une base de données ou d'une table, ou bien encore la
structure d'une table donnée (par exemple, comment se nomment ses colonnes) ?
MySQL répond à ce problème en fournissant plusieurs commandes qui renvoient des
informations à propos des tables et des bases de données les contenant.
Vous avez déjà vu SHOW DATABASES qui liste les bases de données gérées par le serveur.
Pour trouver quelle base de données est actuellement sélectionnée, utilisez la fonction
DATABASE() :
mysql> SELECT DATABASE();
+------------+
| DATABASE() |
+------------+
| menagerie |
+------------+

Si vous n'avez encore sélectionné aucune base de données, le résultat est vide.
Pour trouver quelles sont les tables que la base contient (par exemple, quand vous n'êtes pas
sûr du nom d'une table), utilisez cette commande :
mysql> SHOW TABLES;
+---------------------+
| Tables in menagerie |
+---------------------+
| evenement |
| animal |
+---------------------+

Si vous voulez en savoir d'avantage sur la structure d'une table, la commande DESCRIBE est
utile ; elle fournit des informations sur chaque colonne de la table :
mysql> DESCRIBE animal;

2
+-----------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-----------+-------------+------+-----+---------+-------+
| nom | varchar(20) | YES | | NULL | |
| maitre | varchar(20) | YES | | NULL | |
| espece | varchar(20) | YES | | NULL | |
| sexe | char(1) | YES | | NULL | |
| naissance | date | YES | | NULL | |
| mort | date | YES | | NULL | |
+-----------+-------------+------+-----+---------+-------+

Field indique le nom de la colonne, Type est son type de données, NULL indique si la
colonne peut contenir des valeurs NULL, Key indique si la colonne est indexée et Default
spécifie la valeur par défaut de la colonne.
Si vous avez des index sur une table, SHOW INDEX FROM nom_de_table vous fournira
des informations sur elles.

2
Les requêtes

Affichage d'une la table article

SELECT * FROM `articles`

Affichage des champs nom et prix H.T.

SELECT `nom`, `prixHT` FROM `articles`

Affichage des articles que l'on a besoin de commander


SELECT `nom`, `prixHT` FROM `articles` WHERE (`QteStock` < `SeuilCritique` )

Si on veut prendre un peu de marge lros de nos commandes...


SELECT `nom`, `prixHT` FROM `articles` WHERE (`QteStock` < (`SeuilCritique`*10) )

On veut préparer la commande directement chez notre fournisseur.

SELECT `nom`, (`SeuilCritique`*10-`QteStock` ) ,`prixHT` FROM `articles` WHERE


(`QteStock` < (`SeuilCritique`*10) )

Et on veut aussi afficher le prix de chaque article de la commande


SELECT `nom`, (`SeuilCritique`*10-`QteStock` ) ,`prixHT` , (`SeuilCritique`*10-`QteStock`
)*`prixHT` FROM `articles` WHERE (`QteStock` < (`SeuilCritique`*10) )

Mais comme il ne s'agit pas du même fournisseur on veut pour chaque fournisseur
par exemple.

SELECT `nom`, (`SeuilCritique`*10-`QteStock` ) ,`prixHT` , (`SeuilCritique`*10-`QteStock`


)*`prixHT` FROM `articles` WHERE (`QteStock` < (`SeuilCritique`*10) ) AND
(`Fournisseur` = '1')

Samedi matin je vais à Paris et je vais donc en profiter pour passer une commande
chez des fournisseurs situé dans cette ville.
On va donc chercher les fournisseur Parisien dans un premier temps.

SELECT * FROM `fournisseurs` where `Ville` like 'pari%'

//Recherche des ville commencant par "a__a%"

SELECT *
FROM `City`
WHERE `name` LIKE "a__a%"
LIMIT 30 , 50
 
//Ajouter un index

Un index a été ajouté sur Name (traitement: 0.0545 sec.) requête SQL:
ALTER TABLE `City` ADD INDEX ( `Name` )
//Count(*)

2
Affichage des enregistrements 0 - 29 (64 total, traitement: 0.0030 sec.) requête SQL:
SELECT `CountryCode` , COUNT( * )
FROM `City`
WHERE `Population` <50000
GROUP BY `CountryCode`
LIMIT 0 , 30
//
Affichage des enregistrements 0 - 70 (71 total, traitement: 0.0033 sec.) requête SQL:
SELECT `CountryCode` , `District` , COUNT( * )
FROM `City`
WHERE `Population` <50000
GROUP BY `CountryCode` , `District`
LIMIT 0 , 300
//
SELECT `p1`.`Societe`, `p2`.`Nom`, (10*`p2`.`SeuilCritique`)-(`p2`.`QteStock`),
`p2`.`PrixHT`, (`p2`.`PrixHT`*((10*`p2`.`SeuilCritique`)-(`p2`.`QteStock`))) FROM 
`fournisseurs` as `p1` , `articles` as `p2`   WHERE (10*`SeuilCritique`)>(`QteStock`) AND
`p1`.`Societe` = `p2`.`Fournisseur`
//alias
SELECT `p1`.`Societe`, `p2`.`Nom`, (10*`p2`.`SeuilCritique`)-(`p2`.`QteStock`),
`p2`.`PrixHT`, (`p2`.`PrixHT`*((10*`p2`.`SeuilCritique`)-(`p2`.`QteStock`))) FROM 
`fournisseurs` as `p1` , `articles` as `p2`   WHERE (10*`SeuilCritique`)>(`QteStock`) AND
`p1`.`Numero` = `p2`.`Fournisseur`
//group by
Affichage des enregistrements 0 - 1 (2 total, traitement: 0.0011 sec.) requête SQL:
SELECT `p1`.`Societe` , `p2`.`Nom` , ( 10 * `p2`.`SeuilCritique` ) - ( `p2`.`QteStock` ) ,
`p2`.`PrixHT` , (
`p2`.`PrixHT` * ( ( 10 * `p2`.`SeuilCritique` ) - ( `p2`.`QteStock` ) ) )
FROM `fournisseurs` AS `p1` , `articles` AS `p2`
WHERE ( 10 * `SeuilCritique` ) > ( `QteStock` )
AND `p1`.`Numero` = `p2`.`Fournisseur`
GROUP BY `p1`.`Societe`
LIMIT 0 , 30
//order by
SELECT `p1`.`Societe`, `p2`.`Nom`, (10*`p2`.`SeuilCritique`)-(`p2`.`QteStock`),
`p2`.`PrixHT`, (`p2`.`PrixHT`*((10*`p2`.`SeuilCritique`)-(`p2`.`QteStock`))) FROM 
`fournisseurs` as `p1` , `articles` as `p2`   WHERE (10*`SeuilCritique`)>(`QteStock`) AND
`p1`.`Numero` = `p2`.`Fournisseur` ORDER BY `p1`.`Societe`
 

2
Les types de Relations
· Un vers Un · Un vers N · N vers Un · N vers N

Dans un modèle relationnel, on distingue plusieurs types de relations entre


les entités. Lors du passage du modèle conceptuel (logique) au modèle
Physique ces relations seront représentées soit par l'insertion de clés
étrangères dans certaines tables, soit par la création de nouvelles tables.
Voici les relations utilisées en pratique : Le modèle conceptuel représente
toutes les relations existantes entre les entités. Par exemple, il peut y
avoir un entité Client et une entité Commande entre lesquelles il existe
une relation Un-vers-N. Le modèle physique est la concrétisation du modèle
logique une fois la base cible choisie. Les entités deviennent des tables,
les propriétés deviennent des champs dans les tables, et on voit apparaître
les clés étrangères ainsi que les tables donnant corps à certaines
relations multiples.

Relation Un-vers-Un

Une relation Un-vers-Un existe quand pour chaque clé primaire il y a zéro
ou une valeur correspondante pour un autre champ ou un autre
enregistrement. Lorsque la relation concerne des champs, ceux-ci sont
généralement placés dans une même table, mais cela n'est pas obligatoire.
Lorsque la relation concerne des entités (des enregistrements dans le
modèle physique) elle peut s'entendre entre deux entités ou bien d'une
entité vers elle -même. Ce dernier cas permet la représentation de
hiérarchies (par exemple l'entité " employé " peut avoir une relation vers
une autre entité "employé " avec la définition " a pour chef... "). Un tel
bouclage dune table sur elle-même s'appelle aussi une auto-jointure

Relation Un-vers-N

Une relation Un-vers-N (un vers plusieurs) existe quand, pour chaque
enregistrement dans une table il existe zéro ou plusieurs enregistrements
liés dans une autre table (exemple : un client a plusieurs commandes).

Relation N-vers-Un

Une telle relation existe lorsque plusieurs enregistrements d'une même


table font référence de façon non ambiguë à un seul enregistrement d'une
autre table. On appelle parfois cette relation une relation " Lookup " ou
table de référence car elle représente une référence vers la clé primaire
d'une autre table. Une relation N-vers-Un impliquant des clés étrangères
peut généralement être renversée (en Un-vers-N), alors qu'une relation Un-
vers-N impliquant que des clés primaires (liens identifiants) ne peut pas
être renversée en N-vers-Un.

Relation N-vers-N

Une telle relation existe lorsque plusieurs enregistrements d'une même


table sont liés à plusieurs autres enregistrements d'une autre table. Cette
relation est réversible par essence. Un exemple classique est celui des
commandes et des articles : plusieurs commandes peuvent faire références au
même article, et plusieurs articles peut être utilisés dans une même
commande. Les bases de données relationnelles ne peuvent représenter
directement les relations N-vers-N, le concepteur de la base doit créer une
table intermédiaire (contenant des couples formés des clés primaires des
deux tables en relation plus d'éventuelles propriétés spécifiques à la
relation).

2
Les variables :

On peut avoir besoin dans certains cas de variables temporaire ou de table temporaire.

La syntaxe utilisé est @nom_variable := fonction …..

select @min_price:=min(price),@max_price:=max(price) from shop;

Avec une table ci-dessous

CREATE TABLE shop (


article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
dealer CHAR(20) DEFAULT '' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL,
PRIMARY KEY(article, dealer));

INSERT INTO shop VALUES


(1,'A',3.45),(1,'B',3.99),(2,'A',10.99),(3,'B',1.45),(3,'C',1.69),
(3,'D',1.25),(4,'D',19.95);

Pour vous entraîner, il faut dupliquer la table (ou la recopier dans une nouvelle).
Par exemple

Pour obtenir le nombre maximum d’article


SELECT MAX(article) AS article FROM shop

Pour obtenir le numéro, le vendeur et le prix de l’article le plus cher

L’article le plus cher


SELECT MAX(`price`) AS `price` FROM `shop`

On peut le mettre dans une variable :


SELECT @max_price:=MAX(`price`) FROM `shop`;
SELECT `article`, `dealer`, `price` FROM `shop` WHERE `price`= @max_price;

On aurait pu aussi faire comme ci-dessous :

SELECT `article`, `dealer`, `price` FROM `shop` WHERE `price`=(SELECT MAX(`price`)


FROM `shop`) mais ceci est valable uniquement en ANSI SQL pas en mysql 4 et 3….

On peux aussi faire :


SELECT `article`, `dealer`, `price` FROM `shop` ORDER BY `price` DESC LIMIT 1

Pour obtenir le plus haut prix de chaque article

SELECT article, MAX(price) AS price FROM shop GROUP BY article

Pour chaque article, il faut trouver le plus cher des vendeurs…


En ansi sql cela peut se faire

2
SELECT article, dealer, price FROM shop s1 WHERE price=(SELECT
MAX(s2.price) shop s2 WHERE s1.article = s2.article)

En mysql on peut le faire d’une autre façon :


A partir d’une table temporaire

CREATE TEMPORARY TABLE tmp (


article INT(4) UNSIGNED ZEROFILL DEFAULT '0000' NOT NULL,
price DOUBLE(16,2) DEFAULT '0.00' NOT NULL);

LOCK TABLES shop read;


INSERT INTO tmp SELECT articl e, MAX(price) FROM shop GROUP BY article;

SELECT shop.article, dealer, shop.price FROM shop, tmp


WHERE shop.article=tmp.article AND shop.price=tmp.price;

UNLOCK TABLES;

DROP TABLE tmp;


Il faut utiliser une table « TEMPORARY » sinon il faut bloquer (verrou =
LOCK) l’accès à cette table.

En un peu plus tiré par les cheveux 

SELECT article,
SUBSTRING( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 7) AS dealer,
0.00+LEFT( MAX( CONCAT(LPAD(price,6,'0'),dealer) ), 6) AS price
FROM shop
GROUP BY article;

Les Foreign Keys

CREATE TABLE persons (


id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
name CHAR(60) NOT NULL,
PRIMARY KEY (id)
);

CREATE TABLE shirts (


id SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
style ENUM('t-shirt', 'polo', 'dress') NOT NULL,
color ENUM('red', 'blue', 'orange', 'white', 'black') NOT NULL,
owner SMALLINT UNSIGNED NOT NULL REFERENCES persons,
PRIMARY KEY (id)
);

INSERT INTO persons VALUES (NULL, 'Antonio Paz');

INSERT INTO shirts VALUES


(NULL, 'polo', 'blue', LAST_INSERT_ID()),
(NULL, 'dress', 'white', LAST_INSERT_ID()),
(NULL, 't-shirt', 'blue', LAST_INSERT_ID());

INSERT INTO persons VALUES (NULL, 'Lilliana Angelovska');

INSERT INTO shirts VALUES


(NULL, 'dress', 'orange', LAST_INSERT_ID()),
(NULL, 'polo', 'red', LAST_INSERT_ID()),
(NULL, 'dress', 'blue', LAST_INSERT_ID()),
(NULL, 't-shirt', 'white', LAST_INSERT_ID());

3
La requête qui correspond à

SELECT s.* FROM persons p, shirts s


WHERE p.name LIKE 'Lilliana%'
AND s.owner = p.id
AND s.color <> 'white';

3
Mysql et la ligne de commande.

Sous unix on utiliser mysql directement en ligne de commande.


Pour se connecter sur mysql avec l’utilisateur formation (-u)
et de saisir le mot de passe (-p).
Le texte ecrit en italique est ce que vous répond mysql.

mysql -u formation –p
Enter password:

mysql> connect formation


Connection id: 489045
Current database: formation

mysql> SHOW tables;

+-------------------------+
| Tables_in_formation |
+-------------------------+
| BLAISE_ARTICLES |
| BLAISE_FOURNISSEURS |
| City |
| DIANA |
| DIANA_F |
| ECHANGE REQUETE |
| JR |
| JRF |
| MEIZONNIER_ARTICLES |
| MEIZONNIER_FOURNISSEURS |
| MOHAMED |
| MOHAMED_F |
| MOUKOURI_FOUTNISSEUR |
| Moukouri |
| YOUSFI |
| YOUSFI_FOURNISSEUR |
| articles |
| fournisseurs |
| persons |
| shirts |
| shop |
+-------------------------+
21 rows in set (0.00 sec)

mysql> CREATE TABLE `eleves` (`nom` VARCHAR( 20 ) NOT NULL ,`prénom`


VARCHAR( 20 ) NOT NULL , `age` TINYINT NOT NULL );
Query OK, 0 rows affected (0.03 sec)

mysql>SELECT * FROM `eleves`;


Empty set (0.00 sec)

mysql> ALTER TABLE `eleves` ADD `numero de sécurité sociale` BIGINT NOT NULL
FIRST;
ERROR 2006: MySQL server has gone away <-MESAGE DE RECONNECTION A LA
No connection. Trying to reconnect... <-BASE CAR CELLE-CI SE COUPE
Connection id: 489135 <- AUTOMATIQUEMENT
Current database: formation

3
Query OK, 0 rows affected (0.01 sec)
Records: 0 Duplicates: 0 Warnings: 0

si on s’est trompé dans le nom du champ :

mysql> ALTER TABLE `eleves` CHANGE `numero de sécurité sociale` `numero de sécurité
social` BIGINT( 20 ) DEFAULT '0' NOT NULL

On va utiliser une clé primaire


ALTER TABLE `eleves` ADD PRIMARY KEY ( `numero de sécurité social` )

3
Les fonctions spécifiques relative à GROUP BY

Si vous utilisez les fonctions de groupement avec une requête ne contenant pas de clause
GROUP BY, cela revient à grouper toutes les lignes.
 AVG(expr)

Retourne la moyenne de l'expression expr :


mysql> SELECT student_name, AVG(test_score)
-> FROM student
-> GROUP BY student_name;
 BIT_AND(expr)

Retourne la combinaison AND bit à bit de expr. Le calcul est fait en précision de 64
bits (BIGINT).
Depuis MySQL 4.0.17, cette fonction retourne 18446744073709551615 s'il n'y avait
pas de lignes. (C'est un entier BIGINT non-signé, dont tous les bits sont à 1.) Avant
4.0.17, la fonction retournait -1 s'il n'y avait pas de ligne trouvées.
 BIT_OR(expr)

Retourne la combinaison OR bit à bit de expr. Le calcul est fait en précision de 64 bits
(BIGINT).
Cette fonction retourne 0 s'il n'y a pas de ligne à traiter.
 BIT_XOR(expr)

Retourne la combinaison XOR bit à bit de expr. Le calcul est fait en précision de 64
bits (BIGINT).
Cette fonction retourne 0 s'il n'y a pas de ligne à traiter.
Cette fonction est disponible depuis MySQL 4.1.1.
 COUNT(expr)

Retourne le nombre de valeurs non-NULL dans les lignes lues par la commande
SELECT :
mysql> SELECT student.student_name,COUNT(*)
-> FROM student,course
-> WHERE student.student_id=course.student_id
-> GROUP BY student_name;

COUNT(*) est un peu différente dans son action, car elle retourne le nombre de lignes,
même si elles contiennent NULL.
COUNT(*) est optimisée pour retourner très rapidement un résultat si SELECT travaille
sur une table, qu'aucune autre colonne n'est lue, et qu'il n'y a pas de clause WHERE. Par
exemple :
mysql> SELECT COUNT(*) FROM student;
Cette optimisation s'applique uniquement pour les tables MyISAM et ISAM, car un
compte exact du nombre de lignes est stocké pour ces types de tables, et il peut être lu

3
très rapidement. Pour les moteurs de tables transactionnels, (InnodB, BDB), le stockage
de cette valeur est plus problématique, car plusieurs transactions peuvent survenir en
même temps, et affecter toutes ce compte.
 COUNT(DISTINCT expr,[expr...])

Retourne le nombre de valeurs non-NULL distinctes :


mysql> SELECT COUNT(DISTINCT results) FROM student;
Avec MySQL, vous po uvez lire le nombre d'expression distinctes qui ne
contiennent pas NULL, en pla¸ant ici une liste d'expression. Avec SQL-99, vous devriez
faire une concaténation de toutes les expressions dans COUNT(DISTINCT ...).
 GROUP_CONCAT(expr)

Syntaxe complète :
GROUP_CONCAT([DISTINCT] expr [,expr ...]
[ORDER BY {unsigned_integer | col_name | formula} [ASC |
DESC] [,col ...]]
[SEPARATOR str_val])
Cette fonction a été ajoutée en MySQL version 4.1. Elle retourne la chaîne résultant de
la concaténation de toutes les valeurs du groupe :
mysql> SELECT student_name,
-> GROUP_CONCAT(test_score)
-> FROM student
-> GROUP BY student_name;
ou :
mysql> SELECT student_name,
-> GROUP_CONCAT(DISTINCT test_score
-> ORDER BY test_score DESC SEPARATOR " ")
-> FROM student
-> GROUP BY student_name;
Avec MySQL, vous pouvez obtenir la concaténation d'une série d'expressions. Vous
pouvez éliminer les doublons en utilisant DISTINCT. Si vous voulez trier les valeurs du
résultat, il faut utiliser ORDER BY. Pour trier en ordre inverse, ajoutez le mot clé DESC
(descendant) au nom de la colonne que vous triez dans la clause ORDER BY. Par défaut,
l'ordre est ascendant. Cela peut être spécifié explicitement avec le mot clé ASC.
SEPARATOR est une chaîne qui sera insérée entre chaque valeur du résultat. La valeur
par défaut est une virgule ‘","’. vous pouvez supprimer le séparateur en spécifiant la
chaîne vide SEPARATOR "".
Vous pouvez donner une taille maximale à la variable group_concat_max_len de
votre configuration. La syntaxe pour faire cela durant l'exécution est :
SET [SESSION | GLOBAL] group_concat_max_len = unsigned_integer;
Si une taille maximale a été atteinte, le résultat sera tronqué à cette taille maximale.
Note : il y a encore de petites limitations pour GROUP_CONCAT() lorsqu'il faut utiliser
des valeurs DISTINCT avec ORDER BY et et en utilisant les valeurs BLOB.
GROUP_CONCAT() a été ajoutée en MySQL 4.1.

 MIN(expr), MAX(expr)

3
Retourne le minimum ou le maximum de expr. MIN() et MAX() peuvent prendre des
chaînes comme argument : dans ce cas, elles retournent la valeur minimale ou
maximale de la valeur de la chaîne. .
mysql> SELECT student_name, MIN(test_score), MAX(test_score)
-> FROM student
-> GROUP BY student_name;
Actuellement, MIN(), MAX() et d'autres fonctions d'agrégation MySQL, le serveur
compare les valeurs de type ENUM et SET avec leur valeur de chaîne, et non pas leur
position relative dans l'ensemble.
STD(expr), STDDEV(expr)

Retourne la déviation standard de expr (la racine carrée de la VARIANCE(). Ceci est
une extension au standard SQL 99. La forme STDDEV() de cette fonction est fournie
pour assurer la compatibilité Oracle.
 SUM(expr)

Retourne la somme de expr. Notez que si le résultat ne contient pas de ligne, cette
fonction retournera NULL.
 VARIANCE(expr)

Retourne la variance standard de l'expression expr (en considérant que les lignes
forment une population totale, et non pas un échantillon. Le nombre de ligne est le
dénominateur. C'est une extension à la norme SQL-99 (disponible en version version
4.1 ou plus récent).

3
Syntaxe de SET

SET variable_assignment [, variable_assignment] ...

variable_assignment:
      user_var_name = expr
    | [GLOBAL | SESSION] system_var_name = expr
    | @@[global. | session.]system_var_name = expr
SET permet de configurer plusieurs options qui affectent le comportement de votre serveur ou de
votre client.
En MySQL 4.0.3, nous avons ajouté les options GLOBAL et SESSION et permis la modification des
variables systèmes les plus importantes dynamiquement, durant l'exécution du serveur. Le
système de variables que vous pouvez utiliser est décrit dans Variables dynamiques système .
Dans les anciennes versions de MySQL, nous avions autorisé l'utilisation de la syntaxe SET
OPTION , mais elle est maintenant abandonnée. Omettez simplement le mot OPTION .
Les exemples suivants montrent les différentes syntaxes qu'on peut utiliser pour configurer des
variables.
Une variable utilisateur s'écrit sous la forme @var_name et peut être configurée comme ceci :
SET @var_name = expr;
Plus d'informations sur les variables utilisateurs sont données dans Variables définies par
l'utilisateur .Les variables système peuvent être identifiées dans une commande SET sous la forme
var_name . Le nom peut être optionnellement précédé par GLOBAL ou @@global. pour indiquer
que cette variable est globale, ou par SESSION , @@session. , ou @@ pour indiquer que cette
variable est une variable de session. LOCAL et @@local. son synonymes de SESSION et
@@session. . Si aucune option n'est présente, SET spécifie une variable de session.
La syntaxe @@var_name pour les variables système est supportée pour rendre la syntaxe MySQL
compatible avec les autres bases.
Si vous configurez plusieurs variables sur une seule ligne de commande, le dernier mode GLOBAL |
SESSION utilisé est pris en compte.

SET sort_buffer_size=10000;
SET @@local.sort_buffer_size=10000;
SET GLOBAL sort_buffer_size=1000000, SESSION sort_buffer_size=1000000;
SET @@sort_buffer_size=1000000;
SET @@global.sort_buffer_size=1000000, @@local.sort_buffer_size=1000000;
Si vous utilisez SESSION (par défaut) l'option que vous configurez garde son effet jusqu'à ce que la
session courante se termine, ou que vous modifiez à nouveau cette option. Si vous utilisez GLOBAL
, qui requière le privilège SUPER , l'option est gardée en mémoire et utilisée pour les nouvelles
connexion jusqu'au redémarrage du serveur. Si vous voulez qu'un changement reste permanent,
vous devez l'effectuer dans l'un des fichiers d'options de MySQL. Utiliser les fichiers d'options
.Pour éviter un mauvais usage, MySQL donnera une erreur si vous utilisez SET GLOBAL avec une
variable qui ne peut être inutilisée que par SET SESSION ou si vous n'utilisez pas SET GLOBAL
avec une variable globale.
Si vous voulez configurer une variable SESSION à une valeur GLOBAL ou une valeur GLOBAL à la
valeur par défaut de MySQL, vous pouvez la configurer à DEFAULT .

SET max_join_size=DEFAULT;
SET @@session.max_join_size=@@global.max_join_size;
Vous pouvez obtenir une liste de la plupart des variables avec SHOW VARIABLES . Syntaxe de
SHOW VARIABLES . Vous pouvez obtenir la valeur d'une variable spécifique avec la syntaxe
@@[global.|local.]nom_variable :

3
SHOW VARIABLES LIKE 'max_join_size';
SHOW GLOBAL VARIABLES LIKE 'max_join_size';
Vous pouvez aussi obtenir une valeur spécifique d'une variable en utilisant la syntaxe @@[global.|
local.]var_name avec SELECT :

SELECT @@max_join_size, @@global.max_join_size;


Lorsque vous lisez la valeur d'une variable avec la syntaxe SELECT @@var_name (c'est à dire,
sans spécifier global. , session. ou local. ), MySQL retourne la valeur de SESSION si elle
existe, et la valeur GLOBAL sinon.
Vous trouverez ici une description des variables qui utilisent une syntaxe non-standard de SET .
Les définitions des autres variables peuvent être trouvées dans la section des Variables sytème du
serveur , avec les options de démarrage ou dans la description de SHOW VARIABLES .
Même si ces variables ne sont pas affichées par SHOW VARIABLES , vous pouvez obtenir leur
valeur avec la commande SELECT (à l'exception de CHARACTER SET ). Par exemple :

mysql> SELECT @@AUTOCOMMIT;


+--------------+
| @@autocommit |
+--------------+
|            1 |
+--------------+
AUTOCOMMIT= {0 | 1}
Si définie à 1 tous les changements dans une table se feront en une seule fois. Pour
démarrer une transaction multi-commandes, vous devez utiliser la commande BEGIN .
Syntaxe des BEGIN/COMMIT/ROLLBACK . Si définie à 0 vous devez utiliser
COMMIT / ROLLBACK pour accepter/annuler cette transaction. Notez que quand vous
passez du mode non AUTOCOMMIT vers le mode AUTOCOMMIT , MySQL fera un COMMIT
automatique sur toutes les transactions en cours.
BIG_TABLES = {0 | 1}
Si définie à 1 , toutes les tables temporaires sont stockées sur le disque plutôt qu'en
mémoire. Cela sera un peu plus lent, mais vous n'obtiendrez jamais l'erreur The table
nom_de_table is full pour les grands SELECT qui requièrent une table temporaire. La
valeur par défaut pour une nouvelle connexion est 0 (qui est d'utiliser la mémoire pour les
tables temporaires). Cette option se nommait avant SQL_BIG_TABLES .
CHARACTER SET {charset_name | DEFAULT}
Cela change le jeu de caractère dans toutes les chaînes du et vers le client avec le jeu
donné. Jusqu'à maintenant, la seule option pour nom_jeu_de_caractères est
cp1251_koi8 , mais vous pouvez facilement ajouter d'autres possibilités en éditant le
fichier sql/convert.cc dans la distribution des sources MySQL. Le jeu de caractères par
défaut peut être restauré en utilisant la valeur DEFAULT de nom_jeu_de_caractères
DEFAULT .
Notez que la syntaxe pour configurer l'option CHARACTER SET diffère de la syntaxe pour
configurer les autres options.
FOREIGN_KEY_CHECKS = {0 | 1}
Si cette option vaut 1 (par défaut), les contraintes de clé étrangères des tables InnoDB
sont vérifiées. Si cette option vaut 0 , elles sont ignorées. Désactiver les clés étrangères
peut être pratique pour recharger des tables InnoDB dans un ordre différent que celui
qu’imposent les relations de contraintes. Cette variable a été ajoutée en MySQL 3.23.52.
Contraintes FOREIGN KEY .
IDENTITY = valeur
Cette variable est un synonyme de la variable LAST_INSERT_ID . Elle existe pour des
raisons de compatibilité avec les autres bases. Depuis MySQL 3.23.25, vous pouvez lire sa
valeur avec SELECT @@IDENTITY . Depuis MySQL 4.0.3, vous pouvez aussi modifier cette
valeur avec SET IDENTITY .
INSERT_ID = valeur

3
Configure la valeur à utiliser par l'appel suivant à la commande INSERT ou ALTER TABLE
lors de l'insertion d'une valeur AUTO_INCREMENT . Cela est souvent utilisé par le log des
modifications.
LAST_INSERT_ID = valeur
Configure la valeur qui doit être retournée par LAST_INSERT_ID() . C'est enregistré dans
le log de mises à jour quand vous utilisez LAST_INSERT_ID() dans une commande qui
met à jour une table.
NAMES {'charset_name' | DEFAULT}
SET NAMES spécifie les valeurs des trois variables systèmes de session
character_set_client , character_set_connection et character_set_results
avec le jeu de caractères donné.La valeur par défaut de ces variables peut être rappelée
avec DEFAULT .
Notez que la syntaxe de SET NAMES diffère en cela des autres options. Cette commande
est disponible depuis MySQL 4.1.0.
SQL_AUTO_IS_NULL = {0 | 1}
Si définie à 1 (par défaut) alors on peut trouver la dernière ligne insérée dans une table
avec une colonne AUTO_INCREMENT avec la construction suivante :

WHERE auto_increment_column IS NULL


Ceci est utilisé par des programmes ODBC tel que Access. SQL_AUTO_IS_NULL a été
ajouté en MySQL 3.23.52.
SQL_BIG_SELECTS = {0 | 1}
Si configuré à 0 , MySQL interrompra les requêtes SELECT qui prendront probablement
trop de temps. C'est utile lorsqu'une clause WHERE déconseillée a été utilisée. Une grosse
requête est définie comme étant un SELECT qui devra probablement étudier plus de
max_join_size lignes. La valeur par défaut d'une nouvelle connexion est 1 (qui permet
toutes les requêtes SELECT ).
SQL_BUFFER_RESULT = {0 | 1}
SQL_BUFFER_RESULT forcera les résultats des requêtes SELECT à être placés dans une
table temporaire. Cela aidera MySQL à libérer les verrous sur table plus tôt et améliorera
les cas où le jeu de résultats de la requête prend trop de temps à être envoyée au client.
SQL_LOG_BIN = {0 | 1}
Si cette option vaut 0 , aucun log n'est fait dans le log binaire du client, si le client a les
droits de SUPER .
SQL_LOG_OFF = {0 | 1}
Si cette option vaut 1 , aucun log n'est fait dans le log standard du client, si le client a les
droits de SUPER .
SQL_LOG_UPDATE = {0 | 1}
Si définie à 0 , aucune trace des requêtes ne sera gardée dans le log des mises à jour pour
le client, si le client à le privilège SUPER . Cette variable est abandonnée depuis la version
5.0.0 et est remplacée par SQL_LOG_BIN ( Changements de la version5.0.0 (22
décembre 2003 : Alpha) ).
SQL_QUOTE_SHOW_CREATE = {0 | 1}
Si vous le configurez à 1 , SHOW CREATE TABLE protégera les noms de tables et de
colonnes. Ceci est activé par défaut, pour que la réplication des tables avec des noms à
risques fonctionne. Syntaxe de SHOW CREATE TABLE .
SQL_SAFE_UPDATES = {0 | 1}
Si définit à 1 , MySQL annulera si un UPDATE ou un DELETE est exécuté alors qu'il n'utilise
pas de clef ou de LIMIT dans la clause WHERE . Cela permet de bloquer les requêtes
erronées crées à la main.
SQL_SELECT_LIMIT = valeur | DEFAULT
Le nombre maximal des enregistrements que doivent retourner les requêtes SELECT . Si
un SELECT possède une clause LIMIT , celle-ci est utilisée. La valeur par défaut pour une
nouvelle connexion est ``illimitée.'' Si vous avez changé la limite, la valeur par défaut peut
être retrouvée en utilisant la valeur DEFAULT avec SQL_SELECT_LIMIT .
SQL_WARNINGS = {0 | 1}
Cette variable contrôle le fait que les insertions mono-ligne INSERT produisent une chaîne
d'information si une alerte survient. La valeur par défaut est 0. Donnez la valeur de 1 pour
avoir un message d'information. Cette variable a été ajoutée en MySQL 3.22.11.

3
TIMESTAMP = valeur_timestamp | DEFAULT
Configure le temps pour ce client. C'est utilisé pour obtenir le timestamp d'origine si vous
utilisez le log de mises à jour pour restaurer des lignes. valeur_timestamp doit être un
timestamp Unix, et non un timestamp MySQL.
UNIQUE_CHECKS = {0 | 1}
Si cette option vaut 1 (par défaut), les tests d'unicité sur les index secondaires des tables
InnoDB sont effectués. Si l'option vaut 0 , aucun test d'unicité n'est fait. Cette variable a
été ajoutée en MySQL 3.23.52. Contraintes FOREIGN KEY .

4
4
Fonctions de dates et d'heures
Cette section décrit les fonctions qui peuvent être utilisées pour manipuler les valeurs temporelles.
Voir Types temporels pour une description détaillée des intervalles de validité de chaque type,
ainsi que les formats valides de spécifications des dates et heures.
Voici un exemple d'utilisation des fonctions de date. La requête suivante sélectionne toutes les
lignes dont la colonne date_col représente une date de moins de 30 jours :

mysql> SELECT quelquechose FROM nom_de_table


           WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;
Notez que cette requête va aussi sélectionner des lignes dont les dates sont dans le futur.Les
fonctions qui utilisent des valeurs de date acceptent les valeurs de type DATETIME et ignore la
partie horaire. Les fonctions qui attendent des heures acceptent les valeurs littérales et ignorent la
partie de date.
Les fonctions qui retourne la date ou l'heure courante sont évaluées une fois par requête, tout au
début. Cela signifie que des références multiples à la fonction NOW() dans une même requête
produiront toujours le même résultat. Ce principe s'applique aussi à CURDATE() , CURTIME() ,
UTC_DATE() , UTC_TIME() , UTC_TIMESTAMP() , et leurs synonymes.
Les intervalles de valeurs de retour des fonctions suivantes s'appliquent aux dates complètes. Si
une date est une valeur ``zéro'' ou une date incomplète, comme '2001-11-00' , les fonctions
qui extraient une partie d'une date retourneront 0 . Par exemple, DAYOFMONTH('2001-11-00')
retourne 0 .
ADDDATE(date,INTERVAL expr type)
ADDDATE(expr,days)
Lorsqu'elle est utilisée avec la forme INTERVAL , ADDDATE() est un synonyme de
DATE_ADD() . La fonction complémentaire SUBDATE() est un synonyme DATE_SUB() .
mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);
        -> '1998-02-02'
mysql> SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);
        -> '1998-02-02'
Depuis MySQL 4.1.1, la seconde syntaxe est utilisée si expr est une expression de type
DATE ou DATETIME , et que days est un nombre de jour à ajouter à expr .

mysql> SELECT ADDDATE('1998-01-02', 31);


        -> '1998-02-02'
ADDTIME(expr,expr2)
ADDTIME() ajoute expr2 à expr et retourne le résultat. expr est une expression de type
DATE ou DATETIME , et expr2 est une expression de type TIME .

mysql> SELECT ADDTIME("1997-12-31 23:59:59.999999", "1 1:1:1.000002");


        -> '1998-01-02 01:01:01.000001'
mysql> SELECT ADDTIME("01:00:00.999999", "02:00:00.999998");
        -> '03:00:01.999997'
ADDTIME() a été ajouté en MySQL 4.1.1.
CURDATE()
CURRENT_DATE
Retourne la date courante au format 'YYYY-MM-DD' ou YYYYMMDD , suivant le contexte
numérique ou chaîne :
mysql> SELECT CURDATE();
        -> '1997-12-15'
mysql> SELECT CURDATE() + 0;
        -> 19971215
CURRENT_DATE
CURRENT_DATE()

4
CURRENT_DATE et CURRENT_DATE() sont synonymes de CURDATE() .
CURTIME()
Retourne l'heure courante au format 'HH:MM:SS' or HHMMSS suivant le contexte
numérique ou chaîne :
mysql> SELECT CURTIME();
        -> '23:50:26'
mysql> SELECT CURTIME() + 0;
        -> 235026
CURRENT_TIME
CURRENT_TIME()
CURRENT_TIME et CURRENT_TIME() sont synonymes de CURTIME() .
CURRENT_TIMESTAMP
CURRENT_TIMESTAMP()
CURRENT_TIMESTAMP et CURRENT_TIMESTAMP() sont synonymes de NOW() .
DATE(expr)
Extrait la partie date de l'expression expr de type DATE ou DATETIME .
mysql> SELECT DATE('2003-12-31 01:02:03');
        -> '2003-12-31'

DATE() est disponible depuis MySQL 4.1.1.


DATEDIFF(expr,expr2)
DATEDIFF() retourne le nombre de jours entre la date de début expr et la date de fin expr2
. expr et expr2 sont des expressions de type DATE ou DATETIME . Seule la partie DATE est
utilisée dans le calcul.
mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');
        -> 1
mysql> SELECT DATEDIFF('1997-11-31 23:59:59','1997-12-31');
        -> -30
DATEDIFF() est disponible depuis MySQL 4.1.1.
DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
Ces fonctions effectuent des calculs arithmétiques sur les dates.Depuis MySQL 3.23,
INTERVAL expr type est autorisé des deux cotés de l'opérateur + si l'expression de
l'autre coté est de type DATE ou DATETIME . Pour l'opérateur - , INTERVAL expr type
est autorisé uniquement du coté droit, car on ne peut pas soustraire une date d'un
intervalle (voir les exemples ci-dessous).
date est une valeur de type DATETIME ou DATE qui spécifie la date de début. expr est
une expression qui spécifie une valeur d'intervalle à ajouter ou soustraire de la date
initiale. expr est une chaîne : elle peut commencer avec '-' pour les intervalles négatifs.
type est un mot-clé, indiquant comment l'expression doit être interprétée.
La table suivante indique la signification des arguments type et expr :
type Valeur Attendue expr Format
MICROSECOND MICROSECONDS
SECOND SECONDS
MINUTE MINUTES
HOUR HOURS
DAY DAYS
WEEK WEEKS
MONTH MONTHS
QUARTER QUARTERS
YEAR YEARS
SECOND_MICROSECOND 'SECONDS.MICROSECONDS'
MINUTE_MICROSECOND 'MINUTES.MICROSECONDS'

4
MINUTE_SECOND 'MINUTES:SECONDS'
HOUR_MICROSECOND 'HOURS.MICROSECONDS'
HOUR_SECOND 'HOURS:MINUTES:SECONDS'
HOUR_MINUTE 'HOURS:MINUTES'
DAY_MICROSECOND 'DAYS.MICROSECONDS'
DAY_SECOND 'DAYS HOURS:MINUTES:SECONDS'
DAY_MINUTE 'DAYS HOURS:MINUTES'
DAY_HOUR 'DAYS HOURS'
YEAR_MONTH 'YEARS-MONTHS'
Les valeurs de type DAY_MICROSECOND , HOUR_MICROSECOND , MINUTE_MICROSECOND ,
SECOND_MICROSECOND , et MICROSECOND ont été ajoutés en MySQL 4.1.1. Les valeurs
QUARTER et WEEK sont disponibles depuis MySQL 5.0.0.
MySQL autorise tous les signes de ponctuation, comme délimiteur dans le format de expr .
Ceux qui sont affichés dans la table sont des suggestions. Si l'argument date est une valeur
DATE et que vos calculs impliquent des parties YEAR , MONTH et DAY (c'est à dire, sans
partie horaire), le résultat sera de type DATE . Sinon, le résultat est de type DATETIME :

mysql> SELECT '1997-12-31 23:59:59' + INTERVAL 1 SECOND;


        -> '1998-01-01 00:00:00'
mysql> SELECT INTERVAL 1 DAY + '1997-12-31';
        -> '1998-01-01'
mysql> SELECT '1998-01-01' - INTERVAL 1 SECOND;
        -> '1997-12-31 23:59:59'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
    ->                 INTERVAL 1 SECOND);
        -> '1998-01-01 00:00:00'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
    ->                 INTERVAL 1 DAY);
        -> '1998-01-01 23:59:59'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
    ->                 INTERVAL '1:1' MINUTE_SECOND);
        -> '1998-01-01 00:01:00'
mysql> SELECT DATE_SUB('1998-01-01 00:00:00',
    ->                 INTERVAL '1 1:1:1' DAY_SECOND);
        -> '1997-12-30 22:58:59'
mysql> SELECT DATE_ADD('1998-01-01 00:00:00',
    ->                 INTERVAL '-1 10' DAY_HOUR);
        -> '1997-12-30 14:00:00'
mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
        -> '1997-12-02'
mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002',
    ->                 INTERVAL '1.999999' SECOND_MICROSECOND);
        -> '1993-01-01 00:00:01.000001'
Si vous spécifiez un intervalle qui est trop court (il n'inclut pas toutes les parties d'intervalle
attendues par type ), MySQL suppose que vous avez omis les valeurs de gauche. Par
exemple, si vous spécifiez un type type de DAY_SECOND , la valeur expr devrait contenir
des jours, heures, minutes et secondes. Si vous fournissez une valeur de la forme
'1:10' , MySQL suppose que les jours et heures manquent, et que la valeur représente
des minutes et secondes. En d'autres termes, '1:10' DAY_SECOND est interprété comme
'1:10' MINUTE_SECOND . C'est similaire au comportement de MySQL avec les valeurs de
type TIME , qui représente des durées plutôt que des horaires.
Notez que si vous ajoutez ou soustrayez à une valeur de type DATE des horaires, le
résultat sera automatiquement au format DATETIME :

mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 DAY);


        -> '1999-01-02'
mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR);

4
        -> '1999-01-01 01:00:00'
Si vous utilisez des dates malformées, le résultat sera NULL . Si vous ajoutez des MONTH ,
YEAR_MONTH ou YEAR , et que le résultat a un jour du mois qui est au-
delà de ce qui est possible dans le mois, le jour sera adapté au plus
grand jour possible du mois. Par exemple :

mysql> SELECT DATE_ADD('1998-01-30', interval 1 month);


        -> '1998-02-28'
Notez que dans l'exemple précédent, le mot clé INTERVAL et le spécificateur type sont
insensibles à la casse.
DATE_FORMAT(date,format)
Formate la date date avec le format format . Les spécificateurs suivants peuvent être utilisé
dans la chaîne format :
Option Description
%% Un signe pourcentage littéral '%' .
%a Nom du jour de la semaine, en abrégé et en anglais ( Sun .. Sat )
%b Nom du mois, en abrégé et en anglais ( Jan .. Dec )
%c Mois, au format numérique ( 1 .. 12 )
%d Jour du mois, au format numérique ( 00 .. 31 )
%D Jour du mois, avec un suffixe anglais ( 1st , 2nd , 3rd , etc.)
%e Jour du mois, au format numérique ( 0 .. 31 )
%f Microsecondes ( 000000 .. 999999 )
%H Heure ( 00 .. 23 )
%h Heure ( 01 .. 12 )
%I Heure ( 01 .. 12 )
%i Minutes, au format numérique ( 00 .. 59 )
%j Jour de l'année ( 001 .. 366 )
%k Heure ( 0 .. 23 )
%l Heure ( 1 .. 12 )
%m Mois, au format numérique ( 01 .. 12 )
%M Nom du mois ( January .. December )
%p AM ou PM
%r Heures, au format 12 heures ( hh:mm:ss [AP]M )
%s Secondes ( 00 .. 59 )
%S Secondes ( 00 .. 59 )
%T Heures, au format 24 heures ( hh:mm:ss )
%U Numéro de la semaine ( 00 .. 53 ), où Dimanche est le premier jour de la semaine
%u Numéro de la semaine ( 00 .. 53 ), où Lundi est le premier jour de la semaine
Numéro de la semaine ( 01 .. 53 ), où Dimanche est le premier jour de la semaine,
%V
utilisé avec '%X'
Numéro de la semaine ( 01 .. 53 ), où Lundi est le premier jour de la semaine,
%v
utilisé avec '%x'
%W Nom du jour de la semaine ( Sunday .. Saturday )
%w Numéro du jour de la semaine ( 0 =Sunday.. 6 =Saturday)
Année, pour les semaines qui commencent le Dimanche, au format numérique, sur
%X
4 chiffres, utilisé avec '%V'
Année, pour les semaines qui commencent le Lundi, au format numérique, sur 4
%x
chiffres, utilisé avec '%v'
%y Année, au format numérique, sur 2 chiffres
%Y Année, au format numérique, sur 4 chiffres
Tous les autres caractères sont simplement copiés dans le résultat sans interprétation:
Le format %f est disponible depuis MySQL 4.1.1.

4
Depuis MySQL version 3.23, le caractère '%' est requis devant les caractères de format.
Dans les versions antérieures de MySQL, '%' était optionnel.
La raison qui fait que les intervalles de mois et de jours commencent avec zéro est que
MySQL autorise les dates incomplètes comme '2004-00-00' , depuis MySQL 3.23.

mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');


        -> 'Saturday October 1997'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
        -> '22:23:00'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
                          '%D %y %a %d %m %b %j');
        -> '4th 97 Sat 04 10 Oct 277'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
                          '%H %k %I %r %T %S %w');
        -> '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
        -> '1998 52'
DAY(date)
DAY() est un synonyme de DAYOFMONTH() . Cette fonction est disponible depuis MySQL
4.1.1.
DAYNAME(date)
Retourne le nom du jour de la semaine de date :
mysql> SELECT DAYNAME('1998-02-05');
        -> 'Thursday'
DAYOFMONTH(date)
Retourne le jour de la date date , dans un intervalle de 1 à 31 :
mysql> SELECT DAYOFMONTH('1998-02-03');
        -> 3
DAYOFWEEK(date)
Retourne l'index du jour de la semaine : pour date ( 1 = Dimanche, 2 = Lundi, ... 7 =
Samedi). Ces index correspondent au standard ODBC :
mysql> SELECT DAYOFWEEK('1998-02-03');
        -> 3
DAYOFYEAR(date)
Retourne le jour de la date date , dans un intervalle de 1 à 366 :
mysql> SELECT DAYOFYEAR('1998-02-03');
        -> 34
EXTRACT(type FROM date)
La fonction EXTRACT() utilise les mêmes types d'intervalles que la fonction DATE_ADD() ou
la fonction DATE_SUB() , mais extrait des parties de date plutôt que des opérations de
date.
mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
       -> 1999
mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
       -> 199907
mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
       -> 20102
mysql> SELECT EXTRACT(MICROSECOND FROM "2003-01-02 10:30:00.00123");
        -> 123
FROM_DAYS(N)
Retourne la date correspondant au nombre de jours ( N ) depuis la date 0 :
mysql> SELECT FROM_DAYS(729669);

4
        -> '1997-10-07'
FROM_DAYS() n'est pas fait pour travailler avec des dates qui précèdent l'avènement du
calendrier Grégorien (1582), car elle ne prend pas en compte les jours perdus lors du
changement de calendrier.
FROM_UNIXTIME(unix_timestamp)
Retourne une représentation de l'argument unix_timestamp sous la forme 'YYYY-MM-DD
HH:MM:SS' ou YYYYMMDDHHMMSS , suivant si la fonction est utilisé dans un contexte
numérique ou de chaîne.
mysql> SELECT FROM_UNIXTIME(875996580);
        -> '1997-10-04 22:23:00'
mysql> SELECT FROM_UNIXTIME(875996580) + 0;
        -> 19971004222300
Si format est donné, le résultat est formaté en fonction de la chaîne format . format peut
contenir les mêmes options de format que celles utilisées par DATE_FORMAT() :

mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),


    ->                      '%Y %D %M %h:%i:%s %x');
        -> '2003 6th August 06:22:58 2003'
GET_FORMAT(DATE | TIME | TIMESTAMP, 'EUR' | 'USA' | 'JIS' | 'ISO' |
'INTERNAL')
Retourne une chaîne de format. Cette fonction est pratique lorsqu'elle est utilisée avec les
fonctions DATE_FORMAT() et STR_TO_DATE() . Les trois valeurs possibles pour le premier
argument, et les cinq valeurs possible pour le second argument donnent 15 formats
d'affichage (pour les options utilisées, voyez la table de la fonction DATE_FORMAT() ) :
Appel fonction Résultat
GET_FORMAT(DATE,'USA') '%m.%d.%Y'
GET_FORMAT(DATE,'JIS') '%Y-%m-%d'
GET_FORMAT(DATE,'ISO') '%Y-%m-%d'
GET_FORMAT(DATE,'EUR') '%d.%m.%Y'
GET_FORMAT(DATE,'INTERNAL') '%Y%m%d'
GET_FORMAT(TIMESTAMP,'USA') '%Y-%m-%d-%H.%i.%s'
GET_FORMAT(TIMESTAMP,'JIS') '%Y-%m-%d %H:%i:%s'
GET_FORMAT(TIMESTAMP,'ISO') '%Y-%m-%d %H:%i:%s'
GET_FORMAT(TIMESTAMP,'EUR') '%Y-%m-%d-%H.%i.%s'
GET_FORMAT(TIMESTAMP,'INTERNAL') '%Y%m%d%H%i%s'
GET_FORMAT(TIME,'USA') '%h:%i:%s %p'
GET_FORMAT(TIME,'JIS') '%H:%i:%s'
GET_FORMAT(TIME,'ISO') '%H:%i:%s'
GET_FORMAT(TIME,'EUR') '%H.%i.%S'
GET_FORMAT(TIME,'INTERNAL') '%H%i%s'
Le format ISO est le format ISO 9075, et non ISO 8601.
mysql> SELECT DATE_FORMAT('2003-10-03', GET_FORMAT(DATE, 'EUR')
        -> '03.10.2003'
mysql> SELECT STR_TO_DATE('10.31.2003', GET_FORMAT(DATE, 'USA'))
        -> 2003-10-31
GET_FORMAT() est disponible depuis MySQL 4.1.1. Voyez Syntaxe de SET .
HOUR(time)
Retourne le nombre d'heures pour l'heure time , dans un intervalle de 0 à 23 :
mysql> SELECT HOUR('10:05:03');
        -> 10
Cependant, l'intervalle des valeurs TIME est bien plus grand, et donc, HOUR peut retourner
des valeurs plus grandes que 23 :

mysql> SELECT HOUR('272:59:59');

4
        -> 272
LAST_DAY(date)
Prend une valeur de format DATE ou DATETIME , et retourne le dernier jour du mois
correspondant. Retourne NULL si l'argument est invalide.

mysql> SELECT LAST_DAY('2003-02-05'), LAST_DAY('2004-02-05');


        -> '2003-02-28', '2004-02-29'
mysql> SELECT LAST_DAY('2004-01-01 01:01:01');
        -> '2004-01-31'
mysql> SELECT LAST_DAY('2003-03-32');
        -> NULL
LAST_DAY() est disponible depuis MySQL 4.1.1.
LOCALTIME
LOCALTIME()
LOCALTIME et LOCALTIME() sont synonymes de NOW() .
LOCALTIMESTAMP
LOCALTIMESTAMP()
LOCALTIMESTAMP et LOCALTIMESTAMP() sont synonymes de NOW() .
MAKEDATE(year,dayofyear)
Retourne une valeur de format DATE , à partir d'une année et du numéro de jour.
dayofyear doit être plus grand que 0 ou le résultat sera NULL .

mysql> SELECT MAKEDATE(2001,31), MAKEDATE(2001,32);


        -> '2001-01-31', '2001-02-01'
mysql> SELECT MAKEDATE(2001,365), MAKEDATE(2004,365);
        -> '2001-12-31', '2004-12-30'
mysql> SELECT MAKEDATE(2001,0);
        -> NULL
MAKEDATE() est disponible depuis MySQL 4.1.1.
MAKETIME(hour,minute,second)
Retourne une valeur de format TIME , calculée à partir des arguments hour , minute et
second .

mysql> SELECT MAKETIME(12,15,30);


        -> '12:15:30'
MAKETIME() est disponible depuis MySQL 4.1.1.
MICROSECOND(expr)
Retourne le nombre de microsecondes dans l'expression de type TIME ou DATETIME expr ,
sous la forme d'un nombre entre 0 et 999999 .

mysql> SELECT MICROSECOND('12:00:00.123456');


        -> 123456
mysql> SELECT MICROSECOND('1997-12-31 23:59:59.000010');
        -> 10
MICROSECOND() est disponible depuis MySQL 4.1.1.
est disponible depuis
MINUTE(time)
Retourne le nombre de minutes pour l'heure time , dans un intervalle de 0 à 59 :
mysql> SELECT MINUTE('98-02-03 10:05:03');
        -> 5
MONTH(date)
Retourne le numéro du mois de la date date , dans un intervalle de 1 à 12 :
mysql> SELECT MONTH('1998-02-03');
        -> 2
MONTHNAME(date)
Retourne le nom du mois de la date date :

4
mysql> SELECT MONTHNAME("1998-02-05");
        -> 'February'
NOW()
Retourne la date courante au format 'YYYY-MM-DD HH:MM:SS' ou YYYYMMDDHHMMSS ,
suivant le contexte numérique ou chaîne :
mysql> SELECT NOW();
        -> '1997-12-15 23:50:26'
mysql> SELECT NOW() + 0;
        -> 19971215235026
PERIOD_ADD(P,N)
Ajoute N mois à la période P (au format YYMM ou YYYYMM ). Retourne une valeur dans le
format YYYYMM .

Notez que l'argument P n'est pas de type date :

mysql> SELECT PERIOD_ADD(9801,2);


        -> 199803
PERIOD_DIFF(P1,P2)
Retourne le nombre de mois entre les périodes P1 et P2 . P1 et P2 doivent être au format
YYMM ou YYYYMM .Notez que les arguments P1 et P2 ne sont pas de type date :

mysql> SELECT PERIOD_DIFF(9802,199703);


        -> 11
QUARTER(date)
Retourne le numéro du trimestre de la date date , dans un intervalle de 1 à 4 :
mysql> SELECT QUARTER('98-04-01');
        -> 2
SECOND(time)
Retourne le nombre de secondes pour l'heure time , dans un intervalle de 0 à 59 :
mysql> SELECT SECOND('10:05:03');
        -> 3
SEC_TO_TIME(seconds)
Retourne l'argument seconds , convertit en heures, minutes et secondes au format
'HH:MM:SS' ou HHMMSS , suivant le contexte numérique ou chaîne :

mysql> SELECT SEC_TO_TIME(2378);


        -> '00:39:38'
mysql> SELECT SEC_TO_TIME(2378) + 0;
        -> 3938
STR_TO_DATE(str,format)
Cette fonction est l'inverse de la fonction DATE_FORMAT() . Elle prend la chaîne str , et une
chaîne de format format , puis retourne une valeur DATETIME . Les valeurs de type DATE ,
TIME ou DATETIME contenues dans la chaîne str doivent être au format format . Pour les
options qui sont utilisables dans la chaîne format , voyez la table dans la description de la
fonction DATE_FORMAT() . Tous les autres caractères sont utilisés littéralement, et ne
seront pas interprétés. Si str contient une valeur illégale, STR_TO_DATE() retourne NULL .

mysql> SELECT STR_TO_DATE('03.10.2003 09.20', '%d.%m.%Y %H.%i')


        -> 2003-10-03 09:20:00
mysql> SELECT STR_TO_DATE('10rap', '%crap')
        -> 0000-10-00 00:00:00
mysql> SELECT STR_TO_DATE('2003-15-10 00:00:00', '%Y-%m-%d %H:%i:%s')
        -> NULL
STR_TO_DATE() est disponible depuis MySQL 4.1.1.
SUBDATE(date,INTERVAL expr type)

4
SUBDATE(expr,days)
Lorsqu'elle est utilisée avec la forme INTERVAL du second argument, SUBDATE() est
synonyme DATE_SUB() .

mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);


        -> '1997-12-02'
mysql> SELECT SUBDATE('1998-01-02', INTERVAL 31 DAY);
        -> '1997-12-02'
Depuis MySQL 4.1.1, la seconde syntaxe est autorisée, où expr est une expression de type
DATE ou DATETIME et days est le nombre de jour à soustraire de l'expression expr .

mysql> SELECT SUBDATE('1998-01-02 12:00:00', 31);


        -> '1997-12-02 12:00:00'
SUBTIME(expr,expr2)
SUBTIME() soustrait expr2 de expr et retourne le résultat. expr est une expression de
format DATE ou DATETIME et expr2 est une expression de type TIME .

mysql> SELECT SUBTIME("1997-12-31 23:59:59.999999", "1 1:1:1.000002");


        -> '1997-12-30 22:58:58.999997'
mysql> SELECT SUBTIME("01:00:00.999999", "02:00:00.999998");
        -> '-00:59:59.999999'
SUBTIME() a été ajoutée en MySQL 4.1.1.
SYSDATE()
SYSDATE() est un synonyme de NOW() .
TIME(expr)
Extrait la partie horaire de l'expression expr , de type TIME ou DATETIME .
mysql> SELECT TIME('2003-12-31 01:02:03');
        -> '01:02:03'
mysql> SELECT TIME('2003-12-31 01:02:03.000123');
        -> '01:02:03.000123'
TIME() a été ajoutée en MySQL 4.1.1.
TIMEDIFF(expr,expr2)
TIMEDIFF() retourne la durée entre l'heure de début expr et l'heure de fin expr2 . expr et
expr2 sont des expressions de type TIME ou DATETIME , et doivent être de même type.

mysql> SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01


00:00:00.000001');
        -> '-00:00:00.000001'
mysql> SELECT TIMEDIFF('1997-12-31 23:59:59.000001','1997-12-30
01:01:01.000002');
        -> '46:58:57.999999'
TIMEDIFF() a été ajoutée en MySQL 4.1.1.
TIMESTAMP(expr)
TIMESTAMP(expr,expr2)
Avec un seul argument, retourne l'expression expr de type DATE ou DATETIME sous la
forme d'une valeur DATETIME . Avec deux arguments, ajouter l'expression expr2 à
l'expression expr et retourne le résultat au format DATETIME .

mysql> SELECT TIMESTAMP('2003-12-31');


        -> '2003-12-31 00:00:00'
mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00');
        -> '2004-01-01 00:00:00'
TIMESTAMP() a été ajoutée en MySQL 4.1.1.
TIMESTAMPADD(interval,int_expr,datetime_expr)
Ajoute l'expression entière int_expr à l'expression datetime_expr au format DATE ou
DATETIME . L'unité de int_expr est donnée avec l'argument interval , qui peut être l'une
des valeurs suivantes : FRAC_SECOND , SECOND , MINUTE , HOUR , DAY , WEEK , MONTH
, QUARTER , ou YEAR .La valeur interval peut être spécifiée, en utilisant un des mots-clé

5
cités, ou avec le préfixe SQL_TSI_ . Par exemple, DAY et SQL_TSI_DAY sont tous les deux
valides.
mysql> SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02');
        -> '2003-01-02 00:01:00'
mysql> SELECT TIMESTAMPADD(WEEK,1,'2003-01-02');
        -> '2003-01-09'
TIMESTAMPADD() a été ajoutée en MySQL 5.0.0.
TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2)
Retourne la différence entière entre les expressions datetime_expr1 et datetime_expr2 , de
format DATE et DATETIME . L'unité du résultat est donné par l'argument interval . Les
valeurs légales de interval sont les mêmes que pour la fonction TIMESTAMPADD() .

mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');


        -> 3
mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01');
        -> -1
TIMESTAMPDIFF() a été ajoutée en MySQL 5.0.0.
TIME_FORMAT(time,format)
Cette fonction est utilisée exactement comme la fonction DATE_FORMAT() ci-dessus, mais
la chaîne format ne doit utiliser que des spécificateurs d'heures, qui gèrent les heures,
minutes et secondes. Les autres spécificateurs génèreront la valeur NULL ou 0 .
Si la valeur time contient une valeur d'heure qui est plus grande que 23 , les formats %H
et %k produiront une valeur qui est hors de l'intervalle 0..23 . L'autre format d'heure
produira une heure modulo 12 :

mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');


        -> '100 100 04 04 4'
TIME_TO_SEC(time)
Retourne l'argument time , convertit en secondes :
mysql> SELECT TIME_TO_SEC('22:23:00');
        -> 80580
mysql> SELECT TIME_TO_SEC('00:39:38');
        -> 2378
TO_DAYS(date)
Retourne le nombre de jours depuis la date 0 jusqu'à la date date :
mysql> SELECT TO_DAYS(950501);
        -> 728779
mysql> SELECT TO_DAYS('1997-10-07');
        -> 729669
TO_DAYS() n'est pas fait pour travailler avec des dates qui précèdent l'avènement du
calendrier Grégorien (1582), car elle ne prend pas en compte les jours perdus lors du
changement de calendrier.
N'oubliez pas que MySQL convertit les années représentées sur deux chiffres en dates à
quatre chiffres, en utilisant les règles de la section Types temporels . Par exemple, '1997-
10-07' et '97-10-07' sont identiques :

mysql> SELECT TO_DAYS('1997-10-07'), TO_DAYS('97-10-07');


        -> 729669, 729669
Pour les dates antérieures à 1582, les résultats sont indéfinis.
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
Lorsqu'elle est appelé sans argument, cette fonction retourne un timestamp Unix (nombre
de secondes depuis '1970-01-01 00:00:00' GMT). Si UNIX_TIMESTAMP() est appelé avec
un argument date , elle retourne le timestamp correspondant à cette date. date peut être

5
une chaîne de type DATE , DATETIME , TIMESTAMP , ou un nombre au format YYMMDD ou
YYYYMMDD , en horaire local :

mysql> SELECT UNIX_TIMESTAMP();


        -> 882226357
mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');
        -> 875996580
Lorsque UNIX_TIMESTAMP est utilisé sur une colonne de type TIMESTAMP , la fonction
reçoit directement la valeur, sans conversion explicite. Si vous donnez à
UNIX_TIMESTAMP() une date hors de son intervalle de validité, elle retourne 0.Si vous
voulez soustraire une colonne de type UNIX_TIMESTAMP() , vous devez sûrement vouloir
un résultat de type entier signé. Fonctions de transtypage .
UTC_DATE
UTC_DATE()
Retourne la date UTC courante au format 'YYYY-MM-DD' ou YYYYMMDD suivant le contexte
numérique ou chaîne :
mysql> SELECT UTC_DATE(), UTC_DATE() + 0;
        -> '2003-08-14', 20030814
UTC_DATE() est disponible depuis MySQL 4.1.1.
UTC_TIME
UTC_TIME()
Retourne l'heure UTC courante au format 'HH:MM:SS' or HHMMSS suivant le contexte
numérique ou chaîne :
mysql> SELECT UTC_TIME(), UTC_TIME() + 0;
        -> '18:07:53', 180753
UTC_TIME() est disponible depuis MySQL 4.1.1.
UTC_TIMESTAMP
UTC_TIMESTAMP()
Retourne l'heure et la date UTC courante au format 'YYYY-MM-DD HH:MM:SS' or
YYYYMMDDHHMMSS suivant le contexte numérique ou chaîne :

mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;


        -> '2003-08-14 18:08:04', 20030814180804
UTC_TIMESTAMP() est disponible depuis MySQL 4.1.1.
WEEK(date [,mode])
Avec un seul argument, retourne le numéro de la semaine dans l'année de la date date ,
dans un intervalle de 0 à 53 (oui, il peut y avoir un début de semaine numéro 53), en
considérant que Dimanche est le premier jour de la semaine. Avec deux arguments, la
fonction WEEK() vous permet de spécifier si les semaines commencent le Dimanche ou le
Lundi et la valeur retournée sera dans l'intervalle 0-53 ou bien 1-52 . Lorsque l'argument
mode est omis, la valeur de la variable default_week_format (ou 0 en MySQL 4.0 ou plus
ancien) est utilisé. Syntaxe de SET .Voici un tableau explicatif sur le fonctionnement du
second argument :
Valeur Signification
La semaine commence le Sunday;l'intervalle de valeur de retour va de 0 à !2; la
0
semaine 1 est la première semaine de l'année
La semaine commence le Monday;l'intervalle de valeur de retour va de 0 à !2; la
1
semaine 1 est la première semaine de l'année qui a plus de trois jours
La semaine commence le Sunday;l'intervalle de valeur de retour va de 1 à !2; la
2
semaine 1 est la première semaine de l'année
La semaine commence le Monday;l'intervalle de valeur de retour va de 1 à !2; la
3
semaine 1 est la première semaine de l'année qui a plus de trois jours
La semaine commence le Sunday;l'intervalle de valeur de retour va de 0 à !2; la
4
semaine 1 est la première semaine de l'année qui a plus de trois jours
La semaine commence le Monday;l'intervalle de valeur de retour va de 0 à !2; la
5
semaine 1 est la première semaine de l'année
6 La semaine commence le Sunday;l'intervalle de valeur de retour va de 1 à !2; la

5
semaine 1 est la première semaine de l'année qui a plus de trois jours
La semaine commence le Monday;l'intervalle de valeur de retour va de 1 à !2; la
7
semaine 1 est la première semaine de l'année
Le mode 3 est disponible depuis MySQL 4.0.5. Le mode 4 est disponible depuis MySQL
4.0.17.
mysql> SELECT WEEK('1998-02-20');
        -> 7
mysql> SELECT WEEK('1998-02-20',0);
        -> 7
mysql> SELECT WEEK('1998-02-20',1);
        -> 8
mysql> SELECT WEEK('1998-12-31',1);
        -> 53
Note : en version 4.0, WEEK(date,0) a été modifiée pour correspondre au système
calendaire des USA. Avant cela, WEEK() était calculé incorrectement, pour des dates
américaines : en effet, WEEK(date) et WEEK(date,0) étaient incorrects.Si vous préférez
que le résultat soit calculé en fonction de l'année qui contient le premier jour de la semaine
de la date utilisée en argument, vous devriez utiliser les valeurs 2, 3, 6, or 7 de l'argument
mode .

mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);


        -> 2000, 0
mysql> SELECT WEEK('2000-01-01',2);
        -> 52
Alternativement, utilisez la fonction YEARWEEK() :

mysql> SELECT YEARWEEK('2000-01-01');


        -> 199952
mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2);
        -> '52'
WEEKDAY(date)
Retourne l'index du jour de la semaine, avec la conversion suivante : date ( 0 = Lundi, 1 =
Mardi, ... 6 = Dimanche).

mysql> SELECT WEEKDAY('1997-10-04 22:23:00');


        -> 5
mysql> SELECT WEEKDAY('1997-11-05');
        -> 2
WEEKOFYEAR(date)
Retourne le numéro de semaine dans l'année, sous forme d'un nombre compris entre 1 et
53 .

mysql> SELECT WEEKOFYEAR('1998-02-20');


        -> 8
WEEKOFYEAR() est disponible depuis MySQL 4.1.1.
YEAR(date)
Retourne l'année de la date date , dans un intervalle de 1000 à 9999 :
mysql> SELECT YEAR('98-02-03');
        -> 1998

mysql> SELECT YEAR('98-02-03');


        -> 1998
YEARWEEK(date)
YEARWEEK(date,start)
Retourne l'année et la semaine d'une date. L'argument start fonctionne exactement comme
l'argument start de la fonction WEEK() . Notez que l'année dans le résultat peut être

5
différente de l'année passée en argument, pour la première et la dernière semaine de
l'année.
mysql> SELECT YEARWEEK('1987-01-01');
        -> 198653
Notez que le numéro de semaine est différent de celui que la fonction WEEK() retourne (
0 ) pour les arguments optionnels 0 ou 1 , comme WEEK() puis retourne la semaine dans
le contexte de l'année.

Fonctions de dates et d'heures


Cette section décrit les fonctions qui peuvent être utilisées pour manipuler les valeurs temporelles.
Voir Types temporels pour une description détaillée des intervalles de validité de chaque type,
ainsi que les formats valides de spécifications des dates et heures.
Voici un exemple d'utilisation des fonctions de date. La requête suivante sélectionne toutes les
lignes dont la colonne date_col représente une date de moins de 30 jours :

mysql> SELECT quelquechose FROM nom_de_table


           WHERE TO_DAYS(NOW()) - TO_DAYS(date_col) <= 30;
Notez que cette requête va aussi sélectionner des lignes dont les dates sont dans le futur.Les
fonctions qui utilisent des valeurs de date acceptent les valeurs de type DATETIME et ignore la
partie horaire. Les fonctions qui attendent des heures acceptent les valeurs littérales et ignorent la
partie de date.
Les fonctions qui retourne la date ou l'heure courante sont évaluées une fois par requête, tout au
début. Cela signifie que des références multiples à la fonction NOW() dans une même requête
produiront toujours le même résultat. Ce principe s'applique aussi à CURDATE() , CURTIME() ,
UTC_DATE() , UTC_TIME() , UTC_TIMESTAMP() , et leurs synonymes.
Les intervalles de valeurs de retour des fonctions suivantes s'appliquent aux dates complètes. Si
une date est une valeur ``zéro'' ou une date incomplète, comme '2001-11-00' , les fonctions
qui extraient une partie d'une date retourneront 0 . Par exemple, DAYOFMONTH('2001-11-00')
retourne 0 .
ADDDATE(date,INTERVAL expr type)
ADDDATE(expr,days)
Lorsqu'elle est utilisée avec la forme INTERVAL , ADDDATE() est un synonyme de
DATE_ADD() . La fonction complémentaire SUBDATE() est un synonyme DATE_SUB() .
mysql> SELECT DATE_ADD('1998-01-02', INTERVAL 31 DAY);
        -> '1998-02-02'
mysql> SELECT ADDDATE('1998-01-02', INTERVAL 31 DAY);
        -> '1998-02-02'
Depuis MySQL 4.1.1, la seconde syntaxe est utilisée si expr est une expression de type
DATE ou DATETIME , et que days est un nombre de jour à ajouter à expr .

mysql> SELECT ADDDATE('1998-01-02', 31);


        -> '1998-02-02'
ADDTIME(expr,expr2)
ADDTIME() ajoute expr2 à expr et retourne le résultat. expr est une expression de type
DATE ou DATETIME , et expr2 est une expression de type TIME .

mysql> SELECT ADDTIME("1997-12-31 23:59:59.999999", "1 1:1:1.000002");


        -> '1998-01-02 01:01:01.000001'
mysql> SELECT ADDTIME("01:00:00.999999", "02:00:00.999998");
        -> '03:00:01.999997'
ADDTIME() a été ajouté en MySQL 4.1.1.
CURDATE()
CURRENT_DATE

5
Retourne la date courante au format 'YYYY-MM-DD' ou YYYYMMDD , suivant le contexte
numérique ou chaîne :
mysql> SELECT CURDATE();
        -> '1997-12-15'
mysql> SELECT CURDATE() + 0;
        -> 19971215
CURRENT_DATE
CURRENT_DATE()
CURRENT_DATE et CURRENT_DATE() sont synonymes de CURDATE() .
CURTIME()
Retourne l'heure courante au format 'HH:MM:SS' or HHMMSS suivant le contexte
numérique ou chaîne :
mysql> SELECT CURTIME();
        -> '23:50:26'
mysql> SELECT CURTIME() + 0;
        -> 235026
CURRENT_TIME
CURRENT_TIME()
CURRENT_TIME et CURRENT_TIME() sont synonymes de CURTIME() .
CURRENT_TIMESTAMP
CURRENT_TIMESTAMP()
CURRENT_TIMESTAMP et CURRENT_TIMESTAMP() sont synonymes de NOW() .
DATE(expr)
Extrait la partie date de l'expression expr de type DATE ou DATETIME .
mysql> SELECT DATE('2003-12-31 01:02:03');
        -> '2003-12-31'
DATE() est disponible depuis MySQL 4.1.1.
DATEDIFF(expr,expr2)
DATEDIFF() retourne le nombre de jours entre la date de début expr et la date de fin expr2
. expr et expr2 sont des expressions de type DATE ou DATETIME . Seule la partie DATE est
utilisée dans le calcul.
mysql> SELECT DATEDIFF('1997-12-31 23:59:59','1997-12-30');
        -> 1
mysql> SELECT DATEDIFF('1997-11-31 23:59:59','1997-12-31');
        -> -30
DATEDIFF() est disponible depuis MySQL 4.1.1.
DATE_ADD(date,INTERVAL expr type)
DATE_SUB(date,INTERVAL expr type)
Ces fonctions effectuent des calculs arithmétiques sur les dates.Depuis MySQL 3.23,
INTERVAL expr type est autorisé des deux cotés de l'opérateur + si l'expression de
l'autre coté est de type DATE ou DATETIME . Pour l'opérateur - , INTERVAL expr type
est autorisé uniquement du coté droit, car on ne peut pas soustraire une date d'un
intervalle (voir les exemples ci-dessous).
date est une valeur de type DATETIME ou DATE qui spécifie la date de début. expr est
une expression qui spécifie une valeur d'intervalle à ajouter ou soustraire de la date
initiale. expr est une chaîne : elle peut commencer avec '-' pour les intervalles négatifs.
type est un mot-clé, indiquant comment l'expression doit être interprétée.
La table suivante indique la signification des arguments type et expr :
type Valeur Attendue expr Format
MICROSECOND MICROSECONDS
SECOND SECONDS
MINUTE MINUTES
HOUR HOURS

5
DAY DAYS
WEEK WEEKS
MONTH MONTHS
QUARTER QUARTERS
YEAR YEARS
SECOND_MICROSECOND 'SECONDS.MICROSECONDS'
MINUTE_MICROSECOND 'MINUTES.MICROSECONDS'
MINUTE_SECOND 'MINUTES:SECONDS'
HOUR_MICROSECOND 'HOURS.MICROSECONDS'
HOUR_SECOND 'HOURS:MINUTES:SECONDS'
HOUR_MINUTE 'HOURS:MINUTES'
DAY_MICROSECOND 'DAYS.MICROSECONDS'
DAY_SECOND 'DAYS HOURS:MINUTES:SECONDS'
DAY_MINUTE 'DAYS HOURS:MINUTES'
DAY_HOUR 'DAYS HOURS'
YEAR_MONTH 'YEARS-MONTHS'
Les valeurs de type DAY_MICROSECOND , HOUR_MICROSECOND , MINUTE_MICROSECOND ,
SECOND_MICROSECOND , et MICROSECOND ont été ajoutés en MySQL 4.1.1. Les valeurs
QUARTER et WEEK sont disponibles depuis MySQL 5.0.0.
MySQL autorise tous les signes de ponctuation, comme délimiteur dans le format de expr .
Ceux qui sont affichés dans la table sont des suggestions. Si l'argument date est une valeur
DATE et que vos calculs impliquent des parties YEAR , MONTH et DAY (c'est à dire, sans
partie horaire), le résultat sera de type DATE . Sinon, le résultat est de type DATETIME :

mysql> SELECT '1997-12-31 23:59:59' + INTERVAL 1 SECOND;


        -> '1998-01-01 00:00:00'
mysql> SELECT INTERVAL 1 DAY + '1997-12-31';
        -> '1998-01-01'
mysql> SELECT '1998-01-01' - INTERVAL 1 SECOND;
        -> '1997-12-31 23:59:59'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
    ->                 INTERVAL 1 SECOND);
        -> '1998-01-01 00:00:00'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
    ->                 INTERVAL 1 DAY);
        -> '1998-01-01 23:59:59'
mysql> SELECT DATE_ADD('1997-12-31 23:59:59',
    ->                 INTERVAL '1:1' MINUTE_SECOND);
        -> '1998-01-01 00:01:00'
mysql> SELECT DATE_SUB('1998-01-01 00:00:00',
    ->                 INTERVAL '1 1:1:1' DAY_SECOND);
        -> '1997-12-30 22:58:59'
mysql> SELECT DATE_ADD('1998-01-01 00:00:00',
    ->                 INTERVAL '-1 10' DAY_HOUR);
        -> '1997-12-30 14:00:00'
mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);
        -> '1997-12-02'
mysql> SELECT DATE_ADD('1992-12-31 23:59:59.000002',
    ->                 INTERVAL '1.999999' SECOND_MICROSECOND);
        -> '1993-01-01 00:00:01.000001'
Si vous spécifiez un intervalle qui est trop court (il n'inclut pas toutes les parties d'intervalle
attendues par type ), MySQL suppose que vous avez omis les valeurs de gauche. Par
exemple, si vous spécifiez un type type de DAY_SECOND , la valeur expr devrait contenir
des jours, heures, minutes et secondes. Si vous fournissez une valeur de la forme
'1:10' , MySQL suppose que les jours et heures manquent, et que la valeur représente
des minutes et secondes. En d'autres termes, '1:10' DAY_SECOND est interprété comme
'1:10' MINUTE_SECOND . C'est similaire au comportement de MySQL avec les valeurs de
type TIME , qui représente des durées plutôt que des horaires.

5
Notez que si vous ajoutez ou soustrayez à une valeur de type DATE des horaires, le
résultat sera automatiquement au format DATETIME :

mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 DAY);


        -> '1999-01-02'
mysql> SELECT DATE_ADD('1999-01-01', INTERVAL 1 HOUR);
        -> '1999-01-01 01:00:00'
Si vous utilisez des dates malformées, le résultat sera NULL . Si vous ajoutez des MONTH ,
YEAR_MONTH ou YEAR , et que le résultat a un jour du mois qui est au-
delà de ce qui est possible dans le mois, le jour sera adapté au plus
grand jour possible du mois. Par exemple :

mysql> SELECT DATE_ADD('1998-01-30', interval 1 month);


        -> '1998-02-28'
Notez que dans l'exemple précédent, le mot clé INTERVAL et le spécificateur type sont
insensibles à la casse.
DATE_FORMAT(date,format)
Formate la date date avec le format format . Les spécificateurs suivants peuvent être utilisé
dans la chaîne format :
Option Description
%% Un signe pourcentage littéral '%' .
%a Nom du jour de la semaine, en abrégé et en anglais ( Sun .. Sat )
%b Nom du mois, en abrégé et en anglais ( Jan .. Dec )
%c Mois, au format numérique ( 1 .. 12 )
%d Jour du mois, au format numérique ( 00 .. 31 )
%D Jour du mois, avec un suffixe anglais ( 1st , 2nd , 3rd , etc.)
%e Jour du mois, au format numérique ( 0 .. 31 )
%f Microsecondes ( 000000 .. 999999 )
%H Heure ( 00 .. 23 )
%h Heure ( 01 .. 12 )
%I Heure ( 01 .. 12 )
%i Minutes, au format numérique ( 00 .. 59 )
%j Jour de l'année ( 001 .. 366 )
%k Heure ( 0 .. 23 )
%l Heure ( 1 .. 12 )
%m Mois, au format numérique ( 01 .. 12 )
%M Nom du mois ( January .. December )
%p AM ou PM
%r Heures, au format 12 heures ( hh:mm:ss [AP]M )
%s Secondes ( 00 .. 59 )
%S Secondes ( 00 .. 59 )
%T Heures, au format 24 heures ( hh:mm:ss )
%U Numéro de la semaine ( 00 .. 53 ), où Dimanche est le premier jour de la semaine
%u Numéro de la semaine ( 00 .. 53 ), où Lundi est le premier jour de la semaine
Numéro de la semaine ( 01 .. 53 ), où Dimanche est le premier jour de la semaine,
%V
utilisé avec '%X'
Numéro de la semaine ( 01 .. 53 ), où Lundi est le premier jour de la semaine,
%v
utilisé avec '%x'
%W Nom du jour de la semaine ( Sunday .. Saturday )
%w Numéro du jour de la semaine ( 0 =Sunday.. 6 =Saturday)
Année, pour les semaines qui commencent le Dimanche, au format numérique, sur
%X
4 chiffres, utilisé avec '%V'
Année, pour les semaines qui commencent le Lundi, au format numérique, sur 4
%x
chiffres, utilisé avec '%v'

5
%y Année, au format numérique, sur 2 chiffres
%Y Année, au format numérique, sur 4 chiffres
Tous les autres caractères sont simplement copiés dans le résultat sans interprétation:
Le format %f est disponible depuis MySQL 4.1.1.
Depuis MySQL version 3.23, le caractère '%' est requis devant les caractères de format.
Dans les versions antérieures de MySQL, '%' était optionnel.
La raison qui fait que les intervalles de mois et de jours commencent avec zéro est que
MySQL autorise les dates incomplètes comme '2004-00-00' , depuis MySQL 3.23.

mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%W %M %Y');


        -> 'Saturday October 1997'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00', '%H:%i:%s');
        -> '22:23:00'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
                          '%D %y %a %d %m %b %j');
        -> '4th 97 Sat 04 10 Oct 277'
mysql> SELECT DATE_FORMAT('1997-10-04 22:23:00',
                          '%H %k %I %r %T %S %w');
        -> '22 22 10 10:23:00 PM 22:23:00 00 6'
mysql> SELECT DATE_FORMAT('1999-01-01', '%X %V');
        -> '1998 52'
DAY(date)
DAY() est un synonyme de DAYOFMONTH() . Cette fonction est disponible depuis MySQL
4.1.1.
DAYNAME(date)
Retourne le nom du jour de la semaine de date :
mysql> SELECT DAYNAME('1998-02-05');
        -> 'Thursday'
DAYOFMONTH(date)
Retourne le jour de la date date , dans un intervalle de 1 à 31 :
mysql> SELECT DAYOFMONTH('1998-02-03');
        -> 3
DAYOFWEEK(date)
Retourne l'index du jour de la semaine : pour date ( 1 = Dimanche, 2 = Lundi, ... 7 =
Samedi). Ces index correspondent au standard ODBC :
mysql> SELECT DAYOFWEEK('1998-02-03');
        -> 3
DAYOFYEAR(date)
Retourne le jour de la date date , dans un intervalle de 1 à 366 :
mysql> SELECT DAYOFYEAR('1998-02-03');
        -> 34
EXTRACT(type FROM date)
La fonction EXTRACT() utilise les mêmes types d'intervalles que la fonction DATE_ADD() ou
la fonction DATE_SUB() , mais extrait des parties de date plutôt que des opérations de
date.
mysql> SELECT EXTRACT(YEAR FROM "1999-07-02");
       -> 1999
mysql> SELECT EXTRACT(YEAR_MONTH FROM "1999-07-02 01:02:03");
       -> 199907
mysql> SELECT EXTRACT(DAY_MINUTE FROM "1999-07-02 01:02:03");
       -> 20102
mysql> SELECT EXTRACT(MICROSECOND FROM "2003-01-02 10:30:00.00123");

5
        -> 123
FROM_DAYS(N)
Retourne la date correspondant au nombre de jours ( N ) depuis la date 0 :
mysql> SELECT FROM_DAYS(729669);
        -> '1997-10-07'
FROM_DAYS() n'est pas fait pour travailler avec des dates qui précèdent l'avènement du
calendrier Grégorien (1582), car elle ne prend pas en compte les jours perdus lors du
changement de calendrier.
FROM_UNIXTIME(unix_timestamp)
Retourne une représentation de l'argument unix_timestamp sous la forme 'YYYY-MM-DD
HH:MM:SS' ou YYYYMMDDHHMMSS , suivant si la fonction est utilisé dans un contexte
numérique ou de chaîne.
mysql> SELECT FROM_UNIXTIME(875996580);
        -> '1997-10-04 22:23:00'
mysql> SELECT FROM_UNIXTIME(875996580) + 0;
        -> 19971004222300
Si format est donné, le résultat est formaté en fonction de la chaîne format . format peut
contenir les mêmes options de format que celles utilisées par DATE_FORMAT() :

mysql> SELECT FROM_UNIXTIME(UNIX_TIMESTAMP(),


    ->                      '%Y %D %M %h:%i:%s %x');
        -> '2003 6th August 06:22:58 2003'
GET_FORMAT(DATE | TIME | TIMESTAMP, 'EUR' | 'USA' | 'JIS' | 'ISO' |
'INTERNAL')
Retourne une chaîne de format. Cette fonction est pratique lorsqu'elle est utilisée avec les
fonctions DATE_FORMAT() et STR_TO_DATE() . Les trois valeurs possibles pour le premier
argument, et les cinq valeurs possible pour le second argument donnent 15 formats
d'affichage (pour les options utilisées, voyez la table de la fonction DATE_FORMAT() ) :
Appel fonction Résultat
GET_FORMAT(DATE,'USA') '%m.%d.%Y'
GET_FORMAT(DATE,'JIS') '%Y-%m-%d'
GET_FORMAT(DATE,'ISO') '%Y-%m-%d'
GET_FORMAT(DATE,'EUR') '%d.%m.%Y'
GET_FORMAT(DATE,'INTERNAL') '%Y%m%d'
GET_FORMAT(TIMESTAMP,'USA') '%Y-%m-%d-%H.%i.%s'
GET_FORMAT(TIMESTAMP,'JIS') '%Y-%m-%d %H:%i:%s'
GET_FORMAT(TIMESTAMP,'ISO') '%Y-%m-%d %H:%i:%s'
GET_FORMAT(TIMESTAMP,'EUR') '%Y-%m-%d-%H.%i.%s'
GET_FORMAT(TIMESTAMP,'INTERNAL') '%Y%m%d%H%i%s'
GET_FORMAT(TIME,'USA') '%h:%i:%s %p'
GET_FORMAT(TIME,'JIS') '%H:%i:%s'
GET_FORMAT(TIME,'ISO') '%H:%i:%s'
GET_FORMAT(TIME,'EUR') '%H.%i.%S'
GET_FORMAT(TIME,'INTERNAL') '%H%i%s'
Le format ISO est le format ISO 9075, et non ISO 8601.
mysql> SELECT DATE_FORMAT('2003-10-03', GET_FORMAT(DATE, 'EUR')
        -> '03.10.2003'
mysql> SELECT STR_TO_DATE('10.31.2003', GET_FORMAT(DATE, 'USA'))
        -> 2003-10-31
GET_FORMAT() est disponible depuis MySQL 4.1.1. Voyez Syntaxe de SET .
HOUR(time)
Retourne le nombre d'heures pour l'heure time , dans un intervalle de 0 à 23 :
mysql> SELECT HOUR('10:05:03');

5
        -> 10
Cependant, l'intervalle des valeurs TIME est bien plus grand, et donc, HOUR peut retourner
des valeurs plus grandes que 23 :

mysql> SELECT HOUR('272:59:59');


        -> 272
LAST_DAY(date)
Prend une valeur de format DATE ou DATETIME , et retourne le dernier jour du mois
correspondant. Retourne NULL si l'argument est invalide.

mysql> SELECT LAST_DAY('2003-02-05'), LAST_DAY('2004-02-05');


        -> '2003-02-28', '2004-02-29'
mysql> SELECT LAST_DAY('2004-01-01 01:01:01');
        -> '2004-01-31'
mysql> SELECT LAST_DAY('2003-03-32');
        -> NULL
LAST_DAY() est disponible depuis MySQL 4.1.1.
LOCALTIME
LOCALTIME()
LOCALTIME et LOCALTIME() sont synonymes de NOW() .
LOCALTIMESTAMP
LOCALTIMESTAMP()
LOCALTIMESTAMP et LOCALTIMESTAMP() sont synonymes de NOW() .
MAKEDATE(year,dayofyear)
Retourne une valeur de format DATE , à partir d'une année et du numéro de jour.
dayofyear doit être plus grand que 0 ou le résultat sera NULL .

mysql> SELECT MAKEDATE(2001,31), MAKEDATE(2001,32);


        -> '2001-01-31', '2001-02-01'
mysql> SELECT MAKEDATE(2001,365), MAKEDATE(2004,365);
        -> '2001-12-31', '2004-12-30'
mysql> SELECT MAKEDATE(2001,0);
        -> NULL
MAKEDATE() est disponible depuis MySQL 4.1.1.
MAKETIME(hour,minute,second)
Retourne une valeur de format TIME , calculée à partir des arguments hour , minute et
second .

mysql> SELECT MAKETIME(12,15,30);


        -> '12:15:30'
MAKETIME() est disponible depuis MySQL 4.1.1.
MICROSECOND(expr)
Retourne le nombre de microsecondes dans l'expression de type TIME ou DATETIME expr ,
sous la forme d'un nombre entre 0 et 999999 .

mysql> SELECT MICROSECOND('12:00:00.123456');


        -> 123456
mysql> SELECT MICROSECOND('1997-12-31 23:59:59.000010');
        -> 10
MICROSECOND() est disponible depuis MySQL 4.1.1.
est disponible depuis
MINUTE(time)
Retourne le nombre de minutes pour l'heure time , dans un intervalle de 0 à 59 :
mysql> SELECT MINUTE('98-02-03 10:05:03');
        -> 5
MONTH(date)
Retourne le numéro du mois de la date date , dans un intervalle de 1 à 12 :

6
mysql> SELECT MONTH('1998-02-03');
        -> 2
MONTHNAME(date)
Retourne le nom du mois de la date date :
mysql> SELECT MONTHNAME("1998-02-05");
        -> 'February'
NOW()
Retourne la date courante au format 'YYYY-MM-DD HH:MM:SS' ou YYYYMMDDHHMMSS ,
suivant le contexte numérique ou chaîne :
mysql> SELECT NOW();
        -> '1997-12-15 23:50:26'
mysql> SELECT NOW() + 0;
        -> 19971215235026
PERIOD_ADD(P,N)
Ajoute N mois à la période P (au format YYMM ou YYYYMM ). Retourne une valeur dans le
format YYYYMM .

Notez que l'argument P n'est pas de type date :

mysql> SELECT PERIOD_ADD(9801,2);


        -> 199803
PERIOD_DIFF(P1,P2)
Retourne le nombre de mois entre les périodes P1 et P2 . P1 et P2 doivent être au format
YYMM ou YYYYMM .Notez que les arguments P1 et P2 ne sont pas de type date :

mysql> SELECT PERIOD_DIFF(9802,199703);


        -> 11
QUARTER(date)
Retourne le numéro du trimestre de la date date , dans un intervalle de 1 à 4 :
mysql> SELECT QUARTER('98-04-01');
        -> 2
SECOND(time)
Retourne le nombre de secondes pour l'heure time , dans un intervalle de 0 à 59 :
mysql> SELECT SECOND('10:05:03');
        -> 3
SEC_TO_TIME(seconds)
Retourne l'argument seconds , convertit en heures, minutes et secondes au format
'HH:MM:SS' ou HHMMSS , suivant le contexte numérique ou chaîne :

mysql> SELECT SEC_TO_TIME(2378);


        -> '00:39:38'
mysql> SELECT SEC_TO_TIME(2378) + 0;
        -> 3938
STR_TO_DATE(str,format)
Cette fonction est l'inverse de la fonction DATE_FORMAT() . Elle prend la chaîne str , et une
chaîne de format format , puis retourne une valeur DATETIME . Les valeurs de type DATE ,
TIME ou DATETIME contenues dans la chaîne str doivent être au format format . Pour les
options qui sont utilisables dans la chaîne format , voyez la table dans la description de la
fonction DATE_FORMAT() . Tous les autres caractères sont utilisés littéralement, et ne
seront pas interprétés. Si str contient une valeur illégale, STR_TO_DATE() retourne NULL .

mysql> SELECT STR_TO_DATE('03.10.2003 09.20', '%d.%m.%Y %H.%i')


        -> 2003-10-03 09:20:00
mysql> SELECT STR_TO_DATE('10rap', '%crap')

6
        -> 0000-10-00 00:00:00
mysql> SELECT STR_TO_DATE('2003-15-10 00:00:00', '%Y-%m-%d %H:%i:%s')
        -> NULL
STR_TO_DATE() est disponible depuis MySQL 4.1.1.
SUBDATE(date,INTERVAL expr type)
SUBDATE(expr,days)
Lorsqu'elle est utilisée avec la forme INTERVAL du second argument, SUBDATE() est
synonyme DATE_SUB() .

mysql> SELECT DATE_SUB('1998-01-02', INTERVAL 31 DAY);


        -> '1997-12-02'
mysql> SELECT SUBDATE('1998-01-02', INTERVAL 31 DAY);
        -> '1997-12-02'
Depuis MySQL 4.1.1, la seconde syntaxe est autorisée, où expr est une expression de type
DATE ou DATETIME et days est le nombre de jour à soustraire de l'expression expr .

mysql> SELECT SUBDATE('1998-01-02 12:00:00', 31);


        -> '1997-12-02 12:00:00'
SUBTIME(expr,expr2)
SUBTIME() soustrait expr2 de expr et retourne le résultat. expr est une expression de
format DATE ou DATETIME et expr2 est une expression de type TIME .

mysql> SELECT SUBTIME("1997-12-31 23:59:59.999999", "1 1:1:1.000002");


        -> '1997-12-30 22:58:58.999997'
mysql> SELECT SUBTIME("01:00:00.999999", "02:00:00.999998");
        -> '-00:59:59.999999'
SUBTIME() a été ajoutée en MySQL 4.1.1.
SYSDATE()
SYSDATE() est un synonyme de NOW() .
TIME(expr)
Extrait la partie horaire de l'expression expr , de type TIME ou DATETIME .
mysql> SELECT TIME('2003-12-31 01:02:03');
        -> '01:02:03'
mysql> SELECT TIME('2003-12-31 01:02:03.000123');
        -> '01:02:03.000123'
TIME() a été ajoutée en MySQL 4.1.1.
TIMEDIFF(expr,expr2)
TIMEDIFF() retourne la durée entre l'heure de début expr et l'heure de fin expr2 . expr et
expr2 sont des expressions de type TIME ou DATETIME , et doivent être de même type.

mysql> SELECT TIMEDIFF('2000:01:01 00:00:00', '2000:01:01


00:00:00.000001');
        -> '-00:00:00.000001'
mysql> SELECT TIMEDIFF('1997-12-31 23:59:59.000001','1997-12-30
01:01:01.000002');
        -> '46:58:57.999999'
TIMEDIFF() a été ajoutée en MySQL 4.1.1.
TIMESTAMP(expr)
TIMESTAMP(expr,expr2)
Avec un seul argument, retourne l'expression expr de type DATE ou DATETIME sous la
forme d'une valeur DATETIME . Avec deux arguments, ajouter l'expression expr2 à
l'expression expr et retourne le résultat au format DATETIME .

mysql> SELECT TIMESTAMP('2003-12-31');


        -> '2003-12-31 00:00:00'
mysql> SELECT TIMESTAMP('2003-12-31 12:00:00','12:00:00');
        -> '2004-01-01 00:00:00'

6
TIMESTAMP() a été ajoutée en MySQL 4.1.1.
TIMESTAMPADD(interval,int_expr,datetime_expr)
Ajoute l'expression entière int_expr à l'expression datetime_expr au format DATE ou
DATETIME . L'unité de int_expr est donnée avec l'argument interval , qui peut être l'une
des valeurs suivantes : FRAC_SECOND , SECOND , MINUTE , HOUR , DAY , WEEK , MONTH
, QUARTER , ou YEAR .La valeur interval peut être spécifiée, en utilisant un des mots-clé
cités, ou avec le préfixe SQL_TSI_ . Par exemple, DAY et SQL_TSI_DAY sont tous les deux
valides.
mysql> SELECT TIMESTAMPADD(MINUTE,1,'2003-01-02');
        -> '2003-01-02 00:01:00'
mysql> SELECT TIMESTAMPADD(WEEK,1,'2003-01-02');
        -> '2003-01-09'
TIMESTAMPADD() a été ajoutée en MySQL 5.0.0.
TIMESTAMPDIFF(interval,datetime_expr1,datetime_expr2)
Retourne la différence entière entre les expressions datetime_expr1 et datetime_expr2 , de
format DATE et DATETIME . L'unité du résultat est donné par l'argument interval . Les
valeurs légales de interval sont les mêmes que pour la fonction TIMESTAMPADD() .

mysql> SELECT TIMESTAMPDIFF(MONTH,'2003-02-01','2003-05-01');


        -> 3
mysql> SELECT TIMESTAMPDIFF(YEAR,'2002-05-01','2001-01-01');
        -> -1
TIMESTAMPDIFF() a été ajoutée en MySQL 5.0.0.
TIME_FORMAT(time,format)
Cette fonction est utilisée exactement comme la fonction DATE_FORMAT() ci-dessus, mais
la chaîne format ne doit utiliser que des spécificateurs d'heures, qui gèrent les heures,
minutes et secondes. Les autres spécificateurs génèreront la valeur NULL ou 0 .
Si la valeur time contient une valeur d'heure qui est plus grande que 23 , les formats %H
et %k produiront une valeur qui est hors de l'intervalle 0..23 . L'autre format d'heure
produira une heure modulo 12 :

mysql> SELECT TIME_FORMAT('100:00:00', '%H %k %h %I %l');


        -> '100 100 04 04 4'
TIME_TO_SEC(time)
Retourne l'argument time , convertit en secondes :
mysql> SELECT TIME_TO_SEC('22:23:00');
        -> 80580
mysql> SELECT TIME_TO_SEC('00:39:38');
        -> 2378
TO_DAYS(date)
Retourne le nombre de jours depuis la date 0 jusqu'à la date date :
mysql> SELECT TO_DAYS(950501);
        -> 728779
mysql> SELECT TO_DAYS('1997-10-07');
        -> 729669
TO_DAYS() n'est pas fait pour travailler avec des dates qui précèdent l'avènement du
calendrier Grégorien (1582), car elle ne prend pas en compte les jours perdus lors du
changement de calendrier.
N'oubliez pas que MySQL convertit les années représentées sur deux chiffres en dates à
quatre chiffres, en utilisant les règles de la section Types temporels . Par exemple, '1997-
10-07' et '97-10-07' sont identiques :

mysql> SELECT TO_DAYS('1997-10-07'), TO_DAYS('97-10-07');


        -> 729669, 729669

6
Pour les dates antérieures à 1582, les résultats sont indéfinis.
UNIX_TIMESTAMP()
UNIX_TIMESTAMP(date)
Lorsqu'elle est appelé sans argument, cette fonction retourne un timestamp Unix (nombre
de secondes depuis '1970-01-01 00:00:00' GMT). Si UNIX_TIMESTAMP() est appelé avec
un argument date , elle retourne le timestamp correspondant à cette date. date peut être
une chaîne de type DATE , DATETIME , TIMESTAMP , ou un nombre au format YYMMDD ou
YYYYMMDD , en horaire local :

mysql> SELECT UNIX_TIMESTAMP();


        -> 882226357
mysql> SELECT UNIX_TIMESTAMP('1997-10-04 22:23:00');
        -> 875996580
Lorsque UNIX_TIMESTAMP est utilisé sur une colonne de type TIMESTAMP , la fonction
reçoit directement la valeur, sans conversion explicite. Si vous donnez à
UNIX_TIMESTAMP() une date hors de son intervalle de validité, elle retourne 0.Si vous
voulez soustraire une colonne de type UNIX_TIMESTAMP() , vous devez sûrement vouloir
un résultat de type entier signé. Fonctions de transtypage .
UTC_DATE
UTC_DATE()
Retourne la date UTC courante au format 'YYYY-MM-DD' ou YYYYMMDD suivant le contexte
numérique ou chaîne :
mysql> SELECT UTC_DATE(), UTC_DATE() + 0;
        -> '2003-08-14', 20030814
UTC_DATE() est disponible depuis MySQL 4.1.1.
UTC_TIME
UTC_TIME()
Retourne l'heure UTC courante au format 'HH:MM:SS' or HHMMSS suivant le contexte
numérique ou chaîne :
mysql> SELECT UTC_TIME(), UTC_TIME() + 0;
        -> '18:07:53', 180753
UTC_TIME() est disponible depuis MySQL 4.1.1.
UTC_TIMESTAMP
UTC_TIMESTAMP()
Retourne l'heure et la date UTC courante au format 'YYYY-MM-DD HH:MM:SS' or
YYYYMMDDHHMMSS suivant le contexte numérique ou chaîne :

mysql> SELECT UTC_TIMESTAMP(), UTC_TIMESTAMP() + 0;


        -> '2003-08-14 18:08:04', 20030814180804
UTC_TIMESTAMP() est disponible depuis MySQL 4.1.1.
WEEK(date [,mode])
Avec un seul argument, retourne le numéro de la semaine dans l'année de la date date ,
dans un intervalle de 0 à 53 (oui, il peut y avoir un début de semaine numéro 53), en
considérant que Dimanche est le premier jour de la semaine. Avec deux arguments, la
fonction WEEK() vous permet de spécifier si les semaines commencent le Dimanche ou le
Lundi et la valeur retournée sera dans l'intervalle 0-53 ou bien 1-52 . Lorsque l'argument
mode est omis, la valeur de la variable default_week_format (ou 0 en MySQL 4.0 ou plus
ancien) est utilisé. Syntaxe de SET .Voici un tableau explicatif sur le fonctionnement du
second argument :
Valeur Signification
La semaine commence le Sunday;l'intervalle de valeur de retour va de 0 à !2; la
0
semaine 1 est la première semaine de l'année
La semaine commence le Monday;l'intervalle de valeur de retour va de 0 à !2; la
1
semaine 1 est la première semaine de l'année qui a plus de trois jours
La semaine commence le Sunday;l'intervalle de valeur de retour va de 1 à !2; la
2
semaine 1 est la première semaine de l'année
3 La semaine commence le Monday;l'intervalle de valeur de retour va de 1 à !2; la

6
semaine 1 est la première semaine de l'année qui a plus de trois jours
La semaine commence le Sunday;l'intervalle de valeur de retour va de 0 à !2; la
4
semaine 1 est la première semaine de l'année qui a plus de trois jours
La semaine commence le Monday;l'intervalle de valeur de retour va de 0 à !2; la
5
semaine 1 est la première semaine de l'année
La semaine commence le Sunday;l'intervalle de valeur de retour va de 1 à !2; la
6
semaine 1 est la première semaine de l'année qui a plus de trois jours
La semaine commence le Monday;l'intervalle de valeur de retour va de 1 à !2; la
7
semaine 1 est la première semaine de l'année
Le mode 3 est disponible depuis MySQL 4.0.5. Le mode 4 est disponible depuis MySQL
4.0.17.
mysql> SELECT WEEK('1998-02-20');
        -> 7
mysql> SELECT WEEK('1998-02-20',0);
        -> 7
mysql> SELECT WEEK('1998-02-20',1);
        -> 8
mysql> SELECT WEEK('1998-12-31',1);
        -> 53
Note : en version 4.0, WEEK(date,0) a été modifiée pour correspondre au système
calendaire des USA. Avant cela, WEEK() était calculé incorrectement, pour des dates
américaines : en effet, WEEK(date) et WEEK(date,0) étaient incorrects.Si vous préférez
que le résultat soit calculé en fonction de l'année qui contient le premier jour de la semaine
de la date utilisée en argument, vous devriez utiliser les valeurs 2, 3, 6, or 7 de l'argument
mode .

mysql> SELECT YEAR('2000-01-01'), WEEK('2000-01-01',0);


        -> 2000, 0
mysql> SELECT WEEK('2000-01-01',2);
        -> 52
Alternativement, utilisez la fonction YEARWEEK() :

mysql> SELECT YEARWEEK('2000-01-01');


        -> 199952
mysql> SELECT MID(YEARWEEK('2000-01-01'),5,2);
        -> '52'
WEEKDAY(date)
Retourne l'index du jour de la semaine, avec la conversion suivante : date ( 0 = Lundi, 1 =
Mardi, ... 6 = Dimanche).

mysql> SELECT WEEKDAY('1997-10-04 22:23:00');


        -> 5
mysql> SELECT WEEKDAY('1997-11-05');
        -> 2
WEEKOFYEAR(date)
Retourne le numéro de semaine dans l'année, sous forme d'un nombre compris entre 1 et
53 .

mysql> SELECT WEEKOFYEAR('1998-02-20');


        -> 8
WEEKOFYEAR() est disponible depuis MySQL 4.1.1.
YEAR(date)
Retourne l'année de la date date , dans un intervalle de 1000 à 9999 :
mysql> SELECT YEAR('98-02-03');
        -> 1998

6
mysql> SELECT YEAR('98-02-03');
        -> 1998
YEARWEEK(date)
YEARWEEK(date,start)
Retourne l'année et la semaine d'une date. L'argument start fonctionne exactement comme
l'argument start de la fonction WEEK() . Notez que l'année dans le résultat peut être
différente de l'année passée en argument, pour la première et la dernière semaine de
l'année.
mysql> SELECT YEARWEEK('1987-01-01');
        -> 198653
Notez que le numéro de semaine est différent de celui que la fonction WEEK() retourne (
0 ) pour les arguments optionnels 0 ou 1 , comme WEEK() puis retourne la semaine dans
le contexte de l'année.

6
Les Fonction arithmétiques
@subsection Fonctions mathématiques Toutes les fonctions mathématiques retournent NULL en cas
d'erreur.
ABS(X)
Retourne la valeur absolue de X .
mysql> SELECT ABS(2);
        -> 2
mysql> SELECT ABS(-32);
        -> 32
Cette fonction est utilisable avec les valeurs issues des champs BIGINT .
ACOS(X)
Retourne l'arccosinus de X , c'est à dire, la valeur de l'angle dont X est la cosinus. Retourne
NULL si X n'est pas dans l'intervalle -1 - 1 .

mysql> SELECT ACOS(1);


        -> 0.000000
mysql> SELECT ACOS(1.0001);
        -> NULL
mysql> SELECT ACOS(0);
        -> 1.570796
ASIN(X)
Retourne l'arcsinus de X , c'est à dire, la valeur de l'angle dont le sinus est X . Retourne
NULL si X n'est pas dans l'intervalle -1 - 1 :

mysql> SELECT ASIN(0.2);


        -> 0.201358
mysql> SELECT ASIN('foo');
        -> 0.000000
ATAN(X)
Retourne l'arctangente de X , c'est à dire, la valeur de l'angle dont la tangente est X .
mysql> SELECT ATAN(2);
        -> 1.107149
mysql> SELECT ATAN(-2);
        -> -1.107149
ATAN(Y,X)
ATAN2(Y,X)
,
Retourne l'arctangente des variables X et Y . Cela revient à calculer l'arctangente de Y / X
excepté que les signes des deux arguments servent à déterminer le quadrant du résultat
:
mysql> SELECT ATAN(-2,2);
        -> -0.785398
mysql> SELECT ATAN2(PI(),0);
        -> 1.570796
CEILING(X)
CEIL(X)
Retourne la valeur entière supérieure de X .
mysql> SELECT CEILING(1.23);
        -> 2
mysql> SELECT CEILING(-1.23);
        -> -1
Notez que la valeur retournée sera de type BIGINT !
COS(X)
Retourne le cosinus de X , où X est donné en radians.

6
mysql> SELECT COS(PI());
        -> -1.000000
COT(X)
Retourne la cotangente de X .
mysql> SELECT COT(12);
        -> -1.57267341
mysql> SELECT COT(0);
        -> NULL
CRC32(expr)
Calcule la somme de contrôle et retourne un entier 32 bits non-signé. Le résultat est la
valeur NULL si l'argument est NULL . L'argument attendu est une chaîne, et sera traité
comme une chaîne s'il n'est pas du bon type.
mysql> SELECT CRC32('MySQL');
        -> 3259397556
CRC32() est disponible en MySQL 4.1.0.
DEGREES(X)
Retourne l'argument X , convertit de radians en degrés.
mysql> SELECT DEGREES(PI());
        -> 180.000000
EXP(X)
Retourne la valeur de e (la base des logarithmes naturels) élevé à la puissance X .
mysql> SELECT EXP(2);
        -> 7.389056
mysql> SELECT EXP(-2);
        -> 0.135335
FLOOR(X)
Retourne la valeur entière inférieure de X .
mysql> SELECT FLOOR(1.23);
        -> 1
mysql> SELECT FLOOR(-1.23);
        -> -2
Notez que la valeur retournée sera de type BIGINT !
LN(X)
Retourne le logarithme naturel de X (népérien).

mysql> SELECT LN(2);


        -> 0.693147
mysql> SELECT LN(-2);
        -> NULL
Cette fonction a été ajoutée à MySQL à partir de la version 4.0.3. C'est un synonyme de la
fonction LOG(X) .
LOG(X)
LOG(B,X)
Appelée avec un seul paramètre, cette fonction retourne le logarithme naturel (népérien)
de X .

mysql> SELECT LOG(2);


        -> 0.693147
mysql> SELECT LOG(-2);
        -> NULL
Appelée avec deux paramètres, cette fonction retourne le logarithme naturel de X pour une
base B arbitraire :

mysql> SELECT LOG(2,65536);

6
        -> 16.000000
mysql> SELECT LOG(1,100);
        -> NULL
Cette base arbitraire a été ajoutée à MySQL à partir de la version 4.0.3. LOG(B,X) est
l'équivalent de LOG(X)/LOG(B) .
LOG2(X)
Retourne le logarithme en base 2 de X .

mysql> SELECT LOG2(65536);


        -> 16.000000
mysql> SELECT LOG2(-100);
        -> NULL
LOG2() est utile pour trouver combien de bits sont nécessaires pour stocker un nombre.
Cette fonction a été ajoutée à MySQL à partir de la version 4.0.3. Dans les versions
antérieures, vous pouvez utiliser LOG(X)/LOG(2) en remplacement.
LOG10(X)
Retourne le logarithme en base 10 de X .

mysql> SELECT LOG10(2);


        -> 0.301030
mysql> SELECT LOG10(100);
        -> 2.000000
mysql> SELECT LOG10(-100);
        -> NULL
MOD(N,M)
N%M
N MOD M
Modulo (équivalent de l'opérateur % dans le langage C). Retourne le reste de la division de
N par M .

mysql> SELECT MOD(234, 10);


        -> 4
mysql> SELECT 253 % 7;
        -> 1
mysql> SELECT MOD(29,9);
        -> 2
Cette fonction ne pose pas de problèmes avec les BIGINT .
PI()
Retourne la valeur de pi. Par défaut, 5 décimales sont retournées, mais MySQL utilise
la double précision pour pi.
mysql> SELECT PI();
        -> 3.141593
mysql> SELECT PI()+0.000000000000000000;
        -> 3.141592653589793116
POW(X,Y)
POWER(X,Y)
Retourne la valeur de X élevée à la puissance Y :
mysql> SELECT POW(2,2);
        -> 4.000000
mysql> SELECT POW(2,-2);
        -> 0.250000
RADIANS(X)
Retourne l'argument X , converti de degrés en radians.
mysql> SELECT RADIANS(90);
        -> 1.570796
RAND()
RAND(N)

6
Retourne un nombre aléatoire à virgule flottante compris dans l'intervalle 0 - 1.0 . Si
l'argument entier N est spécifié, il est utilisé comme initialisation du générateur de
nombres aléatoires.
mysql> SELECT RAND();
        -> 0.9233482386203
mysql> SELECT RAND(20);
        -> 0.15888261251047
mysql> SELECT RAND(20);
        -> 0.15888261251047
mysql> SELECT RAND();
        -> 0.63553050033332
mysql> SELECT RAND();
        -> 0.70100469486881
Vous ne pouvez pas utiliser une colonne de valeur RAND() dans une clause ORDER BY ,
parce que ORDER BY va évaluer la colonne plusieurs fois. Dans la version 3.23 de
MySQL, vous pouvez, tout de même, faire ceci :
mysql> SELECT * FROM tbl_name ORDER BY RAND();
Cette syntaxe est très pratique pour faire une sélection aléatoire de lignes :
mysql> SELECT * FROM table1, table2 WHERE a=b AND c<d
    -> ORDER BY RAND() LIMIT 1000;
Notez que la fonction RAND() dans une clause WHERE sera réévaluée à chaque fois que
WHERE sera exécuté.
RAND() n'est pas un générateur parfait de nombres aléatoires, mais reste une manière
rapide de produire des nombres aléatoires portables selon les différentes plates-formes
pour une même version de MySQL.
ROUND(X)
ROUND(X,D)
Retourne l'argument X , arrondi à un nombre à D décimales. Avec deux arguments, la
valeur est arrondie avec D décimales.
Si D vaut 0 , le résultat n'aura ni de partie décimale, ni de séparateur de décimal.

mysql> SELECT ROUND(-1.23);


        -> -1
mysql> SELECT ROUND(-1.58);
        -> -2
mysql> SELECT ROUND(1.58);
        -> 2
mysql> SELECT ROUND(1.298, 1);
        -> 1.3
mysql> SELECT ROUND(1.298, 0);
        -> 1
mysql> SELECT ROUND(23.298, -1);
        -> 20
Notez que le comportement de l'opérateur ROUND() , lorsque l'argument est exactement
entre deux entiers, dépend de la bibliothèque C active. Certaines arrondissent toujours à
l'entier pair le plus proche, toujours vers le haut, toujours vers le bas, ou toujours vers
zéro. Si vous avez besoin d'un certain type d'arrondissement, vous devez utiliser une
fonction bien définie comme TRUNCATE() ou FLOOR() .
SIGN(X)
Retourne le signe de l'argument sous la forme -1 , 0 , ou 1 , selon que X est négatif, zéro,
ou positif.
mysql> SELECT SIGN(-32);
        -> -1
mysql> SELECT SIGN(0);

7
        -> 0
mysql> SELECT SIGN(234);
        -> 1
SIN(X)
Retourne le sinus de X , où X est donné en radians.
mysql> SELECT SIN(PI());
        -> 0.000000
SQRT(X)
Retourne la racine carrée de X .
mysql> SELECT SQRT(4);
        -> 2.000000
mysql> SELECT SQRT(20);
        -> 4.472136
TAN(X)
Retourne la tangente de X , où X est donné en radians.
mysql> SELECT TAN(PI()+1);
        -> 1.557408
TRUNCATE(X,D)
Retourne l'argument X , tronqué à D décimales. Si D vaut 0 , le résultat n'aura ni
séparateur décimal, ni partie décimale.
mysql> SELECT TRUNCATE(1.223,1);
        -> 1.2
mysql> SELECT TRUNCATE(1.999,1);
        -> 1.9
mysql> SELECT TRUNCATE(1.999,0);
        -> 1
mysql> SELECT TRUNCATE(-1.999,1);
        -> -1.9
A partir de MySQL 3.23.51 tous les nombres sont arrondis vers zéro.
Notez que les nombres décimaux ne sont pas stockés exactement comme les nombres
entiers , mais comme des valeurs doubles. Vous pouvez être dupés par le résultat
suivant :

mysql> SELECT TRUNCATE(10.28*100,0);


       -> 1027
Ce résultat est normal car 10.28 est actuellement stocké comme cela
10.2799999999999999.

7
Options de GROUP BY

Depuis MySQL 4.1.1, la clause GROUP BY permet l'utilisation de l'option WITH ROLLUP qui
fait que des lignes supplémentaires seront ajoutées lors de regroupements. Ces lignes
représentent des regroupements de haut niveau (ou des super-agrégats). ROLLUP vous permet
de répondre simultanément à plusieurs niveaux d'analyse avec une seule requête. Il peut être
utilisée, par exemple, pour supporter des opérations OLAP (Online Analytical
Processing).

Voici une illustration. Supposons que vous ayez une table de ventes sales, avec des colonnes
pour l'année year, le pays country, le produit product et le profit profit :
CREATE TABLE sales
(
year INT NOT NULL,
country VARCHAR(20) NOT NULL,
product VARCHAR(32) NOT NULL,
profit INT
);
Le contenu de cette table peut être agrégé par année avec la clause GROUP BY :
mysql> SELECT year, SUM(profit) FROM sales GROUP BY year;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 | 4525 |
| 2001 | 3010 |
+------+-------------+
Cette requête affiche le profit par année, mais si vous voulez déterminer le profit total de
toutes les années, vous devez ajouter ces valeurs vous-mêmes, ou faire une autre requête.
Ou alors, vous pouvez utiliser la clause ROLLUP, qui fournit les deux niveaux d'analyse dans la
même requête. En ajoutant l'option WITH ROLLUP à la clause GROUP BY, la requête va produire
une autre ligne, avec le grand total de toutes les années :
mysql> SELECT year, SUM(profit) FROM sales GROUP BY year WITH ROLLUP;
+------+-------------+
| year | SUM(profit) |
+------+-------------+
| 2000 | 4525 |
| 2001 | 3010 |
| NULL | 7535 |
+------+-------------+
La ligne du grand total est identifiée par la valeur NULL dans la colonne year.
ROLLUP a des effets plus complexes lorsqu'il y a plusieurs colonnes dans la clause GROUP BY.
Dans ce cas, il a y un changement de valeur pour toutes sauf la dernière colonne de
groupement, et la requête va produire les super-agrégats.
Par exemple, sans la clause ROLLUP, le résumé des ventes de la table sales basé sur l'année
year, le pays country et le produit product peut ressembler à ceci :
mysql> SELECT year, country, product, SUM(profit)
-> FROM sales
-> GROUP BY year, country, product;
+------+---------+------------+-------------+

7
| year | country | product | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
| 2000 | USA | Calculator | 75 |
| 2000 | USA | Computer | 1500 |
| 2001 | Finland | Phone | 10 |
| 2001 | USA | Calculator | 50 |
| 2001 | USA | Computer | 2700 |
| 2001 | USA | TV | 250 |
+------+---------+------------+-------------+
Le résultat indique les valeurs résumées pour chaque triplet année/pays/produit. Si nous
ajoutons la clause ROLLUP, la requête produit plusieurs nouvelles lignes :
mysql> SELECT year, country, product, SUM(profit)
-> FROM sales
-> GROUP BY year, country, product WITH ROLLUP;
+------+---------+------------+-------------+
| year | country | product | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | Finland | NULL | 1600 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
| 2000 | India | NULL | 1350 |
| 2000 | USA | Calculator | 75 |
| 2000 | USA | Computer | 1500 |
| 2000 | USA | NULL | 1575 |
| 2000 | NULL | NULL | 4525 |
| 2001 | Finland | Phone | 10 |
| 2001 | Finland | NULL | 10 |
| 2001 | USA | Calculator | 50 |
| 2001 | USA | Computer | 2700 |
| 2001 | USA | TV | 250 |
| 2001 | USA | NULL | 3000 |
| 2001 | NULL | NULL | 3010 |
| NULL | NULL | NULL | 7535 |
+------+---------+------------+-------------+
Pour cette requête, ajouter ROLLUP fait que la requête ajoute les résumés de quatre niveaux
d'analyse, et non pas un seul. Voici comment interpréter le résultat de la clause ROLLUP :
 Après chaque jeu de ligne sur les produits, pour une année et un pays donnée, un
résumé est ajouté, indiquant le total de tous les produits. Ces lignes voient leur
colonne product contenir la valeur NULL.
 Après chaque jeu de ligne couvrant une année particulière, une nouvelle ligne est
ajoutée pour afficher le total de tous les pays et produits, pour cette année la. Ces
lignes voient leurs colonnes country et products contenir NULL.
 Finalement, suivant toutes les autres lignes, un résumé général est produit, avec le
grand total de toutes les années, pays et produits. Cette ligne contient la valeur NULL
pour toutes les colonnes year, country et products.
Autres considérations avec ROLLUP
Voici quelques comportements spécifiques de MySQL et son implémentation de ROLLUP:

7
Lorsque vous utilisez ROLLUP, vous ne pouvez pas utiliser de clause ORDER BY pour trier les
résultats. En d'autres termes, ROLLUP et ORDER BY sont mutuellement exclusives. Toutefois,
vous avec toujours le contrôle sur l'ordre de tri avec la clause GROUP BY. Vous pouvez utiliser
explicitement les mots ASC et DESC avec les colonnes listées dans GROUP BY pour spécifier les
ordres de tri des colonnes individuelles. Les lignes de résumés de ROLLUP apparaissent
toujours après les lignes pour lesquelles ils sont calculés, quelque soit le tri.
La clause LIMIT peut être utilisée pour restreindre le nombre de lignes retournées au client.
LIMIT s'applique après ROLLUP, et la limite s'appliquera aux lignes ajoutées par ROLLUP. Par
exemple :
mysql> SELECT year, country, product, SUM(profit)
-> FROM sales
-> GROUP BY year, country, product WITH ROLLUP
-> LIMIT 5;
+------+---------+------------+-------------+
| year | country | product | SUM(profit) |
+------+---------+------------+-------------+
| 2000 | Finland | Computer | 1500 |
| 2000 | Finland | Phone | 100 |
| 2000 | Finland | NULL | 1600 |
| 2000 | India | Calculator | 150 |
| 2000 | India | Computer | 1200 |
+------+---------+------------+-------------+
Notez qu'utiliser LIMIT avec ROLLUP peut conduire à des résultats plus difficiles à interpréter,
car vous avez moins de contexte pour comprendre les résumés.
Les indicateurs NULL de chaque super agrégat sont produits lorsque la ligne est envoyée au
client. Le serveur recherche les colonnes citées dans la clause GROUP BY, en les prenant la plus
à gauche, dont la valeur change. Toute colonne du jeu de résultat dont le nom ne correspond
pas lexicalement à un de ces noms, verra sa valeur être NULL. Si vous spécifiez un groupement
par numéro de colonne, le serveur identifiera aussi les colonnes qui devront recevoir NULL.
Comme les valeurs NULL des résumés sont placées dans le résultat aussi tard durant le
traitement de la requête, nous ne pouvons pas les tester comme étant des valeurs NULL
provenant de la requête elle-même. Par exemple, vous ne pourrez pas ajouter HAVING
product IS NULL pour éliminer certains résumés qui ne vous intéressent pas.

D'un autre coté, les valeurs NULL apparaissent comme des valeurs NULL du coté du client, et
peuvent être repérées en tant que telles par le client MySQL.

7
Syntaxe de DELETE
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] FROM table_name
[WHERE where_definition]
[ORDER BY ...]
[LIMIT row_count]
Syntaxe multi-tables :
DELETE [LOW_PRIORITY] [QUICK] [IGNORE] table_name[.*] [,
table_name[.*] ...]
FROM table-references
[WHERE where_definition]
ou :
DELETE [LOW_PRIORITY] [QUICK] [IGNORE]
FROM table_name[.*] [, table_name[.*] ...]
USING table-references
[WHERE where_definition]

Syntaxe de DO
DO expression, [expression, ...]
Exécute l'expression mais ne retourne aucun résultat. C'est un alias de SELECT expression,
expression, mais il a l'avantage d'être plus rapide quand on n'a pas besoin du résultat.

Cela s'avère très utile avec les fonctions qui ont des effets secondaires, comme
RELEASE_LOCK.

 Syntaxe de INSERT ... SELECT

INSERT [LOW_PRIORITY] [IGNORE] [INTO] nom_de_la_table [(liste des


colonnes)] SELECT ...
La requête INSERT ... SELECT permet de rapidement insérer dans une table un grand
nombre de lignes d'une ou plusieurs autres tables.
INSERT INTO tblTemp2 (fldID) SELECT tblTemp1.fldOrder_ID FROM tblTemp1
WHERE
tblTemp1.fldOrder_ID > 100;

Syntaxe de INSERT DELAYED

INSERT DELAYED ...


L'option DELAYED de la commande INSERT est une option spécifique à MySQL très utile si
vos clients ne peuvent pas attendre que INSERT se termine. C'est un problème fréquent quand
on utilise MySQL pour des logs, mais aussi quand on utilise souvent des commandes SELECT
ou UPDATE qui prennent beaucoup de temps. DELAYED a été ajouté à MySQL dans la version
3.22.15. C'est une extension de MySQL au ANSI SQL 92.
En utilisant INSERT DELAYED, le client reçoit immédiatement un acquittement, et la ligne sera
insérée quand la table ne sera plus utilisée par un autre thread.
Un autre avantage de INSERT DELAYED est que les insertions des clients sont regroupées, et
écrits d'un seul bloc. C'est beaucoup plus rapide que de faire des insertions séparées.
Il y a quelques contraintes à l'utilisation de DELAYED :

7
 INSERT DELAYED ne fonctionne qu'avec les tables MyISAM et ISAM. Pour les tables
MyISAM, s'il n'y a plus de blocs libres au milieu du fichier de données, les SELECT et
INSERT simultanés sont supportés. Dans ces circonstances, vous n'aurez que très
rarement besoin de INSERT DELAYED avec MyISAM.

Syntaxe de LOAD DATA INFILE


LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name.txt'
[REPLACE | IGNORE]
INTO TABLE tbl_name
[FIELDS
[TERMINATED BY '\t']
[[OPTIONALLY] ENCLOSED BY '']
[ESCAPED BY '\\' ]
]
[LINES
[STARTING BY '']
[TERMINATED BY '\n']
]
[IGNORE number LINES]
[(col_name,...)]
La commande LOAD DATA INFILE lit les lignes dans un fichier texte et les insère à très grande
vitesse.

Syntaxe de REPLACE
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
VALUES ({expr | DEFAULT},...),(...),...
ou :
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name
SET col_name={expr | DEFAULT}, ...
ou :
REPLACE [LOW_PRIORITY | DELAYED]
[INTO] tbl_name [(col_name,...)]
SELECT ...
REPLACE fonctionne exactement comme INSERT, sauf que si une vieille ligne dans la table à la
même valeur qu'une nouvelle pour un index UNIQUE ou une PRIMARY KEY, la vielle ligne sera
effacée avant que la nouvelle ne soit insérée.

7
Syntaxe de SELECT
- Syntaxe de JOIN

MySQL supporte les syntaxes suivantes de JOIN pour une utilisation dans les SELECT :
reference_table, reference_table
reference_table [CROSS] JOIN reference_table
reference_table INNER JOIN reference_table condition_jointure
reference_table STRAIGHT_JOIN reference_table
reference_table LEFT [OUTER] JOIN reference_table condition_jointure
reference_table LEFT [OUTER] JOIN reference_table
reference_table NATURAL [LEFT [OUTER]] JOIN reference_table
{ OJ reference_table LEFT OUTER JOIN reference_table ON expr_conditionnelle
}
reference_table RIGHT [OUTER] JOIN reference_table condition_jointure
reference_table RIGHT [OUTER] JOIN reference_table
reference_table NATURAL [RIGHT [OUTER]] JOIN reference_table
où reference_table est définie de la manière suivante :
nom_de_table [[AS] alias] [USE INDEX (liste_de_clefs)] [IGNORE INDEX
(liste_de_clefs)]
et condition_jointure est définie comme suit :
ON expr_conditionnelle |
USING (column_list)
Généralement, vous ne devez avoir aucune condition, dans la partie ON, qui soit utilisée pour
spécifier les lignes que vous voulez obtenir en résultat. (il y a des exceptions à cette règle). Si
vous voulez restreindre les lignes résultantes, vous devez le faire dans la clause WHERE.
Notez que dans les versions antérieures à la 3.23.17, INNER JOIN ne prenait pas en compte
condition_jointure !

La dernière syntaxe de LEFT OUTER JOIN vue plus haut, n'existe que pour assurer la
compatibilité avec ODBC :
 On peut créer un alias sur une référence de table en utilisant nom_de_table AS
alias_name ou nom_de_table alias_name :
 mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
 -> WHERE t1.name = t2.name;
 La condition ON est de la même forme qu'une condition pouvant être utilisée dans la
clause WHERE.
 Si aucune ligne ne correspond dans la table de droite dans la partie ON ou USING du
LEFT JOIN, une ligne avec toutes les colonnes mises à NULL est utilisé en
remplacement. Vous pouvez utiliser ce fait pour trouver les enregistrements dans une
table qui n'ont pas de correspondances dans une autre :
 mysql> SELECT table1.* FROM table1
 -> LEFT JOIN table2 ON table1.id=table2.id
 -> WHERE table2.id IS NULL;
Cet exemple retourne toutes les lignes trouvées dans table1 avec une valeur de id qui
n'est pas présente dans table2 (autrement dit, toutes les lignes de table1 sans

7
correspondances dans la table table2). Cela demande que table2.id soit déclaré NOT
NULL, bien sur.

 La clause USING (column_list) recense la liste des colonnes qui doivent exister dans
les deux tables. Les clauses USING suivantes sont identiques :
 a LEFT JOIN b USING (c1,c2,c3)
 a LEFT JOIN b ON a.c1=b.c1 AND a.c2=b.c2 AND a.c3=b.c3
 La jointure de deux tables avec NATURAL [LEFT] JOIN est définie pour être
sémantiquement équivalent à un INNER JOIN ou un LEFT JOIN avec une clause USING
qui nomme toutes les colonnes qui existent dans les deux tables.
 INNER JOIN et , (virgule) sont sémantiquement équivalents. Les deux opèrent une
jointure totale sur les tables utilisées. Normalement, vous spécifiez les conditions de
jointure dans la clause WHERE.
 RIGHT JOIN fonctionne de fa¸on analogue à LEFT JOIN. Pour garder un code
facilement portable, il est recommandé d'utiliser les LEFT JOIN à la place des RIGHT
JOIN.

 STRAIGHT_JOIN est identique à JOIN, sauf que la table de gauche est toujours lues
avant celle de droite. Cela peut être utilisé dans les cas (rares) où l'optimiseur des
jointures place les tables dans le mauvais ordre.
A partir de la version 3.23.12 de MySQL, vous pouvez donner des indications à propos de
l'index à utiliser lors de la lecture d'informations d'une table. C'est utile si EXPLAIN montre
que MySQL utilise un mauvais index de la liste de ceux disponibles. En spécifiant USE INDEX
(liste_de_clefs), vous pouvez forcer MySQL à utiliser un index spécifique pour trouver
les enregistrements dans la table. Une alternative réside dans l'utilisation de IGNORE INDEX
(liste_de_clefs) pour dire à MySQL de ne pas utiliser certains index.

En MySQL 4.0.9, vous pouvez aussi utiliser la clause FORCE INDEX. Elle se comporte comme
USE INDEX (key_list) mais en supposant que les scan de tables seront très coûteux. En
d'autres termes, les scans de tables seront utilisés que s'il n'y a pas d'autres méthodes pour
trouver les lignes.
USE/IGNORE KEY sont des synonymes de USE/IGNORE INDEX.
Note : USE INDEX, IGNORE INDEX et FORCE INDEX affectent uniquement les index qui sont
utilisés lors du choix de la méthode de sélection des lignes dans la table, et comment faire une
jointure. Elles n'affectent pas l'utilisation finale de l'index dans les clauses ORDER BY ou
GROUP BY.

Quelques exemples :
mysql> SELECT *
FROM table1,table2 WHERE table1.id=table2.id;
mysql> SELECT *
FROM table1 LEFT JOIN table2 ON table1.id=table2.id;
mysql> SELECT *
FROM table1 LEFT JOIN table2 USING (id);
mysql> SELECT *
FROM table1 LEFT JOIN table2 ON table1.id=table2.id
-> LEFT JOIN table3 ON table2.id=table3.id;
mysql> SELECT * FROM table1 USE INDEX (key1,key2)
-> WHERE key1=1 AND key2=2 AND key3=3;
mysql> SELECT * FROM table1 IGNORE INDEX (key3)
-> WHERE key1=1 AND key2=2 AND key3=3;

7
- Syntaxe de UNION

SELECT ...
UNION [ALL | DISTINCT]
SELECT ...
[UNION [ALL | DISTINCT]
SELECT ...]
UNION est implémentée en MySQL 4.0.0.
UNION est utilisé pour combiner le résultat de plusieurs requêtes SELECT en un seul résultat.
Les colonnes listées dans la partie select_expression du SELECT doivent être du même
type. Les noms de colonnes utilisés dans le premier SELECT seront utilisé comme nom de
champs pour les résultats retournés.
Les commandes SELECT sont des sélections normales, mais avec les restrictions suivantes :
 Seule la dernière commande SELECT peut avoir une clause INTO OUTFILE.
 HIGH_PRIORITY ne peut être utilisée avec les commandes SELECT qui ne font pas
partie de l'UNION. Si vous la spécifiez pour la première commande SELECT, elle n'aura
pas d'effet. Si vous la spécifiez pour toute autre commandes SELECT suivante, une
erreur de syntaxe sera signalée.
Si vous n'utilisez pas le mot clef ALL pour l'UNION, toutes les lignes retournées seront uniques,
comme si vous aviez fait un DISTINCT pour l'ensemble du résultat. Si vous spécifiez ALL,
vous aurez alors tout les résultats retournés par toutes les commandes SELECT.
Si vous voulez utiliser un ORDER BY pour le résultat final de UNION, vous devez utiliser des
parenthèses :
(SELECT a FROM nom_de_table WHERE a=10 AND B=1 ORDER BY a LIMIT 10)
UNION
(SELECT a FROM nom_de_table WHERE a=11 AND B=2 ORDER BY a LIMIT 10)
ORDER BY a;
Note : vous ne pouvez pas mélanger les clauses UNION ALL et UNION DISTINCT dans la même
requête. Si vous utilisez ALL dans une des UNION, alors elle devra être utilisée partout.
Les types et longueurs des colonnes du jeu de résultat de UNION prend en compte les valeurs
lues dans tous les SELECT. Avant MySQL 4.1.1, une limitation de UNION est que seules les
valeurs du premier SELECT étaient utilisée pour déterminer le type de résultats, et leur taille.
Cela peut conduire à un raccourcissement de la valeur si, par exemple, le second SELECT
trouvait des valeurs plus grandes que le premier SELECT :
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+
| a |
| b |
+---------------+
Cette limitation a été supprimée en MySQL version 4.1.1 :
mysql> SELECT REPEAT('a',1) UNION SELECT REPEAT('b',10);
+---------------+
| REPEAT('a',1) |
+---------------+

7
| a |
| bbbbbbbbbb |
+---------------+

Syntaxe de SELECT

SELECT [STRAIGHT_JOIN]
[SQL_SMALL_RESULT] [SQL_BIG_RESULT] [SQL_BUFFER_RESULT]
[SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] [HIGH_PRIORITY]
[DISTINCT | DISTINCTROW | ALL]
select_expression,...
[INTO {OUTFILE | DUMPFILE} 'nom_fichier' export_options]
[FROM table_references
[WHERE where_definition]
[GROUP BY {unsigned_integer | nom_de_colonne | formula} [ASC | DESC],
...
[HAVING where_definition]
[ORDER BY {unsigned_integer | nom_de_colonne | formula} [ASC |
DESC] ,...]
[LIMIT [offset,] lignes]
[PROCEDURE procedure_name(argument_list)]
[FOR UPDATE | LOCK IN SHARE MODE]]

Syntaxe de TRUNCATE
TRUNCATE TABLE nom_de_table
Dans la version 3.23, TRUNCATE TABLE est équivalent à COMMIT ; DELETE FROM
nom_de_table.

TRUNCATE TABLE diffère de DELETE FROM ... des façons suivantes :


 Implémentée comme une destruction/création de table, ce qui accélère la suppression
des enregistrements.
 Ne respecte pas les transactions. Vous aurez des erreurs si vous avez une transaction
active ou une table protégée en écriture.
 Ne retourne pas le nombre de lignes effacées.
 Tant que le fichier de définition nom_de_table.frm est valide, la table peut être
recréée, me si les données ou un index a été corrompu.
 Le gestionnaire de table ne se souvient pas de la dernière valeur AUTO_INCREMENT
utilisée, mais peut commencer à compter depuis le début. C'est vrai pour les tables
MyISAM, ISAM et BDB.

TRUNCATE est une extension Oracle SQL. Cette commande a été ajoutée en MySQL 3.23.28,
même si dans les versions 3.23.28 à 3.23.32, le mot clé TABLE devait être omis.

Syntaxe de UPDATE
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
[ORDER BY ...]
[LIMIT row_count]

8
Syntaxe multi-tables :
UPDATE [LOW_PRIORITY] [IGNORE] tbl_name [, tbl_name ...]
SET col_name1=expr1 [, col_name2=expr2 ...]
[WHERE where_definition]
UPDATE met à jour des enregistrements dans une tables avec de nouvelles valeurs. La clause
SET indique les colonnes à modifier et les valeurs à leur donner. La clause WHERE, si fournie,
spécifie les enregistrements à mettre à jour. Sinon, tous les enregistrements sont mis à jour. Si
la clause ORDER BY est fournie, les enregistrements seront mis à jour dans l'ordre spécifié.
La commande UPDATE accepte les options suivantes :
 Si vous spécifiez le mot clef LOW_PRIORITY, l'exécution de l'UPDATE sera repoussé
jusqu'à ce que aucun client ne lise plus de la table.
 Si vous spécifiez le mot clef IGNORE, la mise à jour ne s'interrompra pas même si on
rencontre des problèmes d'unicité de clefs durant l'opération. Les enregistrements
posant problèmes ne seront pas mis à jour.
Si vous accédez à une colonne d'une table tbl_name dans une expression, UPDATE utilisera la
valeur courante de la colonne. Par exemple, la requête suivante ajoute une année à l'âge actuel
de tout le monde :
mysql> UPDATE persondata SET age=age+1;
Les requêtes UPDATE sont évaluées de gauche à droite. Par exemple, la requête suivante
double la valeur de la colonnes âge, puis l'incrémente :
mysql> UPDATE persondata SET age=age*2, age=age+1;
Si vous changez la valeur d'une colonne en lui spécifiant sa valeur actuelle, MySQL s'en
aperçoit et ne fait pas la mise à jour.
UPDATE retourne le nombre d'enregistrements ayant changé. Depuis la version 3.22 de
MySQL, la fonction mysql_info() de l'API C retourne le nombre de colonnes qui
correspondaient, le nombre de colonnes mises à jour et le nombre d'erreurs générées pendant
l'UPDATE.
Dans la version 3.23 de MySQL, vous pouvez utilisez le code LIMIT # pour vous assurer que
seul un nombre d'enregistrements bien précis est changé.
 Avant MySQL 4.0.13, LIMIT est une restrictions sur le nombre de lignes affectées.
Cette clause stoppe dès que row_count ont été trouvées par la clause WHERE.
 Depuis la version 4.0.13, LIMIT est une restriction sur le nombre de lignes trouvées.
La commande s'arrête une fois que row_count lignes ont été trouvées par la clause
WHERE, qu'elles ait été changées ou pas.

Ai une clause ORDER BY est utilisée (disponible depuis MySQL version 4.0.0), les lignes
seront modifiées selon cet ordre. Ce n'est vraiment utile qu'en conjonction avec LIMIT.
Depuis MySQL version 4.0.4, vous pouvez aussi faire des opérations de UPDATE qui couvrent
plusieurs tables :
UPDATE items,month SET items.price=month.price
WHERE items.id=month.id;

8
L'exemple ci-dessus montre une jointure interne, en utilisant la virgule comme séparateur,
mais une commande UPDATE multi table peut utiliser n'importe quel type de jointure autorisée
dans une commande SELECT, tel qu'un LEFT JOIN.
Note : vous ne pouvez pas utiliser ORDER BY ou LIMIT avec les UPDATE multi table.

8
8
Les problèmes avec les requêtes

Explication de la faille SQL Injection


Vous êtes webmaster et vous programmez en PHP et SQL ? Lisez ce message pour apprendre
comment éviter une des failles PHP les plus courantes.

Une injection SQL est en fait l'action de modifier une requête SQL via les variables
utilisateurs.
En gros, il s'agit de modifier la requête SQL via les variables contenant, par exemple, le login,
le pass, etc ...

Un exemple simple

Voici un exemple simple d'un injection SQL "basique" sur une requête de type select. (Pour
rappel, la requête select sert à retourner les données d'une table SQL.)
Imaginons que nous avons un site avec avec un panneau d'administration.
Nous avons deux input (un input est un champ libre qu'il faut compléter) : un pour le login et
un pour le pass.
Dans le script PHP de la page de vérification nous avons cette requête SQL:

SELECT * FROM admin WHERE login='$login' AND pass='$pass'

Explication : Ce code est chargé de sélectionner toutes les données de la table admin où les
login et pass sont égaux à ceux qu'à entré la personne voulant se connecter à l'espace amdin...

Une méthode d'exploiter cette faille consiste à donner aux variables login et pass des valeurs
qui retourneront true (vrai).
Par exemple, nous allons utiliser comme login et pass :

' OR '1'='1

Le lamer mal intentionné rentre ces valeurs dans les champs login et pass et presse le bouton
pour se connecter...

A l'origine, la requête devait donc comparer si les variables login et pass étaient les mêmes
que celles contenues dans la base MySQL.
Mais grâce aux conditions injectées dans les variables la requête SQL va être modifiée en
ceci:

SELECT * FROM admin WHERE login='' OR '1'='1' AND pass='' OR '1'='1'

1 étant toujours égal à 1, la condition est toujours remplie, et permet à la personne ayant
renseigné ces valeurs de se retrouver... admin.

D'autres méthodes existent, comme utiliser le caractère dièse #, qui est utilisé en SQL pour
commenter les scripts : c'est à dire que tout ce qui se trouve après le # n'est pas exécuté...

Comment s'en protéger ?

Pour éviter les désagréments que peuvent engendrer cette faille, il suffit d'utiliser la fonction
addslashes() de PHP, qui sert à rajouter des back-slashes (\) devant les caractères spéciaux,
comme les simple-quote (') et les dièses (#). Un back-slash permet "d'échapper" les caractères

8
spéciaux, c'est à dire qu'ils seront pas pris en compte comme faisant partie de la chaîne.

La requête SQL ressemblera donc à ceci :

SELECT * FROM admin WHERE login = '".addslashes($login)."' AND pass =


'".addslashes($pass)."'

8
Description de l’encodage des chaînes de caractères
Une chaîne est une séquence de caractères, entourée de guillemets simples ( ''' ) ou doubles
( '"' ). Exemples:
Si le serveur SQL est en mode ANSI_QUOTES , les chaînes littérales ne peuvent être mises
qu'entre guillemets simples. Une chaîne avec des guillemets double sera interprétée comme
un identifiant.

'une chaîne'
"une autre chaîne"
Depuis MySQL 4.1.1, les littéraux disposent d'une option de jeu de
caractères et de collation avec la clause COLLATE :

[_charset_name]'string' [COLLATE collation_name]


Exemples :

SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;
Pour plus d'informations sur ces formes de chaîne de caractères, voyez
Character String Literal Character Set and Collation .
A l'intérieur d'une chaîne, certains séquences de caractères ont une signification spéciale.
Chacune d'elle commence par un anti-slash ( '\' ), connu comme le caractère
d'échappement . MySQL reconnaît les séquences suivantes :
\0 Un 0 ASCII ( NUL ).
\' Un guillemet simple ( ''' ).
\" Un guillemet double ( '"' ).
\b Un effacement.
\n Une nouvelle ligne.
\r Un retour chariot.
\t Une tabulation.
ASCII(26) (Contrôle-Z). Ce caractère peut être encodé pour vous éviter des problèmes
\z avec Windows, vu qu'il équivaut à une fin de fichier sur cet OS. (ASCII(26) vous posera
des problèmes si vous utilisez mysql base < fichier .)
\\ Un anti-slash ( '\' ).
\% Un signe pourcentage littéral : '%' . Voir les notes ci-dessous.
\_ Un signe souligné littéral : '_' . Voir les notes ci-dessous.
Ces séquences sont sensibles à la casse. Par exemple, '\b' est interprétée comme un anti-
slash, mais '\B' est interprété comme la lettre 'B' .
Les caractères '\%' et '\_' sont utilisés pour rechercher des chaînes littérales '%' et '_' dans
un contexte d'expressions régulières. Sinon, ces caractères sont interprétés comme des
caractères joker. Fonctions de comparaison de chaînes de caractères . Notez que si vous
utilisez '\%' ou '\_' dans d'autres contextes, ces séquences retourneront '\%' et '\_' et non
'%' et '_' .

Il y a plusieurs façons d'intégrer un guillemet dans une chaîne :


 Un ''' à l'intérieur d'une chaîne entourée de ''' peut être noté '''' .
 Un '"' à l'intérieur d'une chaîne entourée de '"' peut être noté '""' .
 Vous pouvez faire précéder le guillemet par caractère d'échappement ( '\' ).

8
 Un guillemet simple ''' à l'intérieur d'une chaîne à guillemets doubles '"' n'a besoin
d'aucun traitement spécial (ni doublage, ni échappement). De même, aucun traitement
spécial n'est requis pour un guillemet double '"' à l'intérieur d'une chaîne à guillemets
simples ''' .
Le SELECT montré ici explique comment les guillemets et les échappements fonctionnent :
mysql> SELECT 'bonjour', '"bonjour"', '""bonjour""', 'bon''jour',
'\'bonjour';
+---------+-----------+-------------+----------+----------+
| bonjour | "bonjour" | ""bonjour"" | bon'jour | 'bonjour |
+---------+-----------+-------------+----------+----------+

mysql> SELECT "bonjour", "'bonjour'", "''bonjour''", "bon""jour",


"\"bonjour";
+---------+-----------+-------------+----------+----------+
| bonjour | 'bonjour' | ''bonjour'' | bon"jour | "bonjour |
+---------+-----------+-------------+----------+----------+

mysql> SELECT "Voilà\n3\nlignes";


+--------------------+
| Voilà
3
lignes |
+--------------------+
Si vous voulez insérer des données binaires dans un champ chaîne (comme un
BLOB ), les caractères suivants doivent être échappés :
NUL ASCII 0. Représentez le avec '\0' (un anti-slash suivi du caractère ASCII '0' ).
\ ASCII 92, anti-slash. A représenter avec '\\' .
' ASCII 39, guillemet simple. A représenter avec '\'' .
" ASCII 34, guillemet double. A représenter avec '\"' .
Lorsque vous écrivez des applications, toutes les chaînes qui risquent de contenir ces
caractères spéciaux doivent être protégés avant d'être intégrée dans la commande SQL. Vous
pouvez faire cela de deux manières différentes :
 passez la chaîne à une fonction qui protège les caractères spéciaux. Par exemple, en
langage C, vous pouvez utiliser la fonction mysql_real_escape_string() .
mysql_real_escape_string() . Au lieu de protéger explicitement tous les caractères, de
nombreuses interfaces MySQL fournissent un système de variables qui vous
permettent de mettre des marqueurs dans la requête, et de lier les variables à leur
valeur au moment de leur exécution. Dans ce cas, l'interface se charge de protéger les
caractères spéciaux pour vous.

8
Jeu de caractères et collation des chaînes littérales
Chaque chaîne de caractères littérale a un jeu de caractères et une collation qui ne peut pas
être nulle.
Une chaîne de caractères littérale peut avoir un spécificateur optionnel de jeu de caractères
optionnel et une clause COLLATE :

[_character_set_name]'string' [COLLATE collation_name]


Exemples :
SELECT 'string';
SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;
La simple commande SELECT 'string' utilise le jeu de caractères par défaut de la
connexion.
L'expression _character_set_name est formellement appelée un spécificateur ( introducer
). Elle indique à l'analyseur : "la chaîne qui va suivre utilise le jeu de caractère X .'' Cela a été
source de confusions par le passé; aussi nous insistons sur le fait qu'un spécificateur ne
provoque pas de conversion. C'est strictement une indication, qui ne change pas la valeur de
la chaîne. Un spécificateur est aussi autorisé avant des notations littérales hexadécimale et
numérique ( x'literal' et 0xnnnn ), et avant ? (qui est une substitution de paramètre lorsque
l'on utilise des commandes préparées avec une interface de langage de programmation).
Exemples :
SELECT _latin1 x'AABBCC';
SELECT _latin1 0xAABBCC;
SELECT _latin1 ?;
MySQL détermine le jeu de caractères et la collation de la façon suivante :
 Si, à la fois _X et COLLATE Y ont été précisés, alors le jeu de caractères est X et la
collation littérale est Y .
 Si _X est précisé mais que COLLATE ne l'est pas, alors le jeu de caractères de la chaîne
littérale est X et la collation est la collation par défaut du jeu de caractères X .
 Sinon, on utilise le jeu de caractères et la collation par défaut de la connexion.
Exemples:
 Une chaîne avec le jeu de caractères latin1 et la collation latin1_german1_ci :

SELECT _latin1'Müller' COLLATE latin1_german1_ci;


 Une chaîne avec le jeu de caractères latin1 et sa collation par défaut, c'est à dire
latin1_swedish_ci :

SELECT _latin1'Müller';
 Une chaîne avec le jeu de caractère et la collation connexion/littérale :

SELECT 'Müller';
Les introducteurs de jeux de caractères et la clause COLLATE sont implémentés selon les
spécifications standard SQL.

8
Procédures stockées et fonctions
Les procédures stockées et les fonctions sont de nouvelles fonctionnalités de MySQL version
5.0. Une procédure stockées est un jeu de commandes SQL qui réside sur le serveur. Une fois
qu'elle sont enregistrées, les clients n'ont pas besoin de soumettre chaque commande
individuellement, mais peuvent les lancer d'un seul coup.
Les procédures stockées fournissent un gain de performances, car moins d'informations sont
échangées entre le serveur et le client. En échange, cela augmente la charge du serveur, car ce
dernier doit réaliser plus de travail. Souvent, il y a de nombreux clients, mais peut de serveurs.
Les procédures stockées permettent aussi l'utilisation de bibliothèques et de fonctions sur le
serveur. Les langages de programmation modernes ont déjà intégré ce type de concept, et
l'utilisation de ces langages de programmation externes reste valable et utile, en dehors de la
base de données.
Quelques situations où les procédures stockées sont utiles :
 Lorsque plusieurs applications clientes sont écrites dans différents langages sur
différentes plates-formes, et utilisent le serveur comme point d'interaction.
 Lorsque la sécurité est prioritaire. Les banques, par exemple, utilisent les procédures
stockées pour toutes les opérations standards. Cela conduit à un environnement
cohérent et sécurisé, car les procédures assurent que les opérations sont correctement
faîtes et enregistrées. Dans une telle configuration, les applications et les utilisateurs
n'ont aucun accès direct aux tables, mais passent par des procédures stockées pre-
définies.
MySQL suit la syntaxe de la norme SQL:2003 pour les procédures stockées, qui est aussi
utilisée par IBM dans DB2. La compatibilité avec les autres langages de procédures stockées,
comme PL/SQL ou T-SQL sera ajouté ultérieurement.
L'implémentation des procédures stockées de MySQL est en cours de développement. Toutes
les syntaxes décrites dans ce chapitre sont supportées, et les limitations ou extensions sont
documentés lorsque c'est nécessaire.
Les procédures stockées requièrent la table proc dans la base mysql . Cette table est créée
durant l'installation de MySQL 5.0. Si vous passez à MySQL 5.0 depuis une ancienne version,
assurez-vous de bien mettre à jour vos tables de droits, et que la table proc existe.

CREATE PROCEDURE sp_name ([parameter[,...]])


[characteristic ...] routine_body

CREATE FUNCTION sp_name ([parameter[,...]])


[RETURNS type]
[characteristic ...] routine_body

paramètre :
  [ IN | OUT | INOUT ] param_name type

type :
  Any valid MySQL data type

characteristic:
    LANGUAGE SQL
  | [NOT] DETERMINISTIC
  | SQL SECURITY {DEFINER | INVOKER}
  | COMMENT string

8
routine_body :
  Commande(s) SQL valide(s)

Exemple

mysql> delimiter |

mysql> CREATE PROCEDURE simpleproc (OUT param1 INT)


    -> BEGIN
    ->   SELECT COUNT(*) INTO param1 FROM t;
    -> END
    -> |
Query OK, 0 rows affected (0.00 sec)

mysql> CALL simpleproc(@a)|


Query OK, 0 rows affected (0.00 sec)

mysql> SELECT @a|


+------+
| @a   |
+------+
| 3    |
+------+
1 row in set (0.00 sec)

L'exemple suivant est une fonction qui prend un paramètre, effectue une opération avec une
fonction SQL, et retourne le résultat :

mysql> delimiter |

mysql> CREATE FUNCTION bonjour (s CHAR(20)) RETURNS CHAR(50)


    -> RETURN CONCAT('Bonjour, ',s,'!');
    -> |
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT bonjour('le monde')|


+---------------------+
| bonjour('le monde') |
+---------------------+
| Bonjour, le monde!  |
+---------------------+
1 row in set (0.00 sec)

ALTER PROCEDURE et ALTER FUNCTION

ALTER PROCEDURE | FUNCTION sp_name [characteristic ...]

characteristic:
    NAME newname
  | SQL SECURITY {DEFINER | INVOKER}
  | COMMENT string
Cette commande peut être utilisée pour renommer une procédure stockée ou
une fonction, et pour en changer les caractéristiques. Plusieurs
modifications peut être spécifiées dans une commande ALTER PROCEDURE et
ALTER FUNCTION .

9
DROP PROCEDURE et DROP FUNCTION

DROP PROCEDURE | FUNCTION [IF EXISTS] sp_name


Cette commande sert à effacer une procédure stockée ou une fonction. C'est
à dire que la routine spécifiée est supprimée du serveur. La clause IF
EXISTS est une extension de MySQL. Elle permet d'éviter une erreur si la
routine n'existe pas. Une alerte est alors produite, et peut être lue avec
SHOW WARNINGS .

SHOW CREATE PROCEDURE et SHOW CREATE FUNCTION

SHOW CREATE PROCEDURE | FUNCTION sp_name


Cette commande est une extension MySQL. Similaire à SHOW CREATE TABLE ,
elle retourne la chaîne exacte qui permet de recréer la routine.

9
Les vues

Les vues (y compris les vues modifiables) sont implémentées en version 5 de MySQL.
Création ou modification de vues avec les commandes CREATE VIEW ou ALTER VIEW
 Destruction de vues avec DROP VIEW
 Affichage des méta-données de vues avec SHOW CREATE VIEW

Syntaxe de CREATE VIEW

CREATE [OR REPLACE] [ALGORITHM = {MERGE | TEMPTABLE}] VIEW view_name


[(column_list)] AS select_statement [WITH [CASCADED | LOCAL] CHECK
OPTION]
Cette commande crée une nouvelle vue, ou remplace une vue existante si la clause OR
REPLACE est fournie. La clause select_statement est une commande SELECT qui fournit la
définition de la vue. La liste optionnelle de colonnes peut être fournie pour définir
explicitement les noms des colonnes.
WITH CHECK OPTION, if given, is parsed and ignored.
Une vue peut être créée par différents types de commandes SELECT. Par exemple, SELECT
peut faire référence à une table seule, une jointure ou une UNION. La commande SELECT peut
ne pas faire de référence à une table. Les exemples suivants définissent une vue qui
sélectionne 2 colonnes dans une table, et leur applique une transformation :
mysql> CREATE TABLE t (qty INT, price INT);
mysql> INSERT INTO t VALUES(3, 50);
mysql> CREATE VIEW v AS SELECT qty, price, qty*price AS value FROM t;
mysql> SELECT * FROM v;
+------+-------+-------+
| qty | price | value |
+------+-------+-------+
| 3 | 50 | 150 |
+------+-------+-------+
Par défaut, la vue est placée dans la base de données par défaut. Pour créer une vue
explicitement dans une base de données, spécifiez le nom de la base de données lors de la
création : db_name.view_name.
mysql> CREATE VIEW test.v AS SELECT * FROM t;

Syntaxe ALTER VIEW


ALTER VIEW view_name [(column_list)] AS select_statement
Cette commande modifie la définition d'une vue. select_statement est le même que pour
CREATE VIEW.

9
Syntaxe DROP VIEW
DROP VIEW [IF EXISTS]
view_name [, view_name] ...
[RESTRICT | CASCADE]
DROP VIEW supprime une ou plusieurs vues. Vous devez avoir les droits de DROP pour chaque
vue.
Vous pouvez utiliser le mot clé IF EXISTS pour éviter l'affichage d'un message d'alerte
lorsque les vues n'existent pas. Lorsque cette clause est utilisée, une NOTE est générée pour
chaque vue inexistante. RESTRICT et CASCADE, si utilisés, sont analysés mais ignorés.

Syntaxe SHOW CREATE VIEW


SHOW CREATE VIEW view_name
Cette commande montre la commande CREATE VIEW qui créera la vue spécifiée.
mysql> SHOW CREATE VIEW v;
+-------+----------------------------------------------------+
| Table | Create Table |
+-------+----------------------------------------------------+
| v | CREATE VIEW `test`.`v` AS select 1 AS `a`,2 AS `b` |
+-------+----------------------------------------------------+

9
Les déclencheurs
Le support rudimentaire des déclencheurs (triggers) est inclus dans les versions de MySQL à
partir de la version 5.0.2. Un déclencheur est un objet de base de données nommé, qui est
associé à une table et qui s'active lorsqu'un événement particulier survient dans une table. Par
exemple, les commandes suivantes configurent une table, ainsi qu'un déclencheur pour les
commandes INSERT sur cette table. Le déclencheur va effectuer la somme des valeurs insérées
dans une des colonnes :
mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
-> FOR EACH ROW SET @sum = @sum + NEW.amount;

Syntaxe de CREATE TRIGGER


CREATE TRIGGER trigger_name trigger_time trigger_event
ON tbl_name FOR EACH ROW trigger_stmt
Un déclencheur est un objet de base de données associé à une table, qui s'active lorsqu'un
événement particulier survient.
Le déclencheur est associé à la table appelée tbl_name. tbl_name doit faire référence à une
table permanente. Vous ne pouvez pas associer un déclencheur avec une table TEMPORARY ou
une vue.
trigger_time est le moment d'action du déclencheur. Il peut être BEFORE (avant) ou AFTER
(après), pour indiquer que le délencheur s'active avant ou après la commande qui le
déclenche.
trigger_event indique le type de commande qui active le déclencheur. Il peut valoir
INSERT, UPDATE ou DELETE. Par exemple, un déclencheur BEFORE pour une commande
INSERT peut être utilisé pour vérifier les valeurs avant leur insertion dans la table.

Il ne peut pas y avoir deux déclencheurs pour une même table avec les mêmes configurations
de moment et de commande. Par exemple, vous ne pouvez pas avor deux déclencheurs
BEFORE UPDATE pour la même table. Mais vous pouvez avoir un déclencheur BEFORE UPDATE
et un déclencheur BEFORE INSERT, ou un déclencheur BEFORE UPDATE et un déclencheur
AFTER UPDATE.

trigger_stmt est la commande a exécuter lorsque le déclencheur s'active. Si vous voulez


utiliser plusieurs commandes, utilisez les agrégateurs BEGIN ... END. Cela vous permet aussi
d'utiliser les mêmes codes que ceux utilisés dans des procédures stockées.
Note : actuellement, les déclencheurs ont les mêmes limitations que les procédures stockées :
ils ne peuvent pas contenir de références directes aux tables via leur nom. Cette limitation sera
levée dès que possible.
Cependant, dans la commande d'activation d'un déclencheur, vous pouvez faire référence aux
colonnes dan la table associée au déclencheur en utilisant les mots OLD et NEW. OLD.col_name
faire référence à une colonne d'une ligne existante avant sa modification ou son effacement.
NEW.col_name faire référence à une colonne d'une ligne après insertion ou modification.

L'utilisation de SET NEW.col_name = value requiert le droit de UPDATE sur la colonne.


L'utilisation de SET value = NEW.col_name requiert le droit de SELECT sur la colonne.

9
La commande CREATE TRIGGER requiert le droit de SUPER.

Syntaxe de DROP TRIGGER


DROP TRIGGER tbl_name.trigger_name
Supprime un déclencheur. Le nom du déclencheur doit inclure le nom de la table, car chaque
déclencheur est associé à une table particulière.
La commande DROP TRIGGER requiert le droit de SUPER.

Utiliser les déclencheurs


Le support des déclencheurs (aussi appelés trigger) a commencé avec MySQL 5.0.2.
Actuellement, le support des déclencheurs est rudimentaire, et il y existe des limitations dans
les fonctionnalités. Cette section présente comment utiliser les déclencheurs et quelles sont
leurs limitations actuelles.
Un déclencheur est une objet de base de données qui est associé à une table, et qui s'active
lorsqu'un événement spécifié survient dans la table. Il est possible d'utiliser les déclencheurs
pour effectuer des vérifications de valeurs avant insertion, ou pour effectuer des calculs de
macrodonnées après une modifications d'une table.
Un déclencheur est associé à une table, et est défini pour s'activer lorsqu'une commande
INSERT, DELETE ou UPDATE s'exécute sur la table. Un déclencheur peut être configuré pour
s'activer avant ou après l'événement. Par exemple, déclencheur peut être appelé avant que la
ligne soit effacée ou modifié dans la table.
Pour créer un déclencheur ou l'effacer, utilisez les commandes CREATE TRIGGER ou DROP
TRIGGER. La syntaxe de ces commandes est décrite dans les sections Section 20.1, « Syntaxe
de CREATE TRIGGER » et Section 20.2, « Syntaxe de DROP TRIGGER ».
Voici un exemple simple qui associe un déclencheur avec une table pour les commandes
INSERT. Il sert d'accumulateur des sommes insérées dans une des colonnes de la table.

La commande suivante crée la table et le déclencheur :


mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2));
mysql> CREATE TRIGGER ins_sum BEFORE INSERT ON account
-> FOR EACH ROW SET @sum = @sum + NEW.amount;
La commande CREATE TRIGGER crée un déclencheur appelé ins_sum qui est associé avec la
table account. Il inclut aussi des clauses pour spécifier le moment d'activation, l'événement et
l'action du déclencheur :
 Le mot réservé BEFORE (avant, en anglais) indique le moment d'activation. Dans ce
cas, le déclencheur sera activé avant l'insertion des lignes dans la table. L'autre mot
réservé est AFTER (Après, en anglais).
 Le mot réservé INSERT indique l'événement qui active le déclencheur. Dans l'exemple,
le déclencheur s'active lors des commandes INSERT. Vous pouvez créer des
déclencheur pour les commandes DELETE et UPDATE.
 La commande qui suit le mot clé FOR EACH ROW définit la commande à exécuter à
chaque fois que le déclencheur s'active, ce qui arrive à dès qu'une ligne est insérée.
Dans l'exemple, la commande du déclencheur est un simple SET qui accumule la
somme des valeurs insérées dans les colonnes amount. La commande utiliser la valeur

9
de la colonne avec la syntaxe NEW.amount (en anglais, nouvelle.montant) ce qui
signifie ``la valeur de la colonne amount qui va être insérée''.
Pour utiliser le déclencheur, initialisé l'accumulateur à zéro, puis exécutez une commande
INSERT et voyez la valeur finale de l'accumulateur :
mysql> SET @sum = 0;
mysql> INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00);
mysql> SELECT @sum AS 'Total amount inserted';
+-----------------------+
| Total amount inserted |
+-----------------------+
| 1852.48 |
+-----------------------+
Dans ce cas, la valeur de @sum après la commande INSERT est 14.98 + 1937.50 - 100 soit
1852.48.

Pour détruire un déclencheur, utilisez la commande DROP TRIGGER. Le nom du déclencheur


doit inclure le nom de la table :
mysql> DROP TRIGGER ins_sum;
Comme le déclencheur est associé avec une table, vous ne pouvez pas avoir plusieurs
déclencheurs sur une même table qui portent le même nom. Soyez aussi conscients que
l'espace de noms des déclencheurs risque de changer à l'avenir. C'est à dire que l'unicité des
noms de déclencheurs par table risque d'être étendu à l'unicité de déclencheurs au niveau du
serveur. Pour faciliter la compatibilité ascendante, essayez d'utiliser des noms de déclencheurs
qui soient uniques dans toute la base.
En plus du fait que les noms de déclencheurs doivent être uniques pour une table, il y a
d'autres limitations sur le type de déclencheurs que vous pouvez mettre en place. En
particulier, vous ne pouvez pas avoir deux déclencheurs qui ont le même moment d'activation
et le même événement d'activation. Par exemple, vous ne pouvez pas définir deux
déclencheurs BEFORE INSERT et deux déclencheurs AFTER UPDATE pour la même table. Ce
n'est probablement pas une limitation importate, car il est possible de définir un déclencheur
qui exécute plusieurs commandes en utilisant une commande complexe, encadrée par les mots
BEGIN … END, après le mot clé FOR EACH ROW. Un exemple vous est présenté ultérieurement
dans cette section.
Il y a aussi des limitations dans ce qui peut apparaître dans la commande que le déclencheur
peut éxecuter lorsqu'il est activé :
 Le déclencheur ne peut pas faire référence directe aux tables par leur nom, y copmris
la table à laquelle il est associé. Par contre, vous pouvez utiliser les mots clés OLD
(ancien en anglais) et NEW (nouveau en anglais). OLD fait référence à la ligne existante
avant la modification ou l'effacement. NEW faire référence à la nouvelle ligne insérée
ou à la ligne modifiée.
 Le déclencheur ne peut pas exécuter de procédures avec la commande CALL. Cela
signifie que vous ne pouvez pas contourner le problèmes des noms de tables en
appelant une procédure stockée qui utilise les noms de tables.
 Le déclencheur ne peut pas utiliser de commande qui ouvre ou ferme une transaction
avec START TRANSACTION, COMMIT ou ROLLBACK.

9
Les mots clé OLD et NEW vous permette d'accéder aux colonnes dans les lignes affectées par le
déclencheur. OLD et NEW ne sont pas sensibles à la casse. Dans un déclencheur INSERT, seul
NEW.col_name peut être utilisée : il n'y a pas d'ancienne ligne. Dans un déclencheur DELETE,
seul la valeur OLD.col_name peut être utilisée : il n'y a pas de nouvelle ligne. Dans un
déclencheur UPDATE, vous pouvez utiliser OLD.col_name pour faire référence aux colonnes
dans leur état avant la modification, et NEW.col_name pour faire référence à la valeur après la
modifcation.
Une colonne identifiée par OLD est en lecture seule. Vous pouvez lire sa valeur mais vous ne
pouvez pas la modifier. Une colonne identifiée avec la valeur NEW peut être lue si vous avez
les droits de SELECT dessus. Dans un déclencheur BEFORE, vous pouvez aussi changer la
valeur avec la commande SET NEW.col_name = value si vous avez les droits de UPDATE.
Cela signifie que vous pouvez utiliser un déclencheur pour modifier les valeurs insérées dans
une nouvelle ligne ou les valeurs modifiées.
Dans un déclencheur BEFORE, la valeur NEW d'une colonne AUTO_INCREMENT vaut 0, et non pas
le nombre séquentiel automatiquement généré car ce nombre sera généré lorsque la ligne sera
réellement insérée.
OLD et NEW sont des extensions de MySQL aux déclencheurs.
En utilisant la syntaxe BEGIN … END, vous pouvez définir un déclencheur qui exécute
plusieurs commandes. À l'intérieur d'un bloc BEGIN, vous pouvez aussi utiliser les autres
syntaxes autorisées dans les routines stockées, telles que les conditions et les boucles.
Cependant, tout comme pour les procédures stockées, lorsque vous définissez un déclencheur
qui s'exéctue sur plusieurs commandes, il est nécessaire de redéfinir le délimiteur de
commande si vous saisissez le déclencheur à l'aide d'un utilisatier en ligne de commande tel
que mysql pour que vous puissiez utiliser le caractère ‘;’ à l'intérieur de la définition.
L'exemple ci-dessous illustre ces points. Il définit un déclencheur UPDATE qui vérifie la valeur
d'une ligne avant sa modification, et s'arrange pour que les valeurs soient dans l'intervalle de 0
à 100. Cela doit être fait avant (BEFORE) la modification, pour que la valeur soit vérifié avant
d'être utilisée :
mysql> delimiter //
mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON account
-> FOR EACH ROW
-> BEGIN
-> IF NEW.amount < 0 THEN
-> SET NEW.amount = 0;
-> ELSEIF NEW.amount > 100 THEN
-> SET NEW.amount = 100;
-> END IF;
-> END//
mysql> delimiter ;
Il vous viendra surement à l'esprit qu'il serait plus facile de définir une procédure stockée
séparément, pour l'invoquer depuis le déclencheur grâce à un simple appel à CALL. Cela serait
surement avantageux si vous voulez appeler la même routine depuis plusieurs déclencheurs.
Cependant, les déclencheurs ne peuvent pas utiliser la commande CALL. Vous devez
absolument réécrire les commandes composées de chaque commande CREATE TRIGGER que
vous voulez utiliser.

9
Jeux de caractères et Unicode

Jeux de caractères et collation : généralités


Un jeu de caractères est un ensemble de symboles et de codes. Une collation est un
ensemble de règles permettant les comparaisons de caractères dans un jeu. Pour rendre ces
définitions plus concrètes, voici un exemple avec un alphabet imaginaire.
Supposons que nous avons un alphabet de 4 lettres : ‘A’, ‘B’, ‘a’, ‘b’. Nous assignons à chaque
lettre un nombre comme ceci : ‘A’ = 0, ‘B’ = 1, ‘a’ = 2, ‘c’ = 3. La lettre ‘A’ est un symbole, le
chiffre 0 est le code de ‘A’, et la combinaison des quatre lettres et de leur code forme le jeu de
caractères.
Maintenant, supposons que nous voulions comparer deux chaînes de caractères : ‘A’ et ‘B’. Le
plus simple pour cela est de regarder leurs codes : 0 pour ‘A’ et 1 pour ‘B’, et comme 0 est
inférieure à 1, nous pouvons dire que ‘A’ est plus petit que ‘B’. Ce que nous venons de faire
est une collation pour notre jeu de caractères. la collation est un ensemble de règle, qui se
résume à ceci dans notre cas : ``compare les codes''. Cette règle est la plus simple collation
binaire.
Si nous devons différentier les majuscules des minuscules, nous aurons au moins deux règles :
(1) traiter les minuscules ‘a’ et ‘b’ comme des équivalents de ‘A’ et ‘B’; (2) puis comparer
leurs codes respectifs. Nous appelons cette règle une collation sensible à la casse. C'est un
peu plus complexe que la règle précédente.
En réalité, la plupart des jeux de caractères ont de nombreux caractères : ce n'est pas
simplement ‘A’ et ‘B’ mais des alphabets entiers, ou des systèmes d'écriture orientaux avec des
milliers de caractères, incluant des caractères spéciaux et la ponctuation. Dans la vraie vie,
une collation a de très nombreuses règles, concernant la sensibilité à la casse ou encore
l'insensibilité aux accents (un accent est une marque attachée aux lettres comme le ‘Ö’)
allemand) et les caractères multiples comme le e dans l'o ‘œ’ = ‘oe’ de l'une des deux
collations allemandes.
MySQL 4.1 peut faire cela pour vous :
 Stocker des chaînes dans différents jeux de caractères
 Comparer des chaînes à l'aide de différentes collations
 Mélanger différents jeux de caractères et collations sur le même serveur, la même base
ou même la même table.
 Permettre la spécification du jeu de caractère et de la collation à n'importe quel niveau
Sous cet angle, MySQL 4.1 est bien plus souple que MySQL 4.0 et que les autres bases de
données. Mais, pour pouvoir utiliser ces nouvelles fonctionnalités, vous devez savoir quels
sont les jeux de caractères et les collations disponibles, comment les modifier ou comment les
utiliser avec les opérateurs.

9
Jeux de caractères et collation dans MySQL
Un jeu de caractères a toujours au moins une collation. Pour lister les jeux de caractères
disponibles, utilisez la commande SHOW CHARACTER SET :
mysql> SHOW CHARACTER SET;
+----------+-----------------------------+---------------------+
| Charset | Description | Default collation |
+----------+-----------------------------+---------------------+
| big5 | Big5 Traditional Chinese | big5_chinese_ci |
| dec8 | DEC West European | dec8_swedish_ci |
| cp850 | DOS West European | cp850_general_ci |
| hp8 | HP West European | hp8_english_ci |
| koi8r | KOI8-R Relcom Russian | koi8r_general_ci |
| latin1 | ISO 8859-1 West European | latin1_swedish_ci |
| latin2 | ISO 8859-2 Central European | latin2_general_ci |
...
Le résultat inclut en réalité une autre colonne, qui n'est pas présentée dans cette page, à des
fins de publication.
Tout jeu de caractères a toujours au moins une collation. Il peut en avoir plusieurs.
Pour lister les collations d'un jeu de caractères, utilisez la commande SHOW COLLATION. Par
exemple, pour afficher les collations du jeu de caractères latin1 (``ISO-8859-1 West
European''), utilisez cette commande, et recherchez les noms de collation qui commencent par
latin1 :
mysql> SHOW COLLATION LIKE 'latin1%';
+-------------------+---------+----+---------+----------+---------+
| Collation | Charset | Id | Default | Compiled | Sortlen |
+-------------------+---------+----+---------+----------+---------+
| latin1_german1_ci | latin1 | 5 | | | 0 |
| latin1_swedish_ci | latin1 | 8 | Yes | Yes | 1 |
| latin1_danish_ci | latin1 | 15 | | | 0 |
| latin1_german2_ci | latin1 | 31 | | Yes | 2 |
| latin1_bin | latin1 | 47 | | Yes | 1 |
| latin1_general_ci | latin1 | 48 | | | 0 |
| latin1_general_cs | latin1 | 49 | | | 0 |
| latin1_spanish_ci | latin1 | 94 | | | 0 |
+-------------------+---------+----+---------+----------+---------+
Les collations latin1 ont les significations suivantes :
Collation Signification
latin1_bin Binaire, suivant l'encodage latin1
latin1_danish_ci Danois/Norvégien
latin1_general_ci Multilingue
latin1_general_cs Multilingue, sensible à la casse
latin1_german1_ci Allemand DIN-1
latin1_german2_ci Allemand DIN-2
latin1_spanish_ci Espagnol moderne
latin1_swedish_ci Suédois/Finlandais
Les collations ont les caractéristiques suivantes :
 Deux jeux de caractères différents ne peuvent pas avoir la même collation.

9
 Chaque jeu de caractère a une collation qui est la collation par défaut. Par exemple, la
collation par défaut de latin1 est latin1_swedish_ci.
 Il y a une convention pour les noms de collation : elles commencent par le nom du jeu
de caractères auquel elles sont associées; elles incluent généralement un nom de
langue, et finissent par _ci (case insensitive, insensible à la casse), _cs (case
sensitive, sensible à la casse), _bin (binaire), ou _uca (Algorithme Unicode,
Unicode Collation Algorithm).

1
Déterminer le jeu de caractères et la collation par défaut
Il y a une configuration par défaut pour chaque jeu de caractères et collation à quatre
niveaux : serveur, base de données, table, connexion. La description suivante peut paraître
complexe, mais il a été montré qu'en pratique la mise par défaut par niveaux multiples mène à
des résultats simples et évidents.

Jeu de caractères et collation serveur


Le serveur MySQL a un jeu de caractères et une collation serveur, qui ne peuvent pas être
nuls.
MySQL détermine le jeu de caractères et la collation serveurs comme suit :
 En fonction de l'option de configuration active quand le serveur démarre.
 En fonction des valeurs de configuration à l'exécution.
A ce niveau, la décision est simple. Le jeu de caractères serveur et sa collation dépendent des
options que vous utilisez au démarrage de mysqld. Vous pouvez utiliser --default-
character-set=character_set_name comme jeu de caractères et vous pouvez en même
temps ajouter --default-collation=collation_name pour la collation. Si vous n'indiquez
pas de jeu de caractères, cela revient à dire --default-character-set=latin1. Si vous
indiquez un jeu de caractères (par exemple, latin1) mais pas de collation, cela revient à dire :
--default-charset=latin1 --collation=latin1_swedish_ci car latin1_swedish_ci
est la collation par défaut de latin1. par conséquent, les trois commandes suivantes ont
toutes le même effet :
shell> mysqld
shell> mysqld --default-character-set=latin1
shell> mysqld --default-character-set=latin1
--default-collation=latin1_swedish_ci
Une façon de changer la configuration par défaut est de recompiler MySQL. Si vous voulez
changer le jeu de caractères et la collation par défaut du serveur quand vous compilez depuis
les sources, utilisez --with-character-set et --with-collation comme arguments pour
configure. Par exemple :
shell> ./configure --with-character-set=latin1
ou :
shell> ./configure --with-character-set=latin1
--with-collation=latin1_german1_ci
mysqld et configure vérifient aussi que la combinaison jeu de caractères/collation est valide.
Ces programmes affichent un message erreur et se terminent si la combinaison n'est pas
valide.

Jeu de caractères et collation de base de données


Toute base de données a un jeu de caractères de base de données et une collation de base de
données, qui ne peuvent pas être nulles. Les commandes CREATE DATABASE et ALTER
DATABASE permettent de utiliser optionnellement ces deux attributs :
CREATE DATABASE db_name
[DEFAULT CHARACTER SET character_set_name [COLLATE collation_name]]

1
ALTER DATABASE db_name
[DEFAULT CHARACTER SET character_set_name [COLLATE collation_name]]
Exemple :
CREATE DATABASE db_name
DEFAULT CHARACTER SET latin1 COLLATE latin1_swedish_ci;
MySQL choisit le jeu de caractères et la collation de base de données comme ceci :
 Si les deux clauses CHARACTER SET X et COLLATE Y ont été spécifiées, alors leurs
valeurs sont utilisées.
 Si CHARACTER SET X a été spécifiée sans COLLATE, alors le jeu de caractères est X et sa
collation par défaut.
 Sinon, le jeu de caractères et la collation par défaut du serveur sont utilisés.
La syntaxe MySQL CREATE DATABASE ... DEFAULT CHARACTER SET ... est analogue à la
syntaxe du standard SQL CREATE SCHEMA ... CHARACTER SET .... Il est donc possible de
créer des bases de données avec différents jeux de caractères et collations, sur le même
serveur MySQL.
Le jeu de caractères et la collation sont utilisées comme valeur par défaut pour les tables,
lorsque ces informations ne sont pas spécifiées dans les commandes CREATE TABLE. Elles
n'ont pas d'autres utilité.

Jeu de caractères de tables et collation


Chaque table a un jeu de caractères et une collation de table qui ne peut pas être nulle. Les
commandes CREATE TABLE et ALTER TABLE ont maintenant des options pour préciser le jeu
de caractères et la collation :
CREATE TABLE table_name ( column_list )
[DEFAULT CHARACTER SET character_set_name [COLLATE collation_name]]

ALTER TABLE table_name


[DEFAULT CHARACTER SET character_set_name] [COLLATE collation_name]
Exemple :
CREATE TABLE t1 ( ... ) DEFAULT CHARACTER SET latin1 COLLATE
latin1_danish_ci;
MySQL choisit le jeu de caractère et la collation :
 Si CHARACTER SET X et COLLATE Y sont précisés tous les deux, alors on adopte le jeu
de caractères X et la collation Y.
 Si CHARACTER SET X était précisé sans COLLATE, alors on adopte le jeu de caractères X
et sa collation par défaut.
 Sinon, le jeu de caractères et la collation de la base de données sont utilisés.
Le jeu de caractères et la collation sont utilisés comme valeurs par défaut si ces deux attributs
ne sont pas précisés par la définition d'une colonne. Le jeu de caractères et la collation sont
des extensions MySQL : il n'y a pas de telles fonctionnalités en SQL standard.

1
Jeu de caractères de colonne et collation
Chaque colonne de ``character'' (c'est à dire les colonnes de type CHAR, VARCHAR, ou TEXT) a
un jeu de caractères de colonne et une collation de colonne qui ne peut pas être nulle. La
syntaxe de définition de colonne a maintenant des clauses optionnelles pour préciser le jeu de
caractères de colonne et la collation :
column_name {CHAR | VARCHAR | TEXT} (column_length)
[CHARACTER SET character_set_name [COLLATE collation_name]]
Exemple :
CREATE TABLE Table1
(
column1 VARCHAR(5) CHARACTER SET latin1 COLLATE latin1_german1_ci
);
MySQL choisit le jeu de caractères et la collation de colonne comme ceci :
 Si CHARACTER SET X et COLLATE Y sont spécifiés, alors le jeu de caractères est X et la
collation Y.
 Si CHARACTER SET X a été spécifié sans la clause COLLATE, alors le jeu de caractères
est X et la collation est sa collation par défaut.
 Sinon, MySQL utilise le jeu de caractères et la collation par défaut.
Les clauses CHARACTER SET et COLLATE font partie du standard SQL.

1
Exemples d'attribution de jeu de caractères et collation
Les exemples suivants montrent comment MySQL détermine le jeu de caractère par défaut et
les valeurs de collation.
Exemple 1 : définition de table et colonne
CREATE TABLE t1
(
c1 CHAR(10) CHARACTER SET latin1 COLLATE latin1_german1_ci
) DEFAULT CHARACTER SET latin2 COLLATE latin2_bin;
Vous avez ici une colonne avec un jeu de caractères latin1 et une collation
latin1_german1_ci. La définition est explicite, c'est donc direct. Veuillez noter qu'il n'y a
pas de problème à stocker une colonne latin1 dans une table latin2.
Exemple 2 : définition de table et colonne
CREATE TABLE t1
(
c1 CHAR(10) CHARACTER SET latin1
) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;
Cette fois-ci nous avons une colonne avec un jeu de caractères latin1 et une collation par
défaut. Maintenant, bien que cela puisse sembler naturel, la collation par défaut n'est pas
spécifiée au niveau de la table. A la place, comme la collation par défaut de latin1 est
toujours latin1_swedish_ci, la colonne c1 aura la collation latin1_swedish_ci (et non
latin1_danish_ci).

Exemple 3 : définition de table et colonne


CREATE TABLE t1
(
c1 CHAR(10)
) DEFAULT CHARACTER SET latin1 COLLATE latin1_danish_ci;
Nous avons une colonne avec un jeu de caractères par défaut et une collation par défaut. Dans
ces conditions, MySQL regarde au niveau de la table pour déterminer le jeu de caractères et la
collation. Par conséquent le jeu de caractères de la colonne c1 est latin1 et sa collation est
latin1_danish_ci.

Exemple 4: définition de base, table et colonne


CREATE DATABASE d1 DEFAULT CHARACTER SET latin2 COLLATE latin2_czech_ci;
USE d1;
CREATE TABLE t1
(
c1 CHAR(10)
);
Nous créons une colonne sans préciser son jeu de caractère ni sa collation. Nous ne spécifions
pas non plus de jeu de caractères ni de collation au niveau de la table. Dans ces conditions,
MySQL cherche au niveau de la base de données. (La configuration de la base de donnée
devient celle de la table, et par conséquent celle de la colonne.) Donc le jeu de caractères de
colonne c1 est latin2 et sa collation est latin2_czech_ci.

Jeux de caractères et collations de connexion


Plusieurs variables contrôlent les jeux de caractères et collation du système pour un client.
Certaines ont déjà été mentionnées précédemment :

1
 Le jeu de caractères et la collation sont disponibles dans les variables
character_set_server et collation_server.

 Le jeu de caractères et la collation par défaut de la base de données sont disponibles


dans character_set_database et collation_database.
D'autres variables et collations sont impliquées dans la gestion des connexions entre un client
et un serveur. Chaque client a un jeu de caractères et une collation attitrés.
Pensez à ce qu'est une "connexion" : c'est ce que vous faites lorsque vous vous connectez au
serveur. Le client envoie des SQL commandes comme des requêtes, au travers de la
connexion, vers le serveur. Le serveur renvoie des réponses, comme des jeux de résultats, au
client, au travers de la connexion. Ceci mène à plusieurs questions telles que :
 Dans quel jeu de caractères est la requête lorsqu'elle quitte le client?
Le serveur utilise la variable character_set_client pour connaître le jeu de
caractères des requêtes émises par le client.
 dans quel jeu de caractère le serveur devrait il traduire la requête après l'avoir re¸ue?
Pour cela, character_set_connection et collation_connection sont utilisées par
le serveur. Il convertit les requêtes envoyées par le client de character_set_client
en character_set_connection (hormis les chaînes littérales qui sont précédées de
_latin1 ou _utf8). collation_connection est importante pour les comparaisons de
chaînes littérales. Pour les comparaisons de chaînes avec des colonnes, la collation de
la colonne a la priorité.
 Dans quel jeu de caractères le serveur devrait-il traduire les résultats ou messages
d'erreur avant de les renvoyer au client?
La variable character_set_results indique le jeu de caractères que le serveur
utilise pour retourner les résultats aux clients. Cela inclut les données telles que les
noms de colonnes ou les meta-données.
Vous pouvez configurez ces options là, ou vous pouvez vous fier aux configurations par
défaut (auquel cas vous pouvez sauter cette section).
Il y a deux commandes qui permettent de modifier le jeu de caractères de la connexion :
SET NAMES 'charset_name'
SET CHARACTER SET charset_name
SET NAMES indique ce qui est dans la commande SQL que le client envoie. Par conséquent,
SET NAMES cp1251 indique au serveur : ``les futurs messages fournis par ce client seront dans
le jeu de caractères cp1251'' et le serveur est libre de les traduire dans son propre jeu de
caractères, éventuellement.
La commande SET NAMES 'x' est équivalente à ces trois commandes :
mysql> SET character_set_client = x;
mysql> SET character_set_results = x;
mysql> SET character_set_connection = x;
SET CHARACTER SET est similaire, mais spécifie le jeu de caractères et la collation par défaut
des bases pour la connexion. Une commande SET CHARACTER SET x est équivalente à :
mysql> SET character_set_client = x;
mysql> SET character_set_results = x;

1
mysql> SET collation_connection = @@collation_database;
Lorsque vous exécutez la commande SET NAMES ou SET CHARACTER SET, vous changez aussi
la collation de la connexion. Cependant, la collation de connexion existe uniquement par
cohérence. Généralement sa valeur n'a pas d'importance.
Avec le client mysql, il n'est pas nécessaire d'exécuter la commande SET NAMES à chaque
démarrage. Vous pouvez ajouter l'option --default-character-set-name dans la ligne de
commande de mysql, ou dans le fichier d'options. Par exemple, la ligne suivante est exécutée
automatiquement à chaque démarrage de mysql :
[mysql]
default-character-set=koi8r
EXEMPLE : supposez que column1 est défini par CHAR(5) CHARACTER SET latin2. Si vous
n'indiquez pas SET CHARACTER SET, alors la commande SELECT column1 FROM t retournera
les valeurs de la colonne column1 en utilisant le jeu de caractères latin2. Si, d'un autre coté,
vous utilisez la commande SET CHARACTER SET latin1, le serveur va alors convertir le
résultat de latin2 en latin1 juste avant de l'envoyer. De telles conversion sont lentes.
Si vous ne voulez pas que le serveur fasse des conversions, utilisez la valeur NULL à
character_set_results :
mysql> SET character_set_results = NULL;

Jeu de caractères et collation des chaînes littérales


Chaque chaîne de caractères littérale a un jeu de caractères et une collation qui ne peut pas
être nulle.
Une chaîne de caractères littérale peut avoir un spécificateur optionnel de jeu de caractères
optionnel et une clause COLLATE :
[_character_set_name]'string' [COLLATE collation_name]
Exemples :
SELECT 'string';
SELECT _latin1'string';
SELECT _latin1'string' COLLATE latin1_danish_ci;
La simple commande SELECT 'string' utilise le jeu de caractères par défaut de la
connexion.
L'expression _character_set_name est formellement appelée un spécificateur
(introducer). Elle indique à l'analyseur : "la chaîne qui va suivre utilise le jeu de caractère
X.'' Cela a été source de confusions par le passé; aussi nous insistons sur le fait qu'un
spécificateur ne provoque pas de conversion. C'est strictement une indication, qui ne change
pas la valeur de la chaîne. Un spécificateur est aussi autorisé avant des notations littérales
hexadécimale et numérique (x'literal' et 0xnnnn), et avant ? (qui est une substitution de
paramètre lorsque l'on utilise des commandes préparées avec une interface de langage de
programmation).
Exemples :
SELECT _latin1 x'AABBCC';
SELECT _latin1 0xAABBCC;
SELECT _latin1 ?;
MySQL détermine le jeu de caractères et la collation de la fa¸on suivante :

1
 Si, à la fois _X et COLLATE Y ont été précisés, alors le jeu de caractères est X et la
collation littérale est Y.
 Si _X est précisé mais que COLLATE ne l'est pas, alors le jeu de caractères de la chaîne
littérale est X et la collation est la collation par défaut du jeu de caractères X.
 Sinon, on utilise le jeu de caractères et la collation par défaut de la connexion.
Exemples:
 Une chaîne avec le jeu de caractères latin1 et la collation latin1_german1_ci :
 SELECT _latin1'Müller' COLLATE latin1_german1_ci;
 Une chaîne avec le jeu de caractères latin1 et sa collation par défaut, c'est à dire
latin1_swedish_ci:
 SELECT _latin1'Müller';
 Une chaîne avec le jeu de caractère et la collation connexion/littérale :
 SELECT 'Müller';
Les introducteurs de jeux de caractères et la clause COLLATE sont implémentés selon les
spécifications standard SQL.

Clause COLLATE dans différentes parties d'une requête SQL


Avec la clause COLLATE, vous pouvez remplacer la collation par défaut, quelle qu'elle soit, par
une comparaison. COLLATE peut être utilisé dans différentes parties des requêtes SQL. Voici
quelques exemples :
 Avec ORDER BY :
 SELECT k
 FROM t1
 ORDER BY k COLLATE latin1_german2_ci;
 Avec AS :
 SELECT k COLLATE latin1_german2_ci AS k1
 FROM t1
 ORDER BY k1;
 Avec GROUP BY :
 SELECT k
 FROM t1
 GROUP BY k COLLATE latin1_german2_ci;
 Avec les fonctions d'agrégation :
 SELECT MAX(k COLLATE latin1_german2_ci)
 FROM t1;
 Avec DISTINCT :
 SELECT DISTINCT k COLLATE latin1_german2_ci
 FROM t1;
 Avec WHERE :

1
 SELECT *
 FROM t1
 WHERE _latin1 'Müller' COLLATE latin1_german2_ci = k;
 Avec HAVING :
 SELECT k
 FROM t1
 GROUP BY k
 HAVING k = _latin1 'Müller' COLLATE latin1_german2_ci;

COLLATE clause de précédence


La clause COLLATE a précédence (plus haute que ||), donc les expressions suivantes sont
équivalentes :
x || y COLLATE z
x || (y COLLATE z)

Quelques cas spéciaux où la détermination de la collation est difficile


Dans la grande majorité des requêtes, la collation utilisée par MySQL pour résoudre une
comparaison est évidente. Par exemple, dans les cas suivants, il devrait être clair que la
collation sera "la collation de colonne de la colonne x'' :
SELECT x FROM T ORDER BY x;
SELECT x FROM T WHERE x = x;
SELECT DISTINCT x FROM T;
Cependant, quand des opérandes multiples sont, en jeu il peut y avoir des ambiguïtés. Par
exemple :
SELECT x FROM T WHERE x = 'Y';
Cette requête devrait elle utiliser la collation de la colonne x, ou celle de la chaîne littérale
'Y'?

Le standard SQL résout de telles questions en utilisant ce qui portait le nom de règles
coercitives (``coercibility''). L'essence de la question est : puisque x et 'Y' ont tous deux
des collations différentes, laquelle a priorité? C'est une question complexe, mais ces règles
devraient résoudre la plupart des situations :
 Une clause explicite COLLATE a pour priorité 4.
 Une concaténation de deux chaînes avec des collations différentes à pour priorité 3.
 La collation d'une colonne a priorité 2.
 La collation d'une chaîne littérale a pour priorité 1.
Ces règles résolvent les ambiguités de la fa¸on suivante :
 Utiliser la collation qui a la précédence la plus élevée.
 Si les deux opérandes ont une collation de même priorité, alors il y a erreur si les
collations ne sont pas les mêmes.

1
Exemples :
column1 = 'A' Utilise la collation de la colonne column1
column1 = 'A' COLLATE x Utilise la collation de 'A'
column1 COLLATE x = 'A' COLLATE y Erreur

La fonction COERCIBILITY() peut être utilisée pour déterminer la coercibilité d'une chaîne :
mysql> SELECT COERCIBILITY('A' COLLATE latin1_swedish_ci);
-> 0
mysql> SELECT COERCIBILITY('A');
-> 3

1
Exercice :

Allez sur http://s5.adeli.fr/WebCalendar-1.0.4


Le login de la base est webcalendar le mot de passe webcalformation
La base s’appelle intranet

1
La pratique

La création d’une base de donnée


CREATE DATABASE `essai` ;

On s’est trompé et on veut l’effacer

DROP DATABASE `essai`

CREATE DATABASE `formation` ;


On crée la table élève avec des champs de type varchar

CREATE TABLE `eleves` (


`nom` VARCHAR( 20 ) NOT NULL ,
`prénom` VARCHAR( 20 ) NOT NULL ,
`age` TINYINT NOT NULL
);

Oups on a oublié de mettre un champ « numéro de sécurité sociale »

ALTER TABLE `eleves` ADD `numero de sécurité sociale` BIGINT NOT NULL
FIRST ;
On s’est trompé dans le nom du champ :
ALTER TABLE `eleves` CHANGE `numero de sécurité sociale` `numero de sécurité
social` BIGINT( 20 ) DEFAULT '0' NOT NULL

On va utiliser une clé primaire


ALTER TABLE `eleves` ADD PRIMARY KEY ( `numero de sécurité social` )

On affiche
SELECT * FROM `eleves` WHERE 1

1
Exemple
CREATE TABLE `articles` (
`Référence` varchar(30) NOT NULL default '',
`Categorie` varchar(30) NOT NULL default '',
`Nom` varchar(30) NOT NULL default '',
`Fournisseur` varchar(30) NOT NULL default '0',
`PrixHT` float NOT NULL default '0',
`TauxTVA` float NOT NULL default '0',
`QteStock` int(11) NOT NULL default '0',
`SeuilCritique` int(11) NOT NULL default '0',
PRIMARY KEY (`Référence`)
) TYPE=MyISAM;

#
# Contenu de la table `articles`
#

# --------------------------------------------------------

#
# Structure de la table `fournisseurs`
#

CREATE TABLE `fournisseurs` (


`Numero` varchar(30) NOT NULL default '',
`Societe` varchar(30) NOT NULL default '',
`Contact` varchar(30) NOT NULL default '',
`Adresse` text NOT NULL,
`CodePostal` int(5) NOT NULL default '0',
`Ville` varchar(30) NOT NULL default '',
`Tel` varchar(20) NOT NULL default '',
`Fax` varchar(20) NOT NULL default ''
) TYPE=MyISAM;

#
# Contenu de la table `fournisseurs`
#

INSERT INTO `fournisseurs` VALUES ('1', 'Buro Compagnie', 'M Buro', '3 rue
des bureaux', 45000, 'ORLEANS', '02.38.38.38.38', '02.38.38.38.37');
INSERT INTO `fournisseurs` VALUES ('3', 'Papier Compagnie Paris', 'M
Papierfils', '14 rue du bloc note', 75000, 'Paris', '012.38.38.38.00',
'02.38.38.38.01');
INSERT INTO `fournisseurs` VALUES ('2', 'Papier Compagnie', 'M Pappier', '4
rue des Papiers', 45000, 'ORLEANS', '02.38.38.38.xx', '02.38.38.38.yy');
INSERT INTO `fournisseurs` VALUES ('4', 'bureau Compagnie Paris', 'M
Porte', '1 rue de la serrure', 75000, 'Paris', '01.38.38.38.00',
'01.38.38.38.01');

INSERT INTO `articles` VALUES ('1', '1', 'Crayon bille noir', '1', 0.4,
0.19, 2000, 100);
INSERT INTO `articles` VALUES ('2', '1', 'Crayon bille rouge', '1', 0.4,
0.19, 3000, 100);
INSERT INTO `articles` VALUES ('3', '2', 'Rame papier blanc 80g', '2', 2,
0.19, 2000, 100);
INSERT INTO `articles` VALUES ('4', '2', 'Rame papier bleu 80g', '2', 2.05,
0.19, 3000, 10000);

1
INSERT INTO `articles` VALUES ('5', '3', 'Agenda 2005', '1', 15, 0.19, 100,
10);
INSERT INTO `articles` VALUES ('6', '2', 'Recharge 2005', '1', 3, 0.19, 10,
10);
INSERT INTO `articles` VALUES ('7', '1', 'Crayon bille rouge', '1', 0.8,
0.25, 3000, 100);

1
Les requêtes
A : Trouver moi les informations du fournisseur n° 2
Trouver les produits qui lui appartiennent dans le stock
Trouver les articles de la catégorie 2

1
Les références
http://dev.mysql.com/doc/refman/5.0/fr/index.html
http://wwwlsi.supelec.fr/www/yb/poly_bd/sql/tdm_sql.html
http://cerig.efpg.inpg.fr/tutoriel/bases-de-donnees/chap18.htm
http://sgbd.developpez.com/cours/#sgbd
http://doc.domainepublic.net/mysql/doc.mysql/manual.html

Annexe Table decodage


ISO 8859-1

Western European (Albanian, Basque, Breton, Catalan, Danish, Dutch, English, Faeroese,
Finnish, French, German, Greenlandic, Icelandic, Irish Gaelic, Italian, Latin, Luxemburgish,
Norwegian, Portuguese, Rhaeto-Romanic, Scottish Gaelic, Spanish, Swedish)

ISO 8859-2

Eastern European (Albanian, Croatian, Czech, English, German, Hungarian, Latin, Polish,
Romanian, Slovak, Slovenian, Serbian)

ISO 8859-3

Southeastern European (Afrikaans, Catalan, Dutch, English, Esperanto, German, Italian,


Maltese, Spanish, Turkish)

ISO 8859-4

Northern European (Danish, English, Estonian, Finnish, German, Greenlandic, Latin, Latvian,
Lithuanian, Norwegian, Sámi, Slovenian, Swedish)

1
ISO 8859-5

Eastern European (Cyrillic-based: Bulgarian, Byelorussian, Macedonian, Russian, Serbian,


Ukrainian)

ISO 8859-6

Arabic

ISO 8859-7

Greek

ISO 8859-8

Hebrew

ISO 8859-9

Western European (Albanian, Basque, Breton, Catalan, Cornish, Danish, Dutch, English,
Finnish, French, Frisian, Galician, German, Greenlandic, Irish Gaelic, Italian, Latin,
Luxemburgish, Norwegian, Portuguese, Rhaeto-Romanic, Scottish Gaelic, Spanish, Swedish,
Turkish)

ISO 8859-10

Northern European (Danish, English, Estonian, Faeroese, Finnish, German, Greenlandic,


Icelandic, Irish Gaelic, Latin, Lithuanian, Norwegian, Sámi, Slovenian, Swedish)

ISO 8859-13

Baltic Rim (English, Estonian, Finnish, Latin, Latvian, Norwegian)

ISO 8859-14

Celtic (Albanian, Basque, Breton, Catalan, Cornish, Danish, English, Galician, German,
Greenlandic, Irish Gaelic, Italian, Latin, Luxemburgish, Manx Gaelic, Norwegian,
Portuguese, Rhaeto-Romanic, Scottish Gaelic, Spanish, Swedish, Welsh)

ISO 8859-15

Western European (Albanian, Basque, Breton, Catalan, Danish, Dutch, English, Estonian,
Faroese, Finnish, French, Frisian, Galician, German, Greenlandic, Icelandic, Irish Gaelic,

1
Italian, Latin, Luxemburgish, Norwegian, Portuguese, Rhaeto-Romanic, Scottish Gaelic,
Spanish, Swedish)

1
Syntaxes de START TRANSACTION, COMMIT et ROLLBACK
Par défaut, MySQL est lancé en mode autocommit. Cela signifie que chaque modification
effectué est enregistré immédiatement sur le disque par MySQL.
Si vous utilisez des tables supportant les transactions (comme InnoDB, BDB), vous pouvez
configurer MySQL en mode non-autocommit grâce à la commande:
SET AUTOCOMMIT=0

A partir de là, vous devez utiliser COMMIT pour enregistrer les modifications sur le disque ou
ROLLBACK pour ignorer les modifications apportées depuis le début de la transaction.
Si vous souhaitez sortir du mode AUTOCOMMIT pour une série d'opérations, vous pouvez
utiliser les commandes BEGIN ou BEGIN WORK :
START TRANSACTION;
SELECT @A:=SUM(salary) FROM table1 WHERE type=1;
UPDATE table2 SET summmary=@A WHERE type=1;
COMMIT;

BEGIN et BEGIN WORK peuvent être utilisé à la place de START TRANSACTION pour
initialiser une transaction. START TRANSACTION a été ajouté en MySQL 4.0.11; C'est une
syntaxe SQL-99, et il est recommandé de l'utiliser pour lancer une transaction. BEGIN et
BEGIN WORK sont disponibles pour MySQL 3.23.17 et 3.23.19, respectivement.
Notez que si vous n'utilisez pas de table transactionnelles, les modifications seront validées
automatiquement, indépendamment du mode de validation.
Si vous faites un ROLLBACK après avoir modifié une table non transactionnelle, vous
obtiendrez (ER_WARNING_NOT_COMPLETE_ROLLBACK) comme message d'alerte. Toutes
les tables supportant les transactions seront restaurées, mais aucune des autres tables ne
changera.
Si vous utilisez START TRANSACTION ou SET AUTOCOMMIT=0, il est recommandé
d'utiliser les "binary log" de MySQL à la place des anciens logs de modifications pour les
sauvegardes. Les transactions sont stockées dans les logs binaires en un seul bloc, après
COMMIT, pour être sûr que les transactions qui ont été annulées ne soient pas enregistrées.
Vous pouvez changer le niveau d'isolation des transactions avec SET TRANSACTION
ISOLATION LEVEL ....

Syntaxe de SET TRANSACTION


SET [GLOBAL | SESSION] TRANSACTION ISOLATION LEVEL
{ READ UNCOMMITTED | READ COMMITTED | REPEATABLE READ | SERIALIZABLE }

Configuration du niveau d'isolation des transactions en général, pour la totalité de la session,


ou pour la prochaine transaction.
Le comportement par défaut est de configurer le niveau d'isolation pour la transaction
suivante (qui n'a pas encore été commencée) En utilisant le paramètre GLOBAL, on configure
le niveau par défaut global pour toutes les nouvelles connections. Cette commande requiert

1
les privilèges SUPER. En utilisant le paramètre SESSION, on configure le niveau par défaut
pour toutes les prochaines transactions effectuées durant la session actuelle.

 InnoDB et SET ... TRANSACTION ISOLATION LEVEL

En terme de niveau d'isolation des transactions SQL-92, le comportement par défaut de


InnoDB est REPEATABLE READ. Depuis la version 4.0.5, InnoDB offre 4 niveaux
différents d'isolation de transactions, tels que décrit dans la norme SQL-92. Vous pouvez
configurer le niveau d'isolation par défaut dans le groupe [mysqld] du fichier my.cnf:
transaction-isolation = {READ-UNCOMMITTED | READ-COMMITTED
| REPEATABLE-READ | SERIALIZABLE}

Un utilisateur peut changer le niveau d'isolation d'une session ou des nouvelles connexion
avec la commande SET TRANSACTION. La syntaxe est la suivante :
SET [SESSION | GLOBAL] TRANSACTION ISOLATION LEVEL
{READ UNCOMMITTED | READ COMMITTED
| REPEATABLE READ | SERIALIZABLE}

Notez qu'il n'y a pas de tiret dans les noms de niveaux de la syntaxe SQL.
Le comportement par défaut est de configurer le niveau d'isolation de la prochaine transaction
non démarrée. Si vous utilisez le mot clé GLOBAL, la commande configure le niveau
d'isolation globalement, pour toutes les nouvelles connexions, mais pas pour les connexions
existantes. Vous devez avoir les droits de SUPER pour faire cela. En utilisant le mot clé
SESSION, vous allez configurer le niveau d'isolation des prochaines transactions de la
session courante. Tous les clients sont autorisés à changer le niveau d'isolation de la session,
même au milieu d'une transaction, ainsi que le niveau d'isolation de la prochaine transaction.
Dans les versions 3.23.50 et plus anciennes, SET TRANSACTION n'avait pas d'effet sur les
tables InnoDB. Dans les versions < 4.0.5, seules REPEATABLE READ et SERIALIZABLE
étaient disponibles.
Vous pouvez connaître les niveaux d'isolation de transaction de session et global avec ces
commandes :
SELECT @@global.tx_isolation;
SELECT @@tx_isolation;

Pour le verrouillage de ligne, InnoDB utilise le système dit de verrouillage de la prochaine


clé. Cela signifie qu'en plus des lignes d'index, InnoDB peut aussi verrouiller le ``trou'' après
une ligne d'index pour éviter les insertions des autres utilisateurs. Un verrou de prochaine clé
représente un verrou qui bloque la ligne d'index et le trou qui le précède. Un verrou de trou
représente un verrou qui ne bloque que le trou avant la ligne.
Voici une description détaillée de chaque niveau d'isolation de InnoDB :
 READ UNCOMMITTED This is also called ``dirty read'' : Les commandes SELECT
non-verrouillantes sont effectuées sans rechercher de versions plus récente de la ligne.
Elles sont donc non-cohérentes, sous ce niveau d'isolation. SInon, ce niveau
fonctionne comme le niveau READ COMMITTED.

1
 READ COMMITTED Proche du niveau d'isolation d'Oracle. Toutes les commandes
SELECT ... FOR UPDATE et SELECT ... LOCK IN SHARE MODE ne
verrouille que les lignes d'index, et non pas les trous entre elles, ce qui permet
l'insertion de nouvelles lignes, adjacentes aux lignes verrouillées. UPDATE et DELETE
qui utilisent un seul index avec une condition de recherche unique ne verrouille que la
ligne d'index trouvée, pas le trou qui la précède. Mais, pour un intervalle de lignes
traitées par UPDATE et DELETE, InnoDB doit méler des verrous de prochaine clé ou
des verrous de trous et bloquer les insertions des autres utilisateurs dans les espaces
couvert par l'intervalle. Ceci est nécessaire car les ``lignes fantômes'' doivent être
bloquées pour la réplication MySQL et la restauration. La lecture cohérente se
comporte comme avec Oracle : chaque lecture cohérente, même dans une transaction,
lit et modifie son propre contexte. See « Lecture cohérente non-bloquante ».
 REPEATABLE READ
C'est le niveau d'isolation par défaut d'InnoDB. Les commandes SELECT ... FOR
UPDATE, SELECT ... LOCK IN SHARE MODE, UPDATE et DELETE qui
utilisent un index unique dans une condition de recherche, ne verrouille que la ligne
d'index trouvée, et non pas le trou précédent. SInon, ces opérations utilisent le
verrouillage de prochaine clé, en verrouillant l'intervalle utilisé, et bloque les
insertions des utilisateurs. Avec les lectures cohérentes il y a une importante différence
avec le niveau d'isolation précédent : dans ce mode, toutes les lectures cohérentes
d'une même transaction liront les mêmes données, établies par la première lecture.
Cette convention signifie que si vous émettez plusieurs commandes SELECT dans la
même transaction, ces SELECT seront cohérents les uns avec les autres. See « Lecture
cohérente non-bloquante ».
 SERIALIZABLE Ce niveau est identique au précédent, mais toutes les lectures
SELECT sont implicitement converties en SELECT ... LOCK IN SHARE MODE.

1
Lecture cohérente non-bloquante
Une lecture cohérente signifie que InnoDB utilise son système de multi-versionnage pour
présenter à une requête, une photo de la base à un moment donné. La requête va alors voir les
différentes modifications apportées par les transactions qui ont eu lieu avant cette date, et
masquera les transactions qui ont eu lieu depuis, ou n'ont pas été archivées. L'exception à
cette règle est que la requête verra les modifications apportées par la requête qui a émis cette
commande.
Si vous utilisez le niveau d'isolation REPEATABLE READ, alors les lectures cohérentes dans
une même transaction liront le même bilan. Vous pouvez obtenir un bilan plus récent pour vos
requêtes en archivant la requête courante, et en démarrant une autre.
Les lectures cohérentes sont le mode par défaut de traitement des commandes SELECT par
InnoDB avec les niveaux d'isolation READ COMMITTED et REPEATABLE READ. Une
lecture cohérente ne pose aucun verrou sur les tables auxquelles elle accède, et par
conséquent, les autres utilisateurs peuvent librement modifier ces tables en même temps
qu'une lecture cohérente est exécutée.

Verrous de lecture SELECT ... FOR UPDATE et SELECT ... LOCK IN


SHARE MODE
Une lecture cohérente n'est pas toujours pratique, dans certaines circonstances. Supposons que
vous voulez ajouter une ligne dans votre table CHILD, et vous assurer que l'enfant a déjà un
parent dans la table PARENT.
Supposez que vous utilisiez une lecture cohérente, pour lire la table PARENT, et que vous
découvrez le parent de l'enfant dans cette table. Pouvez vous ajouter tranquillement la ligne
fille dans la table CHILD? Non, car il peut arriver que durant ce temps, un autre utilisateur a
effacé la ligne parente dans la table PARENT, et vous n'en êtes pas conscient.
La solution est d'exécuter la commande SELECT en mode verrouillage, avec LOCK IN
SHARE MODE.
SELECT * FROM PARENT WHERE NAME = 'Jones' LOCK IN SHARE MODE;

Effectuer une lecture en mode partagé signifie que vous allons lire les dernières données
disponibles, et que nous allons poser un verrou sur les lignes que nous lisons. Si les dernières
données appartiennent à une transaction non validée d'un autre utilisateur, nous allons
attendre que ce soit fait. Un verrou partagé évite que les autres utilisateurs ne modifient ou
n'effacent la ligne que nous lisons. Après que nous ayons obtenu le nom du parent, nous
pouvons tranquillement ajouter le nom du fils dans la table CHILD, et valider notre
transaction. Cet exemple montre comment implémenter l'intégrité référentielle dans votre
application.
Ajoutons un autre exemple : nous avons un champs compteur dans la table CHILD_CODES
que nous utilisons pour assigner un identifiant unique à chaque enfant que nous ajoutons dans
la table CHILD. Evidemment, en utilisant une lecture cohérente ou une lecture partagée pour
lire la valeur courante du compteur n'est pas une bonne idée, car deux utilisateurs de la base
peuvent simultanément lire la même valeur de compteur, et nous allons obtenir une erreur de
clé doublon lorsque nous ajouterons le second des deux fils.

1
Ici, LOCK IN SHARE MODE n'est pas une bonne solution, car si deux utilisateurs lisent le
compteur en même temps, au moins l'un des deux sera bloqué lorsqu'il tentera de modifier le
compteur.
Dans ce cas, il y a deux bonnes méthodes pour implémenter la lecture et l'incrémentation du
compteur : (1) modifiez le compteur d'une unité, et lisez le après cela ou (2) lisez le compteur
d'abord, avec un verrou en mode FOR UPDATE, puis incrémentez le :
SELECT COUNTER_FIELD FROM CHILD_CODES FOR UPDATE;
UPDATE CHILD_CODES SET COUNTER_FIELD = COUNTER_FIELD + 1;

Une commande SELECT ... FOR UPDATE va lire les dernières données disponibles pour
chaque ligne, et pose un verrou dessus en même tant qu'il lit. De cette façon, il pose le même
verrou que la commande UPDATE.
Notez que la commande ci-dessus est simplement un exemple de fonctionnement de SELECT
... FOR UPDATE. En MySQL, la tâche spécifique de création d'un identifiant unique peut
être réalisée avec un seul accès à la table :
UPDATE child_codes
SET counter_field = LAST_INSERT_ID(counter_field + 1);
SELECT LAST_INSERT_ID();

La commande SELECT ne fait que lire l'identifiant spécifique à la connexion. Il ne fait aucun
accès à la table.

Verrou de clé suivante : éviter le problème des lignes fantômes


Avec le verrouillage de ligne, InnoDB utilise un algorithme appelé le verrouillage de la clé
suivante. InnoDB fait un verrouillage de telle sorte que lorsqu'il fait une recherche ou un
scan d'index, il pose des verrous partagés ou exclusifs sur les lignes d'index qu'il rencontre.
Par conséquent, les verrous de lignes sont plus exactement appelés des verrous d'index.
Les verrous que InnoDB posent affectent aussi l'espace qui le sépare de la ligne suivante. Si
un utilisateur a un verrou partagé ou exclusif sur une ligne L dans un index, alors un autre
utilisateur ne peut faire d'insertion immédiatement avant la ligne L, dans l'ordre de l'index. Ce
verrouillage est fait pour éviter le problème de la ligne fantôme. Supposons que je veuille lire
et verrouiller tous les enfants ayant un identifiant supérieur à 100 dans la table CHILD, puis
modifier certains champs des lignes ainsi identifiées :
SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

Supposons qu'il y ait un index sur la table CHILD, sur la colonne ID. Notre requête va
scanner l'index à partir de la première ligne où ID est plus grand que 100. Maintenant, si le
verrou posé sur les lignes d'index n'empêche pas l'utilisation des intervalles entre les lignes
d'index, un nouvel enfant peut être inséré dans la table durant la lecture. Et maintenant, si ma
transaction exécute la commande :
SELECT * FROM CHILD WHERE ID > 100 FOR UPDATE;

je vais trouver un nouvel enfant dans le résultat de ma requête. Ceci va à l'encontre du


principe d'isolation des transactions : une transaction doit être capable de s'exécuter sans que
les lectures soient affectées durant ce temps. Si nous considérons un intervalle de données,
alors la nouvelle ligne 'fantôme' va casser le principe d'isolation.

1
Lorsque InnoDB scanne un index, il va aussi verrouille l'espace après la dernière ligne de
l'index. C'est ce qui est arrivé dans l'exemple ci-dessus : le verrou posé par InnoDB va éviter
qu'une insertion n'intervienne dans la table où ID serait plus grand que 100.
Vous pouvez utiliser le verrouillage de la clé suivant pour implémenter des vérifications
d'unicité dans votre application : si vous lisez des données en mode partagé, et que vous ne
voyez pas de duplicata de la ligne que vous allez insérer, alors vous pouvez l'insérer sans
problème, en sachant que le verrou de clé suivante va vous garantir que durant ce temps,
personne ne pourra insérer de ligne, qui déboucherait sur un duplicata de la votre. Le verrou
de clé suivante permet de verrouiller aussi la non-existence de ligne dans votre table.

1
Un exemple de lecture cohérente avec InnoDB
Supposons que vous exécutez MySQL avec le niveau d'isolation des transactions de
REPEATABLE READ. Lorsque vous demandez une lecture cohérente avec une commande
SELECT ordinaire, InnoDB va donner à votre transaction une date jalon, en fonction de
laquelle votre requête va voir la base. Ainsi, si une transaction B efface une ligne après
l'assignation de ce jalon, vous ne verrez pas cette ligne. De même pour une insertion ou une
modification.
Vous pouvez faire avancer votre date jalon en validant votre transaction et en exécutant un
autre SELECT.
Cela s'appelle le contrôle simultané multi-versions.
User A User B

SET AUTOCOMMIT=0; SET AUTOCOMMIT=0;


time
| SELECT * FROM t;
| empty set
| INSERT INTO t VALUES (1, 2);
|
v SELECT * FROM t;
empty set
COMMIT;

SELECT * FROM t;
empty set;

COMMIT;

SELECT * FROM t;
---------------------
| 1 | 2 |
---------------------

De cette façon, A voit la ligne insérée par B uniquement lorsque B a validé son insertion, et
que A a validé sa propre transaction, de façon à ce que la date jalon soit plus récente que la
validation de B.
Si vous voulez avoir une vision aussi ``fraîche'' que possible de votre base, vous devez utiliser
le verrou en lecture :
SELECT * FROM t LOCK IN SHARE MODE;

1
Les verrous posés par différentes requêtes SQL avec InnoDB
Un verrou de lecture, une commande UPDATE ou DELETE pose généralement des verrous
sur toutes les lignes qui sont analysée durant l'opération. La présence d'une clause WHERE n'a
pas d'importance. InnoDB ne se souvient pas de la condition WHERE exacte, mais sait quels
intervalles d'index ont été scannés. Les verrous sont du type 'prochaine clé', et cela empêche
aussi les insertions dans l'``espace'' immédiatement après la ligne.
Si le verrou est exclusif, alors InnoDB essaie de lire les groupes d'index et de poser un verrou
dessus.
Si vous n'avez d'index valable pour votre requête, et que MySQL scanne toute la table, chaque
ligne sera verrouillée, et bloquera ainsi toutes les insertions. Il est important de bien
configurer ses index, pour que les requêtes ne fassent pas de scan de table inutiles.
 SELECT ... FROM ... : ceci est une lecture cohérente, qui lit un bilan de la base,
et ne pose aucun verrou.
 SELECT ... FROM ... LOCK IN SHARE MODE : pose un verrou partagé sur
la prochaine clé sur tous les index que la lecture rencontre.
 SELECT ... FROM ... FOR UPDATE : pose un verrou exclusif sur la prochaine
clé sur tous les index que la lecture rencontre.
 INSERT INTO ... VALUES (...) : pose un verrou exclusif sur la ligne
insérée. Notez que ce verrou n'est pas un verrou de clé, et il n'empêche pas les autres
utilisateurs d'insérer des lignes. Si une erreur de clé double apparaît, un verrou sera
posé sur la ligne doublon.
 Durant l'initialisation d'une colonne AUTO_INCREMENT dans une table, InnoDB
pose un verrou exclusif à la fin de l'index associé à la colonne AUTO_INCREMENT.
Lors de l'accession au compteur d'incrémentation, InnoDB utilise un verrou
spécifique, en mode AUTO-INC où le verrou ne dure que jusqu'à la fin de la requête
SQL courante, au lieu de la fin de la transaction. See« InnoDB et AUTOCOMMIT ».
Avant MySQL 3.23.50, SHOW TABLE STATUS posait aussi un verrou exclusif sur
les tables ayant une colonne AUTO_INCREMENT. Cela signifie que la commande
SHOW TABLE STATUS pouvait aussi causer un blocage de verrou, ce qui surprenait
beaucoup les utilisateurs. Depuis MySQL 3.23.50, InnoDB lit la valeur d'une table
dont la colonne AUTO_INCREMENT a été initialisée, sans poser de verrou.
 INSERT INTO T SELECT ... FROM S WHERE ... : pose un verrou exclusif
sur chaque ligne inséré dans T. Effectue la recherche sur S sous la forme d'une lecture
cohérente, mais pose un verrou partagé sur l'index de prochaine clé de S si MySQL a
activé le log. InnoDB doit poser un verrou dans cette dernière situation, car en cas
d'exécution des instructions dans une phase de restauration, toutes les requêtes doivent
être exécutées dans le même ordre.
 CREATE TABLE ... SELECT ... effectue une commande SELECT sous la
forme d'une lecture cohérente, ou avec des verrous partagés, comme précédemment.
 REPLACE est similaire à une insertion, si il n'y a pas de collision sur la clé unique.
Sinon, une verrou exclusif sur l'index de prochaine clé est posé sur la ligne qui sera
modifiée.
 UPDATE ... SET ... WHERE ... : pose un verrou exclusif sur l'index de
prochaine clé, à chaque ligne que la recherche trouve.

1
 DELETE FROM ... WHERE ... : pose un verrou exclusif sur l'index de
prochaine clé à chaque ligne que la recherche trouve.
 Si la contrainte de FOREIGN KEY est définie sur une table, toute insertion,
modification ou effacement qui requiert la vérification de la contrainte va poser un
verrou de ligne sur la ligne dont il doit vérifier la contrainte. De plus, dans certains cas
où la contrainte échoue, InnoDB pose ces verrous.
 LOCK TABLES ...  : pose un verrou de table. L'implémentation de la couche
MySQL pose ce verrou. La détection automatique des blocages de InnoDB ne peut
détecter les blocages lorsque de tels verrous sont posés. Voyez la section suivante. See
« Détection des blocages et annulation ».
De plus, comme MySQL ne connaît pas le verrouillage de lignes, il est possible que
vous posiez un verrou sur une table où un autre utilisateur a déjà posé un verrou. Mais
cela ne pose pas de problème quant à l'intégrité de la requête. « Restrictions sur les
tables InnoDB ».

Quand est-ce que MySQL valide ou annule implicitement une


transaction?
MySQL ouvre les connexions des clients en mode d'auto-validation, par défaut. Lorsque
l'auto-validation est activée, MySQL fait une validation après chaque commande SQL, si la
commande n'a pas retourné d'erreur.
Si vous n'avez pas de mode d'auto-validation, et que vous fermez une connexion sans valider
explicitement vos transactions, alors MySQL annule votre transaction.
Si une erreur est retournée par une commande SQL, le comportement de la transaction dépend
de l'erreur. « Gestion des erreurs InnoDB ».
Les commandes SQL suivantes causent une validation implicite de la transaction courante :
 ALTER TABLE, BEGIN, CREATE INDEX, DROP DATABASE, DROP INDEX,
DROP TABLE, LOAD MASTER DATA, LOCK TABLES, RENAME TABLE, SET
AUTOCOMMIT=1, START TRANSACTION, TRUNCATE, UNLOCK TABLES.
 CREATE TABLE (elle valide uniquement avant MySQL 4.0.13 et si le log binaire
MySQL est utilisé).
 La commande CREATE TABLE de InnoDB est traitée comme une seule transaction.
Cela signifie qu'une commande ROLLBACK ne va pas annuler la commande CREATE
TABLE qui a été faite dans la transaction.

Détection des blocages et annulation


InnoDB détecte automatiquement les blocages de transactions et annule une ou plusieurs
transactions pour l'éviter. Depuis la version 4.0.5, InnoDB va essayer d'annuler les petites
transactions. La taille de la transaction est déterminée par le nombre de lignes qu'elle a inséré,
modifié ou effacé. Avant la version 4.0.5, InnoDB annulait toujours la transaction qui avait
posé le dernier verrou avant le blocage, c'est à dire, un cycle dans le graphe des transactions.
InnoDB ne peut pas détecter les blocages causés par la commande MySQL LOCK TABLES,
ou si un verrou est posé par un autre gestionnaire de table que InnoDB. Vous devez résoudre
ces situations avec l'option innodb_lock_wait_timeout du fichier de configuration.

1
Lorsque InnoDB effectue une annulation de transaction, tous les verrous de cette transaction
sont libérés. Cependant, si une commande SQL est annulée pour cause d'erreur, certains
verrous de la transaction peuvent être conservés. Ceci est dû au fait que InnoDB enregistre
les verrous dans un format qui ne permet pas de savoir qui l'a posé.

Comment gérer les blocages de verrous?


Les blocages de verrous sont un problème classique des bases de données transactionnelles,
mais ils ne sont pas dangeureux, à moins qu'ils ne se répètent si souvent que vous ne puissiez
pas exécuter tranquillement certaines transactions. Normalement, vous devriez écrire vos
applications de manière à ce qu'elles soient prêtes à tenter à nouveau une transaction si la
transaction est annulée pour cause de blocage.
InnoDB utilise un verrouillage de lignes automatique. Vous pouvez obtenir des blocages sur
une ligne, même si votre transactions ne fait que modifier ou insérer une seule ligne. Cela est
dû au fait que les opérations ne sont pas réellement 'atomiques' : elles posent automatiquement
des verrous (éventuellement plusieurs) sur les lignes d'index de l'enregistrement concerné.
Vous pouvez gérer ces blocages et réduire leur nombre avec les trucs suivants :
 Utilisez la commande SHOW INNODB STATUS avec MySQL version supérieure à
3.23.52 et 4.0.3, pour déterminer la cause du dernier blocage. Cela peut vous aider à
optimiser votre application pour les éviter.
 Soyez toujours prêts à tenter une nouvelle fois une transaction si elle échoue à cause
d'un blocage. Les verrous ne sont pas dangeureux. Essayez juste une autre fois.
 Validez souvent vos transactions. Les petites transactions sont moins sujettes aux
blocages.
 Si vous utilisez des verrous en lectures avec SELECT ... FOR UPDATE ou ...
LOCK IN SHARE MODE, essayez d'utiliser un niveau d'isolation plus bas comme
READ COMMITTED.
 Accédez à vos tables et lignes dans un ordre fixé. Les transactions vont alors former
des queues, et non pas des blocages.
 Ajoutez de bons index à vos tables. Vos requêtes devront scanner moins souvent les
tables, et poseront donc moins de verrous. Utilisez EXPLAIN SELECT pour
déterminer si MySQL choisit les bons index pour vos requêtes.
 Limitez votre utilisation des verrous. Si vous pouvez vous permettre de faire retourner
à une commande SELECT des données un peu anciennes, n'ajoutez pas la clause FOR
UPDATE ou LOCK IN SHARE MODE. Utiliser le niveau d'isolation READ
COMMITTED est bon ici, car chaque lecture cohérente dans la même transaction lira
avec des données aussi fraîches que possible à chaque fois.
 En dernier recours, vous pouvez forcer les verrous avec la commande :
LOCK TABLES t1 WRITE, t2 READ, ...;
[faire quelquechose avec les tables t1 et t2];
UNLOCK TABLES;

Les verrous de niveau de table forcent les transactions à se mettre en ligne, et les
blocages sont évités. Notez que LOCK TABLES démarre implicitement une

1
transaction, tout comme BEGIN, et UNLOCK TABLES termine une transaction avec
un COMMIT.
 Une dernière solution est de créer un sémaphore auxiliaire sous la forme d'une table
avec une seule ligne. Chaque transaction modifie cette table avant d'accéder aux autres
tables. Dans ce cas, toutes les transactions se font en ordre séquentiel. Notez que dans
cette configuration, même l'algorithme InnoDB de détection des blocages fonctionne,
car le sémaphore est un verrou de ligne. Avec les verrous de niveau de table de
MySQL, nous devons nous résoudre à une méthode de délai d'expiration pour résoudre
un verrou.

1
Conseils pour l'amélioration des performances InnoDB
Le moniteur InnoDB

 Si l'outil Unix top ou si le Task Manager de Windows montre que l'utilisation du


CPU, lors de la charge de travail, est inférieure à 70%, votre calcul est probablement
limité par les disques. Vous faites peut être trop d'écriture de transaction, ou le tampon
de traitement ("buffer pool") est peut être trop petit. Augmenter la taille du tampon
peut aider, mais il ne faut pas qu'il dépasse 80% de la mémoire physique.
 Regrouper les modifications dans une seule transaction. InnoDB doit écrire les
données de log sur le disque à chaque validation de transaction, si la transaction a fait
des modifiations dans la base. Comme la vitesse de rotation d'un disque est
typiquement de 167 revolutions/seconde au mieux, cela réduit le nombre de
validations à 167 par seconde, si le disque ne veut pas induire le système d'exploitation
en erreur.
 Si vous pouvez accepter la perte des toutes dernières transactions validées, vous
pouvez modifier dans le fichier my.cnf le paramètre
innodb_flush_log_at_trx_commit à 0. InnoDB essaie d'écrire sur le disque
au moins une fois par seconde, mais cette écriture n'est plus garantie.
 Utilisez de gros fichiers de log, même aussi grand que le pool de buffer. Lorsque
InnoDB a écrit les fichiers de log, il doit écrire les contenus modifiés du pool de
buffer sur le disque, avec un jalon. Les fichiers de logs de petites tailles imposeront
des écritures inutiles. L'inconvénient d'un gros fichier de log est que le temps de
restauration sera plus long.
 Le buffer de logs doit être assez grand, au moins 8 Mo.
 Utilisez le type de colonne VARCHAR au lieu de CHAR si vous stockez des chaînes de
taille variable, ou si une colonne peut contenir plusieurs valeurs NULL. Une colonne
CHAR(N) prend toujours N octets pour stocker les données, même si la chaîne est plus
petite, ou que sa valeur est NULL. Des tables plus petites rentrent plus facilement dans
les buffers et réduisent les accès disques.
 (Valable depuis MySQL version 3.23.39 et plus récent) Dans certaines versions de
MySQL et Unix, l'écriture des fichiers sur les disques avec fdatasync et d'autres
commandes similaires sont étonnament lentes. La méthode par défaut de InnoDB est
la fonction fdatasync. Si vous n'êtes pas satisfaits avec les performances en
écriture de la base, vous pouvez essayer d'utiliser l'option innodb_flush_method
dans le fichier my.cnf avec la valeur O_DSYNC, même si O_DSYNC semble être la
méthode la plus lente sur la plupart des systèmes.
 Lors de l'importation de données avec InnoDB, assurez vous que MySQL n'a pas
autocommit=1. Sinon, chaque insertion implique une écriture sur le disque.
Ajoutez cette commande dans votre fichier SQL d'import :
SET AUTOCOMMIT=0;
/* commandes d'importation SQL ... */
COMMIT;

Si vous utilisez l'option --opt de l'utilitaire mysqldump, vous allez obtenir des
fichiers d'export qui sont rapides à importer dans une table InnoDB, même sans

1
utiliser l'astuce de la transaction ci-dessus : SET AUTOCOMMIT=0; ...
COMMIT;.
 Attention aux annulations lors des insertions de masse : InnoDB utilise une buffer
d'insertion pour éviter les accès disques, mais la fonction d'annulation correspondante
n'utilise pas ce mécanisme. Une annulation qui utilise beaucoup d'accès disque est
environ 30 fois plus lente que l'insertion équivalent. Interrompre la base ne va pas
aider, car l'annulation reprendra lors du redémarrage de la base. La seule solution pour
ce débarasser de cette annulation lénifiante est d'augmenter la taille du pool de buffer,
pour que l'annulation soit limitée par le processeur et non plus par le disque. Ou alors,
effacez toute la base InnoDB. See Section 15.9.1, « Forcer la restauration ».
 Attention aux opérations qui ont de gros impacts sur le disque : utilisez DROP TABLE
ou TRUNCATE depuis MySQL 4.0 et, pour vider une table, et non pas DELETE FROM
votre_table.
 Utilisez les INSERT multiples pour réduire les communications entre le client et le
serveur, si vous devez insérer plusieurs lignes :
INSERT INTO yourtable VALUES (1, 2), (5, 5);

Ce conseil est valable pour tous les types des tables, pas seulement InnoDB.
 Si vous avez une contrainte UNIQUE sur les clés secondaires, depuis MySQL version
3.23.52 et 4.0.3, vous pouvez accélérer les imports de tables en désactivant
temporairement les vérifications d'unicité durant l'importation :
SET UNIQUE_CHECKS=0;

Pour les grandes tables, cela économise de nombreux accès disques, car les tables
InnoDB peuvent utiliser le buffer d'insertion pour écrire des index secondaires par
paquets.
 Si vous avez des contraîntes FOREIGN KEY dans vos tables, depuis MySQL 3.23.52
et 4.0.3, vous pouvez accélérer les imports de tables en désactivant temporairement les
vérifications d'unicité durant l'importation :
SET FOREIGN_KEY_CHECKS=0;

Pour les grandes tables, cela économise beaucoup d'accès disques.


 Si vous avez des requêtes récurrentes dans vos tables, qui ne sont pas modifiées
souvent, vous pouvez utiliser le cache de requêtes depuis MySQL 4.0 :
[mysqld]
query_cache_type = ON
query_cache_size = 10M

En MySQL 4.0, le cache temporaire fonctionne uniquement si l'auto-commit est


activé. Cette restriction a été levée depuis MySQL 4.1.1.