Mysql 如何对巨大的二进制列执行位操作
我在mysql表中有一个字段,称为“调色板”。它的行为就像一个rgb十六进制代码,但不是3种颜色,我有12种。如果我不计算“0x”的2个字符,那么这个二进制字段的长度是24。问题是我似乎无法对它们执行位运算,好像程序认为它们太大了 我想围绕这些行做一些事情(我将使它变小以便于理解):mysql中的0x123456和0x00FF00,并获得0x003400。但这似乎根本不起作用,因为这不是我得到的价值Mysql 如何对巨大的二进制列执行位操作,mysql,sql,binary,hex,Mysql,Sql,Binary,Hex,我在mysql表中有一个字段,称为“调色板”。它的行为就像一个rgb十六进制代码,但不是3种颜色,我有12种。如果我不计算“0x”的2个字符,那么这个二进制字段的长度是24。问题是我似乎无法对它们执行位运算,好像程序认为它们太大了 我想围绕这些行做一些事情(我将使它变小以便于理解):mysql中的0x123456和0x00FF00,并获得0x003400。但这似乎根本不起作用,因为这不是我得到的价值 我希望得到一个精确的值,但大多数时候我得到的是0(即使有明确的值)或0的相反值(当十六进制只填充
我希望得到一个精确的值,但大多数时候我得到的是0(即使有明确的值)或0的相反值(当十六进制只填充了“F”s)。如果唯一的问题是您无法使用长十六进制字符串,您可以为此实现SP
DELIMITER $$
CREATE FUNCTION `bfunc`(
`op` VARCHAR(3),
`v1` VARCHAR(26) CHARSET latin1,
`v2` VARCHAR(26) CHARSET latin1
)
RETURNS varchar(26) CHARSET latin1
DETERMINISTIC
BEGIN
SET @r = '';
SET @r1 = REVERSE(TRIM(LEADING '0x' FROM v1));
SET @l1 = LENGTH(@r1);
SET @r2 = REVERSE(TRIM(LEADING '0x' FROM v2));
SET @l2 = LENGTH(@r2);
SET @l = IF(@l1 > @l2, @l1, @l2);
SET @i = 1;
WHILE @i < @l DO
SET @c1 = SUBSTR(@r1, @i, 1);
SET @c2 = SUBSTR(@r2, @i, 1);
SET @b1 = CONV(IF(@c1 = '', 0, @c1), 16, 10);
SET @b2 = CONV(IF(@c2 = '', 0, @c2), 16, 10);
SET @b = '';
CASE op
WHEN 'AND' THEN SET @b = @b1 & @b2;
WHEN 'OR' THEN SET @b = @b1 | @b2;
WHEN 'XOR' THEN SET @b = @b1 ^ @b2;
END CASE;
SET @r = CONCAT(@r, HEX(@b));
SET @i = @i + 1;
END WHILE;
RETURN REVERSE(@r);
END
$$
DELIMITER ;
=>
03400000000000000000000
当然,对于生产环境,您需要对其进行优化,并不是在“每字符”的基础上进行逐位计算,而是在“每8字符”的基础上进行逐位计算。如果唯一的问题是无法使用长十六进制字符串,您可以为此实现SP
DELIMITER $$
CREATE FUNCTION `bfunc`(
`op` VARCHAR(3),
`v1` VARCHAR(26) CHARSET latin1,
`v2` VARCHAR(26) CHARSET latin1
)
RETURNS varchar(26) CHARSET latin1
DETERMINISTIC
BEGIN
SET @r = '';
SET @r1 = REVERSE(TRIM(LEADING '0x' FROM v1));
SET @l1 = LENGTH(@r1);
SET @r2 = REVERSE(TRIM(LEADING '0x' FROM v2));
SET @l2 = LENGTH(@r2);
SET @l = IF(@l1 > @l2, @l1, @l2);
SET @i = 1;
WHILE @i < @l DO
SET @c1 = SUBSTR(@r1, @i, 1);
SET @c2 = SUBSTR(@r2, @i, 1);
SET @b1 = CONV(IF(@c1 = '', 0, @c1), 16, 10);
SET @b2 = CONV(IF(@c2 = '', 0, @c2), 16, 10);
SET @b = '';
CASE op
WHEN 'AND' THEN SET @b = @b1 & @b2;
WHEN 'OR' THEN SET @b = @b1 | @b2;
WHEN 'XOR' THEN SET @b = @b1 ^ @b2;
END CASE;
SET @r = CONCAT(@r, HEX(@b));
SET @i = @i + 1;
END WHILE;
RETURN REVERSE(@r);
END
$$
DELIMITER ;
=>
03400000000000000000000
当然,对于生产环境,您需要对其进行优化,并不是在“每字符”的基础上进行位运算,而是在“每8字符”的基础上进行位运算。0x123456&0x00FF00=>0x003400是正确的,不是吗?你是说这是错误的吗?您是否期待0x12FF56?这就是按位or运算符。我的意思是,这就是我所期望的。但是我得到的值可能会有很大的差异。我可以得到类似0x000000或0xFFFFFF的东西。我的字段看起来像0x12341234123412341234412341234,对大十六进制值的按位操作似乎有问题。您是如何存储这些长十六进制值的?作为文本还是VARCHAR?我尝试了很多组合。我试着使用varchar、binary(26)、varbinary、bigint、decimal(30,0)。我还尝试在每种类型中强制转换它们,但它总是返回一个断开的值(我知道它将返回一个int,但一旦我将其转换回hex,它就不适合)。可能是因为它存储在一个字段中或有96位,这就是问题所在?我现在正在运行一些测试,我不会每天处理这些长的十六进制,请稍等。0x123456&0x00FF00=>0x003400是正确的,不是吗?你是说这是错误的吗?您是否期待0x12FF56?这就是按位or运算符。我的意思是,这就是我所期望的。但是我得到的值可能会有很大的差异。我可以得到类似0x000000或0xFFFFFF的东西。我的字段看起来像0x12341234123412341234412341234,对大十六进制值的按位操作似乎有问题。您是如何存储这些长十六进制值的?作为文本还是VARCHAR?我尝试了很多组合。我试着使用varchar、binary(26)、varbinary、bigint、decimal(30,0)。我还尝试在每种类型中强制转换它们,但它总是返回一个断开的值(我知道它将返回一个int,但一旦我将其转换回hex,它就不适合)。也许问题在于它存储在字段中或有96位?我现在正在运行一些测试,我不是每天都处理这些长的十六进制数,请稍等。好吧,那么,你的解决方案更快了,还是我刚才做的“黑客”更优了?我所做的是使它成为一个没有“0x”的varchar,然后我做了一个子字符串。在大量的行上它会变慢吗?我认为你的“原生”解决方案会更快。好吧,那么,你的解决方案是更快,还是我刚才做的“黑客”更优化?我所做的是使它成为一个没有“0x”的varchar,然后我做了一个子字符串。在大量的行上它会变慢吗?我认为您的“本机”解决方案会更快。