Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

MySQL converte o tipo de dados CHAR (32) para BINARY (16) sem perder dados


Parece que você deseja ter um UUID representado como uma sequência de dígitos hexadecimais. Estes normalmente têm quatro traços neles, então o comprimento é na verdade 36 caracteres. Mas se você remover os traços, pode ter 32 caracteres.
mysql> SELECT UUID();
+--------------------------------------+
| UUID()                               |
+--------------------------------------+
| b4d841ec-5220-11e9-901f-a921a9eb9f5b |
+--------------------------------------+

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

Mas em uma string hexadecimal, cada dois caracteres representam dados que podem ser codificados em um byte de dados binários. Por exemplo, FF é o valor hexadecimal de 255, que é o valor máximo de um byte. Portanto, as strings hexadecimais ocupam o dobro de bytes que os dados equivalentes em binário. Se o espaço for restrito, convém converter seus valores UUID em binários para que você possa armazená-los na metade do espaço.

Você pode fazer isso com a função UNHEX() .
mysql> SELECT UNHEX(REPLACE(UUID(), '-', ''));
+---------------------------------+
| UNHEX(REPLACE(UUID(), '-', '')) |
+---------------------------------+
| $S,vR!??!??[                      |
+---------------------------------+

Os dados binários não são agradáveis ​​de exibir ou digitar em interfaces orientadas para humanos, porque alguns bytes correspondem a caracteres não imprimíveis.

Mas quando você fez ALTER TABLE table_name MODIFY device_uuid BINARY(16) , você não decodificou as strings hexadecimais com UNHEX() . Na melhor das hipóteses, isso fez com que os primeiros 16 bytes de caracteres hexadecimais ASCII fossem mapeados para os 16 bytes de sua coluna BINARY(16) e truncou a string nesse ponto. É como se você fizesse isso em todas as linhas:
mysql> SELECT LEFT(REPLACE(UUID(), '-', ''), 16);
+------------------------------------+
| LEFT(REPLACE(UUID(), '-', ''), 16) |
+------------------------------------+
| 364e6db8522211e9                   |
+------------------------------------+

Os primeiros 16 bytes ainda são dígitos hexadecimais. Os bytes são valores ASCII para esses dígitos, não o equivalente binário de cada par de dígitos. Os últimos 16 bytes de cada string foram truncados e não armazenados. Se esses dados foram importantes, espero que você tenha um backup do seu banco de dados, porque restaurar esse backup agora é a única maneira de recuperar esses dados.

O que você deveria ter feito é o seguinte:
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;