Mysql
 sql >> Datenbank >  >> RDS >> Mysql

MySQL konvertiert den Datentyp CHAR(32) in BINARY(16), ohne Daten zu verlieren

Es hört sich so an, als ob Sie eine UUID als Zeichenfolge aus Hexadezimalziffern darstellen möchten. Diese enthalten normalerweise vier Bindestriche, sodass die Länge tatsächlich 36 Zeichen beträgt. Aber wenn Sie die Bindestriche entfernen, können es 32 Zeichen sein.

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

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

Aber in einer Hex-Zeichenfolge stellen jeweils zwei Zeichen Daten dar, die in einem Byte binärer Daten codiert werden könnten. Beispielsweise ist FF der Hexadezimalwert für 255, was dem Höchstwert von einem Byte entspricht. Daher benötigen Hex-Strings doppelt so viele Bytes wie die entsprechenden Daten in Binärform. Wenn der Speicherplatz begrenzt ist, möchten Sie Ihre UUID-Werte möglicherweise in Binärwerte konvertieren, damit Sie sie auf der Hälfte des Speicherplatzes speichern können.

Sie können dies mit der UNHEX()-Funktion .

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

Es ist nicht angenehm, binäre Daten in Benutzeroberflächen anzuzeigen oder einzugeben, da einige Bytes nicht druckbaren Zeichen entsprechen.

Aber wenn Sie ALTER TABLE table_name MODIFY device_uuid BINARY(16) gemacht haben , Sie haben die Hex-Strings nicht mit UNHEX() dekodiert . Dies führte bestenfalls dazu, dass die ersten 16 Bytes der ASCII-Hexadezimalzeichen den 16 Bytes Ihrer BINARY(16)-Spalte zugeordnet wurden, und die Zeichenfolge wurde an dieser Stelle abgeschnitten. Es ist, als ob Sie dies für jede Zeile tun würden:

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

Die ersten 16 Bytes sind noch Hexadezimalziffern. Die Bytes sind ASCII-Werte für diese Ziffern, nicht das binäre Äquivalent jedes Ziffernpaars. Die letzten 16 Bytes jeder Zeichenfolge wurden abgeschnitten und nicht gespeichert. Wenn diese Daten wichtig waren, hoffe ich, dass Sie eine Sicherungskopie Ihrer Datenbank haben, denn die Wiederherstellung dieser Sicherungskopie ist jetzt die einzige Möglichkeit, diese Daten wiederherzustellen.

Folgendes hätten Sie tun sollen:

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;