Mysql
 sql >> Base de données >  >> RDS >> Mysql

MySQL convertit le type de données CHAR(32) en BINARY(16) sans perdre de données

Il semble que vous souhaitiez qu'un UUID soit représenté sous la forme d'une chaîne de chiffres hexadécimaux. Ceux-ci ont normalement quatre tirets, donc la longueur est en fait de 36 caractères. Mais si vous supprimez les tirets, il peut y avoir 32 caractères.

mysql> SELECT UUID();
+--------------------------------------+
| UUID()                               |
+--------------------------------------+
| b4d841ec-5220-11e9-901f-a921a9eb9f5b |
+--------------------------------------+

mysql> SELECT REPLACE(UUID(), '-', '');
+----------------------------------+
| REPLACE(UUID(), '-', '')         |
+----------------------------------+
| d3dbd450522011e9901fa921a9eb9f5b |
+----------------------------------+

Mais dans une chaîne hexadécimale, chacun des deux caractères représente des données qui pourraient être codées dans un octet de données binaires. Par exemple, FF est la valeur hexadécimale de 255, qui est la valeur maximale d'un octet. Par conséquent, les chaînes hexadécimales prennent deux fois plus d'octets que les données équivalentes en binaire. Si l'espace est limité, vous pouvez convertir vos valeurs UUID en binaire afin de pouvoir les stocker dans la moitié de l'espace.

Vous pouvez le faire avec la fonction UNHEX() .

mysql> SELECT UNHEX(REPLACE(UUID(), '-', ''));
+---------------------------------+
| UNHEX(REPLACE(UUID(), '-', '')) |
+---------------------------------+
| $S,vR!??!??[                      |
+---------------------------------+

Les données binaires ne sont pas agréables à afficher ou à saisir dans des interfaces orientées vers l'homme, car certains octets correspondent à des caractères non imprimables.

Mais quand vous avez fait ALTER TABLE table_name MODIFY device_uuid BINARY(16) , vous n'avez pas décodé les chaînes hexadécimales avec UNHEX() . Au mieux, cela a entraîné le mappage des 16 premiers octets de caractères hexadécimaux ASCII sur les 16 octets de votre colonne BINARY(16) et a tronqué la chaîne à ce stade. C'est comme si vous faisiez ceci à chaque ligne :

mysql> SELECT LEFT(REPLACE(UUID(), '-', ''), 16);
+------------------------------------+
| LEFT(REPLACE(UUID(), '-', ''), 16) |
+------------------------------------+
| 364e6db8522211e9                   |
+------------------------------------+

Les 16 premiers octets sont toujours des chiffres hexadécimaux. Les octets sont des valeurs ASCII pour ces chiffres, et non l'équivalent binaire de chaque paire de chiffres. Les 16 derniers octets de chaque chaîne ont été tronqués et non stockés. Si ces données étaient importantes, j'espère que vous disposez d'une sauvegarde de votre base de données, car la restauration de cette sauvegarde est désormais le seul moyen de récupérer ces données.

Voici ce que vous auriez dû faire :

ALTER TABLE table_name ADD COLUMN device_uuid_bin BINARY(16);
UPDATE table_name SET device_uuid_bin = UNHEX(device_uuid);

...check the data to make sure the conversion worked... 
...test any applications work with the binary data... 

ALTER TABLE table_name DROP COLUMN device_uuid;