Ceci est une ancienne révision du document !
ALTER TABLE sujet ADD tmpswap DATETIME; UPDATE sujet SET tmpswap = FROM_UNIXTIME(ancien); ALTER TABLE sujet DROP ancien; ALTER TABLE sujet CHANGE tmpswap ancien DATETIME;
(sujet : nom de la table ; ancien : nom de la colonne initialement en (big)int)
ALTER TABLE sujet ADD tmpswap DATE; UPDATE sujet SET tmpswap = STR_TO_DATE(ancien, '%d/%m/%Y'); ALTER TABLE sujet DROP ancien; ALTER TABLE sujet CHANGE tmpswap ancien DATE;
(sujet : nom de la table ; ancien : nom de la colonne initialement en varchar)
Pourquoi utiliser le type DATE ?
On peut aisément remplacer un CASE comme celui-ci :
SELECT CASE <in> WHEN 'FT' THEN 'Fiche Technique' WHEN 'PV' THEN 'Procès Verbal' WHEN 'NF' THEN 'Norme' ELSE 'Valeur par défaut' END;
Par :
COALESCE( ELT( FIELD(<in>, 'FT', 'PV', 'NF'), 'Fiche Technique', 'Procès Verbal', 'Norme' ), 'valeur par défaut' )
C'est l'"équivalent" PHP de :
Par contre : ça revient éventuellement à "réinventer" le type ENUM
SET FOREIGN_KEY_CHECKS=0; -- les différentes opérations sql à exécuter en ignorant les clés étrangères SET FOREIGN_KEY_CHECKS=1;
Sachez tout d'abord que MySQL dispose de deux types différents par rapport aux date/heure :
Ils diffèrent par ce qu'ils impliquent :
Après cette brève présentation des types date/heure, il est possible de modifier à la volée la timezone courante au lieu d'hériter de celle par défaut (appelée SYSTEM). Pour ce faire, il faut modifier au niveau session la variable nommée … time_zone par une commande SET. Mais, problème, par défaut, vous ne pouvez assigner à cette variable qu'un décalage +/-heure:minute (exemple set time_zone = '+2:00';
) et non utiliser directement des noms comme Europe/Paris à moins d'importer les timezones au sein de MySQL. Autant dire que c'est gênant pour deux raisons :
Donc, pour importer ces fameuses timezones :
mysql_tzinfo_to_sql /usr/share/zoneinfo | mysql -u root -p mysql
Tester que tout fonctionne :
mysql> set time_zone = 'Europe/London'; Query OK, 0 rows affected (0.00 sec) mysql> select now(); +---------------------+ | now() | +---------------------+ | 2013-07-26 15:57:20 | +---------------------+ 1 row in set (0.00 sec) mysql> set time_zone = 'Europe/Paris'; Query OK, 0 rows affected (0.00 sec) mysql> select now(); +---------------------+ | now() | +---------------------+ | 2013-07-26 16:57:20 | +---------------------+ 1 row in set (0.00 sec)
Quant à ceux qui ne peuvent que subir, tout ce que vous pouvez faire, c'est remplacer vos NOW() et autres fonctions MySQL par celles de votre langage. Par exemple, pour PHP, qui embarque toutes ces informations de fuseaux horaire, il suffira de faire un préalable date_default_timezone_set('Europe/Paris');
en début de code et de remplacer les NOW() de vos requêtes par date('Y-m-d H:i:s')
ou autre DateTime.
Si vous avez un élément "unique" et qu'il est identifié comme tel au niveau de MySQL par une clé primaire ou une contrainte unique (UNIQUE KEY) alors vous pouvez utiliser une requête de type INSERT IGNORE.
Pour l'exemple, prenons le cas d'une table d'utilisateurs minimaliste, avec id (clé primaire) plus login qui doit être unique :
Comment s'assurer à l'inscription d'un nouvel utilisateur que le login n'est pas déjà pris par quelqu'un d'autre ? C'est simple, vous tentez de faire silencieusement l'insertion et vous regardez ensuite si une ligne a été insérée ou non (mysql(i) : mysql(i)_affected_rows, pdo : PDO::rowCount) :
(le code est en PHP mais le principe peut être adapté à tout langage)
IGNORE n'est qu'une option pour que lorsque l'on tente d'insérer un "doublon", la requête n'échoue pas. Elle est destinée à considérer qu'une tentative d'insertion de doublon est un cas prévu par notre programme et non une erreur (vous en obtiendriez une sans IGNORE).
Par contre, cette solution ne convient pas si vous avez plusieurs contraintes d'unicité et que vous voulez savoir laquelle a empêché l'insertion. En effet, si vous voulez notamment indiquer à l'utilisateur si c'est l'adresse email ou le login qui est déjà pris, vous devriez faire un SELECT normal par contrainte unique. Je dis "devriez" parce qu'il est éventuellement possible, pour un INSERT sans l'option IGNORE, de parser le message d'erreur où la colonne ou contrainte ou index empêchant l'insertion est mentionné, solution, qui, à mon sens, n'est pas très viable (et encore moins portable).
Comme ci-dessus, si chaque ligne peut être identifiée de manière unique par la valeur d'une ou plusieurs colonnes, définies comme clé primaire (PRIMARY KEY) ou comme clé unique (UNIQUE KEY), alors il est possible de réaliser cette opération insertion sinon mise à jour en une seule requête de type INSERT … ON DUPLICATE KEY UPDATE au lieu d'avoir à recourir à cet "algo" traditionnel :
Pour illustrer, prenons une situation courante, réaliser un import, ici de joueurs, via un flux XML fourni par la fédération. Tout d'abord notre table, volontairement sommaire, joueurs :
On reconnaît un joueur d'un autre via son numéro de licence, unique. Le but, en parsant ce flux, est double :
Encore une fois, c'est codé en PHP mais parfaitement transposable à tout langage puisque c'est la requête SQL qui compte.