7.13 INSERT

    INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] Nom_table [(Nom_col,...)]
        VALUES (expression,...),(...),...
ou  INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] Nom_table [(Nom_col,...)]
        SELECT ...
ou  INSERT [LOW_PRIORITY | DELAYED] [IGNORE]
        [INTO] Nom_table
        SET Nom_col=expression, Nom_col=expression, ...

INSERT insère une nouvelle ligne dans une table existante.. La forme de INSERT ... VALUES est basée sur des colonnes explicitement précisée. forme de INSERT ... SELECT insère des données depuis une autre table. La forme de INSERT ... VALUES avec plusieurs valeurs est acceptée MySQL à partir de la version 3.22.5 . La syntaxe Nom_col=expression est accepté par MySQL à partir de la version 3.22.10.

Nom_table est le nom de la table dans laquelle les lignes vont être insérée. La liste de nom de colonne ou la clause SET indique quelles colonnes vont être assignées.

  • Si aucun nom de colonne n'est précisé dans la commande, INSERT ... VALUES or INSERT ... SELECT, alors des valeurs doivent être fournies pour toutes les colonnes dans la liste de VALUES(). Pour connaître l'ordre des colonnes, il faut utiliser la commande DESCRIBE Nom_table.
  • Toute colonne qui n'a pas de valeur explicitement fournie est mise à sa valeur par défaut. Par exemple, il est possible de fournir une liste de colonne en omettant certains noms : les valeurs de ces colonnes seront les valeurs par défaut. Pour avoir les détails sur les valeurs par défaut, CREATE TABLE.
  • Une expression peut faire référence à n'importe quelle colonne déjà nommée dans la liste des colonnes. Par exemple :
mysql> INSERT INTO Nom_table (col1,col2) VALUES(15,col1*2);

Mais pas ceci :

