由于 MySQL 似乎没有任何“布尔”数据类型,您“滥用”哪种数据类型在 MySQL 中存储真/假信息?
特别是在编写和读取 PHP 脚本的上下文中。
随着时间的推移,我使用并看到了几种方法:
tinyint,包含值 0/1 的 varchar 字段,
包含字符串 '0'/'1' 或 'true'/'false' 的 varchar 字段
最后枚举包含“真”/“假”两个选项的字段。
以上似乎都不是最佳的。我倾向于使用 tinyint 0/1 变体,因为 PHP 中的自动类型转换为我提供了相当简单的布尔值。
那么您使用哪种数据类型?有没有为我忽略的布尔值设计的类型?您是否看到使用一种或另一种类型的任何优点/缺点?
bit(1)
在 Excel 中导入有点**。切换到 tinyint(1)
有效。
对于 MySQL 5.0.3 及更高版本,您可以使用 BIT
。手册说:
从 MySQL 5.0.3 开始,BIT 数据类型用于存储位域值。一种 BIT(M) 可以存储 M 位值。 M 的范围可以从 1 到 64。
否则,根据 MySQL 手册,您可以使用 BOOL
或 BOOLEAN
,它们目前是 tinyint(1) 的别名:
Bool、Boolean:这些类型是 TINYINT(1) 的同义词。零值被认为是错误的。非零值被认为是真的。
MySQL 还指出:
我们打算在未来的 MySQL 版本中根据标准 SQL 实现完整的布尔类型处理。
参考文献:http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html
BOOL
和 BOOLEAN
是 TINYINT(1)
的同义词。零是 false
,其他都是 true
。更多信息here。
(1)
只是确定值的显示方式,如果您意识到存储大小,那么您想改用 BIT
BIT(1)
和 TINYINT(1)
都将使用一个字节的存储空间。直到 MySQL 5.0.3,BIT
实际上是 TINYINT
的同义词。更高版本的 MySQL 更改了 BIT 的实现。但即使实现更改,BIT
数据类型仍然没有“存储大小”优势(至少对于 InnoDB 和 MyISAM;其他存储引擎,例如 NDB 可能对多个 BIT 列声明进行一些存储优化。)更大的问题是某些客户端库无法识别或正确处理返回的 BIT
数据类型列。 TINYINT
效果更好。
true
”是不正确的。
SELECT 'foo' AS bar FROM dual WHERE -7
。表达式 -7 在布尔上下文中计算,查询返回一行。我们可以使用 0 或任何计算结果为整数值 0 的表达式进行测试,并且不返回任何行。如果 WHERE 子句中的表达式计算为除零以外的任何非空整数值,则表达式为 TRUE。 (我相信十进制和浮点值会“四舍五入”为整数,例如 WHERE 1/3
的计算结果为 WHERE 0
。我们使用 WHERE 'foo'
得到相同的结果,因为字符串 'foo'
的计算结果也为整数值 0。
这是一个我非常欣赏的优雅解决方案,因为它使用零数据字节:
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:优化、备份、复制等”中进行了描述。)
NULL
表示为 false 而 ''
表示为 true 指定为 COMMENT
可能对帮助未来理解有一些非常小的帮助。
这个问题已经得到解答,但我想我会投入 0.02 美元。我经常使用 CHAR(0)
,其中 '' == true and NULL == false
。
从 MySQL docs:
当您需要一个只能取两个值的列时,CHAR(0) 也非常好:定义为 CHAR(0) NULL 的列只占用一位并且只能取值 NULL 和 ''(空字符串) .
''
和 null
都是假值。
如果您使用 BOOLEAN 类型,则别名为 TINYINT(1)。如果您想使用标准化 SQL 并且不介意该字段可能包含超出范围的值(基本上任何不为 0 的值都将是“真”),这是最好的选择。
ENUM('False', 'True') 将允许您在 SQL 中使用字符串,MySQL 将在内部将字段存储为整数,其中 'False'=0 和 'True'=1 根据 Enum 指定的顺序.
在 MySQL 5+ 中,您可以使用 BIT(1) 字段来指示 1 位数字类型。我不相信这实际上在存储中使用了更少的空间,但再次允许您将可能的值限制为 1 或 0。
以上所有将使用大约相同数量的存储空间,因此最好选择您认为最容易使用的存储空间。
我使用 TINYINT(1) 来在 Mysql 中存储布尔值。
我不知道使用它是否有任何优势...但是如果我没记错的话,mysql可以存储布尔值(BOOL)并将其存储为tinyint(1)
http://dev.mysql.com/doc/refman/5.0/en/other-vendor-data-types.html
如果您有很多布尔字段,Bit 仅比各种字节选项(tinyint、enum、char(1))更有优势。一个位字段仍然占用一个完整字节。两个位字段适合同一个字节。三、四、五、六、七、八。之后他们开始填充下一个字节。最终节省的成本是如此之小,您应该关注数以千计的其他优化。除非您要处理大量数据,否则这几个字节不会加起来太多。如果您在 PHP 中使用 bit,则需要对输入和输出的值进行类型转换。
我厌倦了试图在 PHP、MySql 和 POST 值的循环中准确地获取零、NULLS 和“”,所以我只使用“是”和“否”。
这完美无瑕,不需要不明显且容易做到的特殊处理。
在 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 评论字段中添加评论。
在实施此方法时,您会发现这些站点很有用:
MySQL — 位函数和运算符
十进制/二进制转换工具
VARCHAR
并在代码中执行取消屏蔽过程(您也不需要将其限制为8 个字段)...
BIT
类型存在。请参阅dev.mysql.com/doc/refman/8.0/en/bit-type.html
由于 MySQL (8.0.16) 和 MariaDB (10.2.1) 都实现了 CHECK 约束,我现在将使用
bool_val TINYINT CHECK(bool_val IN(0,1))
您将只能存储 0
、1
或 NULL
,以及可以转换为 0
或 1
且不会出现 '1'
、0x00
、b'1'
或TRUE
/FALSE
。
如果您不想允许 NULL,请添加 NOT NULL
选项
bool_val TINYINT NOT NULL CHECK(bool_val IN(0,1))
请注意,使用 TINYINT
、TINYINT(1)
或 TINYINT(123)
几乎没有区别。
如果您希望架构向上兼容,还可以使用 BOOL
或 BOOLEAN
bool_val BOOL CHECK(bool_val IN(TRUE,FALSE))
ENUM
(必须是 enum('0', '1')
- 注意:这些是字符串)不是一个好主意。由于它在内部的存储方式以及非字符串值的处理方式,因此存在 too many issues。例如。 0
和 FALSE
无法存储。 1
和 TRUE
变为 '0'
。 2
变为 '1'
。
参考此链接Boolean datatype in Mysql,根据应用使用情况,如果只想存储 0 或 1,bit(1) 是更好的选择。
BIT(1)
只允许存储 b'0'
或 b'1'
值。 BIT
数据类型的最大问题是各种客户端库对数据类型的处理方式各不相同。检查各种 SQL 工具(SQLyog、TOAD for MySQL、SQL Developer)、“逆向工程”数据库模型的工具和各种客户端(如 JDBC、PHP、Perl DBI)中的行为,并测试一些 ORM 框架(休眠,Mybatis,JPA)。在易用性、工具/框架兼容性/原生支持方面,TINYINT(1)
无疑是赢家。
BIT
和 TINYINT
。参考 MyBatis 的 JdbcType 类,mybatis.org/mybatis-3/apidocs/reference/org/apache/ibatis/type/…
在阅读了这里的答案后,我决定使用 bit(1)
,是的,它在空间/时间上更好,但是过了一段时间我改变了主意,我再也不会使用它了。当使用准备好的语句、库等(php)时,这使我的开发变得非常复杂。
从那以后,我一直使用tinyint(1)
,似乎已经足够好了。
您可以使用 BOOL、BOOLEAN 数据类型来存储布尔值。
这些类型是 TINYINT(1) 的同义词
但是,BIT(1) 数据类型更适合存储布尔值(true[1] 或 false[0]),但 TINYINT(1) 在输出数据、查询等时更易于使用并实现 MySQL 与其他数据库之间的互操作性。您也可以检查 this answer or thread。
MySQL 还将 BOOL、BOOLEAN 数据类型转换为 TINYINT(1)。
此外,请阅读 documentation
不定期副业成功案例分享
!$boolean
将永远无法正确评估。