1318

由于 MySQL 似乎没有任何“布尔”数据类型,您“滥用”哪种数据类型在 MySQL 中存储真/假信息?

特别是在编写和读取 PHP 脚本的上下文中。

随着时间的推移,我使用并看到了几种方法:

  • tinyint,包含值 0/1 的 varchar 字段,
  • 包含字符串 '0'/'1' 或 'true'/'false' 的 varchar 字段
  • 最后枚举包含“真”/“假”两个选项的字段。

以上似乎都不是最佳的。我倾向于使用 tinyint 0/1 变体,因为 PHP 中的自动类型转换为我提供了相当简单的布尔值。

那么您使用哪种数据类型?有没有为我忽略的布尔值设计的类型?您是否看到使用一种或另一种类型的任何优点/缺点?

4

13 回答 13

1320

对于 MySQL 5.0.3 及更高版本,您可以使用BIT. 手册说:

从 MySQL 5.0.3 开始,BIT 数据类型用于存储位域值。一种 BIT(M) 可以存储 M 位值。M 的范围可以从 1 到 64。

否则,根据 MySQL 手册,您可以使用BOOLor BOOLEAN,它们目前是tinyint (1) 的别名:

Bool、Boolean:这些类型是TINYINT (1) 的同义词。零值被认为是错误的。非零值被认为是真的。

MySQL 还指出:

我们打算在未来的 MySQL 版本中根据标准 SQL 实现完整的布尔类型处理。

参考资料:http ://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html

于 2008-11-14T10:50:51.943 回答
273

BOOL并且BOOLEAN是 的同义词TINYINT(1)。零是false,其他都是true。更多信息在这里

于 2008-11-14T10:55:02.280 回答
76

这是一个我非常欣赏的优雅解决方案,因为它使用零数据字节:

some_flag CHAR(0) DEFAULT NULL

要将其设置为 true,请设置some_flag = ''并将其设置为 false,请设置some_flag = NULL

然后测试是否为真,检查是否为 some_flag IS NOT NULL,测试为假,检查是否为 some_flag IS NULL

(此方法在 Jon Warren Lentz、Baron Schwartz 和 Arjen Lentz 的“高性能 MySQL:优化、备份、复制等”中进行了描述。)

于 2012-02-10T18:09:21.070 回答
41

这个问题已经得到解答,但我想我会投入 0.02 美元。我经常使用 a CHAR(0), where '' == true and NULL == false

来自MySQL 文档

CHAR(0)当您需要一个只能取两个值的列时,这也很不错:定义为的列CHAR(0) NULL只占用一位并且只能取值NULL''(空字符串)。

于 2009-04-30T17:39:49.200 回答
33

如果您使用 BOOLEAN 类型,则别名为 TINYINT(1)。如果您想使用标准化 SQL 并且不介意该字段可能包含超出范围的值(基本上任何不为 0 的值都将是“真”),这是最好的选择。

ENUM('False', 'True') 将允许您在 SQL 中使用字符串,MySQL 将在内部将字段存储为整数,其中 'False'=0 和 'True'=1 根据 Enum 指定的顺序.

在 MySQL 5+ 中,您可以使用 BIT(1) 字段来指示 1 位数字类型。我不相信这实际上在存储中使用了更少的空间,但再次允许您将可能的值限制为 1 或 0。

以上所有将使用大约相同数量的存储空间,因此最好选择您认为最容易使用的存储空间。

于 2008-11-14T14:59:29.757 回答
18

我使用 TINYINT(1) 来在 Mysql 中存储布尔值。

我不知道使用它是否有任何优势...但是如果我没记错的话,mysql可以存储布尔值(BOOL)并将其存储为tinyint(1)

http://dev.mysql.com/doc/refman/5.0/en/other-vendor-data-types.html

于 2008-11-14T10:42:51.210 回答
18

