I don't understand why
SELECT UUID();
Returns something like:
3f06af63-a93c-11e4-9797-00505690773f
But if I insert it into a binary(16) field (the UUID() function) with for instance a BEFORE INSERT trigger and run a select, it returns something like:
0782ef48-a439-11
Note that these two UUIDs are not the same data.
I realize binary and an UUID string doesn't look identical, but shouldn't the selected data at least be just as long? Otherwise how can it possibly be equally likely to be unique?
Is it better to store it as char(36)? I just need it to be unique to prevent duplicate inserts. It is never selected or used for joins.
EDIT:
before trigger would be like:
BEGIN
if NEW.UUID IS NULL THEN
NEW.UUID = UUID();
END IF
END
Best Answer
So, as a response to comments. The correct way to store a 36-char UUID as binary(16) is to perform the insert in a manner like:
UNHEX
because an UUID is already a hexed value. We trim (REPLACE
) the dashes in the statement to bring the length down to 32 characters (our 16 bytes represented asHEX
). You can do this at any point before storing it, obviously, so it doesn't have to be handled by the database.You may retrieve the UUID like this:
Just in case someone comes across this thread and is unsure how this works.
And remember: If you're selecting a row using the UUID, use
UNHEX()
on the condition:or literal notation (as mentioned by Alexis Wilke):
And NOT
HEX()
on the column:The last solution, while it works, requires that MySQL
HEX
es all UUIDs before it can determine which rows match. It's very inefficient.Edit: If you're using MySQL 8 you should have a look at the UUID functions as mentioned in SlyDave's answer. This answer is still correct, but it doesn't optimise the UUID indexes which can be done natively using those functions. If you're on < MySQL 8 you can implement Devon's polyfill, which provides identical functionality on previous versions of MySQL.