MySQL中的布尔值使用Boolean还是tinyint(1)?

154
在MySQL数据库中,布尔值最好使用哪种列类型?我使用的是boolean,但我的同事使用的是tinyint(1)

5
看起来MySQL会透明地将boolean视为tinyint(1)。因此,您可以使用booleantruefalse,MySQL会将它们分别视为tinyint(1)10 - ADTC
另一个情况是 char 1 和 Y & N,据一些人说应该更快。 - Zon
7个回答

192

这些数据类型是同义词。


9
我不会说数据类型是同义词——tinyint(1)与bool相同,但tinyint和bool并不相同。这只是一个小细节,但你的回答第一次读时让我有些困惑。 - Kyle Chadha
4
这个回答没有解答问题。虽然tinyint(1)在功能上与bool相同,但是提问者询问使用哪个更好。@dj_segfault的答案很好地解释了为什么在存储布尔值时应该优先选择bool而不是tinyint(1)。 - Kyle Morgan
确实,文档表明BOOL和BOOLEAN是tinyint(1)的同义词。 - Woodchuck

122

我要采用不同的方法,并建议您的同行开发人员了解您的代码与编译器/数据库同样重要。使用boolean可能与使用tinyint的效果相同,但它具有语义上的优势,可以传达您的意图,这是非常有价值的。

如果您使用tinyint,那么仅通过代码并不明显只会出现01两个值。
boolean始终是truefalse


41

boolean在MySQL中不是一个独立的数据类型,它只是tinyint的同义词。请参阅MySQL手册上的这个页面。 可以看到下面引用的例子和语句来自于 dev.mysql.com/doc/

    mysql> SELECT IF(0, 'true', 'false');
    +------------------------+
    | IF(0, 'true', 'false') |
    +------------------------+
    | false                  |
    +------------------------+
    mysql> SELECT IF(1, 'true', 'false');
    +------------------------+
    | IF(1, 'true', 'false') |
    +------------------------+
    | true                   |
    +------------------------+
    mysql> SELECT IF(2, 'true', 'false');
    +------------------------+
    | IF(2, 'true', 'false') |
    +------------------------+
    | true                   |
    +------------------------+

然而,TRUE和FALSE的值仅仅是1和0的别名,如下所示:

mysql> SELECT IF(0 = FALSE, 'true', 'false');
+--------------------------------+
| IF(0 = FALSE, 'true', 'false') |
+--------------------------------+
| true                           |
+--------------------------------+
mysql> SELECT IF(1 = TRUE, 'true', 'false');
+-------------------------------+
| IF(1 = TRUE, 'true', 'false') |
+-------------------------------+
| true                          |
+-------------------------------+
mysql> SELECT IF(2 = TRUE, 'true', 'false');
+-------------------------------+
| IF(2 = TRUE, 'true', 'false') |
+-------------------------------+
| false                         |
+-------------------------------+
mysql> SELECT IF(2 = FALSE, 'true', 'false');
+--------------------------------+
| IF(2 = FALSE, 'true', 'false') |
+--------------------------------+
| false                          |
+--------------------------------+

最后两个语句显示的结果是因为2既不等于1也不等于0。

我个人建议使用tinyint,因为布尔类型从其名称上并不能清晰地表达其作用,所以可能会导致代码理解上的误导。但在实际层面上,这并不重要 -- 两者都可以完成相同的工作,所以无论使用哪种类型都不会有任何得失。


1
虽然这是一个非常详尽的回答,但最后你分享了你对tinyint的偏好,指出“布尔值从名称上并不像你想象的那样工作”。你能详细说明一下吗?我发现这个答案在这里非常好(https://dev59.com/dG865IYBdhLWcg3wkPaD#47404140):“...(boolean)携带了你试图做什么的语义含义”。 - Rafael Leite

9

1
我们不能使用枚举,因为我们的数据库还需要支持sqlite。 - tom
15
如果你正在使用InnoDB,bit类型占用的空间和tinyint一样。来自《高性能MySQL》(percona团队):"InnoDB将每个[bit]列存储为足以容纳位的最小整数类型,因此您不会节省任何存储空间。"唯一的好处是,如果您想在BIT(大于1)列中存储多个布尔值。因此,如果只有一个布尔字段,则在InnoDB中使用tinyint与bit相同,并且更可取,因为tinyint通常更易于处理。 - billmalarky
MySQL中不适用的数据类型:BIT(M) - 大约需要 (M+7)/8 字节 参见:https://dev.mysql.com/doc/refman/8.0/en/storage-requirements.html - Jens

8
虽然说booltinyint(1)在功能上是相同的,但是bool应该被优先选择,因为它传达了你所要做的事情的语义含义。此外,许多ORM会将bool转换为你所使用的编程语言的本地布尔类型。

0

我使用Dapper连接MySQL的经验是它确实很重要。我通过使用以下脚本将非空位(1)更改为可空tinyint(1):

ALTER TABLE TableName MODIFY Setting BOOLEAN null;

然后Dapper开始抛出异常。我试图查看脚本之前和之后的区别。并注意到bit(1)已更改为tinyint(1)。

然后我运行了:

ALTER TABLE TableName CHANGE COLUMN Setting Setting BIT(1) NULL DEFAULT NULL;

这解决了问题。


0
无论您选择int还是bool,当可空列出现时,它都很重要。
想象一下一个有多张照片的产品。你怎么知道哪张照片作为产品封面?好吧,我们会使用一个指示它的列。
到目前为止,product_image表有两个列:product_id和is_cover 很酷吧?但还不够。由于产品只能有一个封面,因此我们需要在这两个列上添加唯一索引。
但是等等,如果这两个列将获得唯一索引,那么您如何为同一产品存储许多非封面图像?唯一索引会在这里抛出错误。
所以您可能会认为“好吧,但您可以使用NULL值,因为这些值被唯一索引检查省略了”,是的,这是真的,但我们正在失去语言规则。
布尔类型列中NULL值的目的是什么?是“全部”,“任何”还是“没有”?布尔列中的null值允许我们使用唯一索引,但它也混淆了我们如何解释记录。
我会告诉您,在某些情况下,整数可以更好地发挥作用,因为它不受严格的true或false含义的约束。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接