mysql> INSERT INTO Nom_table (col1,col2) VALUES(col2*2,15);
  • L'option LOW_PRIORITY permet de différer une exécution jusqu'à ce qu'il n'y ait plus de client qui lisent la table.
  • L'option permet, lors de l'insertion dans une table qui a une colonne de type PRIMARY or UNIQUE , de ne pas renvoyer d'erreur si une insertion essaie de doubler une clé déjà existante. Si cette option n'est pas précisée, l'insertion est annulée à partir de la ligne erronée. Le nombre de ligne correctement insérées est accessible avec mysql_info() .
  • Si MySQL a été configuré avec l'option DONT_USE_DEFAULT_FIELDS , une commande INSERT devra avoir la liste complète des colonnes qui requière une valeur non-NULL.
  • Les conditions suivantes s'appliquent aux commandes de type INSERT INTO ... SELECT
    • La requête ne peut pas contenir de clause ORDER BY
    • La table cible de l'insertion ne peut pas apparaître dans la clause FROM du SELECT, car la norme ANSI SQL l'interdit (en effet, le SELECT pourrait trouver des lignes qui viennent juste d'être insérée. Utiliser des sous-selections serait encore pire).
    • Les colonnes de type AUTO_INCREMENT fonctionnent de la même façon.

Lors de l'utilisation de INSERT ... SELECT ou INSERT ... VALUES avec des listes de plusieurs lignes, la fonction mysql_info() permet d'obtenir des informations sur la requête. Le format de la réponse est comme suite :

Records: 100 Duplicates: 0 Warnings: 0

Duplicates indique le nombre de lignes qui n'a pas pus être insérées car elles tentaient de doubler une clé primaire.. Warnings indique le nombre d'insertions qui ont générer une erreur lors de l'insertion. Warnings surviennent lorsqu'il y a une tentative:

  • Insertion d'une valeur NULL dans une colonne déclarée NOT NULL.
  • Assignation d'une valeur numérique qui est hors de l'intervalle de validité de la colonne. Cette valeur est ramenée à la valeur valide la plus proche.
  • Assignation d'une valeur telle que '10.34 a'. Dans ce cas, les résidus inutiles sont éliminés. Si la valeur ne peut pas être interprétée, la valeur 0 est assignée à la place.
  • Insertion d'une chaîne dans une colonne de type CHAR, VARCHAR, TEXT ou BLOB qui excède la longueur maximale. La valeur est alors tronquée à la taille maximale de la colonne.
  • Insertion d'une valeur invalide dans une date ou heure. La valeur est alors fixée au ``zéro'' du type de la colonne.

L'option DELAYED pour la commande INSERT est une caractéristique MySQL qui est très utile lorsque les clients ne peuvent pas attendre la fin de l'insertion. C'est utilisé habituellement par MySQL pour remplir des historiques, et que périodiquement, une longue commande SELECT est effectuée. DELAYED a été introduit à partir de MySQL 3.22.15. C'est une extension MySQL à la norme ANSI SQL92.

Un autre avantage majeur de l'utilisation de la commande INSERT DELAYED est que les insertions sont regroupées et traitées en même temps. C'est une manière plus rapide que d'effectuer autant d'insertions unitaires.

Il faut noter que les insertions en attente sont gardées en mémoire vive, jusqu'à ce qu'elles soient insérées dans la table. Cela signifie que si le processus mysqld est brutalement interrompu (kill -9) ou si mysqld se termine inopinément, les lignes ne seront pas écrites sur le disque, et ainsi perdues !

Les événements suivants surviennent lors de l'utilisation de l'option DELAYED des commandes INSERT ou REPLACE. Dans la description qui suit, le ``thread'' est le thread qui a recu la commande INSERT DELAYED et ``handler'' est le thread qui va gérer les INSERT DELAYED pour une table particulière.

  • Quand un thread exécute la commande DELAYED pour une table, le thread handler est crée pour gérer toutes les commandes DELAYED pour la table, si un tel thread n'existe pas.
  • Le thread vérifie si le handler a bien posé un verrou DELAYED, et si non, il lui dit de le faire. Le verrou DELAYED peut être obtenu même si d'autres threads ont déjà obtenu un verrou de READ ou WRITE sur la table. Cependant, le handler va attendre que tous les verrous ALTER TABLE ou FLUSH TABLES soient libérés, afin de s'assurer que la table est bien à jour.
  • Le thread exécute l'insertion mais, au lieu d'écrire la ligne dans la table, il transmet une copie de la ligne finale au handler, qui l'ajoute dans la queue d'attente. Toutes les erreurs d'insertions sont notées par le thread, et rapportées au client.
  • Le client ne reçoit pas le nombre de doublons, ou la valeur d' AUTO_INCREMENT qu'il pourrait attendre, car ces informations ne sont connues qu'après l'insertion proprement dite. De la même façon, mysql_info()risque de retourner des informations incohérentes.
  • L'historique de mise à jour est modifié par le handler quand la ligne est effectivement insérée dans la table. Si il y a plusieurs lignes insérées simultanément, l'historique de mise à jour est modifié lors de l'insertion de la première ligne.
  • Après chaque bloc de delayed_insert_limit lignes écrites, le handler vérifie si il n'y a pas de commande SELECT en attente. Si c'est le cas, il s'arrête, et l'exécute avant de continuer.
  • Quand le handler n'a plus de ligne dans la queue, la table est déverrouillée. Si aucune autre commandes INSERT DELAYED n'est reçue dans un délai de delayed_insert_timeout secondes, le handler se termine.
  • Si il reste plus de delayed_queue_size lignes en attente d'insertion, le thread attend jusqu'à ce qu'il y ait de la place dans la queue. Ce permet de contrôler la quantité de mémoire utilisé pour les queues d'attentes.
  • Le handler apparaîtra dans la liste des processus MySQL avec le mot delayed_insert dans la colonne de Command . Il sera automatiquement effacé lors d'une commande FLUSH TABLES ou KILL thread_id. Cependant, il enregistrera les lignes dans la table avant de quitter. Durant cette période, le handler n'acceptera plus aucune nouvelle commande INSERT d'un autre thread. Si une nouvelle commande an INSERT DELAYED est éxécutée, un nouveau handler sera créé.
  • Il faut bien noter que les commandes INSERT DELAYED ont une priorité supérieure aux commandes INSERT, si un handler est déjà en fonctionnement. Toutes les autres commandes doivent attendre que la queue d'attente du handler soit vide (même par un kill).
  • Les statuts suivants fournissent des informations sur l'état des commandes INSERT DELAYED :

Ces variables sont accessibles avec la commande SHOW STATUS ou, en ligne, avec mysqladmin extended-status.