sql >> Base de Datos >  >> RDS >> Mysql

MySQL convierte el tipo de datos CHAR (32) a BINARY (16) sin perder datos

Parece que desea tener un UUID representado como una cadena de dígitos hexadecimales. Estos normalmente tienen cuatro guiones, por lo que la longitud es en realidad de 36 caracteres. Pero si elimina los guiones, puede tener 32 caracteres.

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

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

Pero en una cadena hexadecimal, cada dos caracteres representan datos que podrían codificarse en un byte de datos binarios. Por ejemplo, FF es el valor hexadecimal de 255, que es el valor máximo de un byte. Por lo tanto, las cadenas hexadecimales ocupan el doble de bytes que los datos equivalentes en binario. Si el espacio es limitado, es posible que desee convertir sus valores UUID a binario para poder almacenarlos en la mitad del espacio.

Puede hacer esto con la función UNHEX() .

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

Los datos binarios no son agradables de mostrar o escribir en interfaces orientadas a humanos, porque algunos bytes corresponden a caracteres no imprimibles.

Pero cuando hiciste ALTER TABLE table_name MODIFY device_uuid BINARY(16) , no decodificó las cadenas hexadecimales con UNHEX() . En el mejor de los casos, esto provocó que los primeros 16 bytes de caracteres hexadecimales ASCII se asignaran a los 16 bytes de su columna BINARY(16), y truncó la cadena en ese punto. Es como si hicieras esto en cada fila:

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

Los primeros 16 bytes siguen siendo dígitos hexadecimales. Los bytes son valores ASCII para esos dígitos, no el equivalente binario de cada par de dígitos. Los últimos 16 bytes de cada cadena se truncaron y no se almacenaron. Si esos datos eran importantes, espero que tenga una copia de seguridad de su base de datos, porque restaurar esa copia de seguridad ahora es la única forma en que puede recuperar esos datos.

Lo que deberías haber hecho es lo siguiente:

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;