将存储为 VARCHAR(255) 的 ulid 转换为二进制 (16) 的 SQL 函数

问题描述 投票:0回答:1

我有一个mysql数据库,其中所有的id(主键)都是ulid。问题在于它存储为 VARCHAR(255)。我想通过以下方式纠正它(更改为二进制):

  1. 向每个表添加 BINARY(16) 类型的 id_bin 列。
  2. 将 id 值复制到这个新的 id_bin 列,同时将它们转换为二进制。
  3. 删除主主键并向 id_bin 列添加一个新主键。
  4. 将 id_bin 重命名为 id。
  5. 对所有外键进行相同的更改。

问题是将 utf8mb3 字符集中存储为 VARCHAR(255) 的 ulid 转换为二进制。我尝试过以下功能:

DELIMITER //

-- The input is of type CHAR(26) for simplicity as converting varchar(255) to char(26) does not seem to be a problem, the problem is converting it further to binary
CREATE FUNCTION ConvertULIDToBinary(ulid CHAR(26) CHARACTER SET utf8mb3) 
RETURNS BINARY(16)
DETERMINISTIC
BEGIN
    DECLARE result BINARY(16);
    SET result = UNHEX(CONCAT(
        LPAD(CONV(SUBSTRING(ulid, 1, 6), 36, 16), 10, '0'),
        LPAD(CONV(SUBSTRING(ulid, 7, 6), 36, 16), 10, '0'),
        LPAD(CONV(SUBSTRING(ulid, 13, 6), 36, 16), 10, '0'),
        LPAD(CONV(SUBSTRING(ulid, 19, 8), 36, 16), 16, '0')
    ));
    RETURN result;
END //

DELIMITER ;

但是如果我运行它,我会收到以下错误:

SQL Error (1406) in statement #3: Data too long for column 'result' at row 1
sql mysql primary-key
1个回答
0
投票

尝试以下功能

delimiter //
DROP FUNCTION IF EXISTS ULID_DECODE//
CREATE FUNCTION ULID_DECODE (s CHAR(26)) RETURNS BINARY(16) DETERMINISTIC
BEGIN
DECLARE s_base32 CHAR(26);
SET s_base32 = REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(REPLACE(UPPER(s), 'J', 'I'), 'K', 'J'), 'M', 'K'), 'N', 'L'), 'P', 'M'), 'Q', 'N'), 'R', 'O'), 'S', 'P'), 'T', 'Q'), 'V', 'R'), 'W', 'S'), 'X', 'T'), 'Y', 'U'), 'Z', 'V');
RETURN UNHEX(CONCAT(LPAD(CONV(SUBSTRING(s_base32, 1, 2), 32, 16), 2, '0'), LPAD(CONV(SUBSTRING(s_base32, 3, 12), 32, 16), 15, '0'), LPAD(CONV(SUBSTRING(s_base32, 15, 12), 32, 16), 15, '0')));
END//
delimiter ;
© www.soinside.com 2019 - 2024. All rights reserved.