如果您有很多布尔字段,Bit 仅比各种字节选项(tinyint、enum、char(1))更有优势。一个位字段仍然占用一个完整字节。两个位字段适合同一个字节。三、四、五、六、七、八。之后他们开始填充下一个字节。最终节省的成本是如此之小,您应该关注数以千计的其他优化。除非您要处理大量数据,否则这几个字节不会加起来太多。如果您在 PHP 中使用 bit,则需要对输入和输出的值进行类型转换。

于 2012-01-12T16:18:54.063 回答
12

在 MySQL 实现 bit 数据类型之前,如果您的处理确实需要空间和/或时间,例如处理大量事务,请创建一个调用bit_flags所有布尔变量的 TINYINT 字段,并在 SQL 中屏蔽和移动您想要的布尔位询问。

例如,如果您最左边的位代表您的 bool 字段,而最右边的 7 个位不代表任何内容,那么您的bit_flags字段将等于 128(二进制 10000000)。屏蔽(隐藏)最右边的七个位(使用按位运算符&),并将第 8 位向右移动七个空格,以 00000001 结尾。现在整个数字(在本例中为 1)就是您的值。

SELECT (t.bit_flags & 128) >> 7 AS myBool FROM myTable t;

if bit_flags = 128 ==> 1 (true)
if bit_flags = 0 ==> 0 (false)

您可以在测试时运行这样的语句

SELECT (128 & 128) >> 7;

SELECT (0 & 128) >> 7;

等等

由于您有 8 位,因此一个字节可能有 8 个布尔变量。一些未来的程序员总是会使用接下来的七位,所以你必须屏蔽。不要只是转变,否则你将在未来为自己和他人制造地狱。确保你让 MySQL 来做你的屏蔽和转换——这将比让 web 脚本语言(PHP、ASP 等)来做这件事要快得多。此外,请确保在您的bit_flags字段的 MySQL 注释字段中放置注释。

在实施此方法时,您会发现这些站点很有用:

于 2011-07-13T17:13:59.433 回答
11

我厌倦了试图在 PHP、MySql 和 POST 值的循环中准确地获取零、NULLS 和“”,所以我只使用“是”和“否”。

这完美无瑕,不需要不明显且容易做到的特殊处理。

于 2012-07-09T20:10:04.210 回答
8

由于 MySQL (8.0.16) 和 MariaDB (10.2.1) 都实现了 CHECK 约束,我现在将使用

bool_val TINYINT CHECK(bool_val IN(0,1))

您将只能存储0,1NULL, 以及可以转换为01没有错误的值,如'1',或/ 。0x00b'1'TRUEFALSE

如果您不想允许 NULL,请添加NOT NULL选项

bool_val TINYINT NOT NULL CHECK(bool_val IN(0,1))

TINYINT请注意,使用,TINYINT(1)或几乎没有区别TINYINT(123)

如果您希望您的架构向上兼容,您还可以使用BOOLBOOLEAN

bool_val BOOL CHECK(bool_val IN(TRUE,FALSE))

db<>小提琴演示

于 2019-05-26T17:53:19.503 回答
7

参考此链接 Boolean datatype in Mysql,根据应用程序的使用情况,如果只想存储 0 或 1,bit(1) 是更好的选择。

于 2015-02-23T10:41:52.263 回答
4

在阅读了这里的答案后,我决定使用bit(1)它,是的,它在空间/时间上更好,过了一段时间我改变了主意,我再也不会使用它了。当使用准备好的语句、库等(php)时,这使我的开发变得非常复杂。

从那以后,我一直使用tinyint(1),似乎已经足够好了。

于 2018-06-26T10:14:10.300 回答
1

您可以使用 BOOL、BOOLEAN 数据类型来存储布尔值。

这些类型是 TINYINT(1) 的同义词

但是,BIT(1) 数据类型更适合存储布尔值(true[1] 或 false[0]),但 TINYINT(1) 在输出数据、查询等时更易于使用并实现 MySQL 与其他数据库之间的互操作性。您也可以检查这个答案或线程

MySQL 还将 BOOL、BOOLEAN 数据类型转换为 TINYINT(1)。

此外,阅读文档

于 2020-04-26T10:43:59.500 回答