【问题标题】:MySQL bitwise AND 256-bit binary valuesMySQL 按位与 256 位二进制值
【发布时间】:2019-02-07 15:28:17
【问题描述】:

我打算在 MySQL 表列中存储一个 256 位长的二进制值。

我应该使用哪种列类型(blob?),以便我可以对它运行按位运算(AND 的示例是理想的)。

【问题讨论】:

  • 256 位只有 32 字节。不是真正的二进制大对象。您是否只需要在数据库中存储这些值。或者您是否打算对它们执行一些操作(按值搜索、模式匹配、算术运算、按位逻辑运算)...
  • 我打算对它们使用按位运算。
  • 好的,只有按位操作。由于这是一个有趣的问题,我做了一些实验。如果labelBLOB 列,您能否确认bin(label & b'01..00') 下面的答案中的这个表达式按预期工作?对我来说,它不起作用?!?总是返回0...
  • 它在 select 中确实有效,尽管我似乎无法让它适用于 where 子句,而且我还没有检查 >64 位。
  • 我认为这可能可以工作到 64 位。但肯定不在上面。我在下面编辑了我认为唯一可行的解​​决方案的答案:将您的 256 位值拆分为 4 个 64 位 BIGINT UNSIGNED。不是很优雅,但很有效,您将可以使用 MySQL 位运算符的“全部功能”以及各种转换功能(HEX()BIN())。

标签: mysql blob bit-manipulation


【解决方案1】:

我认为您无法找到某种方法在 SQL 级别对 256 位值执行按位运算,因为文档明确指出:

MySQL 使用 BIGINT(64 位)算法进行位运算,因此这些运算符的最大范围为 64 位。

http://dev.mysql.com/doc/refman/5.5/en/bit-functions.html#operator_bitwise-and


至于存储这些值,TINYBLOB 是可能的,但我个人的偏好会简单地转到BINARY(32)二进制字符串 32 字节 -- 256 位)。



在写这篇文章时,我想到了一个技巧。如果我们仅限于 64 位值 (BIGINT UNSIGNED),为什么不将 256 位存储为 4 个 64 位字。不是很优雅,但这会起作用。尤其是在这里,因为您只需要按位运算:

ABCD32 & WXYZ32 == A8 & W8, B8 & X8, C8 & Y8, D8 & Z8

非常基本:

create table t (a bigint unsigned, 
                b bigint unsigned, 
                c bigint unsigned, 
                d bigint unsigned);

在插入时,必须将 256 位值“拆分”为 4 个字:

-- Here I use hexadecimal notation for conciseness. you may use b'010....000' if you want 
insert into t values (0xFFFFFFFF,
                      0xFFFF0000,
                      0xFF00FF00,
                      0xF0F0F0F0);

您可以轻松查询 256 位值:

mysql> select CONCAT(LPAD(HEX(a),8,'0'),
                     LPAD(HEX(b),8,'0'),
                     LPAD(HEX(c),8,'0'),
                     LPAD(HEX(d),8,'0')) from t;
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| CONCAT(LPAD(HEX(a),8,'0'),
                     LPAD(HEX(b),8,'0'),
                     LPAD(HEX(c),8,'0'),
                     LPAD(HEX(d),8,'0')) |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+
| FFFFFFFFFFFF0000FF00FF00F0F0F0F0                                                                                                                      |
+-------------------------------------------------------------------------------------------------------------------------------------------------------+

我在这里再次使用了十六进制,但是您可以通过将 ̀HEX() 替换为 BIN() 来显示为二进制

最后但并非最不重要的是,您可以对它们执行二进制操作。再一次,您只需要“拆分”操作数。假设我想将 256 位掩码 0xFFFFFFFFFFFFFFFF0000000000000000 应用于表中的所有值:

update t set a = a & 0xFFFFFFFF, 
             b = b & 0xFFFFFFFF, 
             c = c & 0x00000000, 
             d = d & 0x00000000;

【讨论】:

  • +1 在 MySQL 实现 Oracle 样式 RAW 数据类型或实现 256 位无符号 REALLYBIGINT UNSIGNED 数据类型之前,整数类型是可行的方法。
【解决方案2】:

看起来 blob 适用于这样的查询,用于按位和:

select id,bin(label & b'01000000010000001000000000000000000') from projects;

【讨论】:

    猜你喜欢
    • 2012-07-06
    • 2011-10-06
    • 2014-10-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-12-11
    • 2014-06-19
    • 2021-06-13
    相关资源
    最近更新 更多