因为MySQL似乎没有任何"布尔"数据类型,所以您"滥用"哪种数据类型来存储MySQL中的真/假信息?
尤其是在编写和读取PHP脚本的上下文中。
随着时间的推移,我使用并看到了几种方法:
tinyint,varchar字段包含值0/1,
包含字符串"0"/"1"或"true"/"false"的varchar字段
最后枚举包含两个选项"true"/"false"的字段。
以上都不是最佳选择。我倾向于使用tinyint 0/1变量,因为PHP中的自动类型转换提供的布尔值非常简单。
那么您使用哪种数据类型呢?是否有一个类型是为我忽略的布尔值设计的?您是否看到使用一种或另一种类型有什么优点/缺点?
任何阅读这个问题的老答案的人都需要理解,MySQL在版本5中添加了一点数据类型。尽可能使用这些信息。dev.mysql.com/doc/refman/5.0/en/bit-type.html版本
第一个tinyint不是上面所暗示的varchar字段。你是说bigint也是varchar字段吗?第二,我建议tinyint存储布尔字段,但没有理由。
关于MySQL中许多布尔值的替代方法的问题?
对于当前版本的mysql boolean类型是可用的-dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html检查这个。根据该值,零被认为是错误的
根据具体情况,例如,对于消息表上的deleted 标志,我使用DATE NULL ,这样我就可以使用它来存储它被删除的日期。
bit(1) 有点**要导入Excel。切换到tinyint(1) 工作。
5年后我们有了布尔值
对于真正的布尔值(而不是tinyint别名),有两个特性请求,这两个请求都有10年的历史:bugs.mysql.com/bug.php?id=24530和bugs.mysql.com/bug.php?ID=24531。我找不到Mariadb的票,但你可以在这里检票。
对于MySQL5.0.3及更高版本,可以使用BIT 。手册上说:
As of MySQL 5.0.3, the BIT data type is used to store bit-field
values. A type of BIT(M) enables storage of M-bit values. M can range
from 1 to 64.
否则,根据mysql手册,您可以使用bool和boolean,这是tinyint(1)的别名:
Bool, Boolean: These types are synonyms for TINYINT(1). A value of
zero is considered false. Non-zero
values are considered true.
MySQL还指出:
We intend to implement full boolean
type handling, in accordance with
standard SQL, in a future MySQL
release.
参考文献:http://dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.html
是的,我要么选择这个,要么选择一个字符(1),然后根据上下文存储"y"/"n"或"t"/"f"等。使用小整数类型的优点是,您可以在RDBMS之间获得最大的可移植性
至少在PHP中使用char会导致更多的代码,因为如果没有进一步的处理,!$boolean 将永远无法正确地评估。
比特(1)怎么样?????
你可以使用位(1),但你需要把它投到布尔,这是不好的。
@罗兰布曼忘记了二进制部分。那是错字。我的意思是,使用第(1)位,你可以为自己节省一些存储空间。
@Pacerier"使用位(1)可以为自己节省一些存储空间。"实际上不是这样。前8位仍需要1字节的存储空间。此外,当您经常使用命令行时,您会感到非常痛苦,因为客户机无论如何都会使用字符类型来表示位字段。最后,bit在不同的RDBMS中意味着不同的东西。即使你的目标是一个MySQL解决方案,仍然更容易坚持使用char,因为这意味着所有地方都一样。只有在我有一个带有多个(>8)标志的非常大的表的情况下,我才会考虑进行一点。
@Rolandbouman在实践中确实节省了存储空间。当然,如果我们在整个表中没有一行,就没有区别了。但是,与优化多行字符(1)相比,该引擎可以优化多行位(1)。
关于"当你经常使用命令行的时候,你会有很多的疼痛感"。我建议您使用更好的MySQL客户端。
关于"位在不同的RDBMS中意味着不同的东西……使用char仍然比较容易,因为这意味着到处都是相同的"…当然,在不同的RDBMS中,许多事情意味着许多不同的事情,这并不是避免使用第(1)位(MySQL5.0.3及更高版本)的一个好理由。
@pacerier"引擎可以优化多行位(1),比它可以优化多行字符(1)"。哪个"引擎"?理论上,它可以。实际上,没有一个MySQL存储引擎跨行打包位字段。坦率地说,在基于行的数据存储中,这种打包是没有意义的。位的每行打包也不太好:如果存储引擎本身不支持位数据类型,那么mysql服务器会将mysql位数据类型列映射到存储引擎中的varchar列,从而导致比理论上的最小值更多的存储。
@关于一个更好的MySQL客户机:好吧,不管怎样。如果你的意思是MySQL命令行客户机不能很好地处理位字段,那当然,我同意。然而,这是事实上的客户,在许多情况下,你根本没有奢侈的依赖于你可能喜欢的任何客户,无论是出于什么原因,无论是好是坏。
@Rolandbouman,我说的是一个紧凑型innodb表的索引。它可以优化多行位(1),比优化多行字符(1)要好得多。我没有消息来源,但如果你声称相反,你也需要消息来源。坦率地说,这种打包在索引中很有意义,我假设这是未来大多数引擎的默认值,除非您有其他来源的引用。你说"mysql服务器将mysql位数据类型列映射到varchar列"…这很可疑。请列举一些资料来源。
@罗兰·布曼,从客户的角度来看,事实上没有客户。这是一个市场。如果你的客户不善于使用位域,那么会有很多更好的客户这样做。在许多情况下,您可以随意使用任何客户。只有在特殊情况下,当你不选择退出位。
@更糟糕的是,你不能自己搜索,但好吧,我会咬人的。首先,请看一看data0type.h。请注意,innodb并不是本地定义的位类型。如果它能像你描述的那样处理位场,我们肯定会在那里找到它存在的一些暗示。其次,阅读mysqlperformanceblog.com/2008/04/23/…。别客气地告诉我们,在"marktetplace"中,哪些出色的MySQL客户机可以很好地处理位字段。毫无疑问,如果有人错过了那篇文章,他们会派上用场的。
当我从标准mysql命令行中进行选择时,客户机位字段显示为完全空白。正因为如此,我更喜欢Tinyint(1)。
我更喜欢tinyint(1) ,因为出于某种原因,如果使用boolean ,就不能向列中添加auto_increment 属性。
@我不想问,但为什么要在表示布尔值的列上使用auto_increment ?
@克里斯海斯:你是对的,你不会是布尔型的。我在查找表的tinyint列中添加了auto_increment,我知道tuple计数将小于255(无符号)
不要使用位(1)类型来表示布尔值。至少要导出/导入csv数据。
这个答案在理论上是正确的,@philip morton的答案在实践中效果更好。看看这个答案I advice to avoid BIT due to problems with client libraries (which PDO issue proves). You will spare yourself a lot of trouble if you modify type of column to TINYINT(1), which will of course consume full byte of storage for every row, but according to mysql docs BIT(1) will do as well. 。
@Rolandbouman博士还有很多其他的。事实上,这并不罕见。你是否只在默认客户机上工作了那么多,以至于没有尝试其他客户机?你说,"在很多情况下,你根本没有奢侈的依赖于任何你喜欢的客户"。请解释如何和为什么经营一个合适的客户被认为是奢侈和不切实际的。此外,当"innodb为每一位(1)列分配1个字节时",……
…&zwnj;&8203;…&zwnj;&8203;……bit(1) 仍然具有优势。它不仅在语义上是正确的,而且没有人会意外地将错误的数据(< 0 || >=2 插入其中。我想知道是不是更令人吃惊的是,5只恐龙否决了你的评论,还是事实上,PPL实际上会选择使用tinyint(1) 而不是bit(1) ,以便更容易地与旧(将来)默认客户玩。
@命令行客户机是默认的——因此,您真正可以依赖的是它。仍然好奇你可能在谈论的其他客户有多少。关于比特在语义上更正确:那是B。比特是比特场,不是布尔场。如果您真的是"语义"上的挂起的操作,那么使用bool数据类型。这只是tinyint(1)的同义词。你是否意识到mysql中的true和false分别是int 1和int 0的同义词?坦白说,我很惊讶你这么长时间后竟然有兴趣打败这匹死马。
@Rolandbouman,1)re,"命令行是可靠的,因为它是默认的":错误。我们已经有多少个bug了?我们还有多少??唯一"可靠"的是ABI,因为所有客户都使用它。2)BIT 工作于phpmyadmin、navicat、heidisql、sqlyog、sqlwave、toad、dbforge。我开始怀疑除了默认客户机之外,您是否还使用其他客户机。3)您将数据语义与命名混淆。它们是完美的矫正器
............................................................与zwnj;与# 8203;.gonal观念。因为它是错误的选择BOOL 地图这一TINYINT 这有2^8 槽。我们有一个2 -和MySQL bit(1) 槽,但槽binary(1) 256 256槽,和一TINYINT / BOOL / boolean ,...................................................垃圾吗?与zwnj吗?……………………………………8203;与#;与zwnj;与# 8203;与……………………………………zwnj;与# 8203;与zwnj;与# 8203;…………………
............................................................与zwnj;与# 8203;……………….他人。4),你没有realize true false 是别名为1 0 。坦率地说,我和lastly)你还surprised肝贮脂TINYINT 布尔数据使用。这是一个公共论坛会作为一个维基为好。MySQL是为活着,这是今天和昨天一样继续,这将是好的未来。这是misleading信息需求的addressed regardless及其给其writer疯了,或是它,你不只是因为其他评论线程后约会很老吗?
一位,一位是美国disadvantage场和InnoDB不能被indexed(或是一部分"index)。
"shlominoach,为什么你说那是不能被indexed部分或是一个指标。create table t(userid int key,a bit(1)not null,b bit(1)not null,c bit(1)not null,index(a),index b_c(b,c))engine=innodb; :1)和2)和3)explain select*from t where a=0b0; explain select*from t where b=0b0 and c=0b1; 。"queries秀的指标,是有用的。
"一个问题,是pacerier asked和answered立即通过自己的人通常是一rhetorical问题。下面的链接,你provide这"怎么多的[错误]我们仍然有[和] MySQL客户端"reveals 6 3的结果,这是在谈论"MySQL客户端(74691,74899,75541)和1(75242)是一种基于请求还比你的错误。我相信这是领导这一问题而stupid比rhetorical一2,因为虫子似乎,恕我直言,respectfully少的软件,是widely是人道的。
"rolandbouman,你可能想从这10。我的反应是,"claim回复你的命令行客户端是违约-因此,只有一个你真的可以rely他"。重复:错了。我根本不answered仍然有不被answered;的链接是一个援助的答案,它的答案本身。6报告吗?那不是我的。我目前在不超过hundreds看着。
"pacerier;一点。我站起来,用以纠正,这或许是他older versions。
马库斯:我一扇的updating信息用于posterity。"这给MySQL版本为5.7"文件的布尔数据类型映射法仍然是tinyint(1)[网址:dev.mysql.com /医生/ / / / refman 5.7个other-vendor-data-types.html ]。"我migrating从MySQL MS SQL是5.7,将使用Java应用程序和为8层,这是一个新的应用(legacy code)是它真正的(用于双关语)",一个8位devote必须对安全的方式这样做。布尔数据?我从位移动的MS SQL数据类型。如果你发现任何wondering advantages或变化从你最后的评论。
马库斯:PS I有如此之多的个位,我将被转换过的。"我希望有一rows很多的数据是advantages和MSSQL这包装的位和字节的共享。我把我的这consideration初始设计。我知道会这样,如果我有这一切throw规划和容易的了。谢谢。
@马库斯做了一些深入的研究,很清楚答案应该是什么。确实发生了变化,我们已经看到了这种处理方法的改进。了解应用程序层/数据访问层中的语言,并了解库支持。我现在正在使用Java,在这个时候,BIT(1)是推荐的选择,比如HyBalEnter和JDBC的使用。这里是url[见表5.2]:dev.mysql.com/doc/connector-j/en/&hellip;
BOOL 和BOOLEAN 是TINYINT(1) 的同义词。0是false ,其他的都是true 。更多信息。
(1) 只不过是确定值的显示方式,如果您知道存储大小,那么您希望使用BIT 来代替它。
@jameshalsall:实际上,BIT(1) 和TINYINT(1) 都将使用一个字节的存储。在mysql 5.0.3之前,BIT 实际上是TINYINT 的同义词。后来版本的mysql改变了bit的实现。但是,即使实现发生了变化,BIT 数据类型(至少对于innodb和myisam,其他存储引擎(如ndb)可能对多位列声明进行了一些存储优化)仍然没有"存储大小"好处。更大的问题是,一些客户端库无法识别或适当地处理返回的edo。cx1〔1〕数据类型列。一个TINYINT 工作得更好。
MySQL5.0手册明确指出布尔值是1或0。"任何其他东西都是true "这句话不是真的。
@沃尔特:事实上是这样的,解释有点缺乏。简言之,在布尔上下文中,表达式的计算结果可以为空、假或真。在mysql语句中,在布尔上下文中计算的表达式首先被计算为整数(十进制和浮点值是四舍五入的,字符串的转换方式通常是mysql将字符串转换为整数)。空值显然是空值(既不是真也不是假)。0的整数值处理为假,任何其他整数值(1、2、-7等)的计算结果都为真。为了兼容性,我们模拟了tinyint布尔值的逻辑/处理
@沃尔特:这很容易测试,例如SELECT 'foo' AS bar FROM dual WHERE -7 。表达式-7在布尔上下文中计算,查询返回一行。我们可以使用0或任何计算为整数值0的表达式进行测试,并且不返回任何行。如果WHERE子句中的表达式的计算结果为除零以外的任何非空整数值,则该表达式为真。(我认为十进制和浮点值"四舍五入"为整数,例如,WHERE 1/3 的计算结果为WHERE 0 。对于WHERE 'foo' ,我们得到了相同的结果,因为字符串'foo' 也计算为整数值0。
这是一个优雅的解决方案,我非常感谢,因为它使用零数据字节:
设置为真,设置some_flag = '' ,设置为假,设置some_flag = NULL 。
然后,为了测试是否正确,检查是否有IS NOT NULL 标志,为了测试是否错误,检查是否有IS NULL 标志。
(此方法由Jon Warren Lentz、Baron Schwartz和Arjen Lentz在"高性能MySQL:优化、备份、复制等"中介绍。)
花花公子!如果使用mysql<5,甚至可能比bit占用更少的内存,这是很有帮助的,但是为了遵守约定并稍微减少计算开销(逻辑与精确值),我会说bit是更好的方法。
可能是"快速的",但它混淆了数据,使任何新开发人员都不知道该列代表什么。
这与位(1)使用的字节数相同。
祝你好运,让ORM能很好地映射到这一点。
我同意@richthofen的观点,很难想象在这种情况下我会提倡使用这种解决方案。但是,如果要使用它,那么在该列的定义中指定为COMMENT ,null 表示错误,'' 表示正确,这对于帮助将来的理解可能会有很小的帮助。
@Craiglabenz不是每个人都喜欢ORM。
这个问题已经回答了,但我想我会把0.02美元投进去。我经常使用char(0),其中''==true和NULL==false。
来自MySQL文档
CHAR(0) is also quite nice when you need a column that can take only
two values: A column that is defined as CHAR(0) NULL occupies only one
bit and can take only the values NULL and '' (the empty string).
嗯,如果你像我一样,这似乎是在自找麻烦。我的意思是,根据语言的不同,很容易发现空值和""之间的差异(例如php)。
在节省空间(用于表示布尔值的字节数)方面,这种方法显然是一个胜利者。这比tinyint节省了一个字节。缺点(正如一些评论指出的那样)是,一些客户机可能难以区分空字符串和空字符串。甚至一些关系数据库(例如Oracle)也不能区分零长度字符串和空值。
这很聪明!我以前写聪明的代码,现在我像躲避瘟疫一样避免了它。我现在希望我的代码有明确的意图,而不仅仅是正确的行为。我的建议是什么?只有当您想混淆必须支持代码/数据库的任何人时,才能这样做。例如,在PHP中,'' 和null 都是错误的值。
@cjdennis如果您已经抽象了存储库模式背后的数据库层,那么您不必担心这个解决方案的晦涩。
如果使用布尔类型,则其别名为tinyint(1)。如果您希望使用标准化的SQL,并且不介意字段可能包含超出范围的值(基本上,任何非0的值都将是"true"),那么这是最好的方法。
枚举("false"、"true")将允许您使用SQL中的字符串,MySQL将在内部将字段存储为一个整数,其中"false"=0和"true"=1基于指定枚举的顺序。
在MySQL5+中,可以使用位(1)字段来表示1位数字类型。我不相信这实际上会占用存储空间,但再次允许您将可能的值限制为1或0。
所有这些都将使用大致相同的存储量,因此最好选择最容易使用的存储量。
您关于枚举的评论不是真的:尝试cast(yourenumcol为unsigned),您会注意到false将是1,true将是2。枚举的另一个问题是它太容易插入""(空字符串)。我不尊重使用这个。
根据我的经验,使用PHP代码中的位(1)字段有点麻烦。tinyint(1)容易得多,生成的代码可读性更高。
@m-peror-"从PHP代码中使用位(1)字段有点麻烦"…没有双关语的意思。但是,是的,我同意。我记得Tinyint(1)也更容易…只是不记得为什么。其他人对此有想法吗?位(1)在表面上看起来更好,因为您可以限制为0或1。我认为比特有时被解释为二进制数据(取决于编程语言和驱动程序/库);然而,tinyint被认为更像一个数字。
@bminer-哈哈,这真是出乎意料,没有注意到:)但是事实上,如果我记得正确的话,位字段被解释为二进制的,而tinyint更容易被当作一个数字来处理,因此,在(布尔)表达式中更容易使用。
直到失宠
我使用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,则需要输入和输出值。
+1表示排版注释。另外,在使用编程语言时,要避免使用懒惰的编程技术而有利于一致性。使用相同的运算符,而不是只使用等号。对于php,如果($var==")对于0、false、null、undefined和"为true。为了测试所有的值,最好使用if(true==empty($var)),因为它也可以避免未定义的错误。您还应该验证正在使用的数据类型if(is_int($var)&;$var==0),或者将其类型化以强制它成为任务的特定数据类型(int)$var。
@Thor对于MySQL来说这是真的吗?在同样程度上,对于MSSQL也是真的吗?我正在将尚未投入生产的新应用程序从mssql迁移到mysql。我不是在使用PHP,而是将C转换到Java 8。考虑到Java是一种强类型语言,我不担心类型处理…只有所有的位标志,从一个字节移动到最多8个标志,到1个字节,每个标志给出tinyint(1)。你知道关于MySQL这个主题的任何文档吗?
@托尔做了一些深入的研究,很清楚答案应该是什么。确实发生了变化,我们已经看到了这种处理方法的改进。了解应用程序层/数据访问层中的语言,并了解库支持。我现在正在使用Java,在这个时候,BIT(1)是推荐的选择,比如HyBalEnter和JDBC的使用。这里是url[见表5.2]:dev.mysql.com/doc/connector-j/en/&hellip;
在mysql实现一个位数据类型之前,如果您的处理真正需要空间和/或时间,例如处理大量事务,那么为所有布尔变量创建一个名为bit_flags 的tinyint字段,并屏蔽和移动SQL查询中需要的布尔位。
例如,如果最左边的位代表您的bool字段,最右边的7位不代表任何内容,那么您的bit_flags 字段将等于128(二进制10000000)。屏蔽(隐藏)七个最右边的位(使用按位运算符& ),并将第8位的七个空格右移,最后得到00000001。现在,整个数字(在本例中是1)就是您的值。
您可以在测试时运行这样的语句
等。
因为您有8位,所以一个字节中可能有8个布尔变量。一些未来的程序员总是使用接下来的7位,所以您必须屏蔽。不要只是改变,否则将来你会为自己和他人创造地狱。确保你让MySQL做你的屏蔽和转移——这将比让Web脚本语言(PHP、ASP等)做的要快得多。另外,请确保在mysql comment字段中为您的bit_flags 字段放置注释。
在实现此方法时,您会发现这些站点很有用:
mysql-位函数和运算符
十进制/二进制转换工具
这看起来就像是一个让未来程序员混淆意图的可怕方法。当然,保存7个字节似乎很麻烦(假设您使用了该单表中的所有8个bool!)
@是的,完全没有混淆!编写文档和MySQL注释,解释表中的每个字段(如答案所述)!建议使用的mysql取消屏蔽策略看起来很可靠,最多存储16个不同的布尔字段(只包含两列)比使用16个布尔字段要好。如果使用位操作过于混乱,并且您更喜欢使用Web脚本语言来获取每个布尔值,只需将其存储为VARCHAR ,并在代码中执行取消屏蔽过程(您也不需要将其限制为8个字段)。
我受够了试图得到零、空值和""精确地循环php、mysql和post值,所以我只使用"yes"和"no"。
这项工作完美无瑕,不需要任何不明显和不容易做到的特殊治疗。
如果您真的想浪费这么多空间并牺牲性能,那么您至少可以使用y和n选项完成char(1)。
在大多数真实世界的情况下,"不"和仅仅是缺乏信息之间存在着真正的区别。例如,如果用户实际上还没有说"否",您可能希望在默认情况下勾选复选框。准确地说,你认为你节省了多少空间,每次你需要区分一个错误和一个空的时候,你要做多少处理——如果你确实能区分的话?在存储图像和数字视频的世界中,节省空间的位或位完全不相关,但清晰度和减少的处理是真实的。
这个答案是正确的,因为它会起作用,而且不会像人们所说的那么糟糕。对于大多数项目(即表大小小于1毫米行),所提供的解决方案之间的性能差异是可以忽略的。如果我的查询在7到5毫秒内返回,我不会抱怨…公平地说,如果您的表增长到10英里或更多行,这可能不是首选的解决方案。
+1,用于使用枚举数据类型。我个人更喜欢这个符号:枚举("y","n")。它是紧凑的(只有一个字节长),直观和良好的外观作为所有布尔标志的应用程序级约定。您可以直接将其用于HTML表单字段。例如,对于php:>yes >否 >select>
哈哈,这让我眼花缭乱,但我不得不说@geofkendall是对的。在很多情况下,不需要优化性能,无论什么方法为您做的工作都是正确的方法。
引用此链接在MySQL中,根据应用程序的使用情况,如果只想存储0或1,那么位(1)是更好的选择。
确实,BIT(1) 只允许存储b'0' 或b'1' 值。BIT 数据类型最大的问题是,不同的客户机库对数据类型的处理方式各不相同。检查各种SQL工具(sqlyog、toad for mysql、sql developer)、"反向工程"数据库模型的工具以及各种客户机(如jdbc、php、perl dbi)中的行为,并测试一些ORM框架(hibernate、mybatis、jpa)以获得良好的度量。在易用性、工具/框架兼容性/本机支持方面,TINYINT(1) 显然是赢家。
对。它的完成取决于应用程序所考虑的框架。例如,php的phalcon框架不处理位数据类型
据记录,mybatis支持BIT 和TINYINT 。请参阅mybatis的jdbctype类,mybatis.org/mybatis-3/apidocs/reference/org/apache/ibatis/ty&zwnj;&误8203;pe/&hellip;
@Vidz我给你一个关于第(1)位的补充,但也会向阅读本文的开发人员指出——了解你将在应用层/数据访问层使用的语言,并了解你的库支持。我现在正在使用Java,在这个时候,BIT(1)是推荐的选择,比如HyBalEnter和JDBC的使用。这里是url[见表5.2]:dev.mysql.com/doc/connector-j/en/&hellip;
在阅读了这里的答案后,我决定使用bit(1) ,是的,它在空间/时间上更好,但过了一会儿我改变了主意,我再也不会使用它了。当使用准备好的语句、库等(PHP)时,它使我的开发复杂了很多。
从那以后,我总是用tinyint(1) ,似乎已经足够好了。