MySQL中BIT(64)列的奇怪行为

时间:2018-05-06 11:14:27

标签: mysql

任何人都可以帮助我理解MySQL(5.7.19)中BIT(64)列的以下问题。

这个简单的例子工作正常,并从临时表中返回记录:

CREATE TEMPORARY TABLE test (v bit(64));
INSERT INTO test values (b'111');
SELECT * FROM test WHERE v = b'111';
-- Returns the record as expected

当使用列的所有64位时,它不再起作用:

CREATE TEMPORARY TABLE test (v bit(64));
INSERT INTO test values (b'1111111111111111111111111111111111111111111111111111111111111111');
SELECT * FROM test WHERE v = b'1111111111111111111111111111111111111111111111111111111111111111';
-- Does NOT return the record

仅在使用64位值时才会发生这种情况。但我希望这是可能的。

任何人都可以向我解释这个吗?

请不要回应,建议我不要使用BIT专栏。我正在研究一个能够处理MySQL所有数据类型的数据库工具。

2 个答案:

答案 0 :(得分:0)

位以二进制形式返回,因此要显示它们,要么添加0,要么使用HEX,OCT或BIN等函数转换它们https://mariadb.com/kb/en/library/bit/或结果集中的位值作为二进制值返回,可能表现不佳。要将位值转换为可打印格式,请在数字上下文中使用它或使用转换函数,如BIN()或HEX()。转换后的值中不显示高位0位数。 https://dev.mysql.com/doc/refman/8.0/en/bit-value-literals.html

答案 1 :(得分:0)

问题似乎是,WHERE子句中的值b'11..11'被认为是SIGNED BIGINT-1并且与表中的值进行比较成为UNSIGNED BIGINT18446744073709551615。当64位中的第一位为1时,这始终是个问题。恕我直言这是一个错误或设计缺陷,因为如果在INSERT语句中使用了相同的表达式(至少在这种情况下),我希望WHERE子句中的表达式匹配一行。

一种解决方法是将值转换为UNSIGNED

SELECT * 
FROM test
WHERE v = CAST(b'1111111111111111111111111111111111111111111111111111111111111111' as UNSIGNED);

或(如果您的应用语言支持)将其转换为long uintdecimal

SELECT * FROM test WHERE v = 18446744073709551615;