Chapitre 13. Syntaxe des commandes SQL
Précédent |  | Suivant

## Chapitre 13. Syntaxe des commandes SQL

Ce chapitre décrit la syntaxe des commandes que MySQL supporte.

## 13.1. Manipulation de données : `SELECT`, `INSERT`, `UPDATE`, `DELETE`

### 13.1.1. 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]

`DELETE` efface les enregistrements de `nom_de_table` qui satisfont la condition donnée par `clause_where`, et retourne le nombre d'enregistrements effacés.

Si vous exécutez un `DELETE` sans clause `WHERE`, tous les enregistrements sont effacés. Si vous le faites en mode `AUTOCOMMIT` cela aura le même effet qu'un `TRUNCATE`. See Section 13.1.9, « Syntaxe de `TRUNCATE` ».

Avec MySQL 3.23, `DELETE` sans clause `WHERE` retournera zéro comme nombre d'enregistrements affectés.

Si vous voulez vraiment savoir combien d'enregistrements ont été effacés quand vous videz une table, et que vous êtes prêts à souffrir d'un léger ralentissement, vous pouvez utiliser une requête `DELETE` de ce genre :

    mysql> DELETE FROM nom_de_table WHERE 1>0;

Notez que c'est plus lent que `DELETE FROM nom_de_table` sans clause `WHERE`, parce que cela efface un enregistrement à la fois.

Si vous effacez des lignes contenant la valeur maximum d'une colonne `AUTO_INCREMENT`, la valeur sera réutilisée pour par une table `ISAM` ou `BDB`, mais pas pour une table `MyISAM` ou `InnoDB`. Si vous effacez toutes les lignes dans une table avec une commande `DELETE FROM tbl_name` (avec une clause `WHERE`) avec le mode `AUTOCOMMIT`, la séquence redémarrer à zéro pour tous les types de table sauf `InnoDB` et, depuis MySQL 4.0, `MyISAM`. Il y a des exceptions à ce comportement pour les tables `InnoDB`, qui sont présentées dans la section Section 15.7.3, « Comment les colonnes `AUTO_INCREMENT` fonctionnent avec `InnoDB` ».

Pour les tables `MyISAM` et `BDB`, vous pouvez spécifier une autre colonne `AUTO_INCREMENT` dans une clé multi-colonnes. Dans ce cas, la réutilisation des clés à partir de la fin de la séquence se fait aussi pour les tables `MyISAM`. See Section 3.6.9, « Utiliser `AUTO_INCREMENT` ».

La commande `DELETE` supporte les clauses suivantes :

- Si vous spécifiez le mot clé `LOW_PRIORITY`, l'exécution de la commande `DELETE` est repoussée jusqu'à ce qu'aucun client ne soit en train de lire la table.

- Pour les tables `MyISAM`, si vous spécifiez l'option `QUICK`, le moteur de stockage ne compacte pas les index durant l'effacement, ce qui peut accélérer certains effacements.

- L'option `IGNORE` fait que MySQL ignore les erreurs durant le traitement des lignes. Les erreurs rencontrées durant la phase d'analyse sont traitées comme d'habitude. Les erreurs qui sont ignorées grâce à cette options sont listées comme des alertes. Cette option a été ajoutée en MySQL 4.1.1.

La vitesse d'exécution des opérations de suppressions peut être affectées par les facteurs présentés dans la section Section 7.2.16, « Rapidité des requêtes `DELETE` ».

Dans les tables de type `MyISAM`, les enregistrements effacés sont maintenus dans une liste liée et les requêtes `INSERT` suivantes réutilisent les vieux emplacements. Pour recouvrir l'espace inutilisé ou réduire la taille des fichiers, utilisez la commande `OPTIMIZE TABLE` ou l'utilitaire `myisamchk` pour réorganiser les tables. `OPTIMIZE TABLE` est plus simple, mais `myisamchk` est plus rapide. Voyez Section 13.5.2.5, « Syntaxe de `OPTIMIZE TABLE` » et Section 5.7.3.10, « Optimisation de table ».

La clause spécifique MySQL `LIMIT row_count` de la commande `DELETE` indique au serveur le nombre maximal de ligne à supprimer avant de rendre le contrôle au client. Elle peut être utilisée pour s'assurer qu'une commande `DELETE` ne prend pas trop de temps. Vous pouvez simplement répéter la commande `DELETE` jusqu'à ce que le nombre de lignes effacées est inférieure à la valeur de `LIMIT`.

Si la commande `DELETE` inclut la clause `ORDER BY`, les lignes sont effacées dans l'ordre spécifiée par cette clause. Elle n'est vraiment utilise que lorsqu'elle est couplée avec la clause `LIMIT`. Par exemple, la commande suivante applique la condition `WHERE`, trie les lignes avec la colonne `timestamp`, et efface la ligne la plus ancienne :

    DELETE FROM somelog
    WHERE user = 'jcole'
    ORDER BY timestamp
    LIMIT 1

`ORDER BY` peut être utilisée avec `DELETE` depuis MySQL version 4.0.0.

Depuis MySQL version 4.0, vous pouvez spécifier plusieurs tables dans la commande `DELETE`, pour effacer des lignes dans plusieurs tables, en fonction d'une condition de liaison. Cependant, vous ne pouvez pas utiliser les clauses `ORDER BY` et `LIMIT` dans une suppression `DELETE` multi-tables.

La première syntaxe de `DELETE` multi-table est supportée depuis MySQL 4.0.0. La deuxième syntaxe de `DELETE` multi-table est supportée depuis MySQL 4.0.2. La partie `table_references` liste les tables impliquées dans la jointure. Sa syntaxe est décrite dans la section Section 13.1.7.1, « Syntaxe de `JOIN` ».

L'idée est que seul les lignes concordante dans les tables énumérées avant le `FROM` ou avant la clause `USING` sont effacés. Le but est de pouvoir effacer des lignes de plusieurs tables en même temps tout en ayant d'autres tables pour les recherches.

Le code `.*` après les noms de tables n'est présent que pour assurer la compatibilité avec `Access` :

    DELETE t1,t2 FROM t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

ou :

    DELETE FROM t1,t2 USING t1,t2,t3 WHERE t1.id=t2.id AND t2.id=t3.id

Dans les cas précédents, nous n'avons supprimé les lignes correspondantes que dans les tables `t1` et `t2`.

Les exemples ci-dessus présente des jointures internes, en utilisant l'opérateur virgule, mais les `DELETE` multi-tables peuvent utiliser n'importe quel type de jointure qu'une commande `SELECT` accepte, comme un `LEFT JOIN`.

La syntaxe autorise `.*` après le nom de la table pour assurer la compatibilité avec `Access`.

Si vous utilisez une commande `DELETE` multi-tables avec des tables `InnoDB` pour lesquelles il y a des contraintes de clés étrangères, l'optimiseur MySQL risque de traiter les tables dans un ordre qui diffère de celui des relations parent/enfant de la clé. Dans ce cas, la commande échouera, et s'annulera. Pour résoudre ce problème, effacez les lignes tables par table, et utilisez les fonctionnalités `ON DELETE` que `InnoDB` fournit pour que les autres tables soient correctement traitées.

Note : en MySQL 4.0, vous devez utiliser le véritable nom de table. En MySQL 4.1, vous devez utiliser l'alias éventuel, lorsque vous nommez la table :

En MySQL 4.0 :

    DELETE test FROM test AS t1, test2 WHERE ...

En MySQL 4.1 :

    DELETE t1 FROM test AS t1, test2 WHERE ...

La raison qui nous a poussé à ne pas faire ce changement en version 4.0, est la compatibilité ascendante avec les vieilles applications 4.0, qui utilisent la vieille syntaxe.

### 13.1.2. 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`.

### 13.1.3. Syntaxe de `HANDLER`

    HANDLER tbl_name OPEN [ AS alias ]
    HANDLER tbl_name READ index_name { = | >= | <= | < } (value1,value2,...)
        [ WHERE ... ] [LIMIT ... ]
    HANDLER tbl_name READ index_name { FIRST | NEXT | PREV | LAST }
        [ WHERE ... ] [LIMIT ... ]
    HANDLER tbl_name READ { FIRST | NEXT }
        [ WHERE ... ] [LIMIT ... ]
    HANDLER tbl_name CLOSE

La commande `HANDLER` fournit un accès direct à l'interface de gestion de la table `MyISAM`.

La première forme de `HANDLER` ouvre la table, la rendant accessible via la requête `HANDLER ... READ` qui la suit. Cette objet table n'est pas partagé par les autres threads et ne sera refermé que si le thread appelle `HANDLER nom_de_table CLOSE` ou que celui ci se termine.

