The ID
column of your table is declared as BINARY(16)
, and your UUID_ENCODE
expects a CHAR(36)
. When you invoke your UUID_ENCODE
function directly without a trigger, it correctly receives your 36 characters string. When you use the trigger instead, the value you are inserting is first converted to the type of the column, so NEW.ID
will contain the results of CAST('323febe6-cd89-4773-a46c-aab794fb7cbc' AS BINARY(16)
. When the trigger invokes the function, it will cast again the value of NEW.ID
to the type expected by your function. So, this is the value your function will receive:
SELECT CAST(CAST('323febe6-cd89-4773-a46c-aab794fb7cbc' AS BINARY(16)) AS CHAR);
323febe6-cd89-47
As you can see, your function receives the value truncated. The results you are getting are equivalent to:
SELECT UUID_DECODE(UUID_ENCODE('323febe6-cd89-47'));
000000000000-0000-0032-3feb-e6cd8947
UPDATE
One way to implement the desired functionality in a trigger would be to add a dummy nullable column with the type your function expects:
CREATE TABLE test (ID BINARY(16) KEY DEFAULT 0, CHARID CHAR(36) NULL);
CREATE TRIGGER test_uuid_encode BEFORE INSERT ON test FOR EACH ROW BEGIN
SET NEW.ID = UUID_ENCODE(NEW.CHARID)
, NEW.CHARID = NULL;
END
This way you can do:
INSERT test (CHARID) VALUES ('323febe6-cd89-4773-a46c-aab794fb7cbc');
SELECT UUID_DECODE(ID) FROM test;
+--------------------------------------+
| uuid_decode(id) |
+--------------------------------------+
| 323febe6cd89-4773-a46c-aab7-94fb7cbc |
+--------------------------------------+
I created a fiddle here.
Note that:
- Although
CHARID
accepts NULLs,ID
does not, so an attempt to insert a NULL value inCHARID
would result in the trigger trying to setID
to NULL and the insertion being rejected. - Attempting to insert an invalid value into
CHARID
that causesUUID_ENCODE
to return NULL will also fail. - The
DEFAULT 0
clause forID
is there only to allow you to omit the column from the insert list. The value written to the table will always be the one generated by your trigger. - A nullable column that is always NULL should take between 0 and 2 bytes of additional storage per row depending on your table layout and row format (you would need to avoid for instance the
FIXED
format of the MyISAM engine). - There are many variations possible. If you don't mind the extra storage, you can keep the
CHARID
value without setting it to NULL. If you want to allow explicit insert of binaryID
values you can add a check to the trigger so you computeNEW.ID
only if it is 0, etc. - You should have a similar trigger for UPDATE operations, if they are allowed.