{"id":2181,"date":"2010-06-03T07:24:11","date_gmt":"2010-06-03T05:24:11","guid":{"rendered":"http:\/\/code.openark.org\/blog\/?p=2181"},"modified":"2010-06-03T07:24:11","modified_gmt":"2010-06-03T05:24:11","slug":"choosing-mysql-boolean-data-types","status":"publish","type":"post","link":"https:\/\/code.openark.org\/blog\/mysql\/choosing-mysql-boolean-data-types","title":{"rendered":"Choosing MySQL boolean data types"},"content":{"rendered":"<p>How do you implement <strong>True<\/strong>\/<strong>False<\/strong> columns?<\/p>\n<p>There are many ways to do it, each with its own pros and cons.<\/p>\n<h4>ENUM<\/h4>\n<p>Create you column as <strong>ENUM(&#8216;F&#8217;, &#8216;T&#8217;)<\/strong>, or <strong>ENUM(&#8216;N&#8217;,&#8217;Y&#8217;)<\/strong> or <strong>ENUM(&#8216;0&#8217;, &#8216;1&#8217;)<\/strong>.<\/p>\n<p>This is the method used in the <strong>mysql<\/strong> tables (e.g. <strong>mysql.user<\/strong> privileges table). It&#8217;s very simple and intuitive. It truly restricts the values to just two options, which serves well. It&#8217;s compact (just one byte).<\/p>\n<p>A couple disadvantages to this method:<\/p>\n<ol>\n<li>Enums are represented by numerical values (which is good) and start with <strong>1<\/strong> instead of <strong>0<\/strong>. This means <strong>&#8216;F&#8217;<\/strong> is <strong>1<\/strong>, and <strong>&#8216;T&#8217;<\/strong> is <strong>2<\/strong>, and they both translate to <strong>True<\/strong> when directly used in a booleanic expression (e.g. <strong>IF(val, &#8216;True&#8217;, &#8216;False&#8217;)<\/strong> always yields <strong>&#8216;True&#8217;<\/strong>)<\/li>\n<li>There&#8217;s no real convention. Is it <strong>&#8216;Y&#8217;\/&#8217;N&#8217;<\/strong>? <strong>&#8216;T&#8217;\/&#8217;F&#8217;<\/strong>? <strong>&#8216;P&#8217;\/&#8217;N&#8217;<\/strong>? <strong>&#8216;1&#8217;\/&#8217;0&#8242;<\/strong>?<\/li>\n<\/ol>\n<h4>CHAR(1)<\/h4>\n<p>Simple again. Proposed values are, as before, <strong>&#8216;F&#8217;<\/strong>, <strong>&#8216;T&#8217;<\/strong> etc. This time there&#8217;s no way to limit the range of values. You cannot (in MySQL, unless using triggers) prevent an &#8216;X&#8217;.<\/p>\n<p>Watch out for the charset! If it&#8217;s <strong>utf8<\/strong> you pay with 3 bytes instead of just 1. And, again, <strong>&#8216;T&#8217;<\/strong>, <strong>&#8216;F&#8217;<\/strong>, <strong>&#8216;Y&#8217;<\/strong>, <strong>&#8216;N&#8217;<\/strong> values all evaluate as <strong>True<\/strong>. It is possible to use the zero-valued character, but it defeats the purpose of using <strong>CHAR<\/strong>.<!--more--><\/p>\n<h4>CHAR(0)<\/h4>\n<p>Many are unaware that it&#8217;s even valid to make this definition. What does it mean? Take a look at the following table:<\/p>\n<blockquote>\n<pre>CREATE TABLE `t1` (\r\n `bval` char(0) DEFAULT NULL\r\n);\r\nmysql&gt; INSERT INTO t1 VALUES ('');\r\nmysql&gt; INSERT INTO t1 VALUES ('');\r\nmysql&gt; INSERT INTO t1 VALUES (NULL);\r\n\r\nmysql&gt; SELECT * FROM t1;\r\n+------+\r\n| bval |\r\n+------+\r\n|\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n|\u00a0\u00a0\u00a0\u00a0\u00a0 |\r\n| NULL |\r\n+------+\r\n<\/pre>\n<\/blockquote>\n<p>NULLable columns cause for an additional storage per row. There&#8217;s one bit per NULLable column which notes down whether the column&#8217;s value is NULL or not. If you only have one NULLable column, you must pay for this bit with 1 byte. If you have two NULLable columns, you still only pay with 1 byte.<\/p>\n<p>Furthermore:<\/p>\n<blockquote>\n<pre>mysql&gt; SELECT bval IS NOT NULL FROM t1;\r\n+------------------+\r\n| bval IS NOT NULL |\r\n+------------------+\r\n|\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 1 |\r\n|\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 1 |\r\n|\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 0 |\r\n+------------------+\r\n<\/pre>\n<\/blockquote>\n<p>So this plays somewhat nicely into booleanic expressions.<\/p>\n<p>However, this method is unintuitive and confusing. I personally don&#8217;t use it.<\/p>\n<h4>TINYINT<\/h4>\n<p>With integer values, we can get down to <strong>0<\/strong> and <strong>1<\/strong>. With <strong>TINYINT<\/strong>, we only pay with 1 byte of storage. As with <strong>CHAR(1)<\/strong>, we cannot prevent anyone from INSERTing other values. But that doesn&#8217;t really matter, if we&#8217;re willing to accept that 0 evaluates as <strong>False<\/strong>, and <em>all other values<\/em> as <strong>True<\/strong>. In this case, boolean expressions work very well with your column values.<\/p>\n<h4>BOOL\/BOOLEAN<\/h4>\n<p>These are just synonyms to <strong>TINYINT<\/strong>. I like to define my boolean values as such. Alas, when issuing a <strong>SHOW CREATE TABLE<\/strong> the definition is just a normal <strong>TINYINT<\/strong>. Still, it is clearer to look at if you&#8217;re storing your table schema under your version control.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>How do you implement True\/False columns? There are many ways to do it, each with its own pros and cons. ENUM Create you column as ENUM(&#8216;F&#8217;, &#8216;T&#8217;), or ENUM(&#8216;N&#8217;,&#8217;Y&#8217;) or ENUM(&#8216;0&#8217;, &#8216;1&#8217;). This is the method used in the mysql tables (e.g. mysql.user privileges table). It&#8217;s very simple and intuitive. It truly restricts the values [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":false,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"enabled":false},"version":2}},"categories":[5],"tags":[18,21],"class_list":["post-2181","post","type-post","status-publish","format-standard","hentry","category-mysql","tag-data-types","tag-sql"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p2bZZp-zb","_links":{"self":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/2181","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/comments?post=2181"}],"version-history":[{"count":28,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/2181\/revisions"}],"predecessor-version":[{"id":2528,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/posts\/2181\/revisions\/2528"}],"wp:attachment":[{"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/media?parent=2181"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/categories?post=2181"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/code.openark.org\/blog\/wp-json\/wp\/v2\/tags?post=2181"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}