La seconde forme récupère une ligne (ou plus, à spécifier dans la clause `LIMIT`) où l'index spécifié remplit les conditions et où la clause `WHERE` est répondue. Si l'index se compose de plusieurs parties, (s'étend sur plusieurs colonnes) les valeurs sont spécifiées dans une liste séparée par des virgules, fournir des valeurs pour quelques premières colonnes est possible. Par exemple :

    HANDLER ... index_name = (col_a_val,col_b_val,col_c_val) ...
    HANDLER ... index_name = (col_a_val,col_b_val) ...
    HANDLER ... index_name = (col_a_val) ...

La troisième forme récupère une ligne (ou plus, à spécifier dans la clause `LIMIT`) de la table dans l'ordre de l'index, qui répond à la clause `WHERE`.

La quatrième forme (sans spécifications relatives à l'index) récupère une ligne (ou plus, à spécifier dans la clause `LIMIT`) de la table dans un ordre naturel des lignes (comme stocké dans le fichier de données) qui correspond à la condition `WHERE`. C'est plus rapide que `HANDLER nom_de_table READ nom_index` quand une lecture entière de la table est requise. See Section 13.1.7, « Syntaxe de `SELECT` ».

`HANDLER ... CLOSE` ferme une table qui a été ouverte avec `HANDLER ... OPEN`.

Note : pour utiliser l'interface `HANDLER` avec la clé primaire d'une table `PRIMARY KEY`, utilisez l'identifiant entre guillemets obliques ``PRIMARY`` :

    HANDLER tbl_name READ `PRIMARY` > (...);

`HANDLER` est en quelque sorte une commande bas-niveau. Par exemple, elle ne propose pas de consistance. En clair, `HANDLER ... OPEN` ne se base pas sur une image de la table, et ne verrouille pas la table. Cela signifie qu'après l'exécution d'une requête `HANDLER ... OPEN`, les données de la table peuvent être modifiées (par ce ou un autre thread) et ces modifications peuvent apparaître partiellement dans les lectures de `HANDLER ... NEXT` ou `HANDLER ... PREV`.

Les raisons d'utiliser cette interface plutôt que les commandes MySQL usuelles sont :

- Plus rapide qu'un `SELECT` car :

  - Un pointeur sur table dédié est alloué au thread dans `HANDLER open`.

  - Il y a moins de traitements.

  - Pas de pertes de temps en optimisation ou vérifications de requêtes.

  - La table utilisée n'a pas besoin d'être verrouillée entre deux requêtes de gestion.

  - L'interface de gestion n'a pas à fournir une vue consistante des données (par exemple, les lectures corrompues sont autorisées), ce qui permet au gestionnaire d'effectuer des optimisations que SQL ne permet pas.

- Cela facilite le port des applications qui utilisent l'interface ISAM pour MySQL.

- Cela permet de traverse plus facilement la base de données qu'avec SQL (dans certains cas, cette opération est impossible avec SQL). L'interface de gestion amène une fa¸on plus naturelle de manipuler les données lorsque vous travaillez avec des applications qui proposent une interface interactive entre l'utilisateur et la base de données.

### 13.1.4. Syntaxe de `INSERT`

    INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        VALUES ({expr | DEFAULT},...),(...),...
        [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

ou :

    INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name
        SET col_name={expr | DEFAULT}, ...
        [ ON DUPLICATE KEY UPDATE col_name=expr, ... ]

ou :

    INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] tbl_name [(col_name,...)]
        SELECT ...

`INSERT` insère une nouvelle ligne dans une table existante. La syntaxe `INSERT ... VALUES` insère une ligne à partir de valeurs explicitement fournies. La syntaxe `INSERT ... SELECT` insère des valeurs à partir d'une autre table. La syntaxe `INSERT ... VALUES` avec plusieurs valeurs est supportées à partir de MySQL 3.22.5 ou supérieure. la syntaxe `nom_colonne=expression` est supportée à partir de la version 3.22.10 de MySQL.

`INSERT ... SELECT` est présenté plus en détails : See Section 13.1.4.1, « Syntaxe de `INSERT ... SELECT` ».

`nom_de_table` est le nom de la table dans laquelle les valeurs seront insérées. La liste de noms de colonne ou la clause `SET` indiquent les colonnes qui seront affectées:

- La liste des noms de colonnes ou la clause `SET` indique explicitement les colonnes utilisées.

- Si vous ne spécifiez pas de liste de colonnes avec `INSERT ... VALUES` ou `INSERT ... SELECT`, les valeurs pour toutes les colonnes doivent être fournies dans la clause `VALUES()` ou par la commande `SELECT`. Si vous ne connaissez pas l'ordre des colonnes, utilisez la commande `DESCRIBE nom_de_table` pour le connaître.

Les valeurs des colonnes peuvent être spécifiées de plusieurs fa¸ons :

- A chaque fois qu'on ne donne pas explicitement une valeur pour une colonne, celle prend la valeur par défaut. Par exemple, si on définit une liste de colonnes qui ne compte pas toutes les colonnes de la tables, toutes les colonnes qui ne sont pas nommées prendront leur valeur par défaut. La définition de la valeur par défaut se fait avec Section 13.2.5, « Syntaxe de `CREATE TABLE` ».

  MySQL a toujours une valeur par défaut pour chaque champs. C'est obligatoire pour MySQL pour pouvoir fonctionner aussi bien avec des tables supportant les transactions qu'avec des tables ne les supportant pas.

  Nous pensons que le contrôle du contenu des champs devrait être fait pas l'application et non par le serveur de base de données.

  Note : si vous voulez que les commandes `INSERT` génèrent une erreur si vous ne spécifiez pas explicitement de valeur pour toutes les colonnes qui requièrent des valeurs non-nulles (`NULL`), vous pouvez aussi configurer MySQL avec l'option `DONT_USE_DEFAULT_FIELDS`. Ce comportement n'est pas disponible si vous compilez MySQL depuis le source. See Section 2.4.2, « Options habituelles de `configure` ».

- Vous pouvez utiliser le mot clé `DEFAULT` pour donner explicitement à une colonne sa valeur par défaut. Cette fonctionnalité a été ajoutée en MySQL version 4.0.3. Cela rend plus simple l'écriture de commandes `INSERT` lors de l'assignation de quelques colonnes, sans écrire de valeurs `VALUES` incomplètes. Sinon, il faut écrire la liste des colonnes utilisées pour chaque valeur de la liste `VALUES`.

- Si la liste de colonnes et de valeurs `VALUES` sont vides, `INSERT` crée une ligne pour chaque colonne avec sa valeur par défaut :

      mysql> INSERT INTO tbl_name () VALUES();

- Une `expression` peut faire référence à n'importe quelle colonne qui a été définie précédemment dans une liste de valeurs. Par exemple, on peut dire ceci :

      mysql> INSERT INTO nom_de_table (col1,col2) VALUES(15,col1*2);

  Mais vous ne pouvez pas faire cela, car la valeur de `col1` fait référence à `col2`, qui est assigné après `col1` :

      mysql> INSERT INTO nom_de_table (col1,col2) VALUES(col2*2,15);

Les commandes `INSERT` supportent les options suivantes :

- Si vous spécifiez l'option `DELAYED`, le serveur met la ligne ou les lignes à insérer dans un tampon, et le client qui a émis la commande `INSERT DELAYED` est immédiatement libéré. Si la table est occupée, le serveur conserve les lignes. Lorsque la table se libère, il va insérer les lignes, tout en vérifiant périodiquement s'il n'y a pas de lectures dans la table. Si une lecture arrive, l'insertion est suspendue jusqu'à la prochaine libération. See Section 13.1.4.2, « Syntaxe de `INSERT DELAYED` ».

- Si on spécifie le mot `LOW_PRIORITY`, l'exécution de `INSERT` sera retardé jusqu'à ce qu'il n'y ait plus de clients qui lisent la table. Dans ce cas le client doit attendre jusqu'à la fin de l'opération d'insertion, ce qui peut prendre beaucoup de temps si la table est fréquemment accédée. C'est la grande différence avec `INSERT DELAYED`, qui laisse le client continuer tout de suite. See Section 13.1.4.2, « Syntaxe de `INSERT DELAYED` ». On peut remarquer que, en principe, `LOW_PRIORITY` ne devrait pas être utilisé avec des tables de type `MyISAM`, étant donné que celles-ci n'autorisent pas les insertions simultanées. See Section 14.1, « Le moteur de tables `MyISAM` ».

- Si on spécifie le mot `IGNORE` dans un `INSERT` avec les valeurs de plusieurs lignes, chaque ligne qui qui ferait doublon avec une clé `PRIMARY` ou `UNIQUE` existante dans la table sera ignoré et ne sera pas insérée. Si on ne spécifie pas `IGNORE`, l'insertion est abandonnée si quelque ligne que ce soit fait doublon avec une clé existante. La fonction `mysql_info()` de l'API C permet de savoir combien de lignes ont été insérées dans la table.

Si vous spécifiez la clause `ON DUPLICATE KEY UPDATE` (nouveau en MySQL 4.1.0), et qu'une ligne insérée engendre un doublon pour une clé `PRIMARY` ou `UNIQUE`, une commande `UPDATE` sera faite à la place de l'insertion. Par exemple, les commandes ont le même effet :

    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
        -> ON DUPLICATE KEY UPDATE c=c+1;

    mysql> UPDATE table SET c=c+1 WHERE a=1;

Note : si la colonne `b` est aussi unique, la commande `UPDATE` sera réécrite telle que

    mysql> UPDATE table SET c=c+1 WHERE a=1 OR b=2 LIMIT 1;

Si `a=1 OR b=2` trouve plusieurs lignes, uniquement une ligne sera mise à jour! En général, il faut éviter d'utiliser la clause `ON DUPLICATE KEY` sur des tables avec des clés `UNIQUE` multiples.

Depuis MySQL version 4.1.1, on peut utiliser la fonction `VALUES(col_name)` pour faire référence à la valeur de la colonne dans la clause `INSERT` d'une commande `INSERT ... UPDATE` : c'est la valeur qui sera insérée s'il n'y a pas de conflit de clé. Cette valeur est particulièrement utile dans les commandes `INSERT ... UPDATE` et retourne `NULL` sinon.

Exemple :

    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
        -> ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);

La commande ci-dessus est identique à :

    mysql> INSERT INTO table (a,b,c) VALUES (1,2,3)
        -> ON DUPLICATE KEY UPDATE c=3;
    mysql> INSERT INTO table (a,b,c) VALUES (4,5,6)
        -> ON DUPLICATE KEY UPDATE c=9;

Lors de l'utilisation de `ON DUPLICATE KEY UPDATE`, l'option `DELAYED` est ignorée.

Vous pouvez trouver la valeur utilisée pour une colonne `AUTO_INCREMENT` en utilisant la fonction `LAST_INSERT_ID()`. Depuis l'interface C, utilisez la fonction `mysql_insert_id()`. Cependant, notez que les deux fonctions ne se comportement pas de la la même fa¸ons dans toutes les circonstances. Le comportement des commandes `INSERT` avec les colonnes `AUTO_INCREMENT` sont décrites dans la section Section 12.8.3, « Fonctions d'informations » et Section 24.2.3.33, « `mysql_insert_id()` ».

Si vous utilisez une commande `INSERT ... VALUES` avec plusieurs listes de valeurs ou `INSERT ... SELECT`, la commande retourne les informations sous ce format :

    Records: 100 Duplicates: 0 Warnings: 0

`Records` indique le nombre de ligne qui ont été traitées par cette commande. Ce n'est pas forcément le nombre de ligne insérées. `Duplicates` peut être non-nulle. `Duplicates` indique le nombre de lignes qui n'ont pas peut être insérées pour cause de conflit avec une clé unique existante. `Warnings` indique le nombre de tentatives d'insertion de valeurs dans une colonne qui ont généré des problèmes. Les `Warnings` peuvent apparaître dans les conditions suivantes:

- Insertion de `NULL` dans une colonne déclarée `NOT NULL`. Pour les commandes d'insertions multiples `INSERT` ou les commandes `INSERT ... SELECT`, la colonne prend la valeur par défaut adaptée au type de colonne. C'est `0` pour les types numériques, la chaîne vide pour les textes et la valeur ``zéro'' pour les types temporels

- Enregistrement dans une colonne numérique d'une valeur qui déborde de la taille de la colonnes. Cette valeur a été tronquée à l'extrémité la plus adaptée de la colonne.

- Attribution à une colonne numérique d'une valeur telle que `'10.34 a'`. Celle valeur refusée est séparée, et la partie numérique résultante est insérée. Si cette valeur n'a pas une valeur numérique sensée, la valeur `0` est insérée.

- L'insertion d'une chaîne dans une colonne `CHAR`, `VARCHAR`, `TEXT`, ou `BLOB` qui dépasse la taille maximale de la colonne. La valeur est tronquée à la taille maximale de la colonne.

- L'insertion d'une valeur illégale pour une colonne de type `DATE` ou `TIME`. La colonne est alors enregistrée avec la valeur de zéro appropriée pour le type.

Si vous utilisez l'interface C, la chaîne d'information peut être obtenue en invoquant la fonction `mysql_info()`. See Section 24.2.3.31, « `mysql_info()` ».

#### 13.1.4.1. 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;

Les conditions suivantes s'appliquent à la requête `INSERT ... SELECT`:

- Avant MySQL version 4.0.1, `INSERT ... SELECT` opérait implicitement en mode `IGNORE`. Depuis MySQL version 4.0.1, vous devez spécifier le mode `IGNORE` explicitement, pour ignorer les lignes qui causeront des erreurs de doublons pour les index uniques.

- N'utilisez pas `DELAYED` avec `INSERT ... SELECT`.

- Avant MySQL version 4.0.14, la table de destination de la requête `INSERT` ne peut apparaître dans la clause `FROM` de la partie `SELECT` de la requête car il est interdit par le ANSI SQL de lire la table dans laquelle on est en train de faire un insert. (le problème est que le `SELECT` pourrait trouver des enregistrements qui aurait été insérés auparavant dans la même exécution. L'utilisation de "subselect" peut rendre la situation confuse !)

- Les colonnes `AUTO_INCREMENT` fonctionnent comme d'habitude.

- Pour s'assurer que les journaux des modifications ou les journaux binaires puissent être utilisés pour re-créer les tables originales, MySQL n'autorise pas les inserts concurrents pendant `INSERT ... SELECT`.

Il est bien sûr possible d'utiliser `REPLACE` à la place de `INSERT` pour remplacer les anciennes lignes.

#### 13.1.4.2. 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 aquitement, 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és, et écrits d'un seul bloc. C'est beaucoup plus rapide que de faire des insertions séparés.

Il y a quelques contraintes à l'utilisation de `DELAYED` :

- `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`. See Section 14.1, « Le moteur de tables `MyISAM` ».

- `INSERT DELAYED` doit être utilisé uniquement avec les commandes `INSERT` qui spécifie une liste de valeur. C'est le cas depuis MySQL 4.0.18. Le serveur ignore `DELAYED` pour les commandes `INSERT DELAYED ... SELECT`.

- Le serveur ignore `DELAYED` dans les commandes `INSERT DELAYED ... ON DUPLICATE UPDATE`.

- Comme la commande s'exécute immédiatement, sans que la ligne ne soit insére, vous ne pouvez pas utiliser `LAST_INSERT_ID()` pour lire la valeur que la colonne `AUTO_INCREMENT` va générer.

- Les lignes `DELAYED` ne sont visibles par les commandes `SELECT` que lorsqu'elles ont été réellement insérées.

Actuellement, les lignes en attente sont uniquement stockées en mémoire tant qu'elle ne sont pas insérées dans la table. Cela signifie que si on tue `mysqld` violemment, (`kill -9`) ou si `mysqld` meurt accidentellement, toutes les lignes en attente qui n'auront pas été écrites sur le disque seront perdues !

Les paragraphes suivants décrivent en détail ce qu'il se passe quand on utilise l'option `DELAYED` dans une requête `INSERT` ou `REPLACE`. Dans cette description, ``thread'' est un thread qui re¸oit une commande `INSERT DELAYED` ans ``handler'' est un thread qui gère toutes les opérations de `INSERT DELAYED` pour une table donnée.

- Quand un thread exécute une opération `DELAYED` sur une table, un thread de gestion est créé pour exécuter toutes les opérations `DELAYED` pour cette table - si ce thread de gestion n'existe pas.

- Le thread vérifie que a déjà re¸u un verrou `DELAYED`; sinon, il dit au thread de gestion de le faire. le verrou `DELAYED` peut être obtenu même si d'autres threads ont des verrous `READ` ou `WRITE` sur la table. Cependant le gestionnaire attendra que tous les verrous `ALTER TABLE` ou `FLUSH TABLES` soient finis pour s'assurer que la structure de la table est à jour.

- Le thread exécute une opération `INSERT`, mais plutôt que d'écrire la ligne dans la table, il va placer une copie de la ligne finale dans une file d'attente gérée par le thread de gestion. Le programme client est avertit de toutes les erreurs de syntaxe.

- Le client ne peut pas faire de rapport sur le nombre de duplicata ou sur la valeur de `AUTO_INCREMENT` de la ligne enregistrée; il ne peut pas les obtenir du serveur, car le `INSERT` est validé avant que l'opération d'insert n'ait été effectuée. Si vous utilisez l' API C, la fonction `mysql_info()` ne retourne pas de valeur intéressante, pour la même raison.

- Le journal de modification est mis à jour par le thread de gestion au moment où la ligne est insérée dans la table. Si plusieurs lignes sont insérées en même temps, le journal des modifications est mis à jour quand la première ligne est insérée.

- Une fois que toutes les lignes `delayed_insert_limit` sont écrites, le gestionnaire vérifie si des requêtes `SELECT` sont en attente, et si c'est le cas, il leur permet de s'exécuter avant de continuer.

- Quand le thread de gestion n'a plus de ligne dans sa file, la table est déverrouillée. Si aucun `INSERT DELAYED` n'est re¸u avant `delayed_insert_timeout` secondes, le gestionnaire s'arrête.

- Si plus de `delayed_queue_size` lignes sont déjà en attente d'un gestionnaire de file donné, le thread qui demande le `INSERT DELAYED` doit attendre qu'il y ait une place dans la file. Cela permet d'être sûr que `mysqld` n'utilisera pas toute la mémoire pour la mémoire des files d'attente d'insertions retardés.

- Le thread de gestion apparaîtra dans la liste des processus de MySQL avec `delayed_insert` dans la colonne `Command`. Il sera tué si on exécute une commande `FLUSH TABLES` ou si on le tue avec `KILL thread_id`. Cependant, il commencera par stocker toutes les lignes en attente dans la table avant de sortir. Pendant ce temps, il n'acceptera aucune commande `INSERT` d'aucun autre thread. Si on exécute une commande `INSERT DELAYED` après cela, un nouveau thread de gestion sera créé.

  Il faut noter que les commandes `INSERT DELAYED` ont une plus grande priorité que les commandes `INSERT` normales si un gestionnaire de `INSERT DELAYED` existe déjà! les autres commandes de modification devront attendre que la file d'attente de `INSERT DELAYED` soit vide, que quelqu'un tue le gestionnaire (avec `KILL thread_id`), ou que quelqu'un exécute `FLUSH TABLES`..

- Les variables suivantes fournissent des informations relatives à la commande `INSERT DELAYED` :

  Variable | Signification
  `Delayed_insert_threads` | Nombre de threads de gestion
  `Delayed_writes` | Nombre de lignes écrites avec `INSERT DELAYED`
  `Not_flushed_delayed_rows` | Nombre de lignes en attente d'être écrites.

  On peut voir ces variables avec la commande `SHOW STATUS` ou en exécutant la commande `mysqladmin extended-status`.

Il faut noter que `INSERT DELAYED` est plus lent qu'un INSERT normal si la table n'est pas utilisée. L'utilisation d'un thread de gestion séparé pour chaque table sur lesquelles on utilise `INSERT DELAYED` rajoute également une surcharge au serveur. Ce qui signifie qu'il vaut mieux utiliser `INSERT DELAYED` uniquement quand c'est vraiment nécessaire!

### 13.1.5. 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. Pour plus d'informations sur l'efficacité des commandes `INSERT` comparativement à `LOAD DATA INFILE` et pour accélérer les commandes `LOAD DATA INFILE`, voyez Section 7.2.14, « Vitesse des requêtes `INSERT` ».

Vous pouvez aussi charger des fichiers de données en utilisant l'utilitaire `mysqlimport`; Il opère en envoyant la commande `LOAD DATA INFILE` au serveur. L'option `--local` fais que `mysqlimport` lit les fichiers de données chez le client. Vous pouvez spécifier l'option `--compress` pour avoir de meilleurs performances avec les connexions lentes si le client et le serveur supportent le protocole compressé. See Section 8.10, « `mysqlimport`, importer des données depuis des fichiers texte ».

Si vous spécifiez le mot clef `LOW_PRIORITY`, l'exécution de la commande `LOAD DATA` est ajournée jusqu'à ce qu'aucun client ne lise plus de la table.

Si vous spécifiez le mot clef `CONCURRENT` avec un table au format `MyISAM`, les autres threads pourront accéder à la table durant l'exécution de la commande `LOAD DATA`. L'utilisation de cette option ralentira un peu les performances de `LOAD DATA` même si aucun thread n'utilise la table en même si aucun autre thread n'accède à la table en même temps.

Si le mot clé `LOCAL` est spécifié, il est interprété en suivant les règles suivantes :

- Si `LOCAL` est spécifié, le fichier est lu par le programme client, et envoyé vers l'hôte.

- Si `LOCAL` n'est pas spécifiée, le fichier doit être sur le serveur hôte, et sera lu directement par le serveur.

`LOCAL` est disponible depuis MySQL 3.22.6 ou plus récent.

Pour des raisons de sécurité, lorsque les fichiers sont lus sur le serveur, ils doivent se trouver dans le répertoire de la base de données courante, ou bien être lisible par tous. Pour utiliser la commande `LOAD DATA INFILE` sur des fichiers du serveur, vous devez avoir le droit de `FILE` sur le serveur. See Section 5.5.3, « Droits fournis par MySQL ».

Utiliser `LOCAL` est plus lent que de laisser le serveur accéder directement aux fichiers, car le contenu du fichier doit être envoyé via le réseau au serveur. D'un autre coté, vous n'aurez pas besoin de droits de `FILE` pour faire un chargement local.

Depuis MySQL 3.23.49 et MySQL 4.0.2 (4.0.13 sur Windows), `LOCAL` fonctionne uniquement si votre serveur et votre client ont été configuré pour. Par exemple, si `mysqld` a été lancé avec `--local-infile=0`, `LOCAL` ne fonctionnera pas. See Section 5.4.4, « Problèmes de sécurité avec LOAD DATA LOCAL ».

Si vous avez besoin de lire des données `LOAD DATA` depuis un pipe, vous devez utiliser la technique suivante :

    mkfifo /mysql/db/x/x
    chmod 666 /mysql/db/x/x
    cat < /dev/tcp/10.1.1.12/4711 > /mysql/db/x/x
    mysql -e "LOAD DATA INFILE 'x' INTO TABLE x" x

Si vous utilisez une version de MySQL plus ancienne que 3.23.25, vous pouvez uniquement utiliser cette technique avec `LOAD DATA LOCAL INFILE`.

Si vous utilisez une version de MySQL antérieure à la 3.23.24 vous ne pouvez lire à partir d'un FIFO avec `LOAD DATA INFILE`. Si vous avez besoin de lire à partir d'un FIFO (par exemple la sortie de gunzip), utilisez `LOAD DATA LOCAL INFILE`.

Lorsque les fichiers de données sont sur le serveur, celui-ci utilise les règles suivantes :

- Si un chemin absolu est fourni, le serveur utilise le chemin tel quel.

- Si un chemin relatif est fourni, avec un ou plusieurs éléments de dossiers, le serveur recherche le fichier relativement à son dossier de données.

- Si le fichier n'a pas d'éléments de dossier, le serveur recherche les données dans le dossier de base de données courante.

Notez que ces règles font qu'un fichier tel que `./myfile.txt` est lu dans le dossier de données du serveur, alors que s'il est nommé `myfile.txt`, il sera lu dans le dossier de base de données courante. Par exemple, la commande `LOAD DATA` suivante lit le fichier `donnees.txt` dans le dossier de la base `db1` car `db1` est la base de données courante, même si la commande charge explicitement le fichier dans la base de données `db2` :

    mysql> USE db1;
    mysql> LOAD DATA INFILE "donnees.txt" INTO TABLE db2.ma_table;

Les mots réservés `REPLACE` et `IGNORE` contrôlent la méthode d'insertion de lignes lorsque des doublons apparaissent pour les clés uniques.

Si vous spécifiez `REPLACE`, les nouvelles lignes remplaceront les anciennes. See Section 13.1.6, « Syntaxe de `REPLACE` ».

Si vous spécifiez `IGNORE`, les nouvelles lignes seront ignorées. Si vous ne spécifiez pas cette option, une erreur sera générée à chaque doublon, et le reste du fichier sera ignoré. Avec l'option `LOCAL`, le comportement par défaut est le même que si `IGNORE` est spécifié : ceci est dû au fait que le serveur n'a pas moyen de stopper la transmission du fichier au milieu de l'opération.

Si vous chargez un fichier sur votre machine client avec l'option `LOCAL`, le serveur ne peut pas interrompre la transmission du fichier au milieu de l'opération : par défaut, il utilisera l'option `IGNORE`.

Si vous voulez ignorer les clés étrangères le temps du chargement du fichier, utilisez la commande `SET FOREIGN_KEY_CHECKS=0` avant d'exécuter `LOAD DATA`.

Si vous utilisez `LOAD DATA INFILE` sur une table vide de type `MyISAM`, tous les index non-uniques seront créés dans un processus séparé (tout comme `REPAIR`). Cela rend `LOAD DATA INFILE` beaucoup plus rapide si vous avez plusieurs index. See Section 5.7.3, « Utilisation de `myisamchk` pour la maintenance des tables et leur recouvrement ».

`LOAD DATA INFILE` est le complémentaire de `SELECT ... INTO OUTFILE`. See Section 13.1.7, « Syntaxe de `SELECT` ». Pour écrire des données depuis une table dans un fichier, utilisez `SELECT ... INTO OUTFILE`. Pour lire les données dans la table, utilisez `LOAD DATA INFILE`. La syntaxe des clauses `FIELDS` et `LINES` est la même pour les deux commandes. Ces deux clauses sont optionnelles, mais `FIELDS` doit précéder `LINES`, si les deux sont spécifiées.

Si vous spécifiez la clause `FIELDS`, les sous-clauses `TERMINATED BY`, `[OPTIONALLY] ENCLOSED BY`, et `ESCAPED BY` sont aussi optionnelles, mais vous devez en spécifier au moins une.

Si vous ne spécifiez par de clause `FIELDS`, les valeurs par défaut sont :

    FIELDS TERMINATED BY '\t' ENCLOSED BY '' ESCAPED BY '\\'

Si vous ne spécifiez par de clause `LINES`, les valeurs par défaut sont :

    LINES TERMINATED BY '\n'

En d'autres termes, les valeurs par défaut font que `LOAD DATA INFILE` lit les données comme suit :

- Recherche des limites de lignes parmi les nouvelles lignes.

- Si `LINES STARTING BY prefix` est utilisé, lit jusqu'au préfixe, et commence à lire après le préfixe. Si la ligne n'inclut pas de préfixe, elle sera ignorée.

- Scinde les lignes en champs avec les tabulations.

- Ne suppose pas que les champs sont entourés de guillemets.

- Interprète les occurrences de tabulation, nouvelle ligne, ‘`'\'`’ précédées par ‘`'\'`’ comme des caractères littéraux qui font partie de la valeur d'un champs.

A l'inverse, les valeurs par défaut font que `SELECT ... INTO OUTFILE` écrit les données comme ceci :

- Ecrivez des tabulations entre les champs.

- N'entourez pas les champs de guillemets.

- Utilisez ‘`\`’ pour échapper les occurrences de tabulation, nouvelle ligne, ‘`\`’ trouvées dans les valeurs.

- Insère une nouvelle ligne entre les lignes.

Notez que pour utiliser `FIELDS ESCAPED BY '\\'`, vous devez spécifier deux anti-slash pour que cette valeur soit interprétée comme un anti-slash simple.

Note : si vous avez généré le fichier sur Windows, vous devrez peut-être utiliser `LINES TERMINATED BY '\r\n'` pour lire le fichier correctement, car les programmes Windows utilisent généralement deux caractères comme fin de ligne. Certains programmes, comme `WordPad`, peuvent utiliser `\r` comme terminateur de ligne lors de l'écriture. Pour lire ces fichiers, utilisez `LINES TERMINATED BY '\r`.

L'option `IGNORE nombre LINES` sert à ignorer une en-tête de fichier, telle que des noms de colonnes, qui débutent parfois un fichier à charger :

    mysql> LOAD DATA INFILE "/tmp/nom_fichier" INTO TABLE test IGNORE 1 LINES;

Lorsque vous utilisez `SELECT ... INTO OUTFILE` conjointement avec `LOAD DATA INFILE` pour écrire des données dans un fichier et les relire dans une table, les options de `FIELDS` et `LINES` doivent être identiques. Sinon, `LOAD DATA INFILE` ne pourra pas interpréter le contenu du fichier correctement. Supposez que la commande `SELECT ... INTO OUTFILE` ait écrit un fichier délimité par des virgules :

    mysql> SELECT * INTO OUTFILE 'donnees.txt'
        ->          FIELDS TERMINATED BY ','
        ->          FROM ...;

Pour lire ce fichier, la commande correcte serait :

    mysql> LOAD DATA INFILE 'donnees.txt' INTO TABLE table2
        ->           FIELDS TERMINATED BY ',';

Si au contraire, vous essayez de lire le fichier avec la commande ci-dessous, cela ne fonctionnera pas, car la commande `LOAD DATA INFILE` essaie de lire des tabulations entre les champs :

    mysql> LOAD DATA INFILE 'donnees.txt' INTO TABLE table2
        ->           FIELDS TERMINATED BY '\t';

Il est probable que chaque ligne d'entrée sera interprétée que comme un seul champ.

La commande `LOAD DATA INFILE` peut être utilisée pour lire des données issues d'autres sources. Par exemple, un fichier au format dBASE présente des champs séparés par des virgules, et entourés de guillemets doubles. Si les lignes sont terminées par de nouvelles lignes, la commande ci-dessous illustre la relecture d'un tel fichier avec MySQL :

    mysql> LOAD DATA INFILE 'donnees.txt' INTO TABLE nom_de_table
        ->           FIELDS TERMINATED BY ',' ENCLOSED BY '"'
        ->           LINES TERMINATED BY '\n';

Les clauses `FIELDS` et `LINES` peuvent prendre des chaînes vides comme valeur. S'il la chaîne n'est pas vide, `FIELDS [OPTIONALLY] ENCLOSED BY` et `FIELDS ESCAPED BY` ne doivent avoir qu'un seul caractère. Les valeurs de `FIELDS TERMINATED BY` et `LINES TERMINATED BY` peuvent avoir plus d'un caractère. Par exemple, pour écrire des lignes terminées par le couple retour chariot/nouvelle ligne, ou pour lire un tel fichier, spécifiez la clause `LINES TERMINATED BY '\r\n'`.

Par exemple, pour charger un fichier de blagues, qui sont séparées par une ligne de `%%`, dans une table vous pouvez faire :

    CREATE TABLE blagues (
       a INT NOT NULL AUTO_INCREMENT PRIMARY KEY,
       blague TEXT NOT NULL
       );
    LOAD DATA INFILE "/tmp/blagues.txt" INTO TABLE blagues FIELDS TERMINATED BY ""
    LINES TERMINATED BY "\n%%\n" (blague);

`FIELDS [OPTIONALLY] ENCLOSED BY` contrôle la mise entre guillemets des champs. Pour l'écriture de fichier (`SELECT ... INTO OUTFILE`), si vous omettez le mot `OPTIONALLY`, tous les champs seront entourés par le caractère spécifié dans la clause `ENCLOSED BY`. Par exemple, si la virgule est utilisée comme séparateur de champs :

    "1","une chaîne","100.20"
    "2","une chaîne contenant une , virgule","102.20"
    "3","une chaîne contenant un \" guillemet","102.20"
    "4","une chaîne contenant un \", guillemet et une virgule","102.20"

Si vous spécifiez `OPTIONALLY`, le caractère `ENCLOSED BY` n'est utilisé que pour protéger les colonnes de types `CHAR` et `VARCHAR` :

    1,"une chaîne",100.20
    2,"une chaîne contenant une , virgule",102.20
    3,"une chaîne contenant un \" guillemet",102.20
    4,"une chaîne contenant un \", guillemet et une virgule",102.20

Notez que les occurrences du caractère `ENCLOSED BY` dans un champs sont échappée en les préfixant avec le caractère `ESCAPED BY`. Notez aussi que si vous spécifiez un caractère d'échappement vide, il n'est pas possible de garantir que les champs seront correctement relus par `LOAD DATA INFILE`. Par exemple, l'exemple ci-dessus apparaîtra comme montré ci-dessous. Notez que le second champ de la quatrième ligne comporte une virgule suivant un guillemet qui semble (mais c'est faux) terminer la ligne :

    1,"une chaîne",100.20
    2,"une chaîne contenant une , virgule",102.20
    3,"une chaîne contenant un " guillemet",102.20
    4,"une chaîne contenant un ", guillemet et une virgule",102.20

Lors des lectures, le caractère `ENCLOSED BY`, s'il est présent, est supprimé des extrémités de la valeur du champ. (ce qui est vrai, qu'il y ait l'option `OPTIONALLY` ou pas). Les occurrences du caractère `ENCLOSED BY`, précédées par le caractère `ESCAPED BY` sont interprétées comme faisant partie de la valeur du champ. Les caractères `ENCLOSED BY` doublées, apparaissant dans la chaîne, sont interprétés comme le caractère `ENCLOSED BY` lui-même. Par exemple, si `ENCLOSED BY '"'` est spécifié, les guillemets sont gérés comme ceci :

    "Le ""GRAND"" chef"  -> Le "GRAND" chef
    Le "GRAND" chef      -> Le "GRAND" chef
    Le ""GRAND"" chef    -> Le ""GRAND"" chef

`FIELDS ESCAPED BY` contrôle les caractères spéciaux. Si le caractère `FIELDS ESCAPED BY` n'est pas vide, il est utilisé pour préfixer les caractères suivants en écriture :

- La caractère `FIELDS ESCAPED BY`

- Le caractère `FIELDS [OPTIONALLY] ENCLOSED BY`

- Le premier caractère des valeurs de `FIELDS TERMINATED BY` et `LINES TERMINATED BY`

- ASCII `0` (en fait, ce qui est écrit après le caractère d'échappement est le caractère ASCII `'0'`, et non pas le code ASCII de zéro)

Si le caractère `FIELDS ESCAPED BY` est vide, aucun caractère ne sera échappé. Ce n'est probablement pas une bonne idée de spécifier un caractère d'échappement vide, en particulier si les valeurs dans vos champs risquent d'utiliser l'un des caractères de la liste ci-dessus.

En lecture, si le caractère `FIELDS ESCAPED BY` n'est pas vide, les occurrences de ce caractère sont supprimées, et le caractère suivant est lu littéralement. Les exceptions à cette règle sont ‘`0`’ ou ‘`N`’ (par exemple, `0` ou `\N` si le caractère d'échappement est ‘`\`’). Ces séquences sont interprétées comme l'octet nul (ASCII `0`) et la valeur `NULL`. Voyez plus bas pour la gestion des valeurs `NULL`.

Pour plus d'informations sur la syntaxe avec les caractères d'échappement ‘`\`’, consultez Section 9.1, « Littéraux : comment écrire les chaînes et les nombres ».

Dans certains cas, les options de `FIELDS` et `LINES` interfèrent entre elles :

- Si le caractère de `LINES TERMINATED BY` est une chaîne vide et que celui de `FIELDS TERMINATED BY` ne l'est pas, ce dernier sera celui utilisé pour `LINES TERMINATED BY`.

- Si les valeurs `FIELDS TERMINATED BY` et `FIELDS ENCLOSED BY` sont vides toutes les deux (`''`), un format à taille de champ fixe est utilisé. Avec ce format, aucun délimiteur n'est utilisé entre les champs. Au lieu de cela, les valeurs des colonnes sont écrites avec leur configuration d'affichage. Par exemple, si une colonne a été déclarée `INT(7)`, la valeur de cette colonne sera écrite avec 7 caractères. Lors de la relecture, la valeur de la colonne sera obtenue en lisant à nouveau 7 caractères. Ce format à taille fixe affecte la gestion de la valeur `NULL`; voyez plus loin pour cela. Notez que ce format ne fonctionne pas avec les jeux de caractères multi-octets.

La gestion des valeurs `NULL` dépend des options `FIELDS` et `LINES` que vous utilisez :

- Pour les valeurs par défaut de `FIELDS` et `LINES`, `NULL` est écrit `\N` et `\N` est lu `NULL` (en supposant que le caractère d'échappement est ‘`\`’).

- Si `FIELDS ENCLOSED BY` n'est pas vide, un champ contenant le mot `NULL` comme valeur sera lu comme la valeur `NULL` (ce qui diffère du mot `NULL`, entouré du caractère `FIELDS ENCLOSED BY`, qui sera lu comme le mot `'NULL'`).

- Si `FIELDS ESCAPED BY` est vide, `NULL` est écrit comme le mot `'NULL'`.

- Avec le format à taille fixe (ce qui arrive si `FIELDS TERMINATED BY` et `FIELDS ENCLOSED BY` sont tous les deux vides), les valeurs `NULL` sont écrites sous forme de chaîne vide. Notez que cela fait que `NULL` et les chaînes vides seront représentées par une valeur qui ne les distingue pas l'une de l'autre. Si vous avez besoin de différencier entre les deux, n'utilisez par ce format !

Certains cas ne sont pas supportés par `LOAD DATA INFILE`:

- Lignes à tailles fixes (`FIELDS TERMINATED BY` et `FIELDS ENCLOSED BY` sont tous les deux vides) et les types de colonne `BLOB` ou `TEXT`.

- Si vous spécifiez un séparateur qui est le même qu'un autre préfixe, `LOAD DATA INFILE` ne sera pas capable de relire proprement le résultat. Par exemple, la clause `FIELDS` suivante posera sûrement des problèmes :

      FIELDS TERMINATED BY '"' ENCLOSED BY '"'

- Si `FIELDS ESCAPED BY` est vide, une valeur de colonne qui contient une occurrence de `FIELDS ENCLOSED BY` ou de `LINES TERMINATED BY` suivi du caractère `FIELDS TERMINATED BY` interrompra la lecture de `LOAD DATA INFILE` trop tôt. Cela est dû au fait que `LOAD DATA INFILE` ne peut pas faire la différence entre la valeur dans le champ et la fin de la ligne.

L'exemple suivant charge toutes les colonnes de la table `persondata` :

    mysql> LOAD DATA INFILE 'persondata.txt' INTO TABLE persondata;

Aucun champ n'est spécifié, ce qui fait que `LOAD DATA INFILE` s'attend à ce que les lignes lues contiennent le bon nombre de champs. Les valeurs par défaut de `FIELDS` et `LINES` sont utilisées.

Si vous voulez charger uniquement quelques colonnes dans une table, spécifiez la liste des champs :

    mysql> LOAD DATA INFILE 'persondata.txt'
        ->           INTO TABLE persondata (col1,col2,...);

Vous devez aussi spécifier les champs si l'ordre dans lequel ils seront lus diffère de l'ordre des colonnes dans la table. Sinon, MySQL ne pourra pas savoir à quelle colonne correspond une valeur.

Si une ligne a trop peu de champs, les colonnes omises prendront leur valeur par défaut. Les affectations de valeurs par défaut sont décrites dans Section 13.2.5, « Syntaxe de `CREATE TABLE` ».

Une valeur de champs vide et un champ manquant ne seront pas interprétés de la même fa¸on :

- Pour les types chaîne, la colonne est remplie avec la chaîne vide.

- Pour les types numériques, la colonne est mise à `0`.

- Pour les types dates et heures, la colonne est mise au zéro approprié pour le type. See Section 11.3, « Les types date et heure ».

Notez que vous obtiendrez le même résultat en assignant à ces différents types de champs la chaîne vide dans une commande `INSERT` ou `UPDATE`.

Les colonnes `TIMESTAMP` prendront la date et l'heure courante uniquement si on leur affecte la valeur `NULL`, ou (pour la première colonne `TIMESTAMP` seulement) si la colonne `TIMESTAMP` est ignorée de la liste des colonnes spécifiée.

Si une ligne d'entrée comporte trop de colonnes, les champs en trop sont ignorés, et le nombre d'alertes est incrémenté.

`LOAD DATA INFILE` considère toutes les valeurs lues comme des chaînes de caractères : vous ne pourrez donc pas utiliser la forme numérique des colonnes `ENUM` ou `SET`, comme d'habitude. Toutes les colonnes `ENUM` et `SET` doivent être spécifiée comme des chaînes ! Si vous utilisez l'API C, vous pouvez obtenir des informations à propos de la requête en utilisant la fonction `mysql_info()` quand `LOAD DATA INFILE` se termine. Le format de la chaîne d'informations est le suivant :

    Records: 1  Deleted: 0  Skipped: 0  Warnings: 0

Les alertes sont générées dans les mêmes circonstances que pour la commande `INSERT` (see Section 13.1.4, « Syntaxe de `INSERT` »), excepté que `LOAD DATA INFILE` génère aussi des alertes s'il y a trop peu ou trop de champs dans une ligne. Les alertes ne sont pas stockées; le nombre d'alertes est la seule indication. Si vous recevez des alertes et vous voulez savoir exactement ce qui s'est passé, exécutez une commande `SELECT ... INTO OUTFILE` dans un autre fichier et comparez le avec le fichier original.

En MySQL version 4.1.1 vous pouvez utiliser `SHOW WARNINGS` pour obtenir la liste des premières `max_error_count` alertes. See Section 13.5.3.19, « `SHOW WARNINGS | ERRORS` ».

Pour plus d'informations sur les performances de `INSERT` comparées à `LOAD DATA INFILE` et accélérer `LOAD DATA INFILE` : See Section 7.2.14, « Vitesse des requêtes `INSERT` ».

### 13.1.6. 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. See Section 13.1.4, « Syntaxe de `INSERT` ».

En d'autres termes, vous ne pouvez pas accéder aux valeurs de l'ancienne ligne à partir d'une requête `REPLACE`. Dans quelques vieilles versions de MySQL, il apparaît que c'était possible, mais c'etait un dysfonctionnement qui a été corrigé depuis.

Pour utiliser `REPLACE` vous devez avoir les privilèges `INSERT` et `DELETE` sur la table.

Quand vous utilisez une commande `REPLACE`, `mysql_affected_rows()` retournera 2 si une nouvelle ligne en remplace une existante, et cela parce qu'il y aura eu une insertion puis une suppression.

Cela aide à savoir si `REPLACE` a ajouté ou a remplacé une ligne : Testez si le nombre de lignes affectées est égal à 1 (ajout) ou s'il est égal à 2 (remplacement).

Notez que si vous n'utilisez pas un index `UNIQUE` ou une `PRIMARY KEY`, utiliser un `REPLACE` n'a pas de sens vu que cela revient à utiliser un `INSERT`. Il devient équivalent à `INSERT`, car il n'y a pas d'index à utiliser pour déterminer si un nouvelle ligne est un double d'une autre.

Voici quelques détails sur l'algorithme utilisé : Il est aussi utilisé par `LOAD DATA ... REPLACE`.

1. Insertion de la ligne dans la table

2. Si une erreur de clé dupliqué ou de clé unique ou de clé primaire survient :

   1. Annuler les changements de clés

   2. Essayer à nouveau d'insérer la clé primaire et unique dans la table

### 13.1.7. 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]]

`SELECT` est utilisé pour obtenir des enregistrements venant d'une ou plusieurs tables. Le support des commandes `UNION` et des sous-requêtes est disponibles depuis MySQL 4.0 et 4.1, respectivement. Voir Section 13.1.7.2, « Syntaxe de `UNION` » et Section 13.1.8, « Sous-sélections (`SubSELECT`) ».

- Chaque `select_expr` indique une colonne à lire.

- `table_references` indique la ou les tables à utiliser. La syntaxe est décrite dans Section 13.1.7.1, « Syntaxe de `JOIN` ».

- `where_definition` indique les conditions que les lignes sélectionnées doivent satisfaire.

`SELECT` peut aussi être utilisée pour lire des lignes calculées, sans référence à une table.

Par exemple :

    mysql> SELECT 1 + 1;
             -> 2

Tous les mots-clés utilisés doivent être donnés exactement dans le même ordre que ci-dessus. Par exemple, une clause `HAVING` doit être placée après toute clause `GROUP BY` et avant toute clause `ORDER BY`.

- Une expression `SELECT` peut recevoir un alias en utilisant `AS`. L'alias est utilisé de la même fa¸on que le nom du champ et peut être employé avec des clauses `ORDER BY` ou `HAVING`. Par exemple :

      mysql> SELECT CONCAT(last_name,', ',first_name) AS full_name
          FROM mytable ORDER BY full_name;

  Le mot clé `AS` est optionnel lors de la création d'un alias pour une expression `SELECT`. L'exemple précédent aurait pu être écrit comme ceci :

      mysql> SELECT CONCAT(last_name,', ',first_name) full_name
          FROM mytable ORDER BY full_name;

  Comme `AS` est optionnel, un problème subtil peut survenir si vous oubliez une virgule entre deux expressions de `SELECT` : MySQL va interpréter la seconde comme un alias de la première. Par exemple, dans la commande suivante, `columnb` est traité comme un nom d'alias :

      mysql> SELECT columna columnb FROM mytable;

- Il n'est pas possible d'utiliser un alias de champ dans une clause `WHERE`, car la valeur du champ peut ne pas être définie lorsque la clause `WHERE` est exécutée. See Section A.5.4, « Problèmes avec les `alias` ».

- La clause `FROM table_references` indique les tables à partir desquelles nous allons obtenir les enregistrements. Si vous indiquez le nom de plusieurs tables, vous faites une jointure. Pour davantage d'informations sur la syntaxe des jointures, consultez Section 13.1.7.1, « Syntaxe de `JOIN` ». Pour chaque table spécifiée, vous pouvez éventuellement indiquer un alias.

      tbl_name [[AS] alias]
          [[USE INDEX (key_list)]
            | [IGNORE INDEX (key_list)]
            | [FORCE INDEX (key_list)]]

  L'utilisation de `USE INDEX`, `IGNORE INDEX`, `FORCE INDEX` pour donner des conseils d'optimisation à l'optimiseur d'index. Section 13.1.7.1, « Syntaxe de `JOIN` ».

  En MySQL 4.0.14, vous pouvez utiliser `SET MAX_SEEKS_FOR_KEY=value` comme une alternative pour forcer MySQL à choisir un scan d'index, plutôt qu'un scan de table.

- Vous pouvez faire référence à une table avec `nom_de_table` (au sein de la base de données courante), ou avec `dbname.nom_de_table` pour expliciter le nom de la base de données. Vous pouvez vous référer à un champ avec `nom_de_colonne`, `nom_de_table.nom_de_colonne`, ou `db_name.nom_de_table.nom_de_colonne`. Vous n'êtes pas obligés d'indiquer de préfixe `nom_de_table` ou `db_name.nom_de_table` pour une référence à un champ dans un `SELECT`, à moins que la référence ne soit ambigue. Consultez Section 9.2, « Noms de bases, tables, index, colonnes et alias », pour des exemples d'ambiguîtés qui nécessitent des formes plus explicites de référence à des champs.

- Depuis la version 4.1.0, vous êtes autorisés à spécifier `DUAL` comme nom de table, dans les situations ou aucune table n'est référencé. C'est une fonctionnalité pure de compatibilité, car certains autres serveurs requièrent cette syntaxe.

      mysql> SELECT 1 + 1 FROM DUAL;
               -> 2

- Une référence à une table peut être aliasée en utilisant `nom_de_table [AS] alias_name` :

      mysql> SELECT t1.name, t2.salary FROM employee AS t1, info AS t2
          ->        WHERE t1.name = t2.name;
      mysql> SELECT t1.name, t2.salary FROM employee t1, info t2
          ->        WHERE t1.name = t2.name;

- Dans la clause `WHERE`, vous pouvez utiliser toutes les fonctions que MySQL supporte, hormis les fonctions d'agrégation. See Chapitre 12, Fonctions à utiliser dans les clauses `SELECT` et `WHERE`.

- Les colonnes sélectionnées dans le résultat peuvent être nommées dans les clauses `ORDER BY` et `GROUP BY` en utilisant leur nom de colonne, les alias ou leur position de colonne. Les positions commencent à 1 :

      mysql> SELECT college, region, seed FROM tournament
          ->        ORDER BY region, seed;
      mysql> SELECT college, region AS r, seed AS s FROM tournament
          ->        ORDER BY r, s;
      mysql> SELECT college, region, seed FROM tournament
          ->        ORDER BY 2, 3;

  Pour trier dans l'ordre inverse, ajoutez le mot-clé `DESC` (descendant) au nom du champ dans la clause `ORDER BY` qui vous permet de trier. Par défaut, l'ordre ascendant est utilisé; ceci peut être indiqué de fa¸on explicite en utilisant le mot-clé `ASC`.

  L'utilisation des positions de colonnes est obsolète, car la syntaxe a été supprimée du SQL standard.

- Si vous utilisez `GROUP BY`, les lignes sont triées en fonction des colonnes `GROUP BY` comme si on avait ajouté la clause `ORDER BY` pour ces colonnes. MySQL a amélioré la clause `GROUP BY` depuis la version 3.23.34 pour que vous puissiez aussi spécifier `ASC` et `DESC` après le nom de la colonne :

      SELECT a, COUNT(b) FROM test_table GROUP BY a DESC

- MySQL améliore l'utilisation de `GROUP BY` en vous autorisant à l'utiliser avec des champs qui ne sont pas mentionnés dans la clause `GROUP BY`. Si vous n'obtenez pas les résultats que vous attendiez, lisez la description de `GROUP BY`. See Section 12.9, « Fonctions et options à utiliser dans les clauses `GROUP BY` ».

- Depuis MySQL 4.1.1, `GROUP BY` dispose de l'option `WITH ROLLUP`. See Section 12.9.2, « Options de `GROUP BY` ».

- La clause `HAVING` peut faire référence à n'importe quel champs ou alias défini dans `select_expr`. C'est évalué en dernier lieu, juste avant que les éléments ne soient envoyés au client, sans aucune optimisation.

- N'utilisez pas `HAVING` pour des éléments qui devraient être dans la clause `WHERE`. Par exemple, n'écrivez pas ceci :

      mysql> SELECT nom_de_colonne FROM nom_de_table HAVING nom_de_colonne > 0;

  Ecrivez plutôt cela :

      mysql> SELECT nom_de_colonne FROM nom_de_table WHERE nom_de_colonne > 0;

  Dans les versions 3.22.5 et supérieures de MySQL, vous pouvez aussi écrire des requêtes ainsi :

      mysql> SELECT user,MAX(salary) FROM users
          ->        GROUP BY user HAVING MAX(salary)>10;

  Dans des versions plus anciennes de MySQL, vous pouvez écrire à la place :

      mysql> SELECT user,MAX(salary) AS sum FROM users
          ->        group by user HAVING sum>10;

- La clause `HAVING` peut utiliser des fonctions d'agrégation, alors que la clause `WHERE` ne le peut pas :

      mysql> SELECT user, MAX(salary) FROM users
          ->     GROUP BY user HAVING MAX(salary)>10;

  Cependant, cela ne fonctionne pas dans les anciennes versions du serveur MySQL, : avant la version 3.22.5. Au lieu de cela, ajoutez un alias de colonne dans la liste de colonnes, et faites référence à cet alias dans la colonne `HAVING` :

      mysql> SELECT user, MAX(salary) AS max_salary FROM users
          ->     GROUP BY user HAVING max_salary>10;

- La clause `LIMIT` peut être utilisée pour limiter le nombre d'enregistrements retournés par la commande `SELECT`. `LIMIT` accepte un ou deux arguments numériques. Ces arguments doivent être des entiers constants.

  Avec un argument, la valeur spécifie le nombre de lignes à retourner depuis le début du jeu de résultat. Si deux arguments sont donnés, le premier indique le décalage du premier enregistrement à retourner, le second donne le nombre maximum d'enregistrement à retourner. Le décalage du premier enregistrement est 0 (pas 1) :

  Pour être compatible avec PostgreSQL, MySQL supporte aussi la syntaxe : `LIMIT row_count OFFSET offset`.

      mysql> SELECT * FROM table LIMIT 5,10;  # Retourne les enregistrements 6 à 15

  Pour obtenir tous les enregistrement d'un certain décalage jusqu'à la fin du résultat, vous pouvez utiliser de grands entier en tant que second paramètre :

      mysql> SELECT * FROM table LIMIT 95,18446744073709551615; # Retourne les enregistrements de 96 jusqu'au dernier.

  Si un seul argument est donné, il indique le nombre maximum d'enregistrements à retourner :

      mysql> SELECT * FROM table LIMIT 5;     # Retourne les 5 premiers enregistrements

  Autrement dit, `LIMIT n` est équivalent à `LIMIT 0,n`.

- La forme `SELECT ... INTO OUTFILE 'nom_fichier'` de `SELECT` écrit les lignes sélectionnées dans un fichier. Le fichier est crée sur le serveur et ne peut y être déjà présent (cela permet entre autre d'éviter la destruction des tables et de fichiers tel que `/etc/passwd`). Vous devez avoir le droit `FILE` sur le serveur pour utiliser cette forme de `SELECT`.

  `SELECT ... INTO OUTFILE` à pour but principal de vous permettre de réaliser des dumps rapides des tables sur la machine serveur. Si vous voulez créer le fichier sur une autre machine, vous ne pouvez utiliser `SELECT ... INTO OUTFILE`. Dans ce cas là, vous pouvez utiliser à la place un programme client comme `mysqldump --tab` ou `mysql -e "SELECT ..." > fichier` pour générer le fichier.

  `SELECT ... INTO OUTFILE` est le complément de `LOAD DATA INFILE`; La syntaxe pour la partie `export_options` de la requête se compose des mêmes clauses `FIELDS` et `LINES` que celles utilisées avec la commande `LOAD DATA INFILE`. See Section 13.1.5, « Syntaxe de `LOAD DATA INFILE` ».

  Dans le fichier résultant, seul les caractères suivants sont protégés par le caractère `ESCAPED BY` :

  - Le caractère `ESCAPED BY`

  - Les premier caractère de `FIELDS TERMINATED BY`

  - Les premier caractère de `LINES TERMINATED BY`

  - `ASCII 0` est convertit en `ESCAPED BY` suivi de 0 (`ASCII 48`).

  Si le caractère `FIELDS ESCAPED BY` est vide, aucun caractère n'est protégé, et `NULL` vaut `NULL`, et non `\N`. Il est probable que ce ne soit pas une bonne idée de spécifier un caractère de protection vide, en particulier sir les valeurs de vos champs peuvent être n'importe quoi.

  La raison de ce qui précède est que vous devez impérativement protéger chaque caractère `FIELDS TERMINATED BY`, `ESCAPED BY`, ou `LINES TERMINATED BY` pour assurer une relecture fiable du fichier. Le caractère `ASCII 0` est échappé pour assurer la lisibilité sur certains clients.

  Comme le fichier résultant ne se doit pas d'être syntaxiquement conforme à SQL, vous n'avez besoin d'échapper rien d'autre.

  Voila un exemple de relecture de fichier au format utilisé par plusieurs anciens programmes.

      SELECT a,b,a+b INTO OUTFILE '/tmp/result.text'
      FIELDS TERMINATED BY ',' OPTIONALLY ENCLOSED BY '"'
      LINES TERMINATED BY '\n'
      FROM test_table;

- Si vous utilisez `INTO DUMPFILE` au lieu de `INTO OUTFILE`, MySQL n'écrira qu'une seule ligne dans le fichier, sans aucun caractère de fin de ligne ou de colonne, ni d'échappement. Cela est utile lorsque vous voulez enregistrer un `BLOB` dans un fichier.

- Note : notez que les fichiers crées par `INTO OUTFILE` et `INTO DUMPFILE` sera lisible par tout les utilisateurs ! La raison est que le serveur MySQL ne peut créer de fichier appartenant à autre que l'utilisateur qui l'a mis en route. (vous devez éviter d'exécuter `mysqld` en tant que root), le fichier doit se composer de mot lisible pour que les données puissent être récupérées.

- Une clause `PROCEDURE` indique une procédure qui doit traiter les lignes du jeu de résultat. Pour un exemple, voyez Section 27.3.1, « La procédure Analyse ».

- Si vous utilisez la clause `FOR UPDATE` avec un gestionnaire de tables qui gère les verrous de lignes ou de pages, les lignes seront verrouillées.

Après le mot `SELECT`, vous pouvez ajouter certaines options qui affectent le comportement de la commande.

Les options `DISTINCT`, `DISTINCTROW` et `ALL` indiquent quels enregistrements avec doublons doivent être retournés. Par défaut, c'est (`ALL`), retournant ainsi tous les enregistrements. `DISTINCT` et `DISTINCTROW` sont synonymes et indique que les doublons doivent être éliminés du résultat.

`HIGH_PRIORITY`, `STRAIGHT_JOIN`, et les options commen¸ants par `SQL_` sont des extensions MySQL au standard SQL.

- `HIGH_PRIORITY` donne à une commande `SELECT` une plus grande priorité qu'une commande qui modifie une table. Vous devez l'utiliser seulement pour les requêtes qui sont très rapides et qui doivent être effectuées en premier lieu. Une requête `SELECT HIGH_PRIORITY` s'exécutera sur une table verrouillée en lecture même si une commande de mise à jour attend que la table soit libérée.

  `HIGH_PRIORITY` ne peut être utilisée avec les commandes `SELECT` qui font partie d'une `UNION`.

- `STRAIGHT_JOIN` force l'optimiseur à joindre les tables dans l'ordre dans lequel elles sont listées dans la clause `FROM`. Vous pouvez utiliser cela pour accélérer la requête, si les tables sont réordonnées sub-optimalement par l'optimiseur. See Section 7.2.1, « Syntaxe de `EXPLAIN` (Obtenir des informations sur les `SELECT`) ». `STRAIGHT_JOIN` peut aussi être utilisée dans la liste `table_references`. See Section 13.1.7.1, « Syntaxe de `JOIN` ».

- `SQL_BIG_RESULT` peut être utilisé avec `GROUP BY` ou `DISTINCT` pour indiquer à l'optimiseur que le résultat comportera beaucoup d'enregistrements. Dans ce cas, MySQL utilisera si besoin directement les bases temporaires stockées sur le disque. MySQL préférera, dans ce cas, trier que d'obtenir une table temporaire avec une clé sur les éléments du `GROUP BY`.

- `SQL_BUFFER_RESULT` forcera le résultat à être stocké dans une table temporaire. Ceci va aider MySQL à libérer plus tôt les verrous des tables et aidera aussi dans les cas ou l'envoi du résultat au client prend un temps assez conséquent.

- `SQL_SMALL_RESULT`, une option spécifique à MySQL, peut être utilisée avec `GROUP BY` ou `DISTINCT` pour indiquer à l'optimiseur que le résultat sera petit. Dans ce cas, MySQL utilise des tables temporaires rapides pour stocker la table résultante plutôt que d'utiliser le tri. Dans MySQL 3.23, ceci n'est normalement pas nécessaire.

- `SQL_CALC_FOUND_ROWS` (version 4.0.0 et supérieure) indique à MySQL de calculer combien d'enregistrements seront dans le jeu de résultats, indépendamment de n'importe quelle clause `LIMIT`. Le nombre d'enregistrements peut alors être obtenu avec `SELECT FOUND_ROWS()`. See Section 12.8.4, « Fonctions diverses ».

  Avant MySQL 4.1.0, cette option ne fonctionne pas avec `LIMIT 0`, qui est optimisée pour se terminer instantanément (le résultat ne contiendra pas de lignes). See Section 7.2.12, « Comment MySQL optimise `LIMIT` ».

- `SQL_CACHE` demande à MySQL de ne pas stocker le résultat de la requête si vous utilisez `query_cache_type` avec la valeur `2` ou `DEMAND`. Pour une requête qui utilise `UNION` ou une sous-requête, cette option prend effet si elle est utilisée dans n'importe quelle partie de la requête `SELECT`. See Section 5.11, « Cache de requêtes MySQL ».

- `SQL_CACHE` indique à MySQL de stocker le résultat de la requête dans le cache de requêtes si vous utilisez `QUERY_CACHE_TYPE=2` (`DEMAND`). See Section 5.11, « Cache de requêtes MySQL ». Pour les requêtes qui utilisent `UNION` ou les sous-requêtes, cette option aura un effet sur toutes les parties de la requête `SELECT`.

#### 13.1.7.1. 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 correspondances dans la table `table2`). Cela demande que `table2.id` soit déclaré `NOT NULL`, bien sur. See Section 7.2.9, « Comment MySQL optimise les clauses `LEFT JOIN` et `RIGHT JOIN` ».

- 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;

See Section 7.2.9, « Comment MySQL optimise les clauses `LEFT JOIN` et `RIGHT JOIN` ».

#### 13.1.7.2. 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) |
    +---------------+
    | a             |
    | bbbbbbbbbb    |
    +---------------+

### 13.1.8. Sous-sélections (`SubSELECT`)

Une sous-requête est une commande `SELECT` dans une autre commande. Par exemple :

    SELECT * FROM table1 WHERE id IN (SELECT id FROM table2);

La requête externe (ou commande externe), et `(SELECT column1 FROM t2)` est la sous-requête. Nous disons que la sous-requête est imbriquée dans la requête externe, et en fait, il est possible d'imbriquer des requêtes dans des sous-requêtes, avec d'autres commandes. Une sous-requête doit toujours être entre parenthèses.

Depuis la version 4.1, MySQL supporte toutes les formes de sous-requêtes et opérations que le standard SQL requiert, ainsi que quelques fonctionnalités spécifiques. Les avantages des sous-requêtes sont :

- Elles permettent aux requêtes d'être structuré pour que chaque partie puisse être isolée.

- Elles fournissent une méthode pour réaliser des opérations qui seraient complexes, et impliqueraient des unions et jointures.

- Elles sont, au dire de nombreuses personnes, lisibles. En fait, c'est les sous-requêtes qui ont donné aux inventeurs le nom original de `SQL` ```Structured Query Language''`.

Dans les versions plus anciennes de MySQL, il fallait trouver des palliatifs, et contourner les sous-requêtes. Il est bien plus facile de se mettre aux sous-requêtes.

Voici un exemple de commande qui montre les principaux avantages des sous-requêtes et de leur syntaxe, aussi bien pour celle qui est proposée par le standard, que celle de MySQL.

    DELETE FROM t1
    WHERE s11 > ANY
     (SELECT COUNT(*) /* no hint */ FROM t2
     WHERE NOT EXISTS
      (SELECT * FROM t3
       WHERE ROW(5*t2.s1,77)=
        (SELECT 50,11*s1 FROM t4 UNION SELECT 50,77 FROM
         (SELECT * FROM t5) AS t5)));

Pour les versions de MySQL antérieure à la version 4.1, la plupart des sous requêtes peuvent être réécrites avec des jointures et d'autres méthodes. See Section 13.1.8.11, « Se passer des sous-requêtes avec les premières versions de MySQL ».

#### 13.1.8.1. Les sous-requêtes comme opérateur scalaire

Dans dans forme la plus simple, une sous-requête scalaire, par opposition à une sous-requête de ligne ou de table qui seront présentées plus loin, est un simple opérande. Vous pouvez l'utilisez à chaque fois qu'une valeur de colonne ou qu'une valeur littérale est valide, et vous pouvez en attendre les mêmes caractéristiques : type de données, taille et indication de nullité, etc. Par exemple :

    CREATE TABLE t1 (s1 INT, s2 CHAR(5) NOT NULL);
    SELECT (SELECT s2 FROM t1);

La sous-requête de la commande `SELECT` ci-dessus est de type `CHAR`, de longueur 5. Son jeu de caractères et sa collation sont ceux fournis par défaut, et elle porte une marque de nullité. En fait, toutes les sous-requêtes peuvent prendre la valeur `NULL`, car si la table est vide, la valeur de la sous-requête sera alors `NULL`. Il y a quelques restrictions :

- Une sous-requête peut être utilisée avec les commandes suivantes : `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `SET` et `DO`.

- Une sous-requête peut contenir les mots-clé et les clauses qu'une commande `SELECT` peut contenir : `DISTINCT`, `GROUP BY`, `ORDER BY`, `LIMIT`, jointures, `UNION`, commentaires, fonctions, etc.

Ainsi, lorsque vous lirez les exemples des sections suivantes qui utilisent la commande spartiate `(SELECT column1 FROM t1)`, imaginez que votre code pourra contenir des commandes bien plus diverses et complexes.

Par exemple, supposons que nous avons ces deux tables :

    CREATE TABLE t1 (s1 INT);
    INSERT INTO t1 VALUES (1);
    CREATE TABLE t2 (s1 INT);
    INSERT INTO t2 VALUES (2);

Puis, que vous envoyons la commande suivante `SELECT` :

    SELECT (SELECT s1 FROM t2) FROM t1;

Le résultat sera `2` car il y a une ligne dans `t2`, dont la colonne `s1` a une valeur de 2.

La sous-requête peut faire partie d'une expression. Si c'est un opérande d'une fonction, n'oubliez pas les parenthèses.

Par exemple :

    SELECT UPPER((SELECT s1 FROM t1)) FROM t2;

#### 13.1.8.2. Comparaisons avec les sous-requêtes

L'utilisation la plus répandue des sous-requêtes est celle-ci :

    <non-subquery operand> <comparison operator> (<subquery>)

où `<comparison operator>` est l'un des opérateurs suivants :

    = > < >= <= <>

Par exemple :

    ... 'a' = (SELECT column1 FROM t1)

Il fut un temps où la seule place possible pour une sous-requête était à la droite de l'opérateur de comparaison, mais vous pourrez rencontrer de vieilles bases qui insisteront sur ce point.

Voici un exemple de comparaison classiques, pour lequel vous ne pouvez pas utiliser de jointure : trouvez toutes les valeurs de la table `t1` qui sont égales au maximum de la valeur dans la table `t2`.

    SELECT column1 FROM t1
           WHERE column1 = (SELECT MAX(column2) FROM t2);

Voici un autre exemple, qui est aussi impossible à réaliser avec une jointure, car elle impose l'agrégation de plusieurs tables : trouver toutes les lignes de la table `t1` qui contiennent une valeur qui apparaît deux fois.

    SELECT * FROM t1
           WHERE 2 = (SELECT COUNT(column1) FROM t1);

#### 13.1.8.3. Sous-requêtes avec les clauses `ANY`, `IN` et `SOME`

Syntaxe :

    <operand> <comparison operator> ANY (<subquery>)
    <operand> IN (<subquery>)
    <operand> <comparison operator> SOME (<subquery>)

Le mot `ANY`, qui doit suivre immédiatement un opérateur de comparaison, signifie : ``retourne `TRUE` si la comparaison est `TRUE` pour `UNE` des lignes que la sous-requête retourne.'' Par exemple :

    SELECT s1 FROM t1 WHERE s1 > ANY (SELECT s1 FROM t2);

Supposons qu'il y ait une ligne dans la table `t1` qui contienne {10}. L'expression est `TRUE` si la table `t2` contient {21,14,7} car il y a une valeur de `t2`, 7, qui est inférieure à 10. Cette expression est `FALSE` si la table `t2` contient {20,10}, ou si la table `t2` est vide. L'expression est `UNKNOWN` si la table `t2` contient {`NULL`,`NULL`,`NULL`}.

Le mot `IN` est un alias de `= ANY`. Les deux commandes suivantes sont identiques :

    SELECT s1 FROM t1 WHERE s1 = ANY (SELECT s1 FROM t2);
    SELECT s1 FROM t1 WHERE s1 IN    (SELECT s1 FROM t2);

Le mot `SOME` est un alias de `ANY`. Les deux commandes suivantes sont identiques :

    SELECT s1 FROM t1 WHERE s1 <> ANY  (SELECT s1 FROM t2);
    SELECT s1 FROM t1 WHERE s1 <> SOME (SELECT s1 FROM t2);

L'utilisation du mot `SOME` est rare, mais les exemples ci-dessus montrent pourquoi il peut être utile. En langage parlé, ``a n'est pas égal à aucun b'' signifie pour la majorité des gens, ``il n'y a pas de b qui est égal à a'' : ce n'est pas la signification de la syntaxe SQL. En utilisant `<> SOME`, vous pouvez vous assurer que tout le monde comprend le véritable sens de la commande.

#### 13.1.8.4. Sous-requêtes avec `ALL`

Syntaxe :

    <operand> <comparison operator> ALL (<subquery>)

Le mot `ALL`, qui doit suivre immédiatement l'opérateur de comparaison, signifie ``retourne `TRUE` si la comparaison est `TRUE` pour `TOUTES` les lignes que la sous-requête retourne''.

Par exemple :

    SELECT s1 FROM t1 WHERE s1 > ALL (SELECT s1 FROM t2);

Supposons qu'il y ait une ligne dans la table `t1` contenant {10}. L'expression est `TRUE` si la table `t2` contient {-5,0,+5} car les trois valeurs de `t2` sont inférieures à 10. L'expression est `FALSE` si la table `t2` contient {12,6,`NULL`,-100} car il y a une des valeurs de la table `t2`, ici 12, qui est plus grande que 10. L'expression est `UNKNOWN` si la table `t2` contient {0,`NULL`,1}.

Finalement, si la table `t2` est vide, le résultat est `TRUE`. Vous pouvez pensez que le résultat doit être indéterminé (`UNKNOWN`), mais c'est bien `TRUE`. Ce qui fait que, bizarrement,

    SELECT * FROM t1 WHERE 1 > ALL (SELECT s1 FROM t2);

est `TRUE` si la table `t2` est vide, mais

    SELECT * FROM t1 WHERE 1 > (SELECT s1 FROM t2);

est `UNKNOWN` si la table `t2` est vide. De plus,

    SELECT * FROM t1 WHERE 1 > ALL (SELECT MAX(s1) FROM t2);

est `UNKNOWN` si la table `t2` est vide. En général, les tables avec des `NULL` et les tables vides sont des cas particuliers : lorsque vous écrivez vos sous-requêtes, pensez bien à les prendre en compte.

#### 13.1.8.5. Sous-requêtes de ligne

Jusqu'ici, nous avons étudié les sous-requêtes scalaires, ou de colonnes : des sous-requêtes qui retournent une seule valeur dans une ligne. Une sous-requête de ligne est une variante qui retourne une seule ligne : elle peut donc retourner plusieurs colonnes. Voici deux exemples :

    SELECT * FROM t1 WHERE (1,2) = (SELECT column1, column2 FROM t2);
    SELECT * FROM t1 WHERE ROW(1,2) = (SELECT column1, column2 FROM t2);

Les requêtes ci-dessus sont toutes les deux `TRUE` si la table `t2` a une ligne où `column1 = 1` et `column2 = 2`.

L'expression `(1,2)` est parfois appelée un constructeur de ligne et est valide dans d'autres contextes. Par exemple, les deux commandes suivantes sont sémantiquement équivalentes, même si la précédente peut être optimisée :

    SELECT * FROM t1 WHERE (column1,column2) = (1,1);
    SELECT * FROM t1 WHERE column1 = 1 AND column2 = 1;

L'utilisation traditionnelle des constructeurs de ligne est lors des comparaisons avec des sous-requêtes qui retournent plusieurs colonnes. Par exemple, cette requête répond à la question : ``trouve toutes les lignes de la table t1 qui sont dupliquées dans la table t2'':

    SELECT column1,column2,column3
           FROM t1
           WHERE (column1,column2,column3) IN
                 (SELECT column1,column2,column3 FROM t2);

#### 13.1.8.6. `EXISTS` et `NOT EXISTS`

Si une sous-requête retourne absolument aucune valeur, alors la clause `EXISTS <subquery>` est `TRUE`, et la clause `NOT EXISTS <subquery>` est `FALSE`. Par exemple :

    SELECT column1 FROM t1 WHERE EXISTS (SELECT * FROM t2);

Traditionnellement, une sous-requête qui `EXISTS` commence avec `SELECT *` mais elle peut commencer aussi bien avec `SELECT 5` ou `SELECT column1` ou n'importe quoi d'autre encore : MySQL ignore la liste de colonnes du `SELECT` de cette requête, ce qui fait que cela n'a pas d'importance.

Dans l'exemple ci-dessus, si la table `t2` ne contient aucune ligne, même pas de ligne avec uniquement des valeurs `NULL`, alors la condition `EXISTS` est `TRUE`. C'est un exemple plutôt exceptionnel, car il y a presque toujours une sous-requête `[NOT] EXISTS` qui contiendra des corrélations. Voici des exemples plus concrets :

- Quel type de magasin est le plus fréquent dans une ou plusieurs villes?

      SELECT DISTINCT store_type FROM Stores
        WHERE EXISTS (SELECT * FROM Cities_Stores
                      WHERE Cities_Stores.store_type = Stores.store_type);

- Quel type de magasin n'est présent dans aucune villes?

      SELECT DISTINCT store_type FROM Stores
        WHERE NOT EXISTS (SELECT * FROM Cities_Stores
                          WHERE Cities_Stores.store_type = Stores.store_type);

- Quel type de magasin est présent dans toutes les villes?

      SELECT DISTINCT store_type FROM Stores S1
        WHERE NOT EXISTS (
          SELECT * FROM Cities WHERE NOT EXISTS (
            SELECT * FROM Cities_Stores
             WHERE Cities_Stores.city = Cities.city
             AND Cities_Stores.store_type = Stores.store_type));

Le dernier exemple est une double imbrication de requête `NOT EXISTS` : elle possède une clause `NOT EXISTS` à l'intérieur de la clause `NOT EXISTS`. Formellement, elle répond à la question : ``Existe-t-il une ville avec un magasin qui n'est pas dans Stores?''. Mais il est plus facile de dire qu'une clause `NOT EXISTS` imbriquée répond à la question ``est-ce que x est vrai pour tous les y?''.

#### 13.1.8.7. Sous-requêtes corrélées

Une sous-requête corrélée est une sous-requête qui contient une référence à une colonne qui est aussi dans une requête différente.

Par exemple :

    SELECT * FROM t1 WHERE column1 = ANY
           (SELECT column1 FROM t2 WHERE t2.column2 = t1.column2);

Notez que dans notre exemple, la sous-requête contient une référence à une colonne de la table `t1`, même si la sous-requête de la clause `FROM` ne mentionne pas la table `t1`. MySQL recherche hors de la requête et trouve `t1` dans la requête externe.

Supposez que la table `t1` contienne une ligne où `column1 = 5` et `column2 = 6`; alors que la table `t2` continue une ligne où `column1 = 5` et `column2 = 7`. l'expression `... WHERE column1 = ANY (SELECT column1 FROM t2)` sera alors `TRUE`, mais dans cet exemple, la clause `WHERE` de la sous-requête est `FALSE` (car 7 <> 5), et donc, toute la sous-requête est `FALSE`.

Règles de contexte : MySQL fait les évaluations de l'intérieur vers l'extérieur. Par exemple :

    SELECT column1 FROM t1 AS x
      WHERE x.column1 = (SELECT column1 FROM t2 AS x
        WHERE x.column1 = (SELECT column1 FROM t3 WHERE x.column2 = t3.column1));

Dans l'exemple ci-dessus, `x.column2` doit être une colonne de la table `t2` car `SELECT column1 FROM t2 AS x ...` prend le nom de `t2`. ce n'est pas une colonne de la table `t1` car `SELECT column1 FROM t1 ...` est une requête externe, qui est à venir.

Pour les sous-requêtes placées dans des clauses `HAVING` ou `ORDER BY`, MySQL recherche aussi les noms de colonnes dans la liste des sélections externes.

Dans certains cas, les sous-requêtes corrélées sont optimisées. Par exemple :

    val IN (SELECT key_val FROM tbl_name WHERE correlated_condition)

Sinon, elles sont inefficaces et plutôt lentes. Réécrire une requête sous forme de jointure peut améliorer les performances.

#### 13.1.8.8. Sous-requêtes dans la clause `FROM`

Les sous-requêtes sont valides dans la clause `FROM` d'une commande `SELECT`. Voici une syntaxe que vous allez rencontrer :

    SELECT ... FROM (<subquery>) AS <name> ...

La clause `AS <name>` est obligatoire, car les tables de la clause `FROM` doivent avoir un nom. Toutes les colonnes de la sous-requête `<subquery>` doivent avoir des noms distincts. Vous pourrez trouver cette syntaxe décrite ailleurs dans ce manuel, sous le nom de ``tables dérivées''.

Par exemple, supposons que vous avons cette table :

    CREATE TABLE t1 (s1 INT, s2 CHAR(5), s3 FLOAT);

Comment utiliser la fonctionnalité de sous-requêtes dans la clause `FROM`, avec cette table d'exemple :

    INSERT INTO t1 VALUES (1,'1',1.0);
    INSERT INTO t1 VALUES (2,'2',2.0);
    SELECT sb1,sb2,sb3
           FROM (SELECT s1 AS sb1, s2 AS sb2, s3*2 AS sb3 FROM t1) AS sb
           WHERE sb1 > 1;

Résultat : 2, '2', 4.0.

Voici un autre exemple : supposons que vous voulez connaître la moyenne de la somme pour un groupe de table. Ceci ne fonctionnera pas :

    SELECT AVG(SUM(column1)) FROM t1 GROUP BY column1;

Mais cette requête-ci vous donnera les informations nécessaires :

    SELECT AVG(sum_column1)
           FROM (SELECT SUM(column1) AS sum_column1
                 FROM t1 GROUP BY column1) AS t1;

Notez que les colonnes sont nommées à partir de la sous-requête : `(sum_column1)` est reconnue dans la requête externe.

Actuellement, les sous-requêtes en clause `FROM` ne peuvent pas être corrélées.

#### 13.1.8.9. Erreurs de sous-requêtes

Il y a de nouvelles erreurs qui ne s'appliquent qu'aux sous-requêtes. Cette section les rassemble, car elles vous aideront à garder en tête certains points importants.

-     ERROR 1235 (ER_NOT_SUPPORTED_YET)
      SQLSTATE = 42000
      Message = "This version of MySQL doesn't yet support
      'LIMIT & IN/ALL/ANY/SOME subquery'"

  Cela signifie que

      SELECT * FROM t1 WHERE s1 IN (SELECT s2 FROM t2 ORDER BY s1 LIMIT 1)

  ne fonctionnera pas, mais uniquement dans certaines versions d'origines, comme MySQL 4.1.1.

-     ERROR 1240 (ER_CARDINALITY_COL)
      SQLSTATE = 21000
      Message = "Operand should contain 1 column(s)"

  Cette erreur va survient dans des cas comme celui-ci :

      SELECT (SELECT column1, column2 FROM t2) FROM t1;

  Il est valide d'utiliser une sous-requête qui utilise plusieurs colonnes, dans le cadre d'une comparaison. See Section 13.1.8.5, « Sous-requêtes de ligne ». Mais dans d'autres contextes, la sous-requête doit être un opérande scalaire.

-     ERROR 1241 (ER_SUBSELECT_NO_1_ROW)
      SQLSTATE = 21000
      Message = "Subquery returns more than 1 row"

  Cette erreur survient dans des cas comme celui-ci :

      SELECT * FROM t1 WHERE column1 = (SELECT column1 FROM t2);

  mais uniquement lorsque plus d'une ligne sont extraites de `t2`. Cela signifie que cette erreur peut survenir dans du code qui fonctionne depuis longtemps : quelqu'un vient de modifier le nombre de ligne que la requête retourne. N'oubliez pas que si votre but est de trouver un nombre arbitraire de lignes, et non pas juste une seule, la commande correcte aurait été :

      SELECT * FROM t1 WHERE column1 = ANY (SELECT column1 FROM t2);

-     Error 1093 (ER_UPDATE_TABLE_USED)
      SQLSTATE = HY000
      Message = "You can't specify target table 'x' for update in FROM clause"

  Cette erreur survient dans des cas comme celui-ci :

      UPDATE t1 SET column2 = (SELECT MAX(column1) FROM t1);

Il est valide d'utiliser une sous-requête lors d'une affectation dans une commande `UPDATE`, car les sous-requêtes sont valides avec les commandes `UPDATE` et `DELETE`, tout comme dans les commandes `SELECT`. Cependant, vous ne pouvez pas les utiliser sur la même table, qui est ici `t1`, car cette table est alors la cible de la clause `FROM` et de la commande `UPDATE`.

Généralement, l'échec d'un sous-requête entraîne l'échec de toute la commande.

#### 13.1.8.10. Optimisation des sous-requêtes

Le développement des sous-requêtes se poursuit, et aucun des conseils d'optimisation ne sera valable longtemps. Voici quelques astuces que vous voulez prendre en compte :

- Utiliser une clause de sous-requête pour affecter le nombre ou l'ordre des lignes dans une sous-requête, par exemple :

      SELECT * FROM t1 WHERE t1.column1 IN
        (SELECT column1 FROM t2 ORDER BY column1);
      SELECT * FROM t1 WHERE t1.column1 IN
        (SELECT DISTINCT column1 FROM t2);
      SELECT * FROM t1 WHERE EXISTS
        (SELECT * FROM t2 LIMIT 1);

- Remplacer une jointure par une sous-requête. Par exemple :

      SELECT DISTINCT column1 FROM t1 WHERE t1.column1 IN (
        SELECT column1 FROM t2);

  au lieu de

      SELECT DISTINCT t1.column1 FROM t1, t2
        WHERE t1.column1 = t2.column1;

- Déplacer une clause `FROM` externe dans une sous-requête, comme ceci :

      SELECT * FROM t1
        WHERE s1 IN (SELECT s1 FROM t1 UNION ALL SELECT s1 FROM t2);

  au lieu de

      SELECT * FROM t1
        WHERE s1 IN (SELECT s1 FROM t1) OR s1 IN (SELECT s1 FROM t2);

  Un autre exemple :

      SELECT (SELECT column1 + 5 FROM t1) FROM t2;

  au lieu de

      SELECT (SELECT column1 FROM t1) + 5 FROM t2;

- Utiliser une sous-requête de ligne plutôt qu'une corrélation. Par exemple :

      SELECT * FROM t1
        WHERE (column1,column2) IN (SELECT column1,column2 FROM t2);

  au lieu de

      SELECT * FROM t1
        WHERE EXISTS (SELECT * FROM t2 WHERE t2.column1=t1.column1
        AND t2.column2=t1.column2);

- Utiliser `NOT (a = ANY (...))` au lieu de `a <> ALL (...)`.

- Utiliser `x = ANY (table containing {1,2})` plutôt que `x=1 OR x=2`.

- Utiliser `= ANY` de préférence à `EXISTS`

Le truc ci-dessus peut accélérer certains programmes, et en ralentir d'autres. En utilisant la fonction utilitaire `BENCHMARK()`, vous pouvez obtenir une idée de votre cas. Ne vous attardez pas trop à transformer vos jointures, sauf si la compatibilité avec les anciennes versions est importante pour vous.

Quelques optimisation que MySQL va prendre en charge lui-même :

- MySQL va exécuter les sous-requêtes non corrélées une seule fois (utilisez la commande `EXPLAIN` pour vous assurer que les requêtes ne sont pas correllées).

- MySQL va transformer les sous-requêtes `IN`/`ALL`/`ANY`/`SOME` pour essayer de profiter de la possibilité que les colonnes sélectionnées dans la sous-requêtes sont indexées.

- MySQL remplacera les sous-requêtes de la forme

      ... IN (SELECT indexed_column FROM single_table ...)

  par une recherche dans un index, que `EXPLAIN` décrira comme une jointure de type spécial.

- MySQL va améliorer les expressions de la forme

      valeur {ALL|ANY|SOME} {> | < | >= | <=} (sous-requête non-correllée)

  avec une expression impliquant `MIN` ou `MAX` (à moins d'une valeur `NULL` ou d'ensembles `SET` vides). Par exemple,

      WHERE 5 > ALL (SELECT x FROM t)

  revient à

      WHERE 5 > (SELECT MAX(x) FROM t)

Il y a un chapitre intitulé ``Comment MySQL adapte les sous-requêtes'' dans les manuels internes de MySQL, que vous pouvez trouver en téléchargeant les sources de MySQL : il est dans un fichier appelé `internals.texi`, dans le dossier `Docs`.

#### 13.1.8.11. Se passer des sous-requêtes avec les premières versions de MySQL

Jusqu'à la version 4.1, seules les requêtes imbriquées de la forme `INSERT ... SELECT ...` et `REPLACE ... SELECT ...` étaient supportées.

La clause `IN()` peut être utilisée dans certains contextes, pour tester la présence de valeur dans un ensemble de données.

Il est souvent possible de réécrire une requête sans sous-requête :

    SELECT * FROM t1 WHERE id IN (SELECT id FROM t2);

Cela peut se réécrire :

    SELECT t1.* FROM t1,t2 WHERE t1.id=t2.id;

Les requêtes :

    SELECT * FROM t1 WHERE id NOT IN (SELECT id FROM t2);
    SELECT * FROM t1 WHERE NOT EXISTS (SELECT id FROM t2 WHERE t1.id=t2.id);

peuvent être réécrites :

    SELECT table1.* FROM table1 LEFT JOIN table2 ON table1.id=table2.id
                                           WHERE table2.id IS NULL;

Une clause `LEFT [OUTER] JOIN` peut être plus rapide qu'une sous-requête équivalent, car le serveur va pouvoir l'optimiser bien mieux : c'est un fait qui n'est pas spécifique à MySQL. Avant SQL-92, les jointures externes n'existaient pas, et les sous-requêtes étaient la seule méthode pour résoudre certains problèmes. Aujourd'hui, le serveur MySQL et d'autres bases de données modernes offrent toute une gamme de jointures externes.

Pour les sous-requêtes plus complexes, vous pouvez simplement créer des tables temporaires pour contenir les résultats intermédiaires. Dans certains cas, cela ne sera pas possible. C'est notamment le cas des commandes de type `DELETE`, pour lesquelles le standard SQL ne supporte pas les jointures, sauf pour les sous-requêtes. Dans ces situations, trois solutions s'offrent à vous :

- Passez en MySQL version 4.1.

- Utilisez un langage de programmation procédural, comme `Perl` ou `PHP`, pour envoyer la requête `SELECT`, lire les clés primaires à effacer, et utiliser ces valeurs pour soumettre des requêtes de type `DELETE` (`DELETE FROM ... WHERE ... IN (key1, key2, ...)`).

- La troisième option est d'utiliser le client interactif de `mysql` pour construire et exécuter une liste de commande `DELETE` automatiquement, avec la fonction `CONCAT()` au lieu de l'opérateur `||`. Par exemple :

      SELECT CONCAT('DELETE FROM tab1 WHERE pkid = ', "'", tab1.pkid, "'", ';')
        FROM tab1, tab2
       WHERE tab1.col1 = tab2.col2;

  Vous pouvez placer cette requête dans un fichier de script, et rediriger son résultat vers le client en ligne de commande `mysql`, pour que ce dernier lance une seconde instance de l'interprêteur :

      shell> mysql --skip-column-names mydb < myscript.sql | mysql mydb

MySQL 4.0 supporte les commandes `DELETE` multi-tables qui peuvent être utilisées pour effacer des lignes dans une table en fonction d'informations qui sont dans une autre table, ou même effacer des lignes simultanément dans plusieurs tables. Les commandes `UPDATE` multi-tables sont aussi supportés depuis la version 4.0.

### 13.1.9. Syntaxe de `TRUNCATE`

    TRUNCATE TABLE nom_de_table

Dans la version 3.23, `TRUNCATE TABLE` est équivalent à `COMMIT ; DELETE FROM nom_de_table`. See Section 13.1.1, « Syntaxe de `DELETE` ».

`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.

### 13.1.10. Syntaxe de `UPDATE`

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

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;

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.

## 13.2. Définition de données : `CREATE`, `DROP`, `ALTER`

### 13.2.1. Syntaxe de `ALTER DATABASE`

    ALTER DATABASE db_name
        alter_specification [, alter_specification] ...

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

`ALTER DATABASE` vous permet de modifier les caractéristiques générales d'une base de données. Ces caractéristiques sont stockées dans le fichier `db.opt` du dossier de base. Pour utiliser `ALTER DATABASE`, vous avez besoin des droits de `ALTER` sur la base.

La clause `CHARACTER SET` modifie le jeu de caractères par défaut de la base. La clause `COLLATE` modifie la collation par défaut de la base. Les noms de jeu de caractères et de collation sont présentés dans la section Chapitre 10, Jeux de caractères et Unicode.

`ALTER DATABASE` a été ajoutée MySQL 4.1.1.

### 13.2.2. Syntaxe de `ALTER TABLE`

    ALTER [IGNORE] TABLE tbl_name
        alter_specification [, alter_specification] ...

    alter_specification:
        ADD [COLUMN] column_definition [FIRST | AFTER col_name ]
      | ADD [COLUMN] (column_definition,...)
      | ADD INDEX [index_name] [index_type] (index_col_name,...)
      | ADD [CONSTRAINT [symbol]]
            PRIMARY KEY [index_type] (index_col_name,...)
      | ADD [CONSTRAINT [symbol]]
            UNIQUE [index_name] [index_type] (index_col_name,...)
      | ADD [FULLTEXT|SPATIAL] [index_name] (index_col_name,...)
      | ADD [CONSTRAINT [symbol]]
            FOREIGN KEY [index_name] (index_col_name,...)
            [reference_definition]
      | ALTER [COLUMN] col_name {SET DEFAULT literal | DROP DEFAULT}
      | CHANGE [COLUMN] old_col_name column_definition
            [FIRST|AFTER col_name]
      | MODIFY [COLUMN] column_definition [FIRST | AFTER col_name]
      | DROP [COLUMN] col_name
      | DROP PRIMARY KEY
      | DROP INDEX index_name
      | DROP FOREIGN KEY fk_symbol
      | DISABLE KEYS
      | ENABLE KEYS
      | RENAME [TO] new_tbl_name
      | ORDER BY col_name
      | CONVERT TO CHARACTER SET charset_name [COLLATE collation_name]
      | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]
      | DISCARD TABLESPACE
      | IMPORT TABLESPACE
      | table_options

`ALTER TABLE` vous permet de changer la structure d'une table existante. Par exemple, vous pouvez ajouter ou supprimer des colonnes, des index, changer le type des colonnes existantes, renommer ces colonnes, ou la table elle-même. Vous pouvez de même changer le commentaire sur la table, ou le type de celle-ci.

La syntaxe de nombreuses altérations est similaires aux clauses de la commande `CREATE TABLE`. See Section 13.2.5, « Syntaxe de `CREATE TABLE` ».

Si vous utilisez `ALTER TABLE` pour modifier les spécifications d'une colonne mais que `DESCRIBE nom_de_table` vous indique que cette colonne n'a pas été modifiée, il est possible que MySQL ait ignoré vos modifications pour une des raisons décrite dans Section 13.2.5.1, « Modification automatique du type de colonnes ». Par exemple, si vous essayez de changer une colonne de type `VARCHAR` en `CHAR`, MySQL continuera d'utiliser `VARCHAR` si la table contient d'autres colonnes de taille variable.

`ALTER TABLE` effectue une copie temporaire de la table originale. Les modifications sont faites sur cette copie, puis l'original est effacée, et enfin la copie est renommée pour remplacer l'originale. Cette méthode permet de rediriger toutes les commandes automatiquement vers la nouvelle table sans pertes. Durant l'exécution de `ALTER TABLE`, la table originale est lisible par d'autres clients. Les modifications et insertions sont reportées jusqu'à ce que la nouvelle table soit prête.

Notez que si vous utilisez une autre option que `RENAME` avec `ALTER TABLE`, MySQL créera toujours une table temporaire, même si les données n'ont pas besoin d'être copiées (comme quand vous changez le nom d'une colonne). Nous avons prévu de corriger cela dans les versions suivantes, mais comme la commande `ALTER TABLE` n'est pas utilisée très souvent, cette correction ne fait pas partie de nos priorités. Pour les tables `MyISAM`, vous pouvez accélérer la réindexation (qui est la partie la plus lente de la modification d'une table) en donnant à la variable système `myisam_sort_buffer_size` une valeur plus grande.

- Pour utiliser `ALTER TABLE`, vous devez avoir les droits `ALTER`, `INSERT`, et `CREATE` sur la table.

- `IGNORE` est une extension MySQL pour ANSI SQL92. Cette option contrôle la fa¸on dont `ALTER TABLE` fonctionne s'il y a des duplications sur une clef unique de la nouvelle table. Si `IGNORE` n'est pas spécifiée, la copie est annulée et la table originale est restaurée. Si `IGNORE` est spécifiée, les lignes contenant les éléments doublons de la table seront effacées, hormis la première, qui sera conservée.

- Vous pouvez effectuer plusieurs opérations de `ADD`, `ALTER`, `DROP`, et `CHANGE` dans une même commande `ALTER TABLE`. C'est une extension de MySQL à la norme ANSI SQL92, qui n'autorise qu'une seule modification par commande `ALTER TABLE`.

- `CHANGE nom_colonne`, `DROP nom_colonne`, et `DROP INDEX` sont des extensions de MySQL à la norme ANSI SQL92.

- `MODIFY` est une extension Oracle à `ALTER TABLE`.

- Le mot optionnel `COLUMN` est purement de la fioriture et peut être ignoré.

- Si vous utilisez `ALTER TABLE nom_de_table RENAME TO nouveau_nom` sans autre option, MySQL va simplement renommer les fichiers qui correspondent à la table `nom_de_table`. Il n'y a pas de création de fichier temporaire. See Section 13.2.9, « Syntaxe de `RENAME TABLE` ».

- La définition `create_definition` utilise la même syntaxe pour les clauses `ADD` et `CHANGE` que dans `CREATE TABLE`. Notez que cette syntaxe inclut le nom de la colonne, et pas seulement son type See Section 13.2.5, « Syntaxe de `CREATE TABLE` ».

- Vous pouvez renommer une colonne avec la syntaxe `CHANGE ancien_nom_de_colonne create_definition`. Pour cela, indiquez l'ancien nom de la colonne, puis le nouveau nom et son type courant. Par exemple, pour renommer une colonne de type `INTEGER`, de `a` en `b`, vous pouvez faire ceci :

      mysql> ALTER TABLE t1 CHANGE a b INTEGER;

  Si vous ne voulez changer que le type de la colonne, avec la clause `CHANGE` vous devrez redonner le nom de la colonne. Par exemple :

      mysql> ALTER TABLE t1 CHANGE b b BIGINT NOT NULL;

  Cependant, à partir de la version 3.22.16a de MySQL, vous pouvez aussi utiliser la clause `MODIFY` pour changer le type d'une colonne sans la renommer :

      mysql> ALTER TABLE t1 MODIFY b BIGINT NOT NULL;

- Si vous utilisez les clauses `CHANGE` ou `MODIFY` pour réduire la taille d'une colonne qui comportait un index sur une partie de la colonne (par exemple, si vous aviez un index sur 10 caractères d'une colonne de type `VARCHAR`), vous ne pouvez pas rendre la colonne plus petite que le nombre de caractères indexés.

- Quand vous changez le type d'une colonne avec `CHANGE` ou `MODIFY`, MySQL essaye de convertir les données au niveau type dans la mesure du possible.

- A partir de la version 3.22 de MySQL, vous pouvez utiliser `FIRST` ou `ADD ... AFTER nom_colonne` pour ajouter la colonne à un endroit spécifique dans la table. Par défaut, la colonne est ajoutée à la fin. A partir de la version 4.0.1, vous pouvez aussi utiliser les mots clés `FIRST` et `AFTER` avec `CHANGE` ou `MODIFY`.

- `ALTER COLUMN` spécifie une nouvelle valeur par défaut pour une colonne ou enlève l'ancienne. si l'ancienne valeur est effacée et que la colonne peut être `NULL`, la nouvelle valeur par défaut sera `NULL`. Si la colonne ne peut être `NULL`, MySQL assigne une valeur par défaut, comme défini dans Section 13.2.5, « Syntaxe de `CREATE TABLE` ».

- `DROP INDEX` supprime un index. C'est une extension MySQL à la norme ANSI SQL92. See Section 13.2.7, « Syntaxe de `DROP INDEX` ».

- Si des colonnes sont effacées d'une table, ces colonnes sont aussi supprimés des index dont elles font partie. Si toutes les colonnes qui forment un index sont effacées, l'index lui même est supprimé.

- Si une table ne comporte qu'une seule colonne, La colonne ne peut être supprimée. Si vous voulez effacer la table, utilisez la commande `DROP TABLE`.

- `DROP PRIMARY KEY` supprime la clef primaire. Si cette clef n'existe pas, cette commande effacera le premier index `UNIQUE` de la table. (MySQL marque la première clef `UNIQUE` en tant que `PRIMARY KEY` si aucune `PRIMARY KEY` n'a été spécifiée explicitement.)

  Si vous ajoutez un `UNIQUE INDEX` ou `PRIMARY KEY` à une table, c'est enregistré avant les index non-`UNIQUE` pour que MySQL puisse détecter les valeurs dupliquées aussi vite que possible.

- `ORDER BY` vous permet de créer une nouvelle table tout en ordonnant les lignes par défaut. Notez que cet ordre ne sera pas conservé après les prochaines insertions et modifications. Dans certains cas, cela aide MySQL si les colonnes sont dans l'ordre dans lequel vous allez trier les valeurs. Cette option n'est vraiment utile que si vous savez à l'avance dans quel ordre vous effectuerez les tris : vous y gagnerez alors en performances.

- Si vous utilisez `ALTER TABLE` sur une table `MyISAM`, tous les index non-uniques sont créés par des opérations séparées. (comme dans `REPAIR`). Cela devrait rendre `ALTER TABLE` plus rapide quand vous avez beaucoup d'index.

  Depuis la version 4.0, la fonctionnalité ci-dessus peut être activée explicitement. `ALTER TABLE ... DISABLE KEYS` force MySQL à ne plus mettre à jour les index non-uniques pour les tables au format `MyISAM`. `ALTER TABLE ... ENABLE KEYS` doit alors être utilisé pour recréer les index manquants. Comme MySQL le fait avec un algorithme spécial qui est plus rapide que le fait d'insérer les clefs une par une, désactiver les clefs peut vous faire gagner en performances.

- Les clauses `FOREIGN KEY` et `REFERENCES` sont supportées par le moteur de tables `InnoDB`, qui implémente les clauses `ADD [CONSTRAINT [symbol]] FOREIGN KEY (...) REFERENCES ... (...)`. See Section 15.7.4, « Contraintes de clés étrangères `FOREIGN KEY` ». Pour les autres moteurs de stockages, ces clauses sont lues mais ignorées. La clause `CHECK` est analysée mais ignorée par tous les moteurs de stockage. See Section 13.2.5, « Syntaxe de `CREATE TABLE` ». La raison pour accepter mais ignorer ces clauses est que cela renforce la compatibilité avec le code des autres serveurs SQL, et qu'il est possible de créer des tables avec des références. See Section 1.5.5, « Différences entre MySQL et le standard SQL-92 ».

- Depuis MySQL 4.0.13, `InnoDB` supporte l'utilisation de `ALTER TABLE` pour effacer des clés étrangères :

      ALTER TABLE yourtablename
          DROP FOREIGN KEY fk_symbol

  Pour plus d'informations, voyez Section 15.7.4, « Contraintes de clés étrangères `FOREIGN KEY` ».

- `ALTER TABLE` ignore les options de tables `DATA DIRECTORY` et `INDEX DIRECTORY`.

- Depuis MySQL 4.1.2, si vous voulez changer dans toutes les colonnes de texte (`CHAR`, `VARCHAR`, `TEXT`) le jeu de caractères, vous pouvez utiliser la commande suivante :

      ALTER TABLE tbl_name CONVERT TO CHARACTER SET charset_name;

  C'est pratique lorsque vous passez de MySQL 4.0.x en 4.1.x. See Section 10.10, « Préparer le passage de version 4.0 en 4.1 ».

  Attention : l'opération précédente va convertir les valeurs des colonnes entre les deux jeux de caractères. Ce n'est pas ce que vous souhaitez faire si une colonne est de type `latin1` mais que les valeurs sont en fait dans un autre jeu de caractères (comme `utf8`). Dans ce cas, vous devez faire ceci avec une telle colonne :

      ALTER TABLE t1 CHANGE c1 c1 BLOB;
      ALTER TABLE t1 CHANGE c1 c1 TEXT CHARACTER SET utf8;

  La raison est que dans ce cas, il n'y aura pas de conversion lorsque vous passer en type `BLOB`.

  Pour ne changer que le type de caractères par défaut, utilisez cette commande :

      ALTER TABLE tbl_name DEFAULT CHARACTER SET charset_name;

  Le mot `DEFAULT` est optionnel. Le jeu de caractères par défaut est utilisé si vous ne spécifiez pas le jeu de caractères de la colonne explicitement, lorsque vous ajoutez une nouvelle colonne : par exemple, avec `ALTER TABLE ... ADD column`.

  Attention : depuis MySQL 4.1.2 et plus récent, `ALTER TABLE ... DEFAULT CHARACTER SET` et `ALTER TABLE ... CHARACTER SET` sont équivalent et ne changent que le jeu de caractères par défaut. Dans les versions antérieures à MySQL 4.1.2, `ALTER TABLE ... DEFAULT CHARACTER SET` changeait le jeu de caractères par défaut, mais `ALTER TABLE ... CHARACTER SET` (sans `DEFAULT`) changeait le jeu de caractères par défaut, et convertissaient les colonnes dans le nouveau jeu.

- Pour une table `InnoDB` qui a été créée avec son propre espace de tables dans un fichier `.ibd`, ce fichier peut être supprimé et importé. Pour supprimer le fichier `.ibd`, utilisez la commande suivante :

      ALTER TABLE tbl_name DISCARD TABLESPACE;

  Elle efface le fichier `.ibd` courant, alors assurez vous que vous avez une copie de sauvegarde. Si vous tentez d'accéder à un espace de table sans ce fichier, vous obtiendrez une erreur.

  Pour importer un fichier de sauvegarde `.ibd` dans la table, copiez le nouveau fichier dans le dossier de la base, et utilisez cette commande :

      ALTER TABLE tbl_name IMPORT TABLESPACE;

  See Section 15.7.6, « Espaces de tables multiples : chaque table `InnoDB` a son fichier `.ibd` ».

- Avec la fonction `mysql_info()` de l'API C, vous pouvez savoir combien d'enregistrements ont été copiés, et (quand `IGNORE` est spécifié) combien d'enregistrements ont été effacés à cause de la clef unique. See Section 24.2.3.31, « `mysql_info()` ».

Voilà un exemple qui montre quelques utilisations de `ALTER TABLE`. On commence par une table `t1` créée comme suit :

    mysql> CREATE TABLE t1 (a INTEGER,b CHAR(10));

Pour renommer la table de `t1` à `t2` :

    mysql> ALTER TABLE t1 RENAME t2;

Pour changer une colonne `a` de `INTEGER` en `TINYINT NOT NULL` (en laissant le même nom), et pour changer une colonne `b` de `CHAR(10)` à `CHAR(20)` et la renommant de `b` en `c` :

    mysql> ALTER TABLE t2 MODIFY a TINYINT NOT NULL, CHANGE b c CHAR(20);

Pour ajouter une nouvelle colonne `TIMESTAMP` nommée `d` :

    mysql> ALTER TABLE t2 ADD d TIMESTAMP;

Pour ajouter un index sur une colonne `d`, et rendre la colonne `a` la clef primaire :

    mysql> ALTER TABLE t2 ADD INDEX (d), ADD PRIMARY KEY (a);

Pour effacer la colonne `c` :

    mysql> ALTER TABLE t2 DROP COLUMN c;

Pour ajouter une nouvelle colonne `AUTO_INCREMENT` nommée `c` :

    mysql> ALTER TABLE t2 ADD c INT UNSIGNED NOT NULL AUTO_INCREMENT,
               ADD INDEX (c);

Notez que nous avons indexé `c`, car les colonnes `AUTO_INCREMENT` doivent être indexées, et que nous définissons aussi `c` en tant que `NOT NULL`, car les colonnes indexées ne peuvent être `NULL`.

Quand vous ajoutez une colonne `AUTO_INCREMENT`, les valeurs de la colonne sont remplies automatiquement pour vous. Vous pouvez choisir la valeur de départ pour l'indexation en utilisant `SET INSERT_ID=#` avant `ALTER TABLE` ou en utilisant l'option `AUTO_INCREMENT = #` de la table. See Section 13.5.2.8, « Syntaxe de `SET` ».

Avec les tables de type `MyISAM`, si vous ne changez pas la colonne `AUTO_INCREMENT`, l'indice d'auto-incrémentation ne sera pas affecté. Si vous effacez une colonne `AUTO_INCREMENT` puis en ajoutez une autre, l'indexation recommencera à partir de 1.

See Section A.7.1, « Problèmes avec `ALTER TABLE`. ».

### 13.2.3. Syntaxe de `CREATE DATABASE`

    CREATE DATABASE [IF NOT EXISTS] db_name
        [create_specification [, create_specification] ...]

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

`CREATE DATABASE` crée une base de données avec le nom donné.

Les règles de nommage des bases de donnée sont présentées dans la section Section 9.2, « Noms de bases, tables, index, colonnes et alias ». Une erreur survient si une base de données de même nom existe déjà, si vous ne spécifiez pas l'option `IF NOT EXISTS`.

Depuis MySQL 4.1.1, les options `create_specification` peuvent être données pour spécifier des caractéristiques de la base. Les caractéristiques de la base sont stockées dans le fichier `db.opt` dans le dossier de la base. La clause `CHARACTER SET` spécifie le jeu de caractères par défaut pour les tables de cette base. La clause `COLLATE` spécifie la collation par défaut de la base de données. Les jeux de caractères et les collations sont présentées dans la section Chapitre 10, Jeux de caractères et Unicode.

Les bases de données MySQL sont implémentées comme des répertoires contenant des fichiers qui correspondent aux tables dans les bases de données. Puisqu'il n'y a pas de tables dans une base de données lors de sa création, la requête `CREATE DATABASE` créera seulement le dossier dans le répertoire de données de MySQL (et le fichier `db.opt`, depuis MySQL 4.1.1).

Vous pouvez aussi créer des bases de données avec `mysqladmin`. See Section 8.4, « `mysqladmin`, administration d'un serveur MySQL ».

### 13.2.4. Syntaxe de `CREATE INDEX`

    CREATE [UNIQUE|FULLTEXT|SPATIAL] INDEX index_name [index_type]
        ON tbl_name (index_col_name,...)

    index_col_name:
        col_name [(length)] [ASC | DESC]

La requête `CREATE INDEX` n'effectue aucune action sur les versions de MySQL antérieures à la version 3.22. Dans les versions 3.22 et supérieures, `CREATE INDEX` est équivalent à une requête `ALTER TABLE` pour créer des index. See Section 13.2.2, « Syntaxe de `ALTER TABLE` ».

Normalement, tous les index sont créés en même temps que la table elle même avec `CREATE TABLE`. See Section 13.2.5, « Syntaxe de `CREATE TABLE` ». `CREATE INDEX` permet d'ajouter des index à une table existante.

Une liste de colonnes de la forme `(col1,col2,...)` crée un index multi-colonnes. Les valeurs de l'index sont créées en concaténant la valeur deux colonnes données.

Pour les colonnes `CHAR` et `VARCHAR`, les index peut être créés sur uniquement une partie de la colonne, avec la syntaxe `col_name(length)`. Pour les colonnes `BLOB` et `TEXT` la longueur d'index est obligatoire. La requête suivante crée un index en utilisant les 10 premiers caractères de la colonne `name` :

    mysql> CREATE INDEX part_of_name ON customer (name(10));

Comme la plupart des noms ont en général des différences dans les 10 premiers caractères, l'index ne devrait pas être plus lent qu'un index créé à partir de la colonne `name` en entier. Ainsi, en n'utilisant qu'une partie de la colonne pour les index, on peut réduire la taille du fichier d'index, ce qui peut permettre d'économiser beaucoup d'espace disque, et peut aussi accélérer les opérations `INSERT`!

Il est important de savoir qu'on peut indexer une colonne qui peut avoir la valeur `NULL` ou une colonne `BLOB`/`TEXT` que si on utilise une version 3.23.2 ou supérieure de MySQL et en utilisant le type `MyISAM`.

Pour plus d'informations à propos de l'utilisation des index dans MySQL, voir Section 7.4.5, « Comment MySQL utilise les index ».

Les index `FULLTEXT` ne peuvent indexer que des colonnes `VARCHAR` ou `TEXT`, et seulement dans les tables `MyISAM`. Les index `FULLTEXT` sont disponibles dans les versions 3.23.23 et supérieures de MySQL. Section 12.6, « Recherche en texte intégral (`Full-text`) dans MySQL ».

Les index `SPATIAL` peuvent indexer les colonnes spatiales, et uniquement avec les tables `MyISAM`. Les index `SPATIAL` sont disponibles en MySQL 4.1 et plus récent. Les colonnes spatiales sont présentées dans section Chapitre 18, Données spatiales avec MySQL.

### 13.2.5. Syntaxe de `CREATE TABLE`

    CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
        [(create_definition,...)]
        [table_options] [select_statement]

ou :

    CREATE [TEMPORARY] TABLE [IF NOT EXISTS] tbl_name
        [(] LIKE old_tbl_name [)];

    create_definition:
        column_definition
      | [CONSTRAINT [symbol]] PRIMARY KEY [index_type] (index_col_name,...)
      | KEY [index_name] [index_type] (index_col_name,...)
      | INDEX [index_name] [index_type] (index_col_name,...)
      | [CONSTRAINT [symbol]] UNIQUE [INDEX]
            [index_name] [index_type] (index_col_name,...)
      | [FULLTEXT|SPATIAL] [INDEX] [index_name] (index_col_name,...)
      | [CONSTRAINT [symbol]] FOREIGN KEY
            [index_name] (index_col_name,...) [reference_definition]
      | CHECK (expr)

    column_definition:
        col_name type [NOT NULL | NULL] [DEFAULT default_value]
            [AUTO_INCREMENT] [[PRIMARY] KEY] [COMMENT 'string']
            [reference_definition]

    type:
        TINYINT[(length)] [UNSIGNED] [ZEROFILL]
      | SMALLINT[(length)] [UNSIGNED] [ZEROFILL]
      | MEDIUMINT[(length)] [UNSIGNED] [ZEROFILL]
      | INT[(length)] [UNSIGNED] [ZEROFILL]
      | INTEGER[(length)] [UNSIGNED] [ZEROFILL]
      | BIGINT[(length)] [UNSIGNED] [ZEROFILL]
      | REAL[(length,decimals)] [UNSIGNED] [ZEROFILL]
      | DOUBLE[(length,decimals)] [UNSIGNED] [ZEROFILL]
      | FLOAT[(length,decimals)] [UNSIGNED] [ZEROFILL]
      | DECIMAL(length,decimals) [UNSIGNED] [ZEROFILL]
      | NUMERIC(length,decimals) [UNSIGNED] [ZEROFILL]
      | DATE
      | TIME
      | TIMESTAMP
      | DATETIME
      | CHAR(length) [BINARY | ASCII | UNICODE]
      | VARCHAR(length) [BINARY]
      | TINYBLOB
      | BLOB
      | MEDIUMBLOB
      | LONGBLOB
      | TINYTEXT
      | TEXT
      | MEDIUMTEXT
      | LONGTEXT
      | ENUM(value1,value2,value3,...)
      | SET(value1,value2,value3,...)
      | spatial_type

    index_col_name:
        col_name [(length)] [ASC | DESC]

    reference_definition:
        REFERENCES tbl_name [(index_col_name,...)]
                   [MATCH FULL | MATCH PARTIAL]
                   [ON DELETE reference_option]
                   [ON UPDATE reference_option]

    reference_option:
        RESTRICT | CASCADE | SET NULL | NO ACTION | SET DEFAULT

    table_options: table_option [table_option] ...

    table_option:
        {ENGINE|TYPE} = {BDB|HEAP|ISAM|InnoDB|MERGE|MRG_MYISAM|MYISAM}
      | AUTO_INCREMENT = value
      | AVG_ROW_LENGTH = value
      | CHECKSUM = {0 | 1}
      | COMMENT = 'string'
      | MAX_ROWS = value
      | MIN_ROWS = value
      | PACK_KEYS = {0 | 1 | DEFAULT}
      | PASSWORD = 'string'
      | DELAY_KEY_WRITE = {0 | 1}
      | ROW_FORMAT = { DEFAULT | DYNAMIC | FIXED | COMPRESSED }
      | RAID_TYPE = { 1 | STRIPED | RAID0 }
            RAID_CHUNKS = value
            RAID_CHUNKSIZE = value
      | UNION = (tbl_name[,tbl_name]...)
      | INSERT_METHOD = { NO | FIRST | LAST }
      | DATA DIRECTORY = 'absolute path to directory'
      | INDEX DIRECTORY = 'absolute path to directory'
      | [DEFAULT] CHARACTER SET charset_name [COLLATE collation_name]

    select_statement:
        [IGNORE | REPLACE] [AS] SELECT ...   (Some legal select statement)

`CREATE TABLE` Crée une table avec le nom donné, dans la base de données courante. Vous avez besoin des droits de `CREATE` pour créer une table.

Les règles de nommage des tables sont disponibles dans Section 9.2, « Noms de bases, tables, index, colonnes et alias ». Par défaut, une table est créée dans la base de données courante. Une erreur est affichée s'il n'y a pas de base courante, si la base de données n'existe pas ou si la table existe déjà.

En MySQL 3.22 et plus récent, le nom de la table peut être spécifié avec la syntaxe `db_name.tbl_name`, pour créer une table dans une base spécifique. Cela fonctionne même s'il n'y a pas de base courante. Si vous utilisez les identifiants protégez, et mettez le nom de la base et de lui de la table entre guillemets, séparément. Par exemple, ``madb`.`matbl`` est valide, mais ``madb.matbl`` ne l'est pas.

Depuis la version 3.22 de MySQL, vous pouvez utiliser le mot réservé `TEMPORARY` lorsque vous créez une table. Une table temporaire sera immédiatement effacée dès que la connexion se termine. Cela signifie que vous pouvez utiliser le même nom de table temporaire depuis deux connexions différentes sans risque de conflit entre les connexions. Vous pouvez aussi utiliser une table temporaire qui a le même nom qu'une table existante (la table existante est alors cachée tant que dure la table temporaire). En MySQL version 4.0.2 ou plus récent, vous avez juste à avoir le privilège `CREATE TEMPORARY TABLES` pour créer des tables temporaires.

Depuis la version 3.23 de MySQL, vous pouvez utiliser le mot réservé `IF NOT EXISTS`, de fa¸on à ce qu'aucune erreur ne soit affiché si la table que vous essayez de créer existe déjà. Notez qu'il n'y a pas de comparaisons entre les structures de table lors du test d'existence.

MySQL représente chaque table par un fichier de définition de table `.frm`, placé dans le dossier de la base de données. Le moteur de la table peut créer d'autres fichiers complémentaires. Dans le cas des tables `MyISAM`, le moteur de stockage utilise trois fichiers, avec le nom `nom_de_table` :

Fichier | Rôle
`nom_de_table.frm` | Fichier de définition de la table
`nom_de_table.MYD` | Fichier de données
`nom_de_table.MYI` | Fichier d'index

Les fichiers créés par les moteurs de stockages pour représenter les tables sont décrits dans la section Chapitre 14, Moteurs de tables MySQL et types de table.

Pour des informations générales sur les propriétés des différentes colonnes, voyez Chapitre 11, Types de colonnes. Pour des informations sur les types de données spatiaux, voyez Chapitre 18, Données spatiales avec MySQL.

- Si ni `NULL`, ni `NOT NULL` n'est spécifié, une colonne utilisera par défaut l'attribut `NULL` (elle acceptera les valeurs `NULL`).

- Une colonne de nombre entier peut se voir attribuer l'attribut `AUTO_INCREMENT`. Lorsque vous insérez la valeur `NULL` (recommandée) ou `0` dans une colonne `AUTO_INCREMENT`, la colonne prendra automatiquement la valeur de `value+1`, où value est la plus grande valeur positive courante dans cette colonne. La série des valeurs `AUTO_INCREMENT` commence à `1`. See Section 24.2.3.33, « `mysql_insert_id()` ».

  Depuis MySQL 4.1.1, en spécifiant l'option `NO_AUTO_VALUE_ON_ZERO` pour le mode `--sql-mode` ou la variable serveur `sql_mode` permet de stocker la valeur `0` dans les colonnes de type `AUTO_INCREMENT`, au lieu de voir `0` prendre le prochain numéro de séquence. See Section 5.2.1, « Options de ligne de commande de `mysqld` ».

  Note : Il ne peut y avoir qu'une seule colonne de type `AUTO_INCREMENT` dans une table, et elle doit être indexée. MySQL version 3.23 ne fonctionnera correctement que si cette colonne n'accueille que des valeurs positives. Insérer un nombre négatif sera considéré comme insérer un nombre de très grande taille, mais positif. Ceci est fait pour éviter les problèmes de précision lorsque les nombres passe de positif à négatif lorsqu'ils atteignent leur valeur maximale positive. C'est aussi pour éviter qu'une colonne de type `AUTO_INCREMENT` ne contienne de valeur 0.

  Si vous effacez la ligne contenant la valeur maximale dans la colonne `AUTO_INCREMENT`, cette valeur sera réutilisée dans les tables de type `ISAM` mais pas dans les tables de type `MyISAM`. Si vous effacez toutes les lignes dans la table avec la commande `DELETE FROM nom_de_table` (sans la clause `WHERE)` en mode `AUTOCOMMIT`, la série des valeurs `AUTO_INCREMENT` recommencera à `0`.

  Avec les tables `MyISAM` et `BDB`, vous pouvez spécifier une colonne secondaire d'`AUTO_INCREMENT` dans une clef multi-colonnes. See Section 3.6.9, « Utiliser `AUTO_INCREMENT` ».

  Pour rendre MySQL avec certaines applications `ODBC`, vous pouvez retrouver la valeur de la dernière valeur automatiquement générée avec la requête suivante :

      SELECT * FROM nom_de_table WHERE auto_col IS NULL

- Depuis MySQL 4.1, la définition des colonnes peut inclure un attribut `CHARACTER SET` pour spécifier le jeu de caractères, et éventuellement la collation de la colonne. Pour des détails, voyez Chapitre 10, Jeux de caractères et Unicode.

      CREATE TABLE t (c CHAR(20) CHARACTER SET utf8 COLLATE utf8_bin);

  Depuis la version 4.1 aussi, MySQL interprète les spécifications de longueur de colonne en caractères. Les anciennes versions l'interprète comme des octets.

- La valeur `NULL` est traitée différemment dans les colonnes de type `TIMESTAMP`. Vous ne pouvez pas stocker de valeur `NULL` littérale dans une colonne `TIMESTAMP`; insérer une valeur `NULL` dans une telle colonne revient à insérer la date et l'heure courante. Car les colonnes `TIMESTAMP` ignorent les attributs NULL et `NOT NULL`.

  Cela facilite grandement l'utilisation des colonnes `TIMESTAMP` pour les clients MySQL : le serveur indique que ces colonnes peuvent se voir assigner une valeur `NULL` (ce qui est vrai), même si les colonnes `TIMESTAMP` ne contiendront jamais de valeur `NULL`. Vous pouvez le constater lorsque vous utiliser la commande `DESCRIBE` `nom_de_table` pour avoir une description de votre table.

  Notez qu'affecter la valeur `0` à une colonne `TIMESTAMP` n'est pas la même chose que lui affecter la valeur `NULL`, car `0` est une valeur `TIMESTAMP` valide.

- Une valeur `DEFAULT` doit être une constante, ¸a ne peut être une fonction ou une expression. Cela signifie notamment que vous ne pouvez pas donner une valeur par défaut à une colonne de date, le résultat de la fonction `NOW()` ou `CURRENT_DATE`.

  Si aucune valeur par défaut (attribut `DEFAULT`) n'est spécifiée, MySQL en assigne une automatiquement

  Si la colonne accepte les valeur `NULL`, la valeur par défaut sera la valeur `NULL`.

  Si la colonne est déclarée comme `NOT NULL` (non-nulle), la valeur par défaut dépendra du type de colonne :

  - Pour les types numériques sans l'attribut `AUTO_INCREMENT`, la valeur sera `0`. Pour une colonne `AUTO_INCREMENT`, la valeur par défaut sera la prochaine valeur de la série.

  - Pour les types dates et heures autres que `TIMESTAMP`, la valeur par défaut est la date zéro appropriée. Pour les colonnes `TIMESTAMP`, la valeur par défaut est la date et l'heure courante. See Section 11.3, « Les types date et heure ».

  - Pour les types de chaînes autres que `ENUM`, la valeur par défaut est la chaîne vide. Pour `ENUM`, la valeur par défaut est la première valeur de l'énumération.

  Les colonnes `BLOB` et `TEXT` ne peuvent pas recevoir de valeur par défaut.

- Un commentaire pour une colonne peut être spécifiée avec `COMMENT`. Le commentaire est affiché par la commande `SHOW CREATE TABLE`, et par `SHOW FULL COLUMNS`. Cette option est disponible depuis MySQL 4.1. Il était autorisé, mais ignoré dans les anciennes versions.

- Depuis MySQL version 4.1.0, l'attribut `SERIAL` peut être utilisé comme alias pour les colonnes `BIGINT UNSIGNED NOT NULL AUTO_INCREMENT UNIQUE`. C'est une fonctionnalité de compatibilité.

- `KEY` est un synonyme de `INDEX`. Depuis la version 4.1, l'attribut de clé `PRIMARY KEY` peut aussi être spécifié avec la clause `KEY`. Il a été implémenté pour assurer la compatibilité avec les autres bases.

- Avec MySQL, une clé `UNIQUE` peut avoir uniquement avoir deux valeurs distinctes. Une erreur surviendra si vous essayez d'ajouter une ligne dont la clé correspond à une ligne existante.

- Une clé primaire (`PRIMARY KEY`) est un index `UNIQUE` avec la contrainte supplémentaire que les toutes les colonnes utilisées doit avoir l'attribut `NOT NULL`. En MySQL, cette clé est dite `PRIMARY`. Une table ne peut avoir qu'une seule clé primaire. Si vous n'avez pas de `PRIMARY KEY` et que des applications demandent la `PRIMARY KEY` dans vos tables, MySQL retournera la première clé `UNIQUE`, qui n'a aucune valeur `NULL`.

- Dans une table créée, la clé primaire `PRIMARY KEY` est placée en première, suivie de tous les index `UNIQUE`, et enfin, les index non-unique. Cela permet à l'optimiseur MySQL d'utiliser en priorité les index, et de détecter rapidement les doublons pour les clés `UNIQUE`.

- Une `PRIMARY KEY` peut être multi-colonnes. Cependant, vous ne pouvez pas créer d'index multi-colonnes avec l'attribut `PRIMARY KEY` dans une spécification de colonne. En faisant cela, le seul résultat sera que cette seule colonne sera marquée comme clé primaire. Vous devez absolument utiliser la syntaxe `PRIMARY KEY` (`index_nom_de_colonne`, ...).

- Si une clé primaire (`PRIMARY`) ou unique (`UNIQUE`) est établit sur une seule colonne, et que cette colonne est de type entier, vous pouvez aussi faire référence à cette colonne sous le nom `_rowid` (nouveau en version 3.23.11).

- Avec MySQL, le nom de la clé primaire `PRIMARY KEY` est `PRIMARY`. Si vous ne donnez pas de nom à un index, l'index prendra le nom de la première colonne qui le compose, avec éventuellement un suffixe (`_2`, `_3`, ...) pour le rendre unique. Vous pouvez voir les noms des index avec la commande `SHOW INDEX FROM tbl_name`. See Section 13.5.3.6, « Syntaxe de `SHOW DATABASES` ».

- Depuis MySQL 4.1.0, certains moteurs de stockage vous permettent de spécifier un type d'index lors de la création d'un index. La syntaxe de `index_type` est `USING type_name`. Les valeurs possibles de `type_name` qui sont supportées par les différents moteurs de stockages sont listés ci-dessous. Lorsque des index multiples sont listés, le premier rencontré est celui par défaut, si aucun `index_type` n'est spécifié.

  Moteur de table | Types d'index
  `MyISAM` | `BTREE`
  `InnoDB` | `BTREE`
  `MEMORY/HEAP` | `HASH`, `BTREE`

  Exemple :

      CREATE TABLE lookup
          (id INT, INDEX USING BTREE (id))
          ENGINE = MEMORY;

  `TYPE type_name` peut être utilisé comme synonyme de `USING type_name`, pour spécifier un type d'index. Cependant, `USING` est la forme recommandée. De plus, le nom d'index qui précède le type d'index dans la syntaxe de spécification n'est pas optionnelle avec `TYPE`. Ceci est dû au fait que contrairement à `USING`, `TYPE` n'est pas un mot réservé, et donc, il pourrait être interprété comme un nom d'index.

  Si vous spécifiez un type d'index qui n'est pas légal pour le moteur de stockage, mais qu'il y a un autre type d'index que le moteur peut utiliser sans affecter les résultats de la requête, le moteur utilisera ce type en remplacement.

- Seuls, les formats de table `MyISAM`, `InnoDB`, et `BDB` supportent des index sur des colonnes qui peuvent contenir des valeurs `NULL`. Dans les autres situations, vous devez déclarer ces colonnes `NOT NULL` ou une erreur sera générée.

- Avec la syntaxe `nom_de_colonne(longueur)`, vous pouvez spécifier un index qui n'utilise qu'une partie de la colonne `CHAR` ou `VARCHAR`. Cela peut réduire la taille des fichiers d'index. See Section 7.4.3, « Index de colonnes ».

  Le format de table `MyISAM`, et depuis la version MySQL 4.0.14, `InnoDB`, supportent l'indexation des colonnes `BLOB` et `TEXT`. Lorsque vous ajoutez un index à une colonne `BLOB` ou `TEXT`, vous devez absolument spécifier une longueur d'index :

      CREATE TABLE test (blob_col BLOB, INDEX(blob_col(10)));

  Le préfixe peut valoir jusqu'à 255 octets de long (où 1000 octets pour les tables `MyISAM` et `InnoDB` depuis MySQL 4.1.2). Notez que le préfixe est mesuré en octets, alors que la longueur du préfixe de `CREATE TABLE` est interprété comme un nombre de caractères. Prenez cela en compte lorsque vous spécifiez une longueur de préfixe pour une colonne dont le jeu de caractères est multi-octets.

- Une spécification `index_col_name` peut se terminer avec `ASC` ou `DESC`. Ces mots clés sont prévus pour des extensions futures qui permettront un stockage dans un ordre donné. Actuellement, ils sont reconnus mais ignorés : les index sont stockés en ordre ascendant.

- Lorsque vous utilisez une clause `ORDER BY` ou `GROUP BY` sur une colonne de type `TEXT` ou `BLOB`, seuls, les `max_sort_longueur` premiers octets seront lus. See Section 11.4.3, « Les types `BLOB` et `TEXT` ».

- En MySQL version 3.23.23 ou plus récent, vous pouvez aussi créer des index spécial `FULLTEXT`. Ils sont utilisés pour faire des recherches en texte plein. Seul, le format de table `MyISAM` supporte les index `FULLTEXT`. Ils peuvent être créés uniquement pour les colonnes de type `VARCHAR` et `TEXT`. L'indexation est alors exécutée sur toute la colonne, et les indexations partielles ne sont pas supportées. Voir Section 12.6, « Recherche en texte intégral (`Full-text`) dans MySQL » pour les détails.

- En MySQL version 4.1 ou plus récent, vous pouvez créer les index spéciaux `SPATIAL` pour les colonnes géographiques. Les types spatiaux sont supportés par les tables `MyISAM`, et les colonnes indexées doivent être déclarées comme `NOT NULL`. Voyez Chapitre 18, Données spatiales avec MySQL.

- En MySQL version 3.23.44 et plus récent, les tables `InnoDB` supportent la vérification de clé étrangères. See Chapitre 15, Le moteur de tables `InnoDB`. Notez que la syntaxe des clés étrangères `FOREIGN KEY` de `InnoDB` est plus restrictive que la syntaxe présentée ci-dessus. `InnoDB` ne permet pas la spécification d'un `index_name`, et les colonnes de la table référencée doivent être explicitement nommées. Depuis la version 4.0.8, `InnoDB` supporte les clauses `ON DELETE` et `ON UPDATE` avec les clés étrangères. Voyez le manuel `InnoDB` pour la syntaxe précise. Section 15.7.4, « Contraintes de clés étrangères `FOREIGN KEY` ».

  Pour les autres types de tables, le serveur MySQL n'analyse pas les clauses `FOREIGN KEY`, `CHECK` et `REFERENCES` dans les commandes `CREATE TABLE`, et aucune action n'est réalisée. See Section 1.5.5.5, « Les clés étrangères ».

- Pour les tables `MyISAM` et `ISAM`, chaque colonne `NULL` requiert un bit supplémentaire, arrondi à l'octet supérieur le plus proche.

  La taille maximale d'enregistrement peut être calculée comme ceci :

      row longueur = 1
                   + (somme des longueurs de colonnes)
                   + (nombre de colonnes NULL + 7)/8
                   + (nombre de colonnes à taille variable)

  `delete_flag` vaut 1 pour les tables avec un format fixe. Les tables à format fixe utilisent un bit dans les lignes pour un marqueur, qui indique si la ligne a été effacée. `delete_flag` vaut 0 pour les tables à ligne dynamique, car le marquer est stocké dans l'entête de la ligne.

  Ces calculs ne s'appliquent pas aux tables `InnoDB`, qui ne font pas la différente entre les colonnes `NULL` et les colonnes `NOT NULL`.

Les options `options_de_table` et `SELECT` ne sont implémentées que dans MySQL version 3.23 et plus récent.

Les options `ENGINE` et `TYPE` spécifie le type de moteur de table. `ENGINE` a été ajouté en MySQL 4.0.18, pour la série des 4.0 et 4.1.2, pour la série des 4.1. C'est le nom d'attribut recommandé pour ces versions et `TYPE` est maintenant abandonné. `TYPE` sera supporté dans les séries 4.x, mais abandonnée probablement en MySQL 5.1.

Les différents types de tables sont :

Table type | Description
`ARCHIVE` | Le moteur d'archivage. See Section 14.7, « Le moteur de table `ARCHIVE` ».
`BDB` | Tables avec transactions. See Section 14.4, « Tables `BDB` ou `BerkeleyDB` ».
`BerkeleyDB` | Un alias de `BDB`.
`CSV` | Tables qui stockent les lignes au format valeurs séparées par des virgules. See Section 14.8, « Le moteur `CSV` ».
`EXAMPLE` | Un moteur d'exemple. See Section 14.5, « Le moteur de table `EXAMPLE` ».
`FEDERATED` | Un moteur qui accède à des tables distantes. See Section 14.6, « Le moteur de table `FEDERATED` ».
`HEAP` | Les données de ces tables ne sont stockées qu'en mémoire. See Section 14.3, « Le moteur de table `MEMORY` (`HEAP`) ».
`ISAM` | Le gestionnaire originel de tables. See Section 14.9, « Tables `ISAM` ».
`InnoDB` | Tables transactionnelles avec verrou de lignes. See Chapitre 15, Le moteur de tables `InnoDB`.
`MEMORY` | Un alias de `HEAP`. (En fait, depuis MySQL 4.1, `MEMORY` est le terme recommandé.)
`MERGE` | Un ensemble de tables `MyISAM` utilisées comme une seule et même table. See Section 14.2, « Tables assemblées `MERGE` ».
`MRG_MyISAM` | Un synonyme pour les tables MERGE.
`MyISAM` | Le nouveau gestionnaire de table binaire et portable. See Section 14.1, « Le moteur de tables `MyISAM` ».
`NDB` | Alias de `NDBCLUSTER`.
`NDBCLUSTER` | Tables en grappe et en mémoire, tolérantes aux pannes. See Chapitre 16, Introduction à MySQL Cluster.

See Chapitre 14, Moteurs de tables MySQL et types de table.

Si un type de table est demandé, mais que ce type particulier n'est pas disponible, MySQL va choisir le type de table le plus proche de celui qui est spécifié. Par exemple, si `TYPE=BDB` est spécifié, et que la distribution de MySQL ne supporte pas les tables `BDB`, la table qui sera créée sera du type `MyISAM`.

Les autres options de tables sont utilisées pour optimiser le comportement de la table. Dans la plupart des cas, vous n'avez pas à les spécifier. Les options fonctionnent pour tous les types de tables (sauf contre-indication) :

- `AUTO_INCREMENT`

  La prochaine valeur `AUTO_INCREMENT` de votre table (`MyISAM`). Ne fonctionne que pour les tables `MyISAM`. Pour donner la première valeur à une colonne `AUTO_INCREMENT` `InnoDB`, insérez une ligne bidon, avec la valeur désirée moins un, puis supprimez la ligne.

- `AVG_ROW_LENGTH`

  La taille moyenne approchée des lignes de votre table. Vous ne devez fournir cette valeur que pour les tables à taille de ligne variable, de très grande taille.

  Lorsque vous créer une table `MyISAM`, MySQL utilise le produit des options `MAX_ROWS` et `AVG_ROW_LENGTH` pour décider de la taille du résultat. Si vous ne spécifiez aucune option, la taille maximale de la table sera de 4 Go (ou 2 Go si votre système d'exploitation ne supporte que les tables de 2 Go). Ceci sert à conserver la taille des pointeurs d'index petite, et rapide, si nous n'avez pas besoin de gros fichiers. Si vous voulez que vos tables dépassent 4 Go de taille, et que vous voulez garder les tables petites taille un peu plus lentes et grosses que nécessaire, vous pouvez augmenter la taille du pointeur d'index en modifiant la variable système globale `myisam_data_pointer_size`, qui a été ajoutée en MySQL 4.1.2. See Section 5.2.3, « Variables serveur système ».

- `CHECKSUM`

  Passez 1 si vous voulez que MySQL génère une somme de vérification (ce qui facilite la recherche des lignes corrompues, mais ralentit les mises à jour). La commande `CHECKSUM TABLE` rapporte cette somme. `MyISAM` uniquement.

- `COMMENT`

  Un commentaire pour votre table (60 caractères).

- `MAX_ROWS`

  Nombre de lignes maximum que vous pensez stocker dans la table.

- `MIN_ROWS`

  Nombre de minimum lignes que vous pensez stocker dans la table.

- `PACK_KEYS`

  Spécifiez 1 si vous voulez un index plus compact. Généralement cela rend les mises à jour plus lentes, mais les lectures plus rapides.

  Spécifier la valeur de 0 désactive tout le compactage de clé. Spécifier la valeur `DEFAULT` (MySQL 4.0) indique au moteur de stockage de ne stocker que les colonnes `CHAR`/`VARCHAR`. (`MyISAM` et `ISAM` uniquement)

  Si vous n'utilisez pas `PACK_KEYS`, le comportement par défaut est de ne stocker que les chaînes, et non pas les nombres. Si vous utilisez `PACK_KEYS=1`, les nombres seront aussi compactés.

  Lors du compactage, MySQL utilise une compression de préfixe :

  - Chaque clé requiert un octet de plus pour indiquer combien d'octets sont identiques dans la clé précédente.

  - Le pointeur de ligne est stocké au format grand-octet-en-premier, directement après la clé, pour améliorer la compression.

  Cela signifie que si vous avez de nombreuses clés proches sur des lignes consécutives, les clés successives ``identiques'' ne prendront généralement que deux octets (incluant le pointeur de ligne). Comparez cela à la situation ordinaire, où les clés successives occupent `taille_de_cle + taille_de_pointeur` (où la taille du pointeur est généralement de 4). En conséquence, vous tirerez le meilleur parti de cette compression si vous avez plusieurs nombres identiques. Si toutes les clés sont totalement différentes, vous utiliserez un octet de plus par clé, si la clé n'accepte pas les valeurs `NULL`. Dans ce cas, la taille de la clé sera stockée dans le même octet que celui qui indique que la clé est `NULL`.)

- `PASSWORD`

  Chiffre le fichier `.frm` avec un mot de passe. Cette option ne fait rien du tout pour la version standard de MySQL.

- `DELAY_KEY_WRITE`

  Spécifiez 1 si vous voulez attendre la fermeture de la table pour mettre à jour les index. `MyISAM` uniquement.

- `ROW_FORMAT`

  Définit la méthode de stockage des lignes (réservé pour le futur). Actuellement, cette option fonctionne uniquement avec des tables `MyISAM` qui supportent le `DYNAMIC` et `FIXED` en format de ligne. See Section 14.1.3, « Formats de table `MyISAM` ».

- `RAID_TYPE`

  L'option `RAID_TYPE` vous permet de dépasser la limite de 2 Go/4 Go de votre fichier de données `MyISAM` (mais pas le fichier d'index), pour les systèmes d'exploitation qui ne supportent pas les grands fichiers. Cette option n'est pas recommandée pour les systèmes d'exploitation qui supportent les grands fichiers.

  Vous pouvez réduire les ralentissements d'E/S en pla¸ant les dossiers `RAID` sur différents disques physiques. Actuellement, le seul type `RAID_TYPE` est `STRIPED`. `1` et `RAID0` sont des alias de `STRIPED`.

  Si vous spécifiez l'option `RAID_TYPE` pour une table `MyISAM`, spécifiez les options `RAID_CHUNKS` et `RAID_CHUNKSIZE` en même temps. La valeur maximale de `RAID_CHUNKS` est 255. `MyISAM` va créer `RAID_CHUNKS` sous-dossiers appelés `00`, `01`, `02`, ... `09`, `0a`, `0b`, ... dans le dossier de données. Dans chaque dossier, `MyISAM` va créer un fichier `tbl_name.MYD`. Lors de l'écriture dans le fichier de données, le gestionnaire `RAID` place les `RAID_CHUNKSIZE*1024` premiers octets dans le premier fichier, les seconds `RAID_CHUNKSIZE*1024` octets dans le fichier suivant, etc.

  `RAID_TYPE` fonctionne sur tous les systèmes d'exploitation, tant que vous avez compilé MySQL avec `--with-raid`, avec le script `configure`. Pour déterminer si votre serveur a le support des tables `RAID`, utilisez `SHOW VARIABLES LIKE 'have_raid'` pour voir si sa valeur vaut `YES`.

- `UNION`

  `UNION` sert lorsque vous voulez que plusieurs tables identiques se comporte comme une seule table. Cela fonctionne avec les tables `MERGE`. See Section 14.2, « Tables assemblées `MERGE` ».

  Pour le moment, vous devez avoir les droits de `SELECT`, `UPDATE` et `DELETE` pour les tables intégrées dans la table `MERGE`. Originalement, toutes les tables utilisées devaient être dans la même base de données, que la table `MERGE`. Cette restriction a été levée depuis MySQL 4.1.1.

- `INSERT_METHOD`

  Si vous voulez insérer des données dans une table `MERGE`, vous devez spécifier la table d'insertion avec l'attribut `INSERT_METHOD`. L'option `INSERT_METHOD` est utilisée uniquement avec les tables `MERGE`. Cette option a été introduite en MySQL 4.0.0. See Section 14.2, « Tables assemblées `MERGE` ».

- `DATA DIRECTORY`, `INDEX DIRECTORY`

  En utilisant `DATA DIRECTORY='directory'` ou `INDEX DIRECTORY='directory'`, vous pouvez spécifier où le moteur de stockage `MyISAM` doit placer les données de la table et le fichier d'index. Notez que vous devez donner un chemin absolu, et non un chemin relatif.

  Ces options ne fonctionnent que pour les tables `MyISAM` depuis MySQL 4.0, lorsque vous n'utilisez pas l'option `--skip-symlink`. Votre système d'exploitation doit aussi disposer d'une fonction `realpath()` compatible avec les threads. See Section 7.6.1.2, « Utiliser les liens symboliques avec les tables sous Unix ».

Depuis MySQL 3.23, vous pouvez créer une table à partir d'une autre, en ajoutant une commande `SELECT` après la commande `CREATE TABLE` :

    CREATE TABLE new_tbl SELECT * FROM orig_tbl;

MySQL va créer une nouvelle colonne pour chaque colonne de résultat de la commande `SELECT`. Par exemple :

    mysql> CREATE TABLE test (a INT NOT NULL AUTO_INCREMENT,
        ->        PRIMARY KEY (a), KEY(b))
        ->        TYPE=MyISAM SELECT b,c FROM test2;

Cela créer une table `MyISAM` avec trois colonnes `a`, `b`, et `c`. Notez que les colonnes de la commande `SELECT` sont ajoutées à droite de la table, et non dans la liste des colonnes. Par exemple :

    mysql> SELECT * FROM foo;
    +---+
    | n |
    +---+
    | 1 |
    +---+

    mysql> CREATE TABLE bar (m INT) SELECT n FROM foo;
    Query OK, 1 row affected (0.02 sec)
    Records: 1  Duplicates: 0  Warnings: 0

    mysql> SELECT * FROM bar;
    +------+---+
    | m    | n |
    +------+---+
    | NULL | 1 |
    +------+---+
    1 row in set (0.00 sec)

Pour chaque ligne de la table `foo`, une ligne est insérée dans la colonne `bar` avec la valeur issue de `foo` et la valeur par défaut pour les nouvelles colonnes.

Si une erreur survient durant la copie de la table, la table est automatiquement effacée.

`CREATE TABLE ... SELECT` ne va pas créer automatiquement les index pour vous. Ceci est fait intentionnellement pour rendre la commande aussi souple que possible. Si vous voulez avoir les mêmes index, vous devez les spécifier dans la commande avant le `SELECT` :

    mysql> CREATE TABLE bar (UNIQUE (n)) SELECT n FROM foo;

Certaines conversions de type pourraient avoir lieu. Par exemple, l'attribut `AUTO_INCREMENT` n'est pas préservé, et les colonnes `VARCHAR` peuvent devenir des colonnes `CHAR`.

Lors de la création de la table avec `CREATE ... SELECT`, assurez vous de mettre un nom d'alias à toutes les fonctions ou expression de la requête. Si vous ne le faîtes pas, la commande `CREATE` peut échouer ou donner des noms de colonnes inattendus.

    CREATE TABLE artists_and_works
    SELECT artist.name, COUNT(work.artist_id) AS number_of_works
    FROM artist LEFT JOIN work ON artist.id = work.artist_id
    GROUP BY artist.id;

Depuis MySQL 4.1, vous pouvez spécifier explicitement le type de colonne généré :

    CREATE TABLE foo (a TINYINT NOT NULL) SELECT b+1 AS a FROM bar;

En MySQL 4.1, vous pouvez aussi utiliser la clause `LIKE` pour créer une table basée sur la définition d'une autre table, y compris les attributs de colonnes et les index originaux :

    CREATE TABLE new_tbl LIKE orig_tbl;

`CREATE TABLE ... LIKE` ne copie pas les options de tables `DATA DIRECTORY` et `INDEX DIRECTORY` qui étaient spécifiées dans la table originale.

Vous pouvez faire précéder `SELECT` par `IGNORE` ou `REPLACE` pour indiquer comment gérer les clés doublons. Avec `IGNORE`, les nouvelles lignes qui sont en double seront ignorés. Avec `REPLACE`, les nouvelles lignes remplaceront les lignes précédentes, qui avaient la même valeur d'index. Si ni `IGNORE`, ni `REPLACE` ne sont spécifié, les doublons génèreront une erreur.

Pour s'assurer que le log binaire peut être réutilisé pour recréer la table originale, MySQL ne permettra pas les insertions concurrentes durant une commande `CREATE TABLE ... SELECT`.

#### 13.2.5.1. Modification automatique du type de colonnes

Dans certains cas, MySQL change automatiquement la spécification d'une colonne fournie dans la commande `CREATE TABLE`. (Cela peut aussi arriver avec `ALTER TABLE`) :

- Les colonnes `VARCHAR` avec une taille inférieure à quatre (4) sont changées en `CHAR`.

- Si l'une des colonnes d'une table est de taille variable, toute la ligne est, par conséquent, de taille variable. Ainsi, si une ligne contient une colonne de taille variable (`VARCHAR`, `TEXT` ou `BLOB`) toutes les colonnes `CHAR` de plus de trois caractères sont transformées en `VARCHAR`. Cela ne change en rien la fa¸on dont vous utilisez les colonnes. Pour MySQL, `VARCHAR` est simplement une autre fa¸on de stocker les caractères. MySQL effectue cette conversion car cela économise de la place, et rend les calculs sur les tables plus rapides. See Chapitre 14, Moteurs de tables MySQL et types de table.

- Depuis la version 4.1.0, si un champ `CHAR` ou `VARCHAR` est spécifié avec une taille supérieure à 255, il est converti en `TEXT`. C'est une fonctionnalité de compatibilité.

- La taille d'affichage de `TIMESTAMP` doit être un nombre pair et être compris entre 2 et 14. (2, 4, 6, 8, 10, 12 ou 14). Si vous spécifiez une taille plus grande que 14, ou inférieure à 2, celle-ci sera transformée en 14. Les valeurs impaires sont ramenées à la valeur pair supérieure la plus proche.

- Vous ne pouvez pas stocker de valeur littérale `NULL` dans une colonne de type `TIMESTAMP`. Cette valeur sera remplacée par la date et l'heure courante. De ce fait, les attributs `NULL` et `NOT NULL` n'ont pas de sens pour ces colonnes et sont ignorés. `DESCRIBE nom_de_table` indiquera toujours que la colonne `TIMESTAMP` accepte les valeurs `NULL`.

- Les colonnes qui font partie d'une `PRIMARY KEY` ont l'attribut `NOT NULL` même si elles ne sont pas déclarées comme tel.

- Depuis MySQL 3.23.51, les espaces terminaux sont automatiquement supprimés des valeurs `ENUM` et `SET` lors de la création de la table.

- MySQL change certains type de colonnes utilisés par d'autres serveurs SQL en types MySQL. See Section 11.7, « Utilisation des types de données issues d'autres SGBDR ».

- Si vous utilisez une clause `USING` pour spécifier un type d'index qui n'est pas légal pour un moteur de stockage, mais qu'un autre type d'index est disponible pour ce moteur sans affecter les résultats, le moteur utilisera le type disponible.

Si vous voulez voir si MySQL a utilisé un autre type que celui que vous avez spécifié, utilisez la commande `DESCRIBE nom_de_table`, après votre création ou modification de structure de table.

Certain types de colonnes peuvent être modifiés si vous compressez une table en utilisant l'utilitaire `myisampack`. See Section 14.1.3.3, « Caractéristiques des tables compressées ».

### 13.2.6. Syntaxe de `DROP DATABASE`

    DROP DATABASE [IF EXISTS] db_name

`DROP DATABASE` détruit toutes les tables dans la base de données et l'efface elle même. Soyez très prudent avec cette commande! Pour utiliser la commande `DROP DATABASE`, vous avez besoin du droit de `DROP` sur cette base.

Depuis la version 3.22 de MySQL, vous pouvez utiliser le mot clef `IF EXISTS` pour éviter l'affichage d'erreur si la base n'existe pas.

Si vous utilisez la commande `DROP DATABASE` sur un lien symbolique pointant sur la base de données, le lien et la base seront effacés.

Depuis MySQL 4.1.2, `DROP DATABASE` retourne le nombre de tables qui ont été supprimées. Cela revient à compter le nombre de fichiers `.frm` qui ont été supprimées.

La commande `DROP DATABASE` efface tous les fichiers du dossier de la base de données, qui ont été créés par MySQL lui-même, durant ses opérations normales :

- Tous les fichiers avec les extensions suivantes :

  `.BAK` | `.DAT` | `.HSH` | `.ISD`
  `.ISM` | `.ISM` | `.MRG` | `.MYD`
  `.MYI` | `.db` | `.frm` |

- Tous les sous-dossiers qui consistent de 2 chiffres hexadécimaux `00`-`ff`. Ce sont des dossiers `RAID`) qui sont aussi supprimés.

- Le fichier `db.opt`, s'il existe.

Si d'autres fichiers ou dossiers restent dans le dossier de base après que MySQL ait supprimés ceux listés ci-dessus, le dossier de base ne pourra pas être supprimé. Dans ce cas, vous devez supprimer manuellement les fichiers restant, et lancer à nouveau la commande `DROP DATABASE`.

Vous pouvez aussi supprimer des bases de données avec `mysqladmin`. See Section 8.4, « `mysqladmin`, administration d'un serveur MySQL ».

### 13.2.7. Syntaxe de `DROP INDEX`

    DROP INDEX nom_de_l_index ON nom_de_table

`DROP INDEX` supprime l'index nommé `nom_de_l_index` de la table `nom_de_table`. `DROP INDEX` ne fait rien avec la version 3.22 et les précédentes. Depuis cette version, `DROP INDEX` est un alias d'`ALTER TABLE` supprimant l'index.

See Section 13.2.2, « Syntaxe de `ALTER TABLE` ».

### 13.2.8. Syntaxe de `DROP TABLE`

    DROP [TEMPORARY] TABLE [IF EXISTS]
        tbl_name [, tbl_name] ...
        [RESTRICT | CASCADE]

`DROP TABLE` supprime une ou plusieurs tables. Toutes les données et la structure de la tables sont perdues, alors soyez prudents avec cette commande !

Depuis la version 3.22 de MySQL, vous pouvez utiliser le mot réservé `IF EXISTS` pour éviter l'affichage des erreurs pour les tables qui n'existent pas. See Section 13.5.3.19, « `SHOW WARNINGS | ERRORS` ».

`RESTRICT` et `CASCADE` sont autorisés pour faciliter le port. Pour le moment, elles ne font rien.

Note : `DROP TABLE` va automatiquement valider les transactions actives (hormis si vous utilisez la version 4.1 et le mot clé `TEMPORARY`).

L'option `TEMPORARY` est ignorée en 4.0. En 4.1, cette option fonctionne comme suit :

- Détruit uniquement les tables temporaires.

- Ne termine pas les transactions en cours.

- Aucun droits d'accès n'est vérifié.

`TEMPORARY` est pour le moment ignoré; Dans un futur proche, il servira à s'assurer qu'on efface vraiment une table temporaire.

### 13.2.9. Syntaxe de `RENAME TABLE`

    RENAME TABLE nom_de_table TO nouveau_nom_de_table[, nom_de_table2 TO nouveau_nom_de_table2,...]

Le changement de nom se fait atomiquement ce qui signifie qu'aucun autre processus ne peut accéder la table tant que l'opération est en cours. Cela rend possible de remplacer une vielle table avec une table vide :

    CREATE TABLE nouvelle_table (...);
    RENAME TABLE ancienne_table TO backup_table, nouvelle_table TO ancienne_table;

L'opération s'effectue de gauche à droite ce qui signifie que si vous voulez échanger deux noms de tables, vous devez :

    RENAME TABLE ancienne_table    TO backup_table,
                 nouvelle_table    TO ancienne_table,
                 backup_table TO nouvelle_table;

Si les deux bases de données sont sur le même disque, vous pouvez renommer à travers les bases :

    RENAME TABLE bdd_courante.nom_de_table TO autre_bdd.nom_de_table;

Quand vous exécutez `RENAME`, vous ne pouvez avoir aucune transaction active ou une table protégée en mode écriture. Vous devez avoir les privilèges `ALTER` et `DROP` sur l'ancienne table, et les privilèges `CREATE` et `INSERT` sur la nouvelle.

Si MySQL rencontre des erreurs dans un renommage multiple, il remettra les noms changés à leurs valeurs d'origine pour revenir à l'état d'origine.

`RENAME TABLE` a été ajouté à la version 3.23.23 de MySQL.

## 13.3. Commandes de bases de l'utilisateur de MySQL

### 13.3.1. Syntaxe de `DESCRIBE` (obtenir des informations sur les colonnes)

    {DESCRIBE | DESC} nom_de_table [nom_de_colonne | wild]

`DESCRIBE` fournit des informations à propos des colonnes de la table. `DESCRIBE` est un raccourci de `SHOW COLUMNS FROM`.

See Section 13.5.3.3, « Syntaxe de `SHOW COLUMNS` ».

`nom_de_colonne` peut être le nom d'une colonne ou une chaîne contenant les caractères spéciaux SQL ‘`%`’ et ‘`_`’. Il n'est pas nécessaire de placer la chaîne entre guillemets, hormis s'il y a des espaces ou d'autres caractères spéciaux.

    mysql> DESCRIBE city;
    +------------+----------+------+-----+---------+----------------+
    | Field      | Type     | Null | Key | Default | Extra          |
    +------------+----------+------+-----+---------+----------------+
    | Id         | int(11)  |      | PRI | NULL    | auto_increment |
    | Name       | char(35) |      |     |         |                |
    | Country    | char(3)  |      | UNI |         |                |
    | District   | char(20) | YES  | MUL |         |                |
    | Population | int(11)  |      |     | 0       |                |
    +------------+----------+------+-----+---------+----------------+
    5 rows in set (0.00 sec)

La colonne `Null` indique si la valeur NULL peut être stockée dans la colonne. YES indique que c'est le cas.

La colonne `Key` indique si un champ est indexé. La valeur `PRI` indique que le champ fait partie de la clé primaire de la table. `UNI` indique que le champ fait partie d'un index `UNIQUE`. La valeur `MUL` indique que plusieurs occurences d'une valeur sont autorisées dans le champ.

Un champ peut être désigné comme `MUL` même si l'index `UNIQUE` est utilisé, si les valeurs `NULL` sont autorisées, car une colonne `UNIQUE` peut contenir plusieurs valeurs `NULL` si la colonne est déclarée comme `NOT NULL`. Une autre cause pour `MUL` sur une colonne `UNIQUE` est lorsque deux colonnes forment un couple `UNIQUE` : même si la combinaison des deux colonnes est toujours unique, chaque colonne peut contenir des valeurs multiples. Notez que dans un index composé, seul le champ de gauche aura une entrée dans la colonne `Key`.

La colonne `Default` indique la valeur par défaut assignée à ce champ.

La colonne `Extra` indique des informations supplémentaires, disponibles sur le champ. Dans notre exemple, la colonne `Extra` indique que la colonne `Id` porte l'attribut `AUTO_INCREMENT`.

Si le type de colonne est différent de celui que vous pensiez avoir définit lors du `CREATE TABLE`, notez que MySQL change le type des colonnes de temps en temps. See Section 13.2.5.1, « Modification automatique du type de colonnes ».

Cette instruction est fournie pour une meilleure compatibilité avec Oracle.

L'instruction `SHOW` renvoie les mêmes informations. See Section 13.5.3, « Syntaxe de `SHOW` ».

### 13.3.2. Syntaxe de `USE`

    USE db_name

La commande `USE db_name` spécifie à MySQL d'utiliser la base `db_name` comme base par défaut pour les requêtes ne les mentionnant pas. La base choisie reste la même jusqu'à la fermeture de la session ou un nouvel appel à `USE` :

    mysql> USE db1;
    mysql> SELECT COUNT(*) FROM ma_table;      # sélectionne à partir de db1.ma_table
    mysql> USE db2;
    mysql> SELECT COUNT(*) FROM ma_table;      # sélectionne à partir de db2.ma_table

Rendre une base de données la base courante (en utilisant `USE`) ne vous interdit pas l'accès à d'autres tables dans d'autres bases. L'exemple suivant accède à la table `author` de la base `db1` et à la table `editor` de la base `db2` :

    mysql> USE db1;
    mysql> SELECT author_name,editor_name FROM author,db2.editor
        ->        WHERE author.editor_id = db2.editor.editor_id;

La commande `USE` est fournie pour assurer la compatibilité Sybase.

## 13.4. Commandes relatives aux verrous et aux transactions

### 13.4.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. See Section 5.9.4, « Le log binaire ».

Vous pouvez changer le niveau d'isolation des transactions avec `SET TRANSACTION ISOLATION LEVEL ...`. See Section 13.4.6, « Syntaxe de `SET TRANSACTION` ».

### 13.4.2. Commandes qui ne peuvent pas être annulées

Certaines commandes ne peuvent pas être annulées. En général, elles incluent le langage de définition des données (DDL), comme les commandes qui créent ou effacent des bases de données, ou celles qui créent, modifient ou effacent des tables de données.

Il est recommandé de concevoir vos transactions pour éviter ces commandes. Si vous soumettez une commande qui ne peut pas être annulée, dès le début de votre transaction, et qu'une commande ultérieure échoue, vous pourrez pas annuler l'ensemble de la transaction avec `ROLLBACK`.

### 13.4.3. Commandes qui peuvent causer une validation implicite

Les commandes suivantes valident implicitement une transaction, comme si vous aviez émis une commande `COMMIT` après :

`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` termine aussi une transaction si toutes les tables courantes sont verrouillées. Avant MySQL version 4.0.13, `CREATE TABLE` terminait une transaction si le log binaire était activé.

Les transactions ne peuvent pas être imbriquées. C'est la conséquence de cette validation `COMMIT` implicite pour toutes les transactions en cours, lorsque vous émettez une commande `START TRANSACTION` ou équivalent.

### 13.4.4. Syntaxe de `SAVEPOINT` et `ROLLBACK TO SAVEPOINT`

Depuis MySQL 4.0.14 et 4.1.1, `InnoDB` supporte les commandes SQL `SAVEPOINT` et `ROLLBACK TO SAVEPOINT`.

    SAVEPOINT identifier

Cette commande pose un jalon de transaction dont le nom est `identifier`. Si la transaction courante a déjà un jalon de ce nom, l'ancien jalon est effacé, et le nouveau est créé à la place.

Cette commande annule la transaction jusqu'au jalon. Les modifications que cette transaction a fait aux lignes depuis le jalon sont annulées, mais `InnoDB` ne libère pas les verrous posés en mémoire après le jalon. Notez que pour une nouvelle ligne insérée, l'information de verrou est conservée par l'identifiant de transaction de la ligne : le verrou n'est pas stocké en mémoire. Dansa ce cas, le verrou sera levé par l'annulation. Les jalons qui ont été posé après celui-ci sont aussi annulés.

Si la commande retourne l'erreur suivante, c'est qu'aucun jalon de ce nom n'a pu être trouvé.

    ERROR 1181: Got error 153 during ROLLBACK

Tous les jalons de la transaction courante sont annulés si vous exécutez les commandes `COMMIT` ou `ROLLBACK`, sans préciser de nom de jalon.

### 13.4.5. Syntaxe de `LOCK TABLES/UNLOCK TABLES`

    LOCK TABLES
        tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}
        [, tbl_name [AS alias] {READ [LOCAL] | [LOW_PRIORITY] WRITE}] ...
    UNLOCK TABLES

`LOCK TABLES` verrouille une table pour le thread courant. `UNLOCK TABLES` déverrouillera automatiquement tous les verrous posés par le thread courant. Toutes les tables verrouillées par le thread courant sont automatiquement déverrouillées quand ce thread utilise à nouveau `LOCK TABLES`, ou quand la connexion au serveur est perdue.

Note : `LOCK TABLES` n'est pas compatible avec les transactions, et valide automatiquement toute transaction active avant de verrouiller une table.

L'utilisation de `LOCK TABLES` dans MySQL 4.0.2 nécessite le privilège `LOCK TABLES` global et un privilège de `SELECT` sur les tables impliquées. Dans MySQL 3.23, il faut les privilèges `SELECT`, `INSERT`, `DELETE` et `UPDATE` sur les tables.

Les principales raisons d'utiliser `LOCK TABLES` sont l'émulation de transactions ou l'accélération des processus de modification de tables. Cela sera détaillé plus loin.

Si un thread obtient un verrouillage `READ` sur une table, ce thread (et tous les autres threads) peuvent uniquement accéder a cette table en lecture. Si un thread obtient un verrouillage `WRITE` sur une table, alors seul le thread qui a posé le verrou peut lire ou écrire sur cette table. Tous les autres threads sont bloqués.

La différence entre `READ LOCAL` et `READ` est que `READ LOCAL` autorise des requêtes `INSERT` non-conflictuelles à être exécutées alors que le verrou est posé. Ceci ne peut cependant pas être utilisé si vous souhaitez modifier les fichiers de la base de données en dehors de MySQL pendant que le verrou est posé.

Quand vous utilisez `LOCK TABLES`, vous devez verrouiller toutes les tables que vous allez utiliser, et vous devez utiliser les mêmes alias sur ce que vous utiliserez dans vos requêtes ! Si vous utilisez une table a plusieurs reprises dans une requête (avec des alias), vous devez verrouiller chacun des alias !

Si vos requêtes utilisent un alias pour une table, alors vous devez verrouiller la table avec l'alias. Le verrouillage ne fonctionnera pas si vous verrouillez la table sans spécifier l'alias :

    mysql> LOCK TABLE t READ;
    mysql> SELECT * FROM t AS myalias;
    ERROR 1100: Table 'myalias' was not locked with LOCK TABLES

De même, lorsque vous verrouillez une table avec un alias, vous devez utiliser le nom de l'alias dans vos requêtes :

    mysql> LOCK TABLE t AS myalias READ;
    mysql> SELECT * FROM t;
    ERROR 1100: Table 't' was not locked with LOCK TABLES
    mysql> SELECT * FROM t AS myalias;

Les verrous `WRITE` ont normalement des priorités supérieures aux verrous `READ`, afin de s'assurer que les modifications sont exécutées au plus vite. Cela signifie que si un thread demande un verrou `READ` et qu'un autre thread demande un verrou `WRITE`, la demande de verrou `READ` attendra que le thread `WRITE` ait abouti pour libérer le verrou. Vous pouvez utiliser le verrou `LOW_PRIORITY WRITE` pour permettre à d'autres threads d'obtenir des verrous `READ` pendant que le thread attend le verrou `WRITE`. Vous ne devriez utiliser les verrous `LOW_PRIORITY WRITE` que si vous êtes sûr qu'il y aura effectivement un moment où aucun thread ne posera de verrou `READ`.

`LOCK TABLES` fonctionne de la manière suivante :

1. Trie toutes les tables à verrouiller dans un ordre défini par MySQL (l'utilisateur ne définit pas d'ordre).

2. Si une table est verrouillée avec un verrou de lecture et un verrou d'écriture, il pose le verrou de lecture avant celui d'écriture.

3. Verrouille une table à la fois jusqu'à ce que le thread ait tous ses verrous.

Cette politique garantit le bon verrouillage des tables. Il faut cependant connaître certaines choses sur ce schéma :

Si vous utilisez un verrou `LOW_PRIORITY WRITE` pour une table, cela signifie seulement que MySQL attendra, pour poser ce verrou, qu'aucun autre thread ne réclame de verrou `READ`. Quand le thread aura le verrou `WRITE` et qu'il attendra que les verrous soient posés sur les autres tables de la liste, tous les autres threads attendront que le verrou `WRITE` soit libéré. Si cela devient un problème grave pour votre application, il est conseillé de convertir des tables en tables supportant les transactions.

Vous pouvez terminer un thread attendant un verrouillage de table en toute sécurité avec `KILL`. See Section 13.5.4.3, « Syntaxe de `KILL` ».

Il est déconseillé de verrouiller des tables utilisées avec `INSERT DELAYED`, car, dans ce cas, la requête `INSERT` est exécutée dans un autre thread.

Normalement, vous n'avez pas besoin de verrouiller les tables puisque chaque requête `UPDATE` est atomique : aucun autre thread ne peut interférer avec une autre requête active. Il existe cependant quelques cas où vous aurez besoin de verrouiller les tables :

- Si vous allez exécuter plusieurs requêtes sur plusieurs tables, il est préférable, d'un point de vue rapidité, de verrouiller les tables dont vous aurez besoin. L'inconvénient, bien sur, est que les autres threads ne pourront pas intervenir sur ces tables durant vos opérations, ni en extraire des informations si la table est verrouillée en `WRITE`.

  La raison pour laquelle les requêtes sont plus rapides avec `LOCK TABLES` est que MySQL ne rafraîchît pas l'index des clés des tables verrouillées tant que `UNLOCK TABLES` n'est pas invoqué (normalement, le cache des clés est rafraîchi après chaque requête SQL). Cela accélère les insertions, les modifications et les suppressions de données dans les tables `MyISAM`.

- Si vous utilisez un type de table dans MySQL qui ne supporte pas les transactions, vous devez utiliser `LOCK TABLES` pour vous assurez qu'aucun autre thread ne s'intercale entre un `SELECT` et un `UPDATE`. L'exemple suivant nécessite `LOCK TABLES` pour s'exécuter en toute sécurité :

      mysql> LOCK TABLES trans READ, customer WRITE;
      mysql> SELECT SUM(value) FROM trans WHERE customer_id=some_id;
      mysql> UPDATE customer SET total_value=sum_from_previous_statement
          ->        WHERE customer_id=some_id;
      mysql> UNLOCK TABLES;

  Sans `LOCK TABLES`, Il est possible qu'un autre thread ait inséré une nouvelle ligne dans la table `trans` entre l'exécution du `SELECT` et l'exécution de la requête `UPDATE`.

L'utilisation de modifications incrémentales (`UPDATE customer SET value=value+nouvelle_valeur`) ou de la fonction `LAST_INSERT_ID()` permet de se passer de `LOCK TABLES` dans de nombreuses situations. See Section 1.5.5.3, « Transactions et opérations atomiques ».

Il est aussi possible de résoudre de nombreux cas en utilisant un verrou utilisateur, avec les fonctions `GET_LOCK()` et `RELEASE_LOCK()`. Ces verrous sont stockés dans une table de hashage dans le serveur et utilisent les fonctions `pthread_mutex_lock()` et `pthread_mutex_unlock()` pour plus de vitesse. See Section 12.8.4, « Fonctions diverses ».

Voir Section 7.3.1, « Méthodes de verrouillage » pour plus de détails.

Il est possible de verrouiller tous les tables de toutes les bases avec la commande `FLUSH TABLES WITH READ LOCK`.

See Section 13.5.4.2, « Syntaxe de `FLUSH` ». C'est une méthode très pratique pour effectuer des sauvegardes si vous utilisez un système de fichiers qui, comme Veritas, permet de créer des instantanés.

Note : `LOCK TABLES` ne fonctionne pas avec les transactions et validera automatiquement toutes les transactions actives avant de poser verrouiller la table. See Section A.7.1, « Problèmes avec `ALTER TABLE`. ».

### 13.4.6. 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 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.

Pour une description de chaque niveau d'isolation de transaction `InnoDB`, voyez Section 15.11.2, « InnoDB et `SET ... TRANSACTION ISOLATION LEVEL ...` ». `InnoDB` supporte chacun des niveaux depuis MySQL 4.0.5. Le niveau par défaut est `REPEATABLE READ`.

On peut configurer le niveau d'isolation global des transactions pour `mysqld` avec `--transaction-isolation=...`. See Section 4.3.1, « Options de ligne de commande de `mysqld` ».

## 13.5. Référence de langage d'administration de la base de données

### 13.5.1. Commande de gestion des comptes utilisateurs

#### 13.5.1.1. Syntaxe de `CREATE USER`

    CREATE USER user [IDENTIFIED BY [PASSWORD] 'password']
        [, user [IDENTIFIED BY [PASSWORD] 'password']] ...

La commande `CREATE USER` crée un nouveau compte MySQL. Pour l'utiliser, vous devez avoir les droits de `CREATE USER` ou les droits d'`INSERT` dans la table de droits de la base `mysql`. Pour chaque compte, `CREATE USER` crée un nouvel enregistrement dans la table `mysql.user`, sans aucun droit. Une erreur survient si le compte existe déjà. Le compte peut recevoir un mot de passe avec la clause optionnelle `IDENTIFIED BY`. La valeur `user` et le mot de passe sont données de la même manière que dans la commande `GRANT`.

La commande `CREATE USER` a été ajoutée en MySQL 5.0.2.

#### 13.5.1.2. Effacer des utilisateurs MySQL

    DROP USER user_name

Cette commande a été ajoutée en MySQL 4.1.1.

Elle efface un utilisateur qui n'a aucun droits.

Pour effacer un utilisateur dans MySQL, vous devriez utiliser l'une des procédures suivantes, dans cet ordre :

1. Vérifiez les droits de l'utilisateur avec la commande `SHOW PRIVILEGES`. See Section 13.5.3.13, « `SHOW PRIVILEGES` ».

2. Effacez tous les droits de l'utilisateur avec la commande `REVOKE`. See Section 13.5.1.3, « Syntaxe de `GRANT` et `REVOKE` ».

3. Effacez l'utilisateur avec `DROP USER`.

Si vous utilisez une vieille version de MySQL, vous devriez commencer par effacer les droits, puis l'utilisateur avec :

    DELETE FROM mysql.user WHERE user='username' and host='hostname';
    FLUSH PRIVILEGES;

#### 13.5.1.3. Syntaxe de `GRANT` et `REVOKE`

    GRANT priv_type [(column_list)] [, priv_type [(column_list)]] ...
        ON {tbl_name | * | *.* | db_name.*}
        TO user [IDENTIFIED BY [PASSWORD] 'password']
            [, user [IDENTIFIED BY [PASSWORD] 'password']] ...
        [REQUIRE
            NONE |
            [{SSL| X509}]
            [CIPHER cipher [AND]]
            [ISSUER issuer [AND]]
            [SUBJECT subject]]
        [WITH [GRANT OPTION | MAX_QUERIES_PER_HOUR count |
                              MAX_UPDATES_PER_HOUR count |
                              MAX_CONNECTIONS_PER_HOUR count]]

    REVOKE priv_type [(column_list)] [, priv_type [(column_list)]] ...
        ON {tbl_name | * | *.* | db_name.*}
        FROM user [, user] ...

    REVOKE ALL PRIVILEGES, GRANT OPTION FROM user [, user] ...

Les commandes `GRANT` et `REVOKE` permettent à l'administrateur système de créer et supprimer des comptes utilisateur et de leur donner ou retirer des droits. `GRANT` et `REVOKE` sont implémentées en MySQL 3.22.11 ou plus récent. Pour les anciennes versions de MySQL, ces commandes ne font rien.

Les informations sur les comptes MySQL sont stockés dans la base `mysql`. Cette base et son accès sont présentés en détails dans la section Chapitre 5, Administration du serveur.

Les droits sont donnés à 4 niveaux :

- Niveau global

  Les droits globaux s'appliquent à toutes les bases de données d'un serveur. Ces droits sont stockés dans la table `mysql.user`. `REVOKE ALL ON *.*` retirera seulement les privilèges globaux.

- Niveau base de données

  Les droits de niveau de base de données s'appliquent à toutes les tables d'une base de données. Ces droits sont stockés dans les tables `mysql.db` et `mysql.host`. `REVOKE ALL ON db.*` retirera seulement les privilèges de base de données.

- Niveau table

  Les droits de table s'appliquent à toutes les colonnes d'une table. Ces droits sont stockés dans la table `mysql.tables_priv`. `REVOKE ALL ON db.table` retirera seulement les privilèges de table.

- Niveau colonne

  Les droits de niveau de colonnes s'appliquent à des colonnes dans une table. Ces droits sont stockés dans la table `mysql.columns_priv`. Quand vous utilisez `REVOKE` vous devez spécifier les mêmes colonnes qui s'étaient vues accorder des privilèges.

Pour faciliter la suppression de tous les droits d'un utilisateur, MySQL 4.1.2 a ajouté la syntaxe suivante, qui efface tous les droits de base, table et colonne pour un utilisateur donné :

    REVOKE ALL PRIVILEGES,GRANT FROM user_name [, user_name ...]

Avant MySQL 4.1.2, tous les droits ne peuvent pas être effacés d'un coup. Il faut deux commandes pour cela :

    REVOKE ALL PRIVILEGES FROM user [, user] ...
    REVOKE GRANT OPTION FROM user [, user] ...

Pour les commandes `GRANT` et `REVOKE`, la clause `priv_type` peut être spécifiée par les constantes suivantes :

Droit | Signification
`ALL [PRIVILEGES]` | Tous les droits sauf `WITH GRANT OPTION`.
`ALTER` | Autorise l'utilisation de `ALTER TABLE`.
`CREATE` | Autorise l'utilisation de `CREATE TABLE`.
`CREATE TEMPORARY TABLES` | Autorise l'utilisation de `CREATE TEMPORARY TABLE`.
`DELETE` | Autorise l'utilisation de `DELETE`.
`DROP` | Autorise l'utilisation de `DROP TABLE`.
`EXECUTE` | Autorise l'utilisateur à exécuter des procédures stockées (pour MySQL 5.0).
`FILE` | Autorise l'utilisation de `SELECT ... INTO OUTFILE` et `LOAD DATA INFILE`.
`INDEX` | Autorise l'utilisation de `CREATE INDEX` et `DROP INDEX`.
`INSERT` | Autorise l'utilisation de `INSERT`.
`LOCK TABLES` | Autorise l'utilisation de `LOCK TABLES` sur les tables pour lesquelles l'utilisateur a les droits de `SELECT`.
`PROCESS` | Autorise l'utilisation de `SHOW FULL PROCESSLIST`.
`REFERENCES` | Réservé pour le futur.
`RELOAD` | Autorise l'utilisation de `FLUSH`.
`REPLICATION CLIENT` | Donne le droit à l'utilisateur de savoir où sont les maîtres et esclaves.
`REPLICATION SLAVE` | Nécessaire pour les esclaves de réplication (pour lire les historiques binaires du maître).
`SELECT` | Autorise l'utilisation de `SELECT`.
`SHOW DATABASES` | `SHOW DATABASES` affiche toutes les bases de données.
`SHUTDOWN` | Autorise l'utilisation de `mysqladmin shutdown`.
`SUPER` | Autorise une connexion unique même si `max_connections` est atteint, et l'exécution des commandes `CHANGE MASTER`, `KILL thread`, `mysqladmin debug`, `PURGE MASTER LOGS` et `SET GLOBAL`.
`UPDATE` | Autorise l'utilisation de `UPDATE`.
`USAGE` | Synonyme de ``pas de droits''.
`GRANT OPTION` | Synonyme pour `WITH GRANT OPTION`

`USAGE` peut être utilisé lorsque vous voulez créer un utilisateur sans aucun droit.

Les droits de `CREATE TEMPORARY TABLES`, `EXECUTE`, `LOCK TABLES`, `REPLICATION ...`, `SHOW DATABASES` et `SUPER` sont nouveaux en version 4.0.2. Pour utiliser ces droits après mise à jour en 4.0.2, vous devez exécuter le script `mysql_fix_privilege_tables`. See Section 2.6.7, « Mise à jour des tables de droits ».

Dans les anciennes versions de MySQL, le droit de `PROCESS` donnait les mêmes droits que le nouveau droit `SUPER`.

Vous pouvez donner des droits globaux en utilisant la syntaxe `ON *.*`. Vous pouvez donner des droits de base en utilisant la syntaxe `ON nom_base.*`. Si vous spécifiez `ON *` et que vous avez une base de données qui est déjà sélectionnée, vous allez donner des droits pour la base de données courante. Attention : si vous spécifiez `ON *` et que vous n'avez pas de base courante, vous allez affecter les droits au niveau du serveur !

Les droits `EXECUTION`, `FILE`, `PROCESS`, `RELOAD`, `REPLICATION CLIENT`, `REPLICATION SLAVE`, `SHOW DATABASES`, `SHUTDOWN` et `SUPER` sont des droits d'administration, qui ne peuvent être donnés que globalement (avec la syntaxe `ON *.*`).

Les autres droits peuvent être donnés globalement ou à des niveaux plus spécifiques.

Les seuls droits `priv_type` que vous pouvez donner au niveau d'une table sont `SELECT`, `INSERT`, `UPDATE`, `DELETE`, `CREATE`, `DROP`, `GRANT OPTION`, `INDEX` et `ALTER`.

Les seuls droits `priv_type` que vous pouvez donner au niveau d'une colonne (avec la clause `column_list`) sont `SELECT`, `INSERT` et `UPDATE`.

`GRANT ALL` assigne des droits que vous possédez au niveau où vous le possédez. Par exemple, si vous utilisez `GRANT ALL ON db_name.*`, qui est un droit de niveau de base de données, aucun des droits globaux, comme `FILE` ne sera donné.

MySQL vous permet de donner des droits au niveau d'une base de données, même si la base de données n'existe pas, pour vous aider à préparer l'utilisation de la base de données. Actuellement, MySQL ne vous permet pas de créer des droits pour une table si la table n'existe pas.

MySQL ne supprime pas les droits lorsqu'un utilisateur efface une table ou une base.

Notez bien : les caractères joker ‘`_`’ et ‘`%`’ sont autorisés lors de la spécification de noms dans la commande `GRANT`. Cela signifie que si vous voulez utiliser par exemple le caractère littéral ‘`_`’ comme nom de base, vous devez le spécifier sous la forme ‘`\_`’ dans la commande `GRANT`, pour éviter à l'utilisateur d'accéder à d'autres bases, dont le nom pourrait correspondre au masque d'expression régulière ainsi créé. Utilisez plutôt `GRANT ... ON `foo\_bar`.* TO ...`.

Afin de permettre l'identification des utilisateurs depuis des hôtes arbitraires, MySQL supporte la spécification du nom d'utilisateur `nom_utilisateur` sous la forme `user@host`. Si vous voulez spécifier un nom d'utilisateur `user` qui contient des caractères spéciaux tels que ‘`-`’, ou une chaîne d'hôte `host` qui contient des caractères joker (comme ‘`%`’), vous pouvez placer le nom de l'utilisateur ou de l'hôte entre guillemets (par exemple, `'test-utilisateur'@'test-nomdhote'`).

Vous pouvez spécifier des caractères jokers dans le nom d'hôte. Par exemple, `user@'%.loc.gov'` fait correspondre l'utilisateur `user` de n'importe quel hôte du domaine `loc.gov`, et `user@'144.155.166.%'` fait correspondre l'utilisateur `user` à n'importe quelle adresse de la classe C `144.155.166`.

La forme simple de `user` est synonyme de `user@"%"`.

MySQL ne supporte pas de caractères joker dans les noms d'utilisateur. Les utilisateurs anonymes sont définis par l'insertion de ligne avec `User=''` dans la table `mysql.user`, ou en créant un utilisateur avec un nom vide, grâce à la commande `GRANT`.

    mysql> GRANT ALL ON test.* TO ''@'localhost' ...

Attention : si vous autorisez des utilisateurs anonymes à se connecter à votre serveur, vous devriez aussi donner ces droits à tous les utilisateurs locaux `user@localhost` car sinon, la ligne dans la table `mysql.user` sera utilisée lorsque l'utilisateur se connectera au serveur MySQL depuis la machine locale ! (Ce compte est créé durant l'installation de MySQL.)

Vous pouvez vérifier si cela s'applique à vous en exécutant la requête suivante :

    mysql> SELECT Host,User FROM mysql.user WHERE User='';

Si vous voulez effacer les utilisateurs anonymes d'un serveur, utilisez ces commandes :

    mysql> DELETE FROM mysql.user WHERE Host='localhost' AND User='';
    mysql> FLUSH PRIVILEGES;

Actuellement, la commande `GRANT` supporte uniquement les noms d'hôte, colonne, table et bases de données d'au plus 60 caractères. Un nom d'utilisateur peut être d'au plus 16 caractères.

Les droits pour les tables et colonnes sont combinés par OU logique, avec les quatre niveaux de droits. Par exemple, si la table `mysql.user` spécifie qu'un utilisateur a un droit global de `SELECT`, ce droit ne pourra pas être annulé au niveau base, table ou colonne.

Les droits d'une colonne sont calculés comme ceci :

    droit global
    OR (droit de base de données ET droit d'hôte)
    OR droit de table
    OR droit de colonne

Dans la plupart des cas, vous donnez des droits à un utilisateur en utilisant un seul des niveaux de droits ci-dessus, ce qui fait que la vie n'est pas aussi compliquée. Le détails de la procédure de vérification des droits et disponible dans Section 5.5, « Règles de sécurité et droits d'accès au serveur MySQL ».

Si vous donnez des droits à une paire utilisateur/hôte qui n'existe pas dans la table `mysql.user`, une ligne sera créée et restera disponible jusqu'à son effacement avec la commande `DELETE`. En d'autre termes, `GRANT` crée une ligne dans la table `user`, mais `REVOKE` ne la supprime pas. Vous devez le faire explicitement avec la commande `DELETE`.

Avec MySQL version 3.22.12 ou plus récent, si un nouvel utilisateur est créé, ou si vous avez les droits de `GRANT` globaux, le mot de passe sera configuré avec le mot de passe spécifié avec la clause `IDENTIFIED BY`, si elle est fournie. Si l'utilisateur a déjà un mot de passe, il sera remplacé par ce nouveau.

Attention : si vous créez un nouvel utilisateur, mais ne spécifiez pas de clause `IDENTIFIED BY`, l'utilisateur n'aura pas de mot de passe. Ce n'est pas sécuritaire.

Les mots de passe peuvent aussi être modifiés avec la commande `SET PASSWORD`. See Section 13.5.1.5, « Syntaxe de `SET PASSWORD` ».

Si vous ne voulez pas transmettre le mot de passe en texte clair, vous pouvez immédiatement utiliser l'option `PASSWORD` suivi du mot de passe déjà chiffré avec la fonction `PASSWORD()` ou l'API C `make_scrambled_password(char *to, const char *password)`.

Si vous donnez les droits de base, une ligne sera ajoutée dans la table `mysql.db`. Lorsque les droits sur cette base seront supprimés avec la commande `REVOKE`, cette ligne disparaîtra.

Si un utilisateur n'a pas de droit sur une table, elle ne sera pas affichée lorsqu'il demandera la liste des tables avec la commande `SHOW TABLES`. Si un utilisateur n'a pas de droit dans une base, le nom de la base ne sera pas affiché par `SHOW DATABASES` à moins que l'utilisateur n'ai un droit de `SHOW DATABASES`.

La clause `WITH GRANT OPTION` donne à l'utilisateur le droit de donner les droits qu'il possède à d'autres utilisateurs. La plus grande prudence est recommandée pour cette commande, car il permettra à terme à deux utilisateurs de combiner les droits dont ils disposent.

Vous ne pouvez pas donner un droit que vous ne possédez pas. le droit de `GRANT OPTION` ne vous donne le droit que de donner les droits que vous possédez.

Sachez que si vous donnez à quelqu'un le droit de `GRANT OPTION`, tous les droits que possède cet utilisateur seront distribuables. Supposez que vous donnez à un utilisateur le droit d'`INSERT` dans une base de données. Si vous donnez le droit de `SELECT` sur une base, et spécifiez l'option `WITH GRANT OPTION`, l'utilisateur peut distribuer non seulement son droit de `SELECT`, mais aussi son droit de `INSERT`. Si vous donnez ensuite le droit de `UPDATE`, il pourra alors distribuer `INSERT`, `SELECT` et `UPDATE`.

Il est recommandé de ne pas donner de droits de `ALTER` à un utilisateur normal. Si vous le faîtes, l'utilisateur pourra essayer de contourner le système de droits en renommant des tables.

`MAX_QUERIES_PER_HOUR #`, `MAX_UPDATES_PER_HOUR #` et `MAX_CONNECTIONS_PER_HOUR #` sont nouveaux en MySQL 4.0.2. Ces deux options limitent le nombre de requêtes et de modifications qu'un utilisateur peut réclamer dans une heure. Si `#` vaut 0 (valeur par défaut), alors cela signifie qu'il n'y a pas de limitations pour cet utilisateur. See Section 5.6.4, « Limiter les ressources utilisateurs ». Note: pour spécifier l'une de ces options pour un utilisateur existant sans ajouter d'autres privilèges additionnels, utilisez `GRANT USAGE ... WITH MAX_...`.

MySQL peut vérifier les attributs X509 en plus des éléments d'identifications habituels, comme le nom d'utilisateur et le mot de passe. Pour spécifier des options SSL pour un compte MySQL, utilisez la clause `REQUIRE` de la commande `GRANT`. Pour des informations générales sur SSL et MySQL, voyez Section 5.6.7, « Utilisation des connexions sécurisées ».

Il y a différentes possibilités pour limiter le type de connexions d'un compte :

- Si un compte ne doit pas utiliser SSL ou X509, les connexions sont autorisées si le mot de passe et le nom d'utilisateur sont valides. Cependant, les connexions non-chiffrées peuvent aussi être utilisées par le client, si le client dispose des bons certificats et clés.

- L'option `REQUIRE SSL` limite le serveur aux connexions chiffrées avec SSL. Notez que cette option peut être omise s'il y a des lignes d'identifications qui autorisent les connexions non chiffrées.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret' REQUIRE SSL;

- `REQUIRE X509` signifie que le client doit avoir un certificat valide, mais que le certificat exact, l'émetteur et le sujet n'ont pas d'importance. La seule obligation est qu'il faut pouvoir vérifier la signature auprès d'une des autorités de certification.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret' REQUIRE X509;

- `REQUIRE ISSUER 'issuer'` impose aux connexions l'utilisation d'un certificat X509 émis par l'autorité de certification `'issuer'`. Si le client présente un certificat d'une autre autorité, le serveur rejette la connexion. L'utilisation des certificats X509 implique toujours un chiffrement, ce qui fait que l'option `SSL` est inutile.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret'
          -> REQUIRE ISSUER '/C=FI/ST=Some-State/L=Helsinki/
             O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com';

  Notez que la valeur de `ISSUER` doit être saisie comme une seule chaîne.

- `REQUIRE SUBJECT 'subject'` impose à la connexion à la présentation d'un certificat X509 avec le sujet `'subject'`. Si le client présente un certificat qui est valide, mais avec un autre sujet, le serveur rejette la connexion.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret'
          -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
             O=MySQL demo client certificate/
             CN=Tonu Samuel/Email=tonu@example.com';

  Notez que la valeur de `SUBJECT` doit être saisie comme une seule chaîne.

- `REQUIRE CIPHER 'cipher'` est nécessaire pour s'assurer que des tailles de clé et chiffrements suffisantes sont utilisées. SSL peut être faible si de vieux algorithmes avec des clés courtes sont utilisées. En utilisant cette option, vous pouvez spécifier un chiffrement spécifique.

      mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
          -> IDENTIFIED BY 'goodsecret'
          -> REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA';

Les clauses `SUBJECT`, `ISSUER` et `CIPHER` peuvent être combinées avec la clause `REQUIRE` comme ceci :

    mysql> GRANT ALL PRIVILEGES ON test.* TO 'root'@'localhost'
        -> IDENTIFIED BY 'goodsecret'
        -> REQUIRE SUBJECT '/C=EE/ST=Some-State/L=Tallinn/
           O=MySQL demo client certificate/
           CN=Tonu Samuel/Email=tonu@example.com'
        -> AND ISSUER '/C=FI/ST=Some-State/L=Helsinki/
           O=MySQL Finland AB/CN=Tonu Samuel/Email=tonu@example.com'
        -> AND CIPHER 'EDH-RSA-DES-CBC3-SHA';

Notez que les valeurs de `SUBJECT` et `ISSUER` doivent être saisies comme une seule chaîne.

Depuis MySQL 4.0.4, le mot clé `AND` est optionnel entre les clauses de `REQUIRE`.

L'ordre des options est libre, mais les options doivent être spécifiées une seule fois.

Notez que si vous utilisez des droits de niveau table ou colonne même pour un utilisateur, le serveur vérifiera alors ces droits pour tous les utilisateurs, et cela ralentira MySQL un peu.

Lorsque `mysqld` démarre, tous les droits sont stockés en mémoire. Les droits de bases, tables et colonnes prennent aussitôt effet, et les droits des utilisateurs prendront effet dès leur prochaine configuration. Les modifications sur les tables de droits que vous effectuez avec les commandes `GRANT` et `REVOKE` sont prises en compte immédiatement par le serveur. Si vous modifiez manuellement les tables (avec `INSERT`, `UPDATE`, etc...), vous devez exécuter la commande `FLUSH PRIVILEGES`, ou la commande en ligne `mysqladmin flush-privileges` pour indiquer au serveur qu'il doit recharger les droits. See Section 5.5.7, « Quand les modifications de privilèges prennent-ils effets ? ».

Les différences notables entre l'ANSI SQL et MySQL pour la commande `GRANT` sont :

- Les droits MySQL sont donnés pour une combinaison nom d'utilisateur + nom d'hôte, et non pas pour un nom d'hôte seulement.

- L'ANSI SQL n'a pas de droits globaux ou de niveau base de données, et l'ANSI SQL ne supporte pas tous les types de droits que MySQL supporte. MySQL ne supporte pas le droit ANSI SQL de `TRIGGER` ou `UNDER`.

- MySQL ne supporte pas les droits standard SQL `TRIGGER` et `UNDER`.

- Les droits ANSI SQL sont structurés de manière hiérarchique. Si vous supprimez un utilisateur, tous les droits donnés à cet utilisateur seront supprimés. Avec MySQL, les droits ne sont pas automatiquement supprimés, et vous devez les supprimer manuellement, si besoin.

- Avec MySQL, si vous avez le droit de `INSERT` sur uniquement quelques colonnes de la table, vous pourrez exécuter des insertions. Les colonnes pour lesquelles vous n'avez pas de droit prendront alors leur valeur par défaut. L'ANSI SQL vous impose d'avoir les droits d'`INSERT` sur toutes les colonnes.

- Lorsque vous détruisez une table avec ANSI SQL, tous les droits liés à la table sont supprimés. Si vous supprimez un droit en ANSI SQL, tous les droits qui étaient basés sur ce droit sont supprimés. Avec MySQL, les droits peuvent être abandonnés explicitement avec la commande `REVOKE`, ou en manipulant les tables de droits de MySQL.

#### 13.5.1.4. Syntaxe de `RENAME USER`

    RENAME USER old_user TO new_user
        [, old_user TO new_user] ...

La commande `RENAME USER` renomme un compte MySQL existant. Pour l'utiliser, vous devez avoir les droits globaux de `CREATE USER` ou les droits de `UPDATE` dans la base `mysql`. Une erreur survient si l'ancien compte n'existe pas, ou que le nouveau compte existe déjà. Les valeurs `old_user` et `new_user` sont données de la même fa¸on que dans la commande `GRANT`.

La commande `RENAME USER` a été ajoutée en MySQL 5.0.2.

#### 13.5.1.5. Syntaxe de `SET PASSWORD`

    SET PASSWORD = PASSWORD('some password')
    SET PASSWORD FOR user = PASSWORD('some password')

La commande `SET PASSWORD` assigne un mot de passe à un compte utilisateur existant.

La première syntaxe modifie le mot de passe de l'utilisateur courant. Tout client qui s'est connecté avec un compte non-anonyme peut changer le mot de passe pour ce compte.

La seconde syntaxe modifie le mot de passe pour un compte tiers, sur le serveur. Seuls les clients qui ont accès aux bases `mysql` peuvent faire cela. La valeur de `user` doit être donnée au format `user_name@host_name`, où `user_name` et `host_name` sont tels que listés dans les colonnes `User` et `Host` de la table `mysql.user`. Par exemple, si vous avez une ligne avec les champs `User` et `Host` qui valent `'bob'` et `'%.loc.gov'`, vous pouvez écrire la commande suivante :

    mysql> SET PASSWORD FOR 'bob'@'%.loc.gov' = PASSWORD('newpass');

C'est l'équivalent de la commande suivante :

    mysql> UPDATE mysql.user SET Password=PASSWORD('newpass')
        -> WHERE User='bob' AND Host='%.loc.gov';
    mysql> FLUSH PRIVILEGES;

### 13.5.2. Commandes d'entretien des tables

#### 13.5.2.1. Syntaxe de `ANALYZE TABLE`

    ANALYZE TABLE nom_de_table[,nom_de_table...]

Cette commande analyse et stocke la clé de distribution de la table. Durant l'analyse, la table est verrouillée en lecture. Cette commande fonctionne avec les tables `MyISAM` et `BDB`.

C'est l'équivalent de la commande en ligne `myisamchk -a`.

MySQL utilise les clés de distribution pour décider dans quel ordre les tables doivent être rassemblées lors des jointures qui ne s'effectuent pas sur une constante.

La commande retourne une table avec les colonnes suivantes :

Colonne | Valeur
Table | Nom de la table
`Op` | ```analyze`'' (toujours)
`Msg_type` | Un des `status`, `error`, `info` ou `warning`.
`Msg_text` | Le message.

Vous pouvez vérifier la clé de distribution stockée avec la commande `SHOW INDEX`. See Section 13.5.3.6, « Syntaxe de `SHOW DATABASES` ».

Si la table n'a pas changé depuis la dernière commande `ANALYZE TABLE`, elle ne sera pas analysée à nouveau.

#### 13.5.2.2. Syntaxe de `BACKUP TABLE`

    BACKUP TABLE nom_de_table[,nom_de_table...] TO '/chemin/vers/le/dossier/de/sauvegardes'

Note : cette commande est obsolète. Nous travaillons à une solution de remplacement améliorée, qui proposera des sauvegardes à chaud. Durant ce temps, le script `mysqlhotcopy` peut être utilisé.

Cette commande copie le nombre minimal de fichiers de table dont en a besoin pour la restaurer vers le dossier de sauvegardes après avoir rafraîchit les changements dans le disque. Cela ne fonctionne actuellement que pour les tables au format `MyISAM`. Pour les tables `MyISAM`, elle ne copie que les fichiers `.frm` (définition) et `.MYD` (données), le fichier d'index `.MYD` pouvant, lui, être reconstruit à partir des deux autres.

Avant d'utiliser cette commande, merci de lire Section 5.7.1, « Sauvegardes de base de données ».

Pendant la sauvegarde, un verrou de lecture est posé sur chaque table, une par une, lors de leur copie. Si vous voulez sauvegarder une image instantanée de plusieurs table, vous devez d'abord exécuter un `LOCK TABLES` obtenant un verrou de lecture pour chaque table concernée.

La commande retourne une table avec les colonnes suivantes :

Colonne | Valeur
`Table` | Nom de la table
`Op` | Toujours ```backup`''
`Msg_type` | `status`, `error`, `info` ou encore `warning`.
`Msg_text` | Le message.

Notez que `BACKUP TABLE` n'est disponible en MySQL que depuis la version 3.23.25.

#### 13.5.2.3. Syntaxe de `CHECK TABLE`

    CHECK TABLE tbl_name[,tbl_name...] [option [option...]]

    option = QUICK | FAST | MEDIUM | EXTENDED | CHANGED

`CHECK TABLE` ne fonctionne qu'avec les tables `MyISAM` et `InnoDB`. Avec les tables `MyISAM`, c'est l'équivalent de la commande `myisamchk -m table_name` sur la table.

Par défaut, l'option `MEDIUM` est utilisée.

Cette commande vérifie l'intégrité des tables. Pour les tables `MyISAM`, des statistiques importantes sont mises à jour. La commande retourne les informations suivantes sur la table dans les colonnes suivantes :

Colonne | Valeur
Table | Nom de la table.
Op | Toujours ``check''.
Msg_type | Un des statut `status`, `error`, `info` ou `warning`.
Msg_text | Le message.

Notez que vous pouvez obtenir de nombreuses lignes d'informations pour chaque table. La dernière ligne sera du type `Msg_type status` et doit être normalement `OK`. Si vous n'obtenez pas de statut `OK` ou `Not checked`, il vous faudra exécuter une réparation de la table. See Section 5.7.3, « Utilisation de `myisamchk` pour la maintenance des tables et leur recouvrement ». `Not checked` signifie que la table a indiqué qu'il n'y a pas de vérification à faire.

Les différents types de vérifications sont les suivants :

Type | Signification
`QUICK` | N'analyse pas les lignes pour vérifier les liens erronés.
`FAST` | Ne vérifie que les tables qui n'ont pas été correctement fermées.
`CHANGED` | Ne vérifie que les tables qui ont changées depuis la dernière vérification, ou bien qui n'ont pas été correctement fermées.
`MEDIUM` | Analyse les lignes pour s'assurer que les liens effacés sont corrects. Cette option calcule aussi la somme de contrôle des lignes, et la vérifie avec la somme de contrôle des clés.
`EXTENDED` | Fait une vérification complète des liens pour chaque ligne. Cela vérifie que la table est totalement cohérente, mais cela peut prendre beaucoup de temps.

Pour les tables à format de dynamique de type `MyISAM`, une vérification de table sera toujours démarrée avec une option de niveau `MEDIUM`. Pour les tables à format de ligne statique, nous évitons les niveaux de `QUICK` et `FAST` car les lignes sont rarement corrompues.

Vous pouvez combiner les options de vérification comme ceci :

    CHECK TABLE test_table FAST QUICK;

L'exemple ci-dessus va simplement faire une vérification de la table, pour s'assurer qu'elle a été correctement fermée.

Note : dans certains cas, `CHECK TABLE` va modifier la table! Cela arrive si la table a été marquée comme "`corrupted`" et "`not closed properly`" mais `CHECK TABLE` n'a trouvé aucun problème dans la table. Dans ce cas, `CHECK TABLE` va marquer la table comme correcte.

Si une table est corrompue, il est probable que les problèmes sont dans les fichiers d'index et non pas dans les données. Tous les types de vérifications présentés ci-dessus vérifient les index soigneusement, et ils devraient trouver la plupart des erreurs.

Si vous voulez simplement vérifier une table que vous supposez correcte, vous pouvez n'utiliser aucune option, ou l'option `QUICK`. Cette dernière peut aussi être utilisée si vous êtes pressé, et que vous pouvez prendre le risque minime que `QUICK` ne trouve pas d'erreur dans votre fichier. Dans la plupart des cas, MySQL doit trouver toutes les erreurs de données, pour un usage normal. Si cela arrive, alors la table est marquée comme 'corrupted', auquel cas, la table ne pourra pas être utilisée tant qu'elle n'a pas été réparée).

`FAST` et `CHANGED` sont surtout destinées à être utilisées depuis un script : par exemple, il peut être exécuté depuis une tâche `cron`, si vous voulez vérifier la table de temps en temps. Dans la plupart des cas, l'option `FAST` doit être préférée à `CHANGED` : le seul cas ou vous pourriez préférez `CHANGED` est lorsque vous soup¸onnez avoir trouvé un bogue dans les tables `MyISAM`.

`EXTENDED` ne doit être utilisé qu'après une vérification normale, et que vous obtenez toujours des erreurs étranges lorsque MySQL essaie de modifier une ligne ou trouve une ligne avec clé (ce qui est très rare, si une vérification a réussie).

Certains problèmes rapportés par la commande `CHECK TABLE`, ne peuvent être corrigés automatiquement :

- `Found row where the auto_increment column has the value 0`.

  Cela signifie que vous avez dans votre table une ligne qui contient la valeur 0 alors qu'elle est de type `AUTO_INCREMENT`. (Il est possible de créer une ligne où la colonne `AUTO_INCREMENT` vaut 0 en spécifiant explicitement la valeur 0 dans la colonne avec la commande `UPDATE`.

  Ce n'est pas une erreur en soit, mais cela peut poser des problèmes si vous décidez de sauver cette table dans un fichier texte, et de la restaurer, ou encore d'appliquer la commande `ALTER TABLE` sur la table. Dans ce cas, la colonne `AUTO_INCREMENT` va changer automatiquement de valeur, en suivant les règles des colonnes de type `AUTO_INCREMENT`, qui vont causer un problème de clé doublon.

  Pour se débarasser de cette alerte, vous devez utiliser une commande `UPDATE` sur la table, pour mettre une valeur différente de 0 dans cette colonne.

#### 13.5.2.4. Syntaxe de `CHECKSUM TABLE`

    CHECKSUM TABLE tbl_name[,tbl_name ...] [ QUICK | EXTENDED ]

Calcule la somme de contrôle de la table.

Si `QUICK` est spécifié, la somme de contrôle instantanée est retournée, ou `NULL` si la table ne supporte pas les sommes de contrôle instantanées. See Section 13.2.5, « Syntaxe de `CREATE TABLE` ».

En mode `EXTENDED`, toute la table est lue, ligne par ligne, et la somme de contrôle est calculée. Cela peut être très lent pour les tables de grande taille.

Par défaut, sans `QUICK` ni `EXTENDED`, MySQL retourne la somme de contrôle si la table le supporte, et sinon, scanne la table.

Cette commande a été ajoutée en MySQL 4.1.1.

#### 13.5.2.5. Syntaxe de `OPTIMIZE TABLE`

    OPTIMIZE [LOCAL | NO_WRITE_TO_BINLOG] TABLE tbl_name [, tbl_name] ...

`OPTIMIZE TABLE` doit être utilisée si une grande partie de la base a été effacée, ou si vous avez fait de nombreuses modifications dans une table à format de ligne dynamique (des tables qui ont des colonnes de type `VARCHAR`, `BLOB` et `TEXT`). Les lignes effacées sont conservées dans une liste, et les prochaines opérations d'`INSERT` réutilisent les vieilles positions de lignes. Vous pouvez vous servir de la commande `OPTIMIZE TABLE` pour récupérer l'espace utilisé et défragmenter le fichier de données.

Dans la plupart des installations, vous n'avez pas à utiliser `OPTIMIZE TABLE`. Même si vous faites beaucoup de mises à jour sur des colonnes à taille dynamique, il n'est pas évident que vous ayez à passer cette commande plus d'une fois par semaine ou par mois, et uniquement sur quelques tables.

Pour le moment, `OPTIMIZE TABLE` fonctionne uniquement avec les tables de type `MyISAM` et `BDB`. Pour les tables `BDB`, `OPTIMIZE TABLE` est actuellement l'équivalent de `ANALYZE TABLE`. See Section 13.5.2.1, « Syntaxe de `ANALYZE TABLE` ».

Vous pouvez vous arranger pour que `OPTIMIZE TABLE` fonctionne sur d'autres types de tables, en démarrant `mysqld` avec `--skip-new` ou `--safe-mode`, mais dans ce cas, `OPTIMIZE TABLE` est simplement l'équivalent de `ALTER TABLE`.

`OPTIMIZE TABLE` fonctionne comme ceci :

1. Si la table contient des lignes effacées ou des lignes fragmentées, la table est compactée.

2. Si les pages d'index ne sont pas triées, `OPTIMIZE TABLE` les trie.

3. Si les statistiques ne sont pas à jour (et que la table n'a pas pu effectuer de réparation en triant l'index), elles sont mises à jour.

Notez que la table est verrouillée durant la commande `OPTIMIZE TABLE`.

Avant MySQL 4.1.1, `OPTIMIZE` n'était pas reportée dans le log binaire. Depuis MySQL 4.1.1 elles le sont, à moins que l'attribut optionnel `NO_WRITE_TO_BINLOG` ou son alias `LOCAL` ne soit utilisé.

#### 13.5.2.6. Syntaxe de `REPAIR TABLE`

    REPAIR TABLE tbl_name[,tbl_name...] [QUICK] [EXTENDED] [USE_FRM]

`REPAIR TABLE` répare une table possiblement corrompue. Par défaut, elle a le même effet que `myisamchk --recover tbl_name` sur une table. `REPAIR TABLE` fonctionne unqiuement avec les tables `MyISAM`.

Normalement, vous n'avez pas à exécuter cette commande, mais si une catastrophe vous frappe, vous êtes presque assurés de retrouver vos données dans les tables MyISAM, avec la commande `REPAIR TABLE`. Si vos tables sont souvent corrompues, vous devrie toutefois rechercher la cause de ce problème! See Section A.4.2, « Que faire si MySQL plante constamment ? ». See Section 14.1.4, « Problèmes avec les tables `MyISAM` ».

`REPAIR TABLE` répare autant que possible les tables corrompues. La commande retourne la table suivante :

Colonne | Valeur
`Table` | Nom de la table
`Op` | Toujours `repair`
`Msg_type` | Un des statut `status`, `error`, `info` ou `warning`.
`Msg_text` | Le message

La commande `REPAIR TABLE` pourrait afficher plusieurs messages pour chaque table. La dernière ligne doit être du format `Msg_type status` et doit être normalement `OK`. Si vous n'obtenez pas `OK`, vous devez essayer de réparer votre table avec la commande `myisamchk -o`, car `REPAIR TABLE` de supporte pas encore toutes les options de `myisamchk`. Dans un futur proche, nous allons rendre cette commande encore plus souple.

Si l'option `QUICK` est fournie, alors MySQL va essayer de ne réparer que le fichier d'index. Ce type de réparation est le même que `myisamchk --recover --quick`.

Si vous utilisez l'option `EXTENDED`, alors MySQL va essayer de créer l'index ligne par ligne, au lieu de créer un index à la fois, par tri. C'est une méthode qui peut s'avérer plus efficace que de trier sur des clés de taille fixe, si vous avez des clés `CHAR` longues qui se compressent bien. Ce type de réparation est l'équivalent de `myisamchk --safe-recover`.

Depuis MySQL 4.0.2, il existe le mode `USE_FRM` pour `REPAIR`. Utilisez-le si le fichier `.MYI` manque, ou si son entête est corrompu. Avec ce mode, MySQL va recréer le fichier `.MYI`, en utilisant les informations du fichier `.frm`. Ce type de réparation ne peut pas être fait avec `myisamchk`.

Attention : si le serveur s'arrête durant l'opération `REPAIR TABLE`, il est important d'exécuter à nouveau la commande `REPAIR TABLE` après le redémarrage (il est bon de faire une sauvegarde de toutes manières). Dans le pire scénario, vous pourriez vous retrouver avec un nouvel index sans relation avec les données, et la prochaine opération risque d'écraser le fichier de données. C'est peu probable, mais possible.

Avant MySQL 4.1.1, les commandes `REPAIR TABLE` n'étaient pas écrites dans le log binaire. Depuis MySQL 4.1.1, elles sont écrites dans le log binaire à moins que la clause `NO_WRITE_TO_BINLOG` ne soit utilisée (aussi connue sous le nom de `LOCAL`).

#### 13.5.2.7. Syntaxe de `RESTORE TABLE`

    RESTORE TABLE nom_de_table[,nom_de_table...] FROM '/chemin/vers/le/dossier/de/sauvegardes'

Restaure la ou les tables à partir d'une sauvegarde effectuée avec `BACKUP TABLE`. Les tables existantes ne seront pas écrasées et dans ce cas là, vous obtiendrez une erreur. La restauration prendra plus de temps que la sauvegarde à cause de la reconstruction du fichier d'index. Plus vous avez de clefs, plus la restauration sera longue. Tout comme `BACKUP TABLE`, `RESTORE TABLE` fonctionne seulement avec les tables `MyISAM`.

La sauvegarde de chaque table est constituée du fichier de format `.frm` et du fichier de données `.MYD`. L'opération de restauration restaure ces fichiers, puis les utilise pour reconstruire le fichier d'index `.MYI`. La restauration prend plus de temps que la sauvegarde, car il faut reconstituer l'index. Plus la table a d'index, plus cela prendra de temps.

Cette commande retourne un tableau avec les colonnes suivantes :

Colonne | Valeur
`Table` | Nom de la table
`Op` | Toujours ```restore`''
`Msg_type` | `status`, `error`, `info` ou encore `warning`.
`Msg_text` | Le message.

#### 13.5.2.8. 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 Section 5.2.3.1, « Variables système dynamiques ».

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 Section 9.3, « Variables 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. See Section 4.3.2, « Fichier d'options `my.cnf` ».

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`. See Section 13.5.3.18, « Syntaxe de `SHOW VARIABLES` ». Vous pouvez obtenir la valeur d'une variable spécifique avec la syntaxe `@@[global.|local.]nom_variable` :

    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 Section 5.2.3, « Variables serveur système », 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`. See Section 13.4.1, « Syntaxes de `START TRANSACTION`, `COMMIT` et `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'impose les relations de contraintes. Cette variable a été ajoutée en MySQL 3.23.52. See Section 15.7.4, « Contraintes de clés étrangères `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`

  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` (see Section C.1.7, « Changements de la version 5.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. Section 13.5.3.5, « 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 insertion 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.

- `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é en MySQL 3.23.52. See Section 15.7.4, « Contraintes de clés étrangères `FOREIGN KEY` ».

### 13.5.3. Syntaxe de `SHOW`

`SET` vous permet de modifier des variables et options.

`SHOW` a de très nombreuses formes, pour donner des informations sur les bases, tables, colonnes ou le serveur. Cette section les décrit.

    SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']
    SHOW CREATE DATABASE db_name
    SHOW CREATE TABLE tbl_name
    SHOW DATABASES [LIKE 'pattern']
    SHOW [STORAGE] ENGINES
    SHOW ERRORS [LIMIT [offset,] row_count]
    SHOW GRANTS FOR user
    SHOW INDEX FROM tbl_name [FROM db_name]
    SHOW INNODB STATUS
    SHOW [BDB] LOGS
    SHOW PRIVILEGES
    SHOW [FULL] PROCESSLIST
    SHOW STATUS [LIKE 'pattern']
    SHOW TABLE STATUS [FROM db_name] [LIKE 'pattern']
    SHOW [OPEN] TABLES [FROM db_name] [LIKE 'pattern']
    SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']
    SHOW WARNINGS [LIMIT [offset,] row_count]

Si la syntaxe d'une commande `SHOW` inclut la clause `LIKE 'pattern'`, `'pattern'` est une expression régulière qui peut contenir les jokers ‘`%`’ et ‘`_`’. Ce expression est utile pour restreindre la commande à une partie des valeurs normalement retournées.

Notez qu'il y a d'autres formes pour ces commandes, décrites à d'autres endroits du manuel :

- La commande `SET PASSWORD` pour assigner un mot de passe à un compte est présentée dans See Section 13.5.1.5, « Syntaxe de `SET PASSWORD` ».

- La commande `SHOW` a des formes pour afficher des informations sur la réplication, pour le maître et l'esclave :

      SHOW BINLOG EVENTS
      SHOW MASTER LOGS
      SHOW MASTER STATUS
      SHOW SLAVE HOSTS
      SHOW SLAVE STATUS

  Ces formes de `SHOW` sont décrites dans Section 13.6, « Commandes de réplication ».

#### 13.5.3.1. Commande `SHOW CHARACTER SET`

La commande `SHOW CHARACTER SET` montre tous les jeux de caractères disponibles. Il faut une clause facultative `LIKE` pour limiter les jeux de caractères à afficher.

Par exemple :

    mysql> SHOW CHARACTER SET LIKE 'latin%';
    +---------+-----------------------------+-------------------+--------+
    | Charset | Description                 | Default collation | Maxlen |
    +---------+-----------------------------+-------------------+--------+
    | latin1  | ISO 8859-1 West European    | latin1_swedish_ci |      1 |
    | latin2  | ISO 8859-2 Central European | latin2_general_ci |      1 |
    | latin5  | ISO 8859-9 Turkish          | latin5_turkish_ci |      1 |
    | latin7  | ISO 8859-13 Baltic          | latin7_general_ci |      1 |
    +---------+-----------------------------+-------------------+--------+
    4 rows in set (0.00 sec)

Remarques sur la liste précédente :

- La colonne `Maxlen` affiche le nombre maximum d'octets utilisés pour stocker un caractère.

#### 13.5.3.2. Syntaxe de `SHOW COLLATION`

    SHOW COLLATION [LIKE 'pattern']

Le résultat de `SHOW COLLATION` inclut tous les jeux de caractères disponibles. Vous pouvez utiliser optionnellement la clause `LIKE` pour limiter le nombre de réponses.

    mysql> SHOW COLLATION LIKE 'latin1%';
    +-------------------+---------+----+---------+----------+---------+
    | Collation         | Charset | Id | Default | Compiled | Sortlen |
    +-------------------+---------+----+---------+----------+---------+
    | latin1_german1_ci | latin1  |  5 |         |          |       0 |
    | latin1_swedish_ci | latin1  |  8 | Yes     | Yes      |       0 |
    | latin1_danish_ci  | latin1  | 15 |         |          |       0 |
    | latin1_german2_ci | latin1  | 31 |         | Yes      |       2 |
    | latin1_bin        | latin1  | 47 |         | Yes      |       0 |
    | latin1_general_ci | latin1  | 48 |         |          |       0 |
    | latin1_general_cs | latin1  | 49 |         |          |       0 |
    | latin1_spanish_ci | latin1  | 94 |         |          |       0 |
    +-------------------+---------+----+---------+----------+---------+
    7 rows in set (0.00 sec)

La colonne `Default` indique si une collation est la collation par défaut pour son jeu de caractères. `Compiled` indique si le jeu de caractères est compilé dans le serveur ou non. `Sortlen` est en relation avec la quantité de mémoire nécessaire pour trier des chaînes exprimées dans le jeu de caractéres.

#### 13.5.3.3. Syntaxe de `SHOW COLUMNS`

    SHOW [FULL] COLUMNS FROM tbl_name [FROM db_name] [LIKE 'pattern']

`SHOW COLUMNS` liste les colonnes de la table. Si les types de colonnes sont différents de ceux que vous avez utilisé avec la commande `CREATE TABLE`, c'est que MySQL a modifié silencieusement le type lors de la création. Les conditions de cette modification sont décrites dans Section 13.2.5.1, « Modification automatique du type de colonnes ».

Le mot clé `FULL` peut être utilisé depuis MySQL 3.23.32. Il fait afficher les droits dont vous disposez pour chaque colonne. Depuis MySQL 4.1, `FULL` affiche aussi les commentaires par colonne.

Vous pouvez utiliser `db_name.tbl_name` comme syntaxe alternative à `tbl_name FROM db_name`. Ces deux commandes sont équivalentes :

    mysql> SHOW COLUMNS FROM mytable FROM mydb;
    mysql> SHOW COLUMNS FROM mydb.mytable;

`SHOW FIELDS` est un synonyme de `SHOW COLUMNS`. Vous pouvez aussi lister les colonnes d'une table avec la commande `mysqlshow db_name tbl_name`.

La commande `DESCRIBE` fournit une information similaire à `SHOW COLUMNS`. See Section 13.3.1, « Syntaxe de `DESCRIBE` (obtenir des informations sur les colonnes) ».

#### 13.5.3.4. Syntaxe de `SHOW CREATE DATABASE`

    SHOW CREATE DATABASE db_name

La requête suivante montre une commande `CREATE DATABASE` qui va créer une base de donnée. Commande ajoutée en MySQL 4.1.

    mysql> SHOW CREATE DATABASE test\G
    *************************** 1. row ***************************
           Database: test
    Create Database: CREATE DATABASE `test`
                     /*!40100 DEFAULT CHARACTER SET latin1 */

#### 13.5.3.5. Syntaxe de `SHOW CREATE TABLE`

    SHOW CREATE TABLE tbl_name

Affiche la commande `CREATE TABLE` nécessaire pour créer une table donnée.

    mysql> SHOW CREATE TABLE t\G
    *************************** 1. row ***************************
           Table: t
    Create Table: CREATE TABLE t (
      id int(11) default NULL auto_increment,
      s char(60) default NULL,
      PRIMARY KEY (id)
    ) TYPE=MyISAM

`SHOW CREATE TABLE` va protéger le nom de la table et des colonnes selon l'option `SQL_QUOTE_SHOW_CREATE`. Section 13.5.2.8, « Syntaxe de `SET` ».

#### 13.5.3.6. Syntaxe de `SHOW DATABASES`

    SHOW {DATABASES | SCHEMAS} [LIKE 'pattern']

`SHOW DATABASES` liste les bases de données disponible sur le serveur MySQL. Vous pouvez aussi obtenir cette liste avec l'utilitaire `mysqlshow`. Depuis MySQL 4.0.2, vous ne verrez que les bases pour lesquelles vous avez des droits, à moins que vous n'ayez le droit de `SHOW DATABASES`.

Si le serveur a été lancé avec l'option `--skip-show-database`, vous ne pouvez pas utiliser cette commande à moins que vous n'ayez le droit de `SHOW DATABASES`.

`SHOW SCHEMAS` est disponible depuis MySQL 5.0.2

#### 13.5.3.7. Syntaxe `SHOW ENGINES`

    SHOW [STORAGE] ENGINES

`SHOW ENGINES` affiche les informations sur les moteurs de stockage du serveur. C'est particulièrement utile pour connaître les moteurs supportés par votre serveur, ou le moteur par défaut. Cette commande a été ajoutée en MySQL 4.1.2. `SHOW TABLE TYPES` est un synonyme, mais est abandonnée.

    mysql> SHOW ENGINES\G
    *************************** 1. row ***************************
       Type: MyISAM
    Support: DEFAULT
    Comment: Default type from 3.23 with great performance
    *************************** 2. row ***************************
       Type: HEAP
    Support: YES
    Comment: Hash based, stored in memory, useful for temporary tables
    *************************** 3. row ***************************
       Type: MEMORY
    Support: YES
    Comment: Alias for HEAP
    *************************** 4. row ***************************
       Type: MERGE
    Support: YES
    Comment: Collection of identical MyISAM tables
    *************************** 5. row ***************************
       Type: MRG_MYISAM
    Support: YES
    Comment: Alias for MERGE
    *************************** 6. row ***************************
       Type: ISAM
    Support: NO
    Comment: Obsolete table type; Is replaced by MyISAM
    *************************** 7. row ***************************
       Type: MRG_ISAM
    Support: NO
    Comment: Obsolete table type; Is replaced by MRG_MYISAM
    *************************** 8. row ***************************
       Type: InnoDB
    Support: YES
    Comment: Supports transactions, row-level locking and foreign keys
    *************************** 9. row ***************************
       Type: INNOBASE
    Support: YES
    Comment: Alias for INNODB
    *************************** 10. row ***************************
       Type: BDB
    Support: YES
    Comment: Supports transactions and page-level locking
    *************************** 11. row ***************************
       Type: BERKELEYDB
    Support: YES
    Comment: Alias for BDB

La valeur `Support` indique que le moteur est supporté, et si le moteur est le moteur par défaut. Par exemple, si le serveur est lancé avec l'option `--default-table-type=InnoDB` alors la valeur de la colonne `Support` de la ligne `InnoDB` contiendra `DEFAULT`.

#### 13.5.3.8. Syntaxe de `SHOW ERRORS`

    SHOW ERRORS [LIMIT [offset,] row_count]
    SHOW COUNT(*) ERRORS

Cette commande est similaire à `SHOW WARNINGS`, hormis le fait qu'au lieu d'afficher les erreurs, alertes et notes, elle n'affiche que les erreurs. `SHOW ERRORS` est disponible depuis MySQL 4.1.0.

La clause `LIMIT` a la même syntaxe que celle de la commande `SELECT`. See Section 13.1.7, « Syntaxe de `SELECT` ».

La commande `SHOW COUNT(*) ERRORS` affiche le nombre d'erreurs. Vous pouvez aussi connaître ce nombre en lisant la variable `error_count` :

    SHOW COUNT(*) ERRORS;
    SELECT @@error_count;

Pour plus d'informations, voyez Section 13.5.3.19, « `SHOW WARNINGS | ERRORS` ».

#### 13.5.3.9. `SHOW GRANTS`

    SHOW GRANTS FOR user

`SHOW GRANTS FOR user` affiche la commande nécessaire pour donner les même droits qu'un utilisateur existant.

    mysql> SHOW GRANTS FOR 'root'@'localhost';
    +---------------------------------------------------------------------+
    | Grants for root@localhost                                           |
    +---------------------------------------------------------------------+
    | GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' WITH GRANT OPTION |
    +---------------------------------------------------------------------+

Depuis MySQL 4.1.2, pour lister les droits de la session courante, vous pouvez connaître le nom d'utilisateur de la session avec ces commandes :

    SHOW GRANTS;
    SHOW GRANTS FOR CURRENT_USER;
    SHOW GRANTS FOR CURRENT_USER();

Avant MySQL 4.1.2, vous pouviez connaître le nom d'identification de l'utilisation avec la fonction `CURRENT_USER()` (nouveau en MySQL 4.0.6). Puis, utilisez cette valeur avec la commande `SHOW GRANTS`. See Section 12.8.3, « Fonctions d'informations ».

`SHOW GRANTS` est disponible depuis MySQL 3.23.4.

#### 13.5.3.10. Syntaxe de `SHOW INDEX`

    SHOW INDEX FROM tbl_name [FROM db_name]

`SHOW INDEX` retourne les informations sur les index de la table, dans un format proche de celui de `SQLStatistics` en ODBC.

`SHOW INDEX` retourne les champs suivants :

- `Table`

  Le nom de la table.

- `Non_unique`

  0 si l'index ne peut pas contenir de doublons, et 1 s'il le peut.

- `Key_name`

  Le nom de l'index.

- `Seq_in_index`

  Le numéro de la colonne dans l'index, en commen¸ant à 1.

- `Column_name`

  Le nom de la colonne.

- `Collation`

  Comment la colonne est triée dans l'index. Avec MySQL, les valeurs peuvent être ‘`A`’ (Ascendant) ou `NULL` (non trié).

- `Cardinality`

  Le nombre de valeurs uniques dans l'index. C'est une valeur qui est mise à jour avec la commande `ANALYZE TABLE` ou `myisamchk -a`. `Cardinality` est compté en se basant sur des statistiques entières : il n'est pas toujours exacte pour les petites tables.

- `Sub_part`

  Le nombre de caractères indexé si la colonne n'est que partiellement indexée. `NULL` si la colonne entière est indexée.

- `Packed`

  Indique comment la clé est compactée. `NULL` si elle ne l'est pas.

- `Null`

  Contient `YES` si la colonne contient `NULL`, `''` sinon.

- `Index_type`

  La méthode d'indexation utilisée (`BTREE`, `FULLTEXT`, `HASH`, `RTREE`).

- `Comment`

  Différentes remarques. Avant MySQL 4.0.2 lorsque la colonne `Index_type` a été ajoutée, `Comment` indiquait si un index était `FULLTEXT`.

Les colonnes `Packed` et `Comment` ont été ajoutée en MySQL 3.23.0. Les colonnes `Null` et `Index_type` ont été ajoutées en MySQL 4.0.2.

Vous pouvez utiliser la syntaxe `db_name.tbl_name` comme alternative à `tbl_name FROM db_name`. Ces deux commandes sont équivalentes :

    mysql> SHOW INDEX FROM mytable FROM mydb;
    mysql> SHOW INDEX FROM mydb.mytable;

`SHOW KEYS` est un synonyme `SHOW INDEX`. Vous pouvez aussi lister les index d'une table avec la commande en ligne `mysqlshow -k db_name tbl_name`.

#### 13.5.3.11. Syntaxe de `SHOW INNODB STATUS`

    SHOW INNODB STATUS

Cette commente donne des informations exhaustives sur le moteur de stockage `InnoDB`.

#### 13.5.3.12. Syntaxe de `SHOW LOGS`

    SHOW [BDB] LOGS

La commande `SHOW LOGS` affiche les informations d'état de vos fichiers de logs. Actuellement, elle n'affiche que les informations pour les fichiers de log des tables Berkeley DB.

- `File` affiche le chemin complet jusqu'au fichier de log.

- `Type` affiche le type de fichier de log (`BDB` pour les tables de types Berkeley DB)

- `Status` affiche le status du fichier de log (`FREE` si le fichier peut être supprimé, ou `IN USE` si le fichier est utilisé par une transaction en cours)

#### 13.5.3.13. `SHOW PRIVILEGES`

    SHOW PRIVILEGES

Cette commande est implémentée en MySQL 4.1.0.

`SHOW PRIVILEGES` affiche la liste des droits que le serveur MySQL supporte.

    mysql> show privileges;
    +------------+--------------------------+-------------------------------------------------------+
    | Privilege  | Context                  | Comment                                               |
    +------------+--------------------------+-------------------------------------------------------+
    | Select     | Tables                   | Lire des lignes d'une table                           |
    | Insert     | Tables                   | Insérer des lignes dans une table                     |
    | Update     | Tables                   | Modifier les lignes existantes                        |
    | Delete     | Tables                   | Effacer des lignes existantes                         |
    | Index      | Tables                   | Créer ou effacer des indexs                           |
    | Alter      | Tables                   | Modifier la structure d'une table                     |
    | Create     | Databases,Tables,Indexes | Créer une nouvelle base ou table                      |
    | Drop       | Databases,Tables         | Effacer une base ou table                             |
    | Grant      | Databases,Tables         | Donner à d'autres les droits courants                 |
    | References | Databases,Tables         | Avoir des références sur les tables                   |
    | Reload     | Server Admin             | Rafraîchir les droits, tables et logs                 |
    | Shutdown   | Server Admin             | Eteindre le serveurver                                |
    | Process    | Server Admin             | Voir la version texte des requêtes en cours           |
    | File       | File access on server    | Lire et écrire des fichiers sur le serveur            |
    +------------+--------------------------+-------------------------------------------------------+
    14 rows in set (0.00 sec)

#### 13.5.3.14. Syntaxe de `SHOW PROCESSLIST`

    SHOW [FULL] PROCESSLIST

`SHOW [FULL] PROCESSLIST` affiche la liste de processus qui sont en cours d'exécution. Vous pouvez aussi obtenir ces informations avec la commande en ligne `mysqladmin processlist`. Si vous avez les droits de `SUPER`, vous pourrez aussi voir les autres threads. Sinon, vous ne pourrez voir que les votre. See Section 13.5.4.3, « Syntaxe de `KILL` ». Si vous n'utilisez pas l'option `FULL`, seuls les 100 premiers caractères de chaque requête seront affichés.

Cette commande est très pratique si vous obtenez trop d'erreurs ‘`too many connections`’ et que vous voulez savoir ce qui se passe. MySQL réserve une connexion supplémentaire pour un client ayant les droits de `SUPER`, de fa¸on à ce qu'il y ait toujours la possibilité de se connecter et de vérifier le système (en supposant que vous ne donnez pas ce droit à tous vos utilisateurs).

Certains états sont souvent disponible dans le résultat de `mysqladmin processlist`

- `Checking table`

  Le thread fait une vérification (automatique) de la table.

- `Closing tables`

  Le thread est en train d'écrire les données modifiées sur le disque, et il va fermer les tables. Cela doit être une opération très rapide. Si ce n'est pas le cas, vous devriez vérifier si vous n'avez pas un disque plein, ou que le disque est sous haute charge.

- `Connect Out`

  Connexion d'un esclave sur le maître.

- `Copying to tmp table on disk`

  Le résultat temporaire était plus grand que `tmp_table_size` et le thread passe d'une table en mémoire à une table sur disque.

- `Creating tmp table`

  Le thread est en train de créer une table temporaire pour contenir le résultat d'une requête.

- `deleting from main table`

  Lors de l'exécution de la première partie d'une requête d'effacement multi-table, et que MySQL n'a commencé à effacer que dans la première table.

- `deleting from reference tables`

  Lors de l'exécution de la deuxième partie d'une requête d'effacement multi-table, et que MySQL a commencé à effacer dans les autres tables.

- `Flushing tables`

  Le thread exécute la commande `FLUSH TABLES` et il attend que tous les threads ferme leur tables.

- `Killed`

  Quelqu'un a envoyé une commande `KILL` et le thread s'annuler la prochaine fois qu'il vérifie l'option de kill. Cette option est vérifiée dans chaque boucle majeure de MySQL, mais dans certains cas, il peut lui prendre un court instant avant de s'arrêter. Si le thread est verrouillé par un autre thread, l'arrêt va prendre effet aussitôt que l'autre thread lève son verrou.

- `Sending data`

  Le thread traite des lignes pour une commande `SELECT` et il envoie les données au client.

- `Sorting for group`

  Le thread est en train de faire un tri pour satisfaire une clause `GROUP BY`.

- `Sorting for order`

  Le thread est en train de faire un tri pour satisfaire une clause `ORDER BY`.

- `Opening tables`

  Cela signifie simplement que le thread essaie d'ouvrir une table. Ce doit être une opération très rapide, à moins que quelque chose ne retarde l'ouverture. Par exemple, une commande `ALTER TABLE` ou `LOCK TABLE` peut empêcher l'ouverture de table, jusqu'à l'achèvement de la commande.

- `Removing duplicates`

  La requête utilisait `SELECT DISTINCT` de telle manière que MySQL ne pouvait pas optimiser les lignes distinctes au début du traitement. A cause de cela, MySQL doit effectuer une opération de plus pour supprimer toutes les lignes en doubles, avant d'envoyer les lignes au client.

- `Reopen table`

  Le thread a re¸u un verrou pour une table, mais a noté après l'avoir re¸u que la structure de la table a changé. Il a libéré le verrou, fermé la table, et maintenant il essaie de la rouvrir.

- `Repair by sorting`

  Le thread répare la table en utilisant la méthode de tri pour créer l'index.

- `Repair with keycache`

  Le thread répare la table en utilisant la méthode de création des clés à partir du cache de clé. C'est bien plus lent que `la réparation par tri`.

- `Searching rows for update`

  Le thread effectue une première phase pour trouver toutes les lignes qui satisfont les critères avant de les modifier. Cela doit être fait si `UPDATE` modifie l'index qui sera utilisé pour trouver les lignes.

- `Sleeping`

  Le thread attend que le client envoie une nouvelle commande.

- `System lock`

  Le thread attend le verrou externe pour la table. Si vous n'utilisez pas de serveurs MySQL multiples qui exploitent les mêmes tables, vous pouvez désactiver les verrous systèmes avec l'option `--skip-external-locking`.

- `Upgrading lock`

  Le gestionnaire de `INSERT DELAYED` essaie d'obtenir un verrou pour insérer des lignes.

- `Updating`

  Le thread recherche des lignes pour les modifier.

- `User Lock`

  Le thread attend un `GET_LOCK()`.

- `Waiting for tables`

  Le thread a re¸u l'annonce que la structure de table a été modifiée, et il doit réouvrir la table pour obtenir une nouvelle structure. Pour être capable de réouvrir la table, il doit attendre que les autres threads aient fermé la table en question.

  Cette annonce survient lorsqu'un autre autre thread a été utilisé avec la commande `FLUSH TABLES` ou une des commandes suivantes, appliquées à la table en question : `FLUSH TABLES table_name`, `ALTER TABLE`, `RENAME TABLE`, `REPAIR TABLE`, `ANALYZE TABLE` ou `OPTIMIZE TABLE`.

- `waiting for handler insert`

  Le gestionnaire de `INSERT DELAYED` a traité toutes insertions, et en attend de nouvelles.

La plupart des états sont des opérations très rapides. Si le thread s'attarde dans un de ces états pour plusieurs secondes, il doit y avoir un problème qui mérite d'être étudié.

Il existe encore d'autres états qui ne sont pas mentionné ci-dessus, mais la majorité sont utilisés pour trouver des bogues dans `mysqld`.

#### 13.5.3.15. Syntaxe de `SHOW STATUS`

    SHOW STATUS [LIKE 'pattern']

`SHOW STATUS` affiche des informations sur le statut du serveur. Cette information est aussi accessible avec la commande la commande `mysqladmin extended-status`.

Un résultat partiel est présenté ci-dessous. La liste complète des variables dépend de votre serveur. Leur signification individuelle est présentée dans la section See Section 5.2.4, « Variables de statut du serveur ».

    mysql> SHOW STATUS;
    +--------------------------+------------+
    | Variable_name            | Value      |
    +--------------------------+------------+
    | Aborted_clients          | 0          |
    | Aborted_connects         | 0          |
    | Bytes_received           | 155372598  |
    | Bytes_sent               | 1176560426 |
    | Connections              | 30023      |
    | Created_tmp_disk_tables  | 0          |
    | Created_tmp_tables       | 8340       |
    | Created_tmp_files        | 60         |
    ...
    | Open_tables              | 1          |
    | Open_files               | 2          |
    | Open_streams             | 0          |
    | Opened_tables            | 44600      |
    | Questions                | 2026873    |
    ...
    | Table_locks_immediate    | 1920382    |
    | Table_locks_waited       | 0          |
    | Threads_cached           | 0          |
    | Threads_created          | 30022      |
    | Threads_connected        | 1          |
    | Threads_running          | 1          |
    | Uptime                   | 80380      |
    +--------------------------+------------+

Avec la clause `LIKE`, la commande peut limiter l'affichage des variables à celles qui vérifient un masque :

    mysql> SHOW STATUS LIKE 'Key%';
    +--------------------+----------+
    | Variable_name      | Value    |
    +--------------------+----------+
    | Key_blocks_used    | 14955    |
    | Key_read_requests  | 96854827 |
    | Key_reads          | 162040   |
    | Key_write_requests | 7589728  |
    | Key_writes         | 3813196  |
    +--------------------+----------+

#### 13.5.3.16. `SHOW TABLE STATUS`

    SHOW TABLE STATUS [FROM db_name] [LIKE wild]

`SHOW TABLE STATUS` (nouveau en version 3.23) fonctionne comme `SHOW STATUS`, mais fournit des informations sur les tables. Vous pouvez aussi obtenir ces informations en utilisant la commande en ligne `mysqlshow --status db_name`. Les données suivantes sont retournées :

- `Name`

  Nom de la table.

- `Type`

  Type de table. See Chapitre 14, Moteurs de tables MySQL et types de table.

- `Row_format`

  Le format de stockage de ligne (`Fixed`, `Dynamic` ou `Compressed`).

- `Rows`

  Nombre de lignes.

- `Avg_row_length`

  Taille moyenne d'une ligne.

- `Data_length`

  Taille du fichier de données.

- `Max_data_length`

  Taille maximale du fichier de données. Pour les formats de lignes fixe, c'est le nombre maximal de lignes dans la table. Pour les formats de lignes dynamique, c'est le nombre total d'octets qui peuvent être stockés dans la table, avec le pointeur de données utilisé.

- `Index_length`

  Taille du fichier d'index.

- `Data_free`

  Nombre d'octets alloués mais non utilisés.

- `Auto_increment`

  Prochaine valeur d'auto_increment.

- `Create_time`

  Date de création de la table.

- `Update_time`

  Date de dernière modification de la table.

- `Check_time`

  Date de dernier entretien de la table.

- `Collation`

  Le jeu de caractères et la collation de la table (nouveau en 4.1.1)

- `Checksum`

  La somme de contrôle en direct (si elle existe). (nouveau en 4.1.1)

- `Create_options`

  Options supplémentaires utilisées avec `CREATE TABLE`.

- `Comment`

  Le commentaire utilisé lors de la création de la table (ou des informations sur pourquoi MySQL n'a pu accéder aux informations de la table).

Les tables `InnoDB` indiqueront l'espace disque libre dans le commentaire de table.

#### 13.5.3.17. Syntaxe de `SHOW TABLES`

    SHOW [OPEN] TABLES [FROM db_name] [LIKE 'pattern']

`SHOW TABLES` liste les tables permanentes (non `TEMPORARY`) dans une base de données. Vous pouvez obtenir cette liste avec la commande en ligne `mysqlshow db_name`.

Note : Si vous n'avez pas les droits sur une table, la table n'apparaîtra pas dans le résultat de `SHOW TABLES` et `mysqlshow db_name`.

`SHOW OPEN TABLES` liste les tables qui sont actuellement ouvertes dans le cache de table. See Section 7.4.8, « Quand MySQL ouvre et ferme les tables ». Le champ `Comment` du résultat indique le nombre d'ouverture de la table en cache (`cached`) et le nombre d'utilisation (`in_use`). `OPEN` est disponible depuis MySQL 3.23.33.

#### 13.5.3.18. Syntaxe de `SHOW VARIABLES`

    SHOW [GLOBAL | SESSION] VARIABLES [LIKE 'pattern']

`SHOW VARIABLES` affiche les valeurs des variables systèmes de MySQL. Vous pouvez aussi obtenir ces informations avec la commande `mysqladmin variables`.

Les options `GLOBAL` et `SESSION` ont été ajoutées en MySQL 4.0.3. Avec `GLOBAL`, vous obtiendrez les valeurs qui seront utilisées pour les nouvelles connexions au serveur MySQL. Avec `SESSION`, vous recevez les valeurs effectives pour la connexion en cours. Si vous ne précisez ni l'une ni l'autre, la valeur par défaut est `SESSION`. `LOCAL` est un synonyme de `SESSION`.

Si les valeurs par défaut ne vous conviennent pas, vous pouvez modifier la plupart de ces variables, en ligne de commande, lorsque `mysqld` est lancé. Voir Section 5.2.1, « Options de ligne de commande de `mysqld` » et Section 13.5.2.8, « Syntaxe de `SET` ».

Voici un extrait du résultat de la commande. La liste complète des variables et de leur valeur peut être différente pour votre serveur. La signification de chaque variable est présentée dans See Section 5.2.3, « Variables serveur système ». Des informations sur comment optimiser ces valeurs sont disponibles dans la section Section 7.5.2, « Réglage des paramètres du serveur ».

    mysql> SHOW VARIABLES;
    +---------------------------------+------------------------------+
    | Variable_name                   | Value                        |
    +---------------------------------+------------------------------|
    | back_log                        | 50                           |
    | basedir                         | /usr/local/mysql             |
    | bdb_cache_size                  | 8388572                      |
    | bdb_log_buffer_size             | 32768                        |
    | bdb_home                        | /usr/local/mysql             |
    ...
    | max_connections                 | 100                          |
    | max_connect_errors              | 10                           |
    | max_delayed_threads             | 20                           |
    | max_error_count                 | 64                           |
    | max_heap_table_size             | 16777216                     |
    | max_join_size                   | 4294967295                   |
    | max_relay_log_size              | 0                            |
    | max_sort_length                 | 1024                         |
    ...
    | timezone                        | EEST                         |
    | tmp_table_size                  | 33554432                     |
    | tmpdir                          | /tmp/:/mnt/hd2/tmp/          |
    | version                         | 4.0.4-beta                   |
    | wait_timeout                    | 28800                        |
    +---------------------------------+------------------------------+

Avec la clause `LIKE`, la commande n'affichera que les variables qui vérifie le masque fourni :

    mysql> SHOW VARIABLES LIKE 'have%';
    +--------------------+----------+
    | Variable_name      | Value    |
    +--------------------+----------+
    | have_bdb           | YES      |
    | have_innodb        | YES      |
    | have_isam          | YES      |
    | have_raid          | NO       |
    | have_symlink       | DISABLED |
    | have_openssl       | YES      |
    | have_query_cache   | YES      |
    +--------------------+----------+

#### 13.5.3.19. `SHOW WARNINGS | ERRORS`

    SHOW WARNINGS [LIMIT [offset,] row_count]
    SHOW COUNT(*) WARNINGS

Cette commande affiche les erreurs, alertes et notes qui ont été générées par la dernière commande. Les erreurs et alertes sont remises à zéro pour chaque nouvelle commande qui utilisent une table. Cette commande a été implémentée depuis MySQL 4.1.0. Une commande connexe, `SHOW ERRORS`, affiche uniquement les erreurs. See Section 13.5.3.8, « Syntaxe de `SHOW ERRORS` ».

La liste de messages est remise à zéro au début de chaque commande qui utilise la table.

La commande `SHOW COUNT(*) WARNINGS` affiche le nombre total d'erreurs, d'alertes et de notes. Vous pouvez aussi lire ce nombre avec la variable `warning_count` :

    SHOW COUNT(*) WARNINGS;
    SELECT @@warning_count;

La valeur de `warning_count` peut être plus grande que le nombre de messages affichés par `SHOW WARNINGS` si la variable système `max_error_count` est configurée assez bas pour que tous les messages ne soient pas stockés. Un exemple plus loin dans cette section montre ce qui arrive.

La clause `LIMIT` a la même syntaxe que la commande `SELECT`. See Section 13.1.7, « Syntaxe de `SELECT` ».

Le serveur MySQL retourne le nombre total d'alertes et d'erreurs que vous avez obtenu lors de la dernière commande. Ils sont disponibles avec la fonction `mysql_warning_count()`. See Section 24.2.3.61, « `mysql_warning_count()` ».

Jusqu'à `max_error_count` messages peuvent être stockés (variable globale et spécifique aux threads).

Vous pouvez lire le nombre d'erreurs dans `@error_count` et le nombre d'alertes dans `@warning_count`.

`SHOW WARNINGS` affiche aussi toutes les erreurs, alertes et notes de la dernière commande, alors que `SHOW ERRORS` ne montre que les erreurs.

    mysql> DROP TABLE IF EXISTS no_such_table;
    mysql> SHOW WARNINGS;

    +-------+------+-------------------------------+
    | Level | Code | Message                       |
    +-------+------+-------------------------------+
    | Note  | 1051 | Unknown table 'no_such_table' |
    +-------+------+-------------------------------+

Notez que depuis MySQL 4.1.0, nous avons ajouté un nouveau système d'alertes, et peu de commandes MySQL génère des alertes. 4.1.1 supporte toutes sortes d'alertes pour `LOAD DATA INFILE` et les commandes DML telles que `INSERT`, `UPDATE` et `ALTER`.

Par exemple, voici une situation simple qui produit des alertes de conversions pour une commande d'insertion :

    mysql> create table t1(a tinyint NOT NULL, b char(4));
    Query OK, 0 rows affected (0.00 sec)

    mysql> insert into t1 values(10,'mysql'),(NULL,'test'),(300,'open source');
    Query OK, 3 rows affected, 4 warnings (0.15 sec)
    Records: 3  Duplicates: 0  Warnings: 4

    mysql> show warnings;
    +---------+------+---------------------------------------------------------------+
    | Level   | Code | Message                                                       |
    +---------+------+---------------------------------------------------------------+
    | Warning | 1263 | Data truncated for column 'b' at row 1                        |
    | Warning | 1261 | Data truncated, NULL supplied to NOT NULL column 'a' at row 2 |
    | Warning | 1262 | Data truncated, out of range for column 'a' at row 3          |
    | Warning | 1263 | Data truncated for column 'b' at row 3                        |
    +---------+------+---------------------------------------------------------------+
    4 rows in set (0.00 sec)

Le nombre maximal d'alertes peut être spécifié en utilisant la variable de serveur `'max_error_count'`, `SET max_error_count=[count]`; Par défaut, c'est 64. Pour désactiver les alertes, donnez simplement la valeur de 0 à la variable. Si `max_error_count` vaut 0, alors le nombre d'alertes représente toujours le nombre d'alertes qui ont eu lieu, mais aucun message d'erreur n'est accessible.

Par exemple, observez la commande `ALTER` suivante, pour l'exemple ci-dessus, qui retourne uniquement une alerte, même si le nombre total d'alertes est de 3 lorsque `'max_error_count'`=1.

    mysql> show variables like 'max_error_count';
    +-----------------+-------+
    | Variable_name   | Value |
    +-----------------+-------+
    | max_error_count | 64    |
    +-----------------+-------+
    1 row in set (0.00 sec)

    mysql> set max_error_count=1;
    Query OK, 0 rows affected (0.00 sec)

    mysql> alter table t1 modify b char;
    Query OK, 3 rows affected, 3 warnings (0.00 sec)
    Records: 3  Duplicates: 0  Warnings: 3

    mysql> show warnings;
    +---------+------+----------------------------------------+
    | Level   | Code | Message                                |
    +---------+------+----------------------------------------+
    | Warning | 1263 | Data truncated for column 'b' at row 1 |
    +---------+------+----------------------------------------+
    1 row in set (0.00 sec)

    mysql>

### 13.5.4. Autres commandes d'administration

#### 13.5.4.1. Syntaxe de `CACHE INDEX`

    CACHE INDEX
      table_index_list [, table_index_list] ...
      IN key_cache_name

    table_index_list:
      tbl_name [[INDEX] (index_name[, index_name] ...)]

La commande `CACHE INDEX` assigne un index de table à un cache de clé spécifique. Cette commande est uniquement disponible pour les tables `MyISAM`.

La commande suivante assigne les index des tables `t1`, `t2` et `t3` au cache de clé appelé `hot_cache` :

    mysql> CACHE INDEX t1, t2, t3 IN hot_cache;
    +---------+--------------------+----------+----------+
    | Table   | Op                 | Msg_type | Msg_text |
    +---------+--------------------+----------+----------+
    | test.t1 | assign_to_keycache | status   | OK       |
    | test.t2 | assign_to_keycache | status   | OK       |
    | test.t3 | assign_to_keycache | status   | OK       |
    +---------+--------------------+----------+----------+

La syntaxe de `CACHE INDEX` vous permet de spécifier des index particuliers à un cache. Cependant, l'implémentation courante assigne tous les index de la table au cache, et il n'y a donc pas d'intérêt à spécifier autre chose que le nom de la table.

Le cache de clé utilisé dans une commande `CACHE INDEX` peut être créé en lui donnant une taille avec une commande de configuration, ou la configuration du serveur. Par exemple :

    mysql> SET GLOBAL keycache1.key_buffer_size=128*1024;

Les paramètres du cache de clé sont accessibles depuis une variable système structurée. See Section 9.4.1, « Variables système structurées ».

Un cache de clé doit exister avant que vous ne l'utilisiez :

    mysql> CACHE INDEX t1 in non_existent_cache;
    ERROR 1283 (HY000): Unknown key cache 'non_existent_cache'

Par défaut, les index de table sont assignée au cache de clé par défaut, créé au moment du démarrage du serveur. Lorsqu'un cache de clé est détruit, tous les index qui lui étaient assigné sont transmis au cache par défaut.

Les assignations d'index affectent le serveur globalement : si un client assigne un index à un cache donné, ce cache sera utilisé pour tous les requêtes, quelque soit le client qui émet la requête.

`CACHE INDEX` a été ajouté en MySQL 4.1.1.

#### 13.5.4.2. Syntaxe de `FLUSH`

    FLUSH flush_option [,flush_option] ...

Vous devez utiliser la commande `FLUSH` si vous voulez effacer certains caches internes de MySQL. Pour exécuter `FLUSH`, vous devez avoir le droit `RELOAD`.

`flush_option` peut être l'une des suivantes :

- `HOSTS`

  Vide le cache des hôtes. Vous devez vider ce cache si certaines des adresses IP de vos clients changent, ou si vous obtenez des erreurs du type `Host ... is blocked`. Lorsque plus de `max_connect_errors` erreurs successives surviennent pour un hôte, lors des connexions au serveur MySQL, MySQL suppose qu'il y a un problème, et interdit l'accès à l'hôte. See Section A.2.5, « Erreur `Host '...' is blocked` ». Vous pouvez démarrer `mysqld` avec `-O max_connect_errors=999999999` pour éviter ce message.

- `DES_KEY_FILE`

  Recharge les clés DES depuis le fichier de stockage spécifié par `--des-key-file` lors du démarrage du serveur.

- `LOGS`

  Ferme et réouvre tous les fichiers de log. Si vous avez spécifié un fichier de log de mise à jour, ou un fichier de log binaire sans extension, le numéro d'extension du fichier de log sera incrémenté d'une unité. Si vous avez utilisé une extension dans le nom du fichier, MySQL va fermer et réouvrir le même fichier. See Section 5.9.3, « Le log de modification ». Ceci est la même chose que d'envoyer le signal `SIGHUP` au serveur `mysqld`.

- `PRIVILEGES`

  Recharge les privilèges des tables de droits dans la base `mysql`.

- `QUERY CACHE`

  Défragmente le cache des requêtes pour mieux en utiliser la mémoire. Cette commande n'effacera aucune requête du cache, à la différence de `RESET QUERY CACHE`.

- `TABLES`

  Ferme toutes les tables ouvertes, et force les tables utilisées à se refermer. Cela vide aussi le cache de requêtes.

- `[TABLE | TABLES] nom_de_table [,nom_de_table...]`

  Vide du cache uniquement les tables nommées.

- `TABLES WITH READ LOCK`

  Ferme toutes les tables ouvertes, et verrouille en lecture toute les tables et bases, jusqu'à ce que vous exécutiez une commande `UNLOCK TABLES`. C'est très pratique pour générer des sauvegardes, si vous avez un système de fichiers comme Veritas, qui peut prendre des photos du système.

- `STATUS`

  Remet la plupart des variables de statut à zéro. A n'utiliser que pour corriger une requête. See Section 1.4.1.3, « Comment rapporter un bogue ou un problème ».

- `USER_RESOURCES`

  Remet toutes les ressources à zéro. Cela va autoriser de nouveau les utilisateurs qui ont été bloqués. See Section 5.6.4, « Limiter les ressources utilisateurs ».

Vous pouvez aussi accéder à toutes les commandes décrites plus haut en les donnant en arguments à `mysqladmin` (exemple : `flush-hosts`, `flush-logs`, `reload`, ou encore `flush-tables`).

Reportez-vous aussi à la commande `RESET` avec la réplication. See Section 13.5.4.5, « Syntaxe de la commande `RESET` ».

#### 13.5.4.3. Syntaxe de `KILL`

    KILL [CONNECTION | QUERY] thread_id

Chaque connexion à `mysqld` utilise un thread unique. Vous pouvez voir les threads en cours d'exécution en utilisant la commande `SHOW PROCESSLIST` et en terminer un avec la commande `KILL thread_id`.

Depuis MySQL 5.0.0, `KILL` autorise les options `CONNECTION` et `QUERY` :

- `KILL CONNECTION` est similaire à `KILL` sans option : elle termine la connexion associée avec le thread `thread_id`.

- `KILL QUERY` termine la requête que la connexion est actuellement en train de traiter, mais laisse la connexion ouverte.

Si vous avez le droit `PROCESS`, vous pouvez voir tous les threads. Si vous avez le droit `SUPER`, vous pouvez terminer tout les threads. Sinon, vous ne pouvez terminer que vos propres threads.

Vous pouvez aussi utiliser les commandes `mysqladmin processlist` et `mysqladmin kill` pour examiner et terminer les threads.

Note : vous ne pouvez actuellement pas utiliser `KILL` avec la bibliothèque du serveur embarqué, car celui-ci utilise les threads de l'application hôte, il ne crée pas ses propres threads.

Quand vous exécutez un `KILL`, un thread spécifique est crée pour ce thread.

Dans la plupart des cas, la terminaison du thread pourra prendre un certain temps vu que le thread de terminaison est invoqué à intervalles spécifiques.

- Pour les boucles de `SELECT`, `ORDER BY` et `GROUP BY`, le thread de terminaison est vérifié après avoir lu un enregistrement. S'il est activé, la requête est abandonnée.

- Lors d'un `ALTER TABLE` le thread de terminaison est vérifié avant la lecture de chacune des colonnes de la table d'origine. S'il est activé, la commande est abandonnée et la table temporaire effacée.

- Lors d'un `UPDATE` ou d'un `DELETE`, le thread de terminaison est vérifié après chaque lecture de bloc et chaque mise à jour ou suppression de ligne. S'il est activé, la requête est abandonnée. Notez que si vous utilisez les transactions, les modifications ne seront pas perdues !

- `GET_LOCK()` stoppera avec `NULL`.

- Un thread `INSERT DELAYED` videra rapidement toutes les lignes en mémoire et se terminera.

- Si le thread est dans le gestionnaire des verrous de tables (état : `Locked`), le verrou sur la table sera vite enlevé.

- Si le thread est en attente de libération d'espace disque lors d'un appel à `write`, l'opération est avortée avec un message d'erreur indiquant que le disque est plein.

#### 13.5.4.4. Syntaxe de `LOAD INDEX INTO CACHE`

    LOAD INDEX INTO CACHE
      table_index_list [, table_index_list] ...

    table_index_list:
      tbl_name
        [[INDEX] (index_name[, index_name] ...)]
        [IGNORE LEAVES]

La commande `LOAD INDEX INTO CACHE` précharge un index dans un cache de clé, qui est explicitement nommé dans dans la commande `CACHE INDEX`, ou dans le cache par défaut. `LOAD INDEX INTO CACHE` ne sert que pour les tables `MyISAM`.

L'option `IGNORE LEAVES` fait que les blocs terminaux de l'index ne sont pas lus.

La commande suivante précharge les noeuds des tables `t1` et `t2` :

    mysql> LOAD INDEX INTO CACHE t1, t2 IGNORE LEAVES;
    +---------+--------------+----------+----------+
    | Table   | Op           | Msg_type | Msg_text |
    +---------+--------------+----------+----------+
    | test.t1 | preload_keys | status   | OK       |
    | test.t2 | preload_keys | status   | OK       |
    +---------+--------------+----------+----------+

Cette commande charge tous les index de `t1`. Elle ne charge que les index non-terminaux de `t2`.

La syntaxe de `LOAD INDEX INTO CACHE` vous permet de spécifier seulement des index particuliers à charger dans la table. Cependant, l'implémentation courante charge tous les index : il n' y a pas de raison pour utiliser autre chose que le nom de la table.

`LOAD INDEX INTO CACHE` a été ajouté en MySQL 4.1.1.

#### 13.5.4.5. Syntaxe de la commande `RESET`

    RESET reset_option [, reset_option] ...

La commande `RESET` sert à remettre à zéro des données. C'est aussi une version plus puissante de la commande `FLUSH`. See Section 13.5.4.2, « Syntaxe de `FLUSH` ».

Pour exécuter la commande `RESET`, vous devez avoir les droits `RELOAD`.

- `MASTER`

  Efface tous les logs binaires listés dans le fichier d'index, et l'index binlog est vidé. Dans les version antérieures à la version 3.23.26, cette commande s'appelait `FLUSH MASTER` (Master) See Section 13.6.1, « Requêtes SQL pour contrôler les maîtres de réplication ».

- `QUERY CACHE`

  Supprime tous les résultats de requêtes du cache de requête.

- `SLAVE`

  Annule la position de réplication de l'esclave dans les historiques du maître. Dans les version antérieures à la version 3.23.26, cette commande s'appelait `FLUSH SLAVE`(Slave)See Section 13.6.2, « Commandes SQL de contrôle des esclaves de réplication ».

## 13.6. Commandes de réplication

Cette section décrit les commandes liées à la réplication. Un groupe de commande peut être utilisé pour contrôler le serveur. L'autre groupe sert avec les esclaves.

### 13.6.1. Requêtes SQL pour contrôler les maîtres de réplication

La réplication est contrôlable via l'interface SQL. Cette section présente les commandes qui contrôlent les maîtres de réplication. La section Section 13.6.2, « Commandes SQL de contrôle des esclaves de réplication » présente les commandes pour gérer les esclaves.

#### 13.6.1.1. `PURGE MASTER LOGS`

    PURGE {MASTER | BINARY} LOGS TO 'log_name'
    PURGE {MASTER | BINARY} LOGS BEFORE 'date'

Efface tous les logs binaires listés dans l'index de logs, qui sont antérieurs à la date ou au log indiqué. Les logs sont aussi supprimés de cette liste : le log donné en paramètre devient alors le premier de la liste.

Exemple :

    PURGE MASTER LOGS TO 'mysql-bin.010';
    PURGE MASTER LOGS BEFORE '2003-04-02 22:46:26';

La variante `BEFORE` est disponible en MySQL 4.1; son argument de date peut être au format `'YYYY-MM-DD hh:mm:ss'`. `MASTER` et `BINARY` sont synonymes, mais `BINARY` ne peut être utilisé que depuis MySQL 4.1.1.

Si vous avez un esclave actif qui est actuellement en train de lire l'un des logs que vous voulez effacer, la commande ne fera rien, et échouera avec une erreur. Cependant, si l'esclave est inactif, et que vous effacez un des logs qu'il utilisait, l'esclave sera incapable de reprendre la réplication. Cette commande peut être utilisée sans problème durant la réplication : vous n'avez pas besoin d'arrêter les esclaves.

Pour purger les logs, suivez cette procédure :

1. Sur chaque esclave, utilisez la commande `SHOW SLAVE STATUS` pour vérifier quel log est lu.

2. Faite une liste des logs sur le maître avec `SHOW MASTER LOGS`.

3. Déterminez le plus ancien log parmi ceux utilisés par les esclaves. C'est votre limite. Si vous les esclaves sont à jour, alors ce sera le dernier log de la liste.

4. Faites une sauvegarde de tous les logs que vous allez effacer. Cette étape est optionnelle, mais c'est une bonne idée.

5. Purgez tous les logs jusqu'à celui qui précède votre limite.

#### 13.6.1.2. `RESET MASTER`

    RESET MASTER

Efface tous les fichiers de logs binaires dans le fichier d'index, et vide le fichier d'index des logs.

Cette commande s'appelait `FLUSH MASTER` avant MySQL 3.23.26.

#### 13.6.1.3. `SET SQL_LOG_BIN`

    SET SQL_LOG_BIN = {0|1}

Inactive ou active le log binaire de la connexion courante (`SQL_LOG_BIN` est une variable de session), si le client se connecte avec un compte qui a les droits de `SUPER`. La commande est ignorée si le client n'a pas de droits.

#### 13.6.1.4. `SHOW BINLOG EVENTS`

    SHOW BINLOG EVENTS [ IN 'log_name' ] [ FROM pos ] [ LIMIT [offset,] row_count ]

Affiche les événements du log binaire. Si vous ne spécifiez pas `'log_name'`, le premier log binaire sera affiché.

La clause `LIMIT` a la même syntaxe que celle de la commande `SELECT`. See Section 13.1.7, « Syntaxe de `SELECT` ».

Cette commande est disponible en MySQL 4.0

#### 13.6.1.5. `SHOW MASTER LOGS`

    SHOW MASTER LOGS

Liste les logs binaires disponibles sur le maître. Vous devriez utiliser cette commande avant `PURGE MASTER LOGS` pour savoir jusqu'où vous pouvez aller.

#### 13.6.1.6. `SHOW MASTER STATUS`

    SHOW MASTER STATUS

Affiche les informations d'état du log binaire du maître.

#### 13.6.1.7. `SHOW SLAVE HOSTS`

    SHOW SLAVE HOSTS

Affiche la liste des esclaves actuellement enregistrée sur le maître. Notez que les esclaves qui ne sont pas lancé avec l'option `--report-host=nom_d_esclave` ne seront pas visible dans cette liste.

### 13.6.2. Commandes SQL de contrôle des esclaves de réplication

La réplication est contrôlable via l'interface SQL. Cette section présente les commandes qui contrôlent les esclaves de réplication. La section Section 13.6.1, « Requêtes SQL pour contrôler les maîtres de réplication » présente les commandes pour gérer les maîtres.

#### 13.6.2.1. `CHANGE MASTER TO`

    CHANGE MASTER TO master_def [, master_def] ...

    master_def =
          MASTER_HOST = 'host_name'
        | MASTER_USER = 'user_name'
        | MASTER_PASSWORD = 'password'
        | MASTER_PORT = port_num
        | MASTER_CONNECT_RETRY = count
        | MASTER_LOG_FILE = 'master_log_name'
        | MASTER_LOG_POS = master_log_pos
        | RELAY_LOG_FILE = 'relay_log_name'
        | RELAY_LOG_POS = relay_log_pos
        | MASTER_SSL = {0|1}
        | MASTER_SSL_CA = 'ca_file_name'
        | MASTER_SSL_CAPATH = 'ca_directory_name'
        | MASTER_SSL_CERT = 'cert_file_name'
        | MASTER_SSL_KEY = 'key_file_name'
        | MASTER_SSL_CIPHER = 'cipher_list'

Modifie les paramètres que l'esclave utilise pour se connecter et pour communiquer avec le serveur maître. Les valeurs possibles pour `master_def` sont présentées ci-dessus.

Les options de log de relais, `RELAY_LOG_FILE` et `RELAY_LOG_POS`, sont disponibles depuis MySQL 4.0.

Les options SSL, `MASTER_SSL`, `MASTER_SSL_CA`, `MASTER_SSL_CAPATH`, `MASTER_SSL_CERT`, `MASTER_SSL_KEY` et `MASTER_SSL_CIPHER`, sont disponibles depuis MySQL 4.1.1. Vous pouvez changer ces options même sur les esclaves qui sont compilé sans le support SSL. Elles seront sauvées dans le fichier `master.info` mais ignorées jusqu'à ce que le support SSL soit activé.

Par exemple :

    mysql> CHANGE MASTER TO
        ->     MASTER_HOST='master2.mycompany.com',
        ->     MASTER_USER='replication',
        ->     MASTER_PASSWORD='bigs3cret',
        ->     MASTER_PORT=3306,
        ->     MASTER_LOG_FILE='master2-bin.001',
        ->     MASTER_LOG_POS=4,
        ->     MASTER_CONNECT_RETRY=10;
    mysql> CHANGE MASTER TO
        ->     RELAY_LOG_FILE='slave-relay-bin.006',
        ->     RELAY_LOG_POS=4025;

`MASTER_USER`, `MASTER_PASSWORD`, `MASTER_SSL`, `MASTER_SSL_CA`, `MASTER_SSL_CAPATH`, `MASTER_SSL_CERT`, `MASTER_SSL_KEY`, et `MASTER_SSL_CIPHER` sont des informations qui permettent à l'esclave de se connecter au maître. Si vous omettez certains paramètres, les paramètres omis conserveront leur ancienne valeur. Par exemple, si le mot de passe sur le maître a changé, il suffit de faire :

    mysql> STOP SLAVE; -- if replication was running
    mysql> CHANGE MASTER TO MASTER_PASSWORD='new3cret';
    mysql> START SLAVE; -- if you want to restart replication

pour indiquer à l'esclave le nouveau mot de passe : il n'y a pas besoin de spécifier les informations qui n'ont pas changé, comme l'hôte, le port, l'utilisateur, etc...

`MASTER_HOST`, `MASTER_PORT` sont le nom d'hôte ou l'adresse IP du maître, et son port TCP. Notez que si `MASTER_HOST` est égal à `localhost`, alors, comme généralement avec MySQL, le port sera ignoré si les sockets Unix sont utilisables.

Si vous spécifiez `MASTER_HOST` ou `MASTER_PORT`, l'esclave supposera que le serveur maître est différent du précédent, même si vous spécifier les mêmes valeurs d'hôte et de port que précédemment. Dans ce cas, les anciennes valeurs et position de l'historique binaire ne sont plus valides. Ainsi, si vous ne spécifiez pas `MASTER_LOG_FILE` et `MASTER_LOG_POS` dans la commande, `MASTER_LOG_FILE=''` et `MASTER_LOG_POS=4` sont ajoutés silencieusement.

`MASTER_LOG_FILE` et `MASTER_LOG_POS` sont les coordonnées auxquelles le thread d'I/O doit commencer à lire chez le maître, lorsque le thread redémarrera. Si vous spécifiez l'un d'entre eux, vous ne pourrez pas spécifier `RELAY_LOG_FILE` ou `RELAY_LOG_POS`. Si `MASTER_LOG_FILE`, ni `MASTER_LOG_POS` n'ont été spécifiés, alors les dernières coordonnées du thread esclave d'avant la commande `CHANGE MASTER` seront utilisées. Cela assure que la réplication ne connaît pas de discontinuité, même si le thread esclave était en retard sur le thread d'I/O, alors que vous ne voulez changer que le mot de passe. Ce comportement sécuritaire a été introduit à partir de MySQL versions 4.0.17 et 4.1.1. Avant ces versions, les coordonnées utilisées celles du thread d'I/O, avant que la commande `CHANGE MASTER` soit émise, ce qui conduisait à des pertes d'événements au niveau du maître, et donc, la corruption de la réplication.

`CHANGE MASTER` efface tous les logs de relais (et en démarre de nouveaux), à moins que vous ne spécifiez l'option `RELAY_LOG_FILE` ou `RELAY_LOG_POS` (dans ce cas, les logs de relais seront conservés; depuis MySQL 4.1.1 la variable globale `RELAY_LOG_PURGE` sera automatiquement mise à 0). `CHANGE MASTER TO` modifie `master.info` et `relay-log.info`.

`CHANGE MASTER` sert à configurer un esclave lorsque vous avez une sauvegarde du maître, son log et la position qui correspond à la sauvegarde du maître. Vous pouvez utiliser la commande `CHANGE MASTER TO MASTER_LOG_FILE='log_name_on_master', MASTER_LOG_POS=log_offset_on_master` sur l'esclave après la restauration de la sauvegarde.

Le premier exemple ci-dessus (`CHANGE MASTER TO MASTER_HOST='master2.mycompany.com' etc`) modifie les coordonnées du maître et de son log binaire. Cela est utile lorsque vous voulez que l'esclave réplique le maître. Le second exemple, moins fréquent, sert lorsque l'esclave a des logs de relais que vous voulez utiliser à nouveau. Pour cela, le maître n'a pas besoin d'être rejoint : il suffit d'utiliser la commande `CHANGE MASTER TO` et de lancer le thread SQL `START SLAVE SQL_THREAD`. Vous pouvez même utiliser cela dans une configuration de réplication, sur un serveur indépendant, pour assurer la restauration après crash. Supposez que votre serveur soit planté, et que vous avez restauré la sauvegarde. Vous voulez que le serveur exécute à nouveau ses propres logs (non pas des logs de relais, mais ses logs binaires), qui sont par exemple, stockés sous le nom `myhost-bin.*`. Tout d'abord, faite une copie des fichiers de log dans un entrepôt, au cas où une erreur de manipulation surviendrait, et que le serveur vide ses logs. Si vous utilisez MySQL 4.1.1 ou plus récent, utilisez la commande suivante pour plus de sécurité : `SET GLOBAL RELAY_LOG_PURGE=0`.

Puis, lancez le serveur sans `log-bin`, et avec un nouvel identifiant (différent du précédent), avec l'option `relay-log=myhost-bin` (pour faire croire au serveur que ses propres logs sont des logs de relais), et `skip-slave-start`. Puis, envoyez cette commande :

    mysql> CHANGE MASTER TO
        ->     RELAY_LOG_FILE='myhost-bin.153',
        ->     RELAY_LOG_POS=410,
        ->     MASTER_HOST='some_dummy_string';
    mysql> START SLAVE SQL_THREAD;

Le serveur va alors lire et exécuter ses propres logs, et rattraper les données jusqu'au crash.

Une fois la restauration finie, faites `STOP SLAVE`, éteignez le serveur, supprimez `master.info` et `relay-log.info`, puis relancez le serveur avec ses options originales.

Pour le moment, spécifier `MASTER_HOST` (même avec une valeur insignifiante) est obligatoire pour que le serveur pense qu'il est un esclave. Donner au serveur un nouvel identifiant, différent du précédent, est aussi obligatoire, car sinon, le serveur va voir des événements avec son identifiant, et il va conclure que c'est une réplication circulaire, et il va les ignorer. Dans le futur, nous envisageons de nous débarasser de ces petites contraintes.

#### 13.6.2.2. `LOAD DATA FROM MASTER`

    LOAD DATA FROM MASTER

Fait une sauvegarde du maître et la copie vers l'esclave. Met à jour les valeurs de `MASTER_LOG_FILE` et `MASTER_LOG_POS` pour que la réplication reprennent à la bonne position. Respecte les interdictions de réplications de tables et de bases spécifiées par les options `replicate-*`.

L'utilisation de cette commande est sujette aux conditions suivantes :

- Fonctionne avec les tables `MyISAM`.

- Pose un verrou global en lecture sur le maître durant la sauvegarde, qui empêche les modifications sur le maître durant la phase de chargement.

Dans le futur, il est prévu de faire que cette commande fonctionne avec les tables `InnoDB`, et qu'elle se passe du verrou global en utilisant des fonctionnalités de sauvegarde à chaud non-bloquantes.

Si vous chargez de très grosses tables, pensez à augmenter les valeurs des options `net_read_timeout` et `net_write_timeout` sur vos maître et esclave. See Section 5.2.3, « Variables serveur système ».

Notez que `LOAD DATA FROM MASTER` ne copie pas les tables de droits de la base `mysql`. C'est fait pour simplifier l'utilisation de droits et utilisateurs différents sur le maître et les esclaves.

Cette commande requiert les droits de `RELOAD` et `SUPER` sur le maître, et le droit de `SELECT` sur toutes les tables du maître qui seront lues. Toutes les tables du maître sur lesquelles l'utilisateur n'a pas de droits de `SELECT` seront ignorées par `LOAD DATA FROM MASTER`; ceci est dû au fait que le maître va masquer ces tables à l'utilisateur : `LOAD DATA FROM MASTER` utilise `SHOW DATABASES` pour connaître les tables à charger, mais `SHOW DATABASES` ne retourne que les bases pour lesquelles l'utilisateur a des droits. Voyez Section 13.5.3.6, « Syntaxe de `SHOW DATABASES` ». Sur l'esclave, l'utilisateur qui envoie la commande `LOAD DATA FROM MASTER` doit avoir les droits de création et d'effacement des tables et bases impliquées.

#### 13.6.2.3. Syntaxe de `LOAD TABLE tbl_name FROM MASTER`

    LOAD TABLE tbl_name FROM MASTER

Télécharge une copie d'une table depuis le maître vers l'esclave. Cette commande est implémentée pour déboguer la commande `LOAD DATA FROM MASTER`. Elle requiert un compte pour se connecter au maître, avec les droits de `RELOAD` et `SUPER`, ainsi que les droits de `SELECT` sur la table a charger. Coté esclave, l'utilisateur qui émet la commande doit avoir les droits de `LOAD TABLE FROM MASTER` pour créer et effacer les tables. Lisez les informations sur les problèmes réseau dans `LOAD DATA FROM MASTER`; elles s'appliquent aussi ici. Notez aussi que les limitations de `LOAD DATA FROM MASTER` s'appliquent aussi (par exemple, `LOAD TABLE FROM MASTER` ne fonctionne que sur les tables de type `MyISAM`).

#### 13.6.2.4. `MASTER_POS_WAIT()`

    SELECT MASTER_POS_WAIT('master_log_file', master_log_pos)

C'est une fonction et non pas une commande. Elle sert à s'assurer que l'esclave a atteint (lu et exécuté) les événements du log binaire du maître jusqu'à une certaine position. Voyez la section See Section 12.8.4, « Fonctions diverses » pour une description complète.

#### 13.6.2.5. `RESET SLAVE`

    RESET SLAVE

Force l'esclave a oublier toute les positions de réplications dans les logs du maître. Cette commande permet de faire un démarrage propre : elle efface les fichiers `master.info` et `relay-log.info`, et les logs de relais, puis créer un nouveau log de relais.

Note : tous les logs de relais sont effacés, même si il n'ont pas été totalement exécutés par le thread SQL. (C'est un état qui est probable si l'esclave de réplication est fortement chargé, ou si vous avez lancé une commande `STOP SLAVE`.) Les informations de connexions stockées dans le fichier `master.info` reprennent immédiatement les valeurs spécifiées dans les options de démarrage, si elles étaient précisées. Ces informations incluent notamment le nom de l'hôte maître, le port, l'utilisateur et le mot de passe. Si le thread esclave était au milieu d'une réplication temporaire lorsqu'il a été arrêté, et que `RESET SLAVE` a été émise, ces tables temporaires sont aussi effacées.

Cette commande s'appelait `FLUSH SLAVE` avant MySQL 3.23.26.

#### 13.6.2.6. `SET GLOBAL SQL_SLAVE_SKIP_COUNTER`

    SET GLOBAL SQL_SLAVE_SKIP_COUNTER = n

Ignore les `n` prochains événements du maître. C'est une commande pratique pour rattraper les arrêts de réplications causés par une commande.

Cette commande n'est valide que lorsque le thread esclave ne fonctionne pas. Sinon, elle produit une erreur.

Avant MySQL 4.0, omettez le mot clé `GLOBAL` dans la commande.

#### 13.6.2.7. `SHOW SLAVE STATUS`

    SHOW SLAVE STATUS

Affiche des informations sur les paramètres essentiels des threads esclaves. Si vous utilisez cette commande avec le client `mysql`, vous pouvez utiliser le terminateur de commande `\G` plutôt que le point-virgule pour avoir un format plus lisible :

    mysql> SHOW SLAVE STATUS\G
    *************************** 1. row ***************************
           Slave_IO_State: Waiting for master to send event
              Master_Host: localhost
              Master_User: root
              Master_Port: 3306
            Connect_Retry: 3
          Master_Log_File: gbichot-bin.005
      Read_Master_Log_Pos: 79
           Relay_Log_File: gbichot-relay-bin.005
            Relay_Log_Pos: 548
    Relay_Master_Log_File: gbichot-bin.005
         Slave_IO_Running: Yes
        Slave_SQL_Running: Yes
          Replicate_Do_DB:
      Replicate_Ignore_DB:
               Last_Errno: 0
               Last_Error:
             Skip_Counter: 0
      Exec_Master_Log_Pos: 79
          Relay_Log_Space: 552
          Until_Condition: None
           Until_Log_File:
            Until_Log_Pos: 0
       Master_SSL_Allowed: No
       Master_SSL_CA_File:
       Master_SSL_CA_Path:
          Master_SSL_Cert:
        Master_SSL_Cipher:
           Master_SSL_Key:
    Seconds_Behind_Master: 8

Suivant votre version de MySQL, vous pourriez ne pas voir tous les champs qui sont dans cet exemple. Notamment, il y a plusieurs champs qui ne sont disponibles qu'avec MySQL 4.1.1.

Les champs affichés par `SHOW SLAVE STATUS` ont les définitions suivantes :

- `Slave_IO_State`

  Une copie de la colonne `State` de la commande `SHOW PROCESSLIST` pour le thread d'I/O. Elle va vous indiquer si le thread essaye de se connecter au maître, attend des événements, se reconnecte, etc. Les différents états possibles sont listés dans la section Section 6.3, « Détails d'implémentation de la réplication ». Etudier cette colonne est nécessaire, par exemple, car le thread peut fonctionner mais ne pas réussir à se connecter au maître : seule cette colonne vous indiquera ce type de problèmes. D'un autre coté, l'état du thread SQL n'est pas indiqué, car les problèmes sont bien plus simples avec lui : soit il fonctionne, et il n'y a pas de problème; soit il ne fonctionne pas, et vous trouverez les messages d'erreur dans la colonne `Last_Error`, décrite plus bas.

  Ce champ a été ajouté en MySQL 4.1.1.

- `Master_Host`

  L'hôte maître courant.

- `Master_User`

  Le nom de l'utilisateur utilisé pour se connecter au maître.

- `Master_Port`

  Le port courant sur le maître.

- `Connect_Retry`

  La valeur courante de l'option `master-connect-retry`.

- `Master_Log_File`

  Le nom du fichier de log binaire que le thread d'I/O utilise sur le maître.

- `Read_Master_Log_Pos`

  La position que le thread d'I/O a atteint dans le fichier de log binaire du maître.

- `Relay_Log_File`

  Le nom du fichier de log de relais dans lequel le thread SQL est actuellement en train de lire et de travailler.

- `Relay_Log_Pos`

  La position à laquelle le thread SQL est en train de travailler.

- `Relay_Master_Log_File`

  Le nom du fichier de log binaire du maître qui contient le dernier événement exécuté par le thread SQL.

- `Slave_IO_Running`

  Indique si le thread d'I/O est lancé ou pas.

- `Slave_SQL_Running`

  Indique si le thread SQL est lancé ou pas.

- `Replicate_Do_DB, Replicate_Ignore_DB`

  La liste des bases de données qui ont été spécifiée dans l'option `--replicate-do-db` et `--replicate-ignore-db`, éventuellement.

- `Replicate_Do_Table, Replicate_Ignore_Table, Replicate_Wild_Do_Table, Replicate_Wild_Ignore_Table`

  La liste des tables qui ont été spécifiées respectivement dans les options `--replicate-do-table`, `--replicate-ignore-table`, `--replicate-wild-do-table` et `--replicate-wild-ignore_table`, éventuellement.

  Ces champs ont été ajoutés en MySQL 4.1.1.

- `Last_Errno, Last_Error`

  `Last_Errno` est le numéro d'erreur de la plus récent requête exécutée. La valeur de 0 signifie ``pas d'erreur''. `Last_Error` est le message d'erreur de la plus récent requête exécutée. Par exemple :

      Last_Errno: 1051
      Last_Error: error 'Unknown table 'z'' on query 'drop table z'

  Le message indique que la table `z` existait sur le maître et a été effacée, mais qu'elle n'existe pas sur l'esclave, et que `DROP TABLE` a échoué sur l'esclave. Cela peut arriver si vous avez oublié de copier une table dans l'esclave avant de lancer la réplication.

  Une chaîne vide signifie ``pas d'erreur''. Si `Last_Error` n'était pas vide, alors le même message apparaîtra dans le log d'erreur de l'esclave.

- `Skip_Counter`

  La dernière valeur utilisée par `SQL_SLAVE_SKIP_COUNTER`.

- `Exec_Master_Log_Pos`

  La position dans les logs binaires du maître (`Relay_Master_Log_File`) pour le dernier événement exécuté par le thread SQL. ((`Relay_Master_Log_File`,`Exec_Master_Log_Pos`) dans le log binaire du maître correspond à (`Relay_Log_File`,`Relay_Log_Pos`) dans le log de relais.

- `Relay_Log_Space`

  La taille combinée de tous les logs de relais.

- `Until_Condition, Until_Log_File, Until_Log_Pos`

  Les valeurs spécifiées dans la clause `UNTIL` de la commande `START SLAVE`.

  `Until_Condition` peut prendre ces valeurs :

  - `None` (aucune) si aucune clause `UNTIL` n'a été spécifiée

  - `Master` (maître), si l'esclave lit depuis une position donnée, dans le log binaire du maître

  - `Relay` (relais) si l'esclave lit dans une position donnée dans le log de relais.

  `Until_Log_File` et `Until_Log_Pos` indique le nom du fichier de log et la position qui définissent le point où le thread SQL va s'arrêter d'exécuter.

  Ces champs ont été ajoutés en MySQL 4.1.1.

- `Master_SSL_Allowed, Master_SSL_CA_File, Master_SSL_CA_Path, Master_SSL_Cert, Master_SSL_Cipher, Master_SSL_Key`

  Ces champs indiquent les paramètres SSL utilisés par l'esclave pour se connecter au maître, s'ils sont fournis.

  `Master_SSL_Allowed` prend ses valeurs :

  - `Yes` (oui) si la connexion SSL au maître est autorisée

  - `No` (non) si la connexion SSL au maître est interdite

  - `Ignored` (ignoré) si la connexion SSL au maître est autorisée par l'esclave mais que le support de SSL n'est pas là.

  Les valeurs des autres champs correspondent aux valeurs des options `--master-ca`, `--master-capath`, `--master-cert`, `--master-cipher` et `--master-key`.

  Ces champs ont été ajoutés en MySQL 4.1.1.

- `Seconds_Behind_Master`

  Le nombre de secondes qui se sont écoulées depuis le timestamp du dernier événement maître exécuté par le thread SQL. Ce sera `NULL` si aucun événement n'a été exécuté, ou après une commande `CHANGE MASTER` et `RESET SLAVE`. Cette colonne sert à mesurer le retard de l'esclave sur le maître. Cela fonctionne même si le maître et l'esclave on des horloges réglées différemment.

  Ce champ a été ajouté en MySQL 4.1.1.

#### 13.6.2.8. `START SLAVE`

    START SLAVE [thread_name [, thread_name] ... ]
    START SLAVE [SQL_THREAD] UNTIL
        MASTER_LOG_FILE = 'log_name', MASTER_LOG_POS = log_pos
    START SLAVE [SQL_THREAD] UNTIL
        RELAY_LOG_FILE = 'log_name', RELAY_LOG_POS = log_pos

    thread_name = IO_THREAD | SQL_THREAD

`START SLAVE`, appelé sans option, démarre les deux threads esclaves. Le thread I/O lire les requêtes du maître et les stocke dans le log de relais. Le thread SQL lire le log de relais, et exécute les requêtes. Notez que si `START SLAVE` réussi à lancer le thread esclave, elle se terminera sans erreur. Mais même dans ce cas, il se peut que le thread esclave se lance, puis s'arrête (car il n'a pas pu se connecter au maître, ou lire le log binaire ou tout autre problème). `START SLAVE` ne vous préviendra pas de cet événement. Vous devez vérifier le log d'erreur de l'esclave pour voir si des messages ont été générés, ou encore vérifier que tout fonctionne avec la commande `SHOW SLAVE STATUS`.

Depuis MySQL 4.0.2, vous pouvez ajouter les options `IO_THREAD` ou `SQL_THREAD` à la commande, pour nommer les threads que vous lancez.

Depuis MySQL 4.1.1, une clause `UNTIL` peut être ajoutée pour spécifier que l'esclave doit commencer à un certain point dans le log binaire, ou dans le log de relais. Lorsque le thread SQL atteint ce point, il s'arrête. Si l'option `SQL_THREAD` est spécifiée dans la commande, seule le thread SQL est lancé. Sinon, les deux threads sont lancés. Si le thread SQL est déjà lancé, la clause `UNTIL` est ignorée, et une alerte est émise.

Avec la clause `UNTIL`, vous devez spécifier à la fois un fichier de log et une position. Ne confondez pas les options du maître et celles du log de relais.

Toute condition `UNTIL` est annulée par une commande `STOP SLAVE`, ou une commande `START SLAVE` qui n'inclut pas de condition `UNTIL`, ou encore un redémarrage serveur.

La clause `UNTIL` peut être utile pour déboguer la réplication, ou pour vous assurer que la réplication s'effectue jusqu'à un certain point. Par exemple, si une commande imprudente `DROP TABLE` a été exécutée sur le maître, vous pouvez utiliser la clause `UNTIL` pour dire à l'esclave de s'exécuter jusqu'à ce moment, puis de s'arrêter. Pour trouver cet événement, utilisez l'utilitaire `mysqlbinlog` sur le log du maître, ou sur le log de relais, ou encore utilisez la commande `SHOW BINLOG EVENTS`.

Si vous utilisez la clause `UNTIL` pour faire des réplications par portions, il est recommandé de lancer l'esclave avec l'option `--skip-slave-start` pour éviter que le thread SQL ne se lance lorsque l'esclave se lance. Il est probablement idéale d'utiliser cette option dans un fichier d'options plutôt qu'en ligne de commande, pour qu'un redémarrage intempestif ne l'oublie pas.

La commande `SHOW SLAVE STATUS` affiche un champ qui indique la valeur courante de la clause `UNTIL`.

#### 13.6.2.9. `STOP SLAVE`

    STOP SLAVE [thread_name [, thread_name] ... ]

    thread_name = IO_THREAD | SQL_THREAD

Arrête l'esclave. Tout comme `START SLAVE`, cette commande peut être utilisée avec les options `IO_THREAD` et `SQL_THREAD` pour identifier le thread par son nom.

Cette commande s'appelait `SLAVE STOP` avant MySQL 4.0.5. Actuellement, `SLAVE STOP` est toujours disponible pour assurer la compatibilité ascendante, mais c'est une commande abandonnée.

## 13.7. Syntaxe SQL pour les commandes préparées

Le support des commandes préparées coté serveur a été ajouté en MySQL 4.1. Ce support tire profit du protocole client/serveur plus efficace, en supposant que vous utilisez la bonne interface client. Les interfaces correctes sont l'API C MySQL (pour les programmes en C), et MySQL Connector/J (pour les programmes Java). Par exemple, l'API C fournit un jeu de fonctions qui prépare les commandes. See Section 24.2.4, « Fonctions C de commandes préparées ». Les autres interfaces de langages peuvent fournir un support pour les commandes préparées, en utilisant le protocole binaire grâce à l'interface du client C. L'extension PHP 5 mysqli est un exemple.

Depuis MySQL 4.1.3, une interface alternative pour les commandes préparées est disponible : la suntaxe SQL pour les commandes préparées. Cette interface n'est pas aussi efficace que le protocole binaire, mais elle n'impose aucune programmation, car elle est disponible directement au niveau SQL.

- Vous pouvez l'utiliser lorsqu'aucune interface de programmation n'est disponible.

- Vous pouvez l'utiliser depuis n'importe quel programme qui vous permet d'envoyer des commandes au serveur, comme le client mysql.

- Vous pouvez l'utiliser même si le client utilise une vieille version de la bibliothèque d'interface. La seule contrainte est que vous devez pouvoir vous connecter à un serveur suffisamment récent pour supporter cette syntaxe.

La syntaxe SQL pour les commandes préparées sert dans les situations suivantes :

- Vous voulez tester les commandes préparées avec votre application sans faire de codage. Ou bien, votre application a des problèmes avec les commandes préparées, et vous voulez déterminer ce problème interactivement.

- Vous voulez créer un cas de test qui décrit les problèmes que vous avez avec les commandes préparées, pour pouvoir envoyer un rapport de bogue.

- Vous deve utiliser les commandes préparées, mais vous n'avez pas accès à une interface qui les supporte.

La syntaxe SQL pour les commandes préparées est basée sur 3 commandes SQL :

    PREPARE stmt_name FROM preparable_stmt;

    EXECUTE stmt_name [USING @var_name [, @var_name] ...];

    DEALLOCATE PREPARE stmt_name;

La commande `PREPARE` prépare la commande, lui assigne le nom `stmt_name`, qui sera utilisé ultérieurement. `preparable_stmt` est soit une chaîne littérale, soit une variable utilisateur, qui contient le texte de la commande. Le texte doit représenter une seule commande SQL, et non pas plusieurs. Dans la commande, le caractère ‘`?`’ sert de variable de requête : ils indiquent que les valeurs seront fournies à l'application ultérieurement. Le caractère ‘`?`’ ne doit pas être placé entre guillemets, même si vous voulez leur donner des valeurs de chaînes de caractères.

Si une commande préparée existe déjà avec le même nom, elle sera détruite implicitement avant la préparation de la nouvelle commande. Cela signifie que si la nouvelle commande contient une erreur et ne peut pas être préparée, une erreur sera retournée, et la commande aura simplement été détruite.

Le contexte d'une commande préparée est celui de la session client dans laquelle elle est créée. Les autres clients ne peuvent y accéder.

Après avoir préparé une commande, vous l'exécutez avec la commande `EXECUTE`, qui fait référence au nom de la commande préparée. Si la commande préparée contient des variables, vous devez fournir leur valeur avec la clause `USING` qui liste les variables contenant les valeurs des paramètres. Les valeurs des paramètres doivent être aussi nombreuses que les paramètres de la commande.

Vous pouvez exécuter une commande préparée plusieurs fois, en lui passant différentes valeurs, ou différentes variables.

Pour détruire une commande préparée, utilisez la commande `DEALLOCATE PREPARE`. Tenter d'exécuter la commande préparée après destruction conduit à une erreur.

Si vous quittez la session client sans libérer les commandes préparées, le serveur le fera pour vous.

Les exemples suivants montre deux méthodes équivalentes pour préparer les commandes qui calculent l'hypothénuse d'un triangle à partir de la taille de deux de ses cotés.

Le premier exemple montre comment créer la commande préparée avec une chaîne littérale :

    mysql> PREPARE stmt1 FROM 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
    mysql> SET @a = 3;
    mysql> SET @b = 4;
    mysql> EXECUTE stmt1 USING @a, @b;
    +------------+
    | hypotenuse |
    +------------+
    |          5 |
    +------------+
    mysql> DEALLOCATE PREPARE stmt1;

Le second exexemple est similaire, mais fournit le texte de la commande dans une variable utilisateur :

    mysql> SET @s = 'SELECT SQRT(POW(?,2) + POW(?,2)) AS hypotenuse';
    mysql> PREPARE stmt2 FROM @s;
    mysql> SET @a = 6;
    mysql> SET @b = 8;
    mysql> EXECUTE stmt2 USING @a, @b;
    +------------+
    | hypotenuse |
    +------------+
    |         10 |
    +------------+
    mysql> DEALLOCATE PREPARE stmt2;

La syntaxe SQL des commandes préparées syntax ne peut pas être utilisée par imbrication. C'est à dire, une commande passée à `PREPARE` ne peut pas exécuter les commandes `PREPARE`, `EXECUTE` ou `DEALLOCATE PREPARE`.

De plus, la syntaxe SQL pour les commandes préparées est distincte de l'API des commandes préparées. Par exemple, vous pouvez utiliser la fonction C `mysql_stmt_prepare()` pour préparer une commande `PREPARE`, `EXECUTE`, or `DEALLOCATE PREPARE`.

This is a translation of the MySQL Reference Manual that can be found at dev.mysql.com. The original Reference Manual is in English, and this translation is not necessarily as up to date as the English version.

Précédent |  | Suivant
Chapitre 12. Fonctions à utiliser dans les clauses `SELECT` et `WHERE` | Sommaire | Chapitre 14. Moteurs de tables MySQL et types de table