ブール値の格納に使用するMySQLデータ型


1207

MySQLには「ブール」データ型がないように見えるため、MySQLに真/偽の情報を格納するためにどのデータ型を「悪用」しますか?

特に、PHPスクリプトの読み書きのコンテキストでは。

時間をかけて私はいくつかのアプローチを使用してきました。

  • tinyint、値0/1を含むvarcharフィールド、
  • 文字列「0」/「1」または「true」/「false」を含むvarcharフィールド
  • 最後に、2つのオプション「true」/「false」を含む列挙型フィールド。

上記のどれも最適ではないようです。私はtinyint 0/1バリアントを好む傾向があります。PHPでの自動型変換により、ブール値がかなり単純に得られるからです。

では、どのデータ型を使用しますか?私が見落としたブール値用に設計されたタイプはありますか?何らかのタイプを使用することによる利点/欠点はありますか?


217
この質問に対する古い回答を読んでいる人は、MySQLがバージョン5でビットデータ型を追加したことを理解する必要があります。dev.mysql.com/doc/refman/5.0/en/bit-type.html
smp7d


7
MYSQLの現在のバージョンでは、ブール型が利用可能です-dev.mysql.com/doc/refman/5.5/en/numeric-type-overview.htmlこれを確認してください。その値に応じて、ゼロは偽と見なさ
DEVT

7
bit(1)Excelにインポートするのに少し時間がかかります。tinyint(1)作品に切り替えています。
Cees Timmerman、2014

8
現在、5年後にブール値があります
V-SHY 2014年

回答:


1232

MySQL 5.0.3以降では、を使用できますBIT。マニュアルは言う:

MySQL 5.0.3以降、BITデータ型はビットフィールド値を格納するために使用されます。タイプBIT(M)は、Mビット値の格納を可能にします。Mの範囲は1〜64です。

それ以外の場合、MySQLのマニュアルによれば、現時点でtinyint(1)のエイリアスであるboolおよびbooleanを使用できます。

ブール、ブール:これらのタイプはTINYINT(1)の同義語です。ゼロの値はfalseと見なされます。ゼロ以外の値はtrueと見なされます。

MySQLは次のようにも述べています。

今後のMySQLリリースでは、標準SQLに従って完全なブール型処理を実装する予定です。

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


11
ええ、私はこれのために、またはCHAR(1)のために行き、コンテキストに応じて 'Y' / 'N'または 'T' / 'F'などを格納します。短整数型を使用する利点は、RDBMS-es全体で最大の移植性が得られることです
Roland Bouman

36
少なくともPHPでcharを使用すると、!$booleanさらに処理しないと適切に評価されないため、より多くのコードが生成されます。
軽度のファズ2011年

10
@Pecerier自分でグーグルできなかったものは何もありませんが、わかりました、噛みます。まずはdata0type.hをご覧ください。innodbはネイティブではBITタイプを定義しないことに注意してください。それがあなたが説明する方法でBITフィールドを扱うなら、確かにそこにその存在のいくつかのヒントを見つけるでしょう。次に、mysqlperformanceblog.com / 2008/04/23 /…をお読みください。そして、「マーケットプレイス」にある驚くべきMySQLクライアントがBITフィールドでうまく機能することを遠慮なく教えてください。それらは間違いなくその記事を見逃した人にとって重宝します。
Roland Bouman

9
標準のmysqlコマンドラインから選択すると、クライアントのビットフィールドが完全に空白で表示されます。このため、私はTINYINT(1)を好みます。
ユーザー

8
@MikePurcell聞きたくないのですauto_incrementが、ブール値を表す列になぜ必要なのでしょうか。
Chris Hayes、

248

BOOLおよびのBOOLEAN同義語ですTINYINT(1)。ゼロはfalse、それ以外はすべてですtrue。詳細はこちら


7
(1)その後、使用するストレージサイズについてあなたしている意識がある場合は、値が表示される方法を決定するよりも、より多くの何もしないBIT代わりに
JamesHalsall

35
@JamesHalsall:実は、BIT(1)およびTINYINT(1)ストレージの両方の使用の1つのバイトはなります。MySQL 5.0.3までBITは、実際にはの同義語でしたTINYINT。MySQLの以降のバージョンでは、BITの実装が変更されました。ただし、実装が変更されても、BITデータ型に「ストレージサイズ」のメリットはまだありません(少なくともInnoDBとMyISAMでは、NDBなどの他のストレージエンジンでは、複数のBIT列宣言に対してストレージの最適化が行われる場合があります)。ライブラリは、返されたBITデータ型列を認識しないか、適切に処理しません。AのTINYINT方が効果的です。
spencer7593 2014

5
MySQL 5.0のマニュアルでは、ブール値は1または0のいずれかであると明記されてtrueいます。
ウォルター

7
@ウォルター:それは実際には一種の真実であり、説明はやや欠けています。簡単に言うと、ブール値のコンテキストでは、式はNULL、FALSE、またはTRUEに評価されます。MySQLステートメントでは、ブールコンテキストで評価された式が最初に整数として評価されます(10進値と浮動小数点値は丸められ、MySQLが文字列を整数に変換する通常の風変わりな方法で文字列が変換されます)。NULLは明らかにNULLです(TRUEでもFALSEでもありません)。0の整数値がFALSEとして扱われ、任意の他の整数値(1、2、-7など)TRUEと評価。互換性のために、TINYINTブール値のロジック/処理を模倣しています
spencer7593 '25

4
@ウォルター:これは簡単にテストでき SELECT 'foo' AS bar FROM dual WHERE -7ます。式-7はブールコンテキストで評価され、クエリは行を返します。0、または整数値0に評価される任意の式でテストできますが、行は返されません。WHERE句の式がゼロ以外のnull以外の整数値に評価される場合、式はTRUEです。(私は、小数点および浮動小数点の値は、例えば整数に「丸い」を取得信じるWHERE 1/3に評価WHERE 0。私たちは、同じ結果を得るWHERE 'foo'文字列があるため、'foo'また、整数値0に評価
spencer7593

71

これはエレガントなソリューションであり、ゼロデータバイトを使用するため、非常に感謝しています。

some_flag CHAR(0) DEFAULT NULL

これをtrueに設定するにはsome_flag = ''、を設定し、falseに設定するには、を設定しsome_flag = NULLます。

次に、trueかどうかIS NOT NULLをテストするには、some_flagかどうかを確認し、falseかどうかをテストするには、some_flagかどうかを確認しIS NULLます。

(この方法については、Jon Warren Lentz、Baron Schwartz、およびArjen Lentzによる「高性能MySQL:最適化、バックアップ、レプリケーションなど」で説明されています。)


3
ファンシートリック!これは、MySQL <5で作業していて、おそらくBITよりもフットプリントが軽い場合に役立ちますが、慣例に準拠し、計算オーバーヘッドをわずかに少なくするため(論理値と正確な値)、BITの方が適しています。
zamnuts 2012

59
「高速」である可能性がありますが、新しい開発者が列の意味を理解できないようにデータを難読化します。
リクトホーフェン2013

5
これはBIT(1)と同じ量のバイトを使用します
ITSアラスカ

25
ORMがこれにうまくマッピングできるように頑張ってください。
Craig Labenz 2013

4
私は@Richthofenに同意し、このソリューションの使用を提唱する状況を想像するのは難しいと思います。ただし、これを使用する場合COMMENT、列の定義でNULLfalseを''示し、true を示すをaとして指定すると、将来の理解に役立つ非常に小さな方法になる可能性があります。
eggyal 2015年

34

BOOLEANタイプを使用する場合、これはTINYINT(1)にエイリアスされます。これは、標準化されたSQLを使用し、フィールドに範囲外の値が含まれる可能性があることを気にしない場合に最適です(基本的に、0以外の値はすべて「true」になります)。

ENUM( 'False'、 'True')を使用すると、SQLで文字列を使用できます。MySQLは、フィールドを整数として内部的に格納します。ここで、Enumが指定された順序に基づいて、 'False' = 0および 'True' = 1になります。 。

MySQL 5+では、BIT(1)フィールドを使用して、1ビットの数値型を示すことができます。これは実際にはストレージ内の使用スペースが少ないとは思いませんが、可能な値を1または0に制限できます。

上記のすべてがほぼ同じ量のストレージを使用するため、最も使いやすいものを選択することをお勧めします。


8
ENUMに関するあなたの発言は真実ではありません:CAST(yourenumcol AS UNSIGNED)を試すと、Falseが1、Trueが2であることがわかります。ENUMのもう1つの問題は、 ''(空の文字列)を挿入するのが簡単すぎることです。 )。これを使用することはお勧めしません。
Roland Bouman、

4
私の経験では、PHPコードのBIT(1)フィールドを使用するのは少し面倒でした。TINYINT(1)ははるかに簡単で、より読みやすいコードを生成しました。
M-Peror 2011

1
@ M-Peror-「PHPコードからBIT(1)フィールドを使用するのは少し面倒でした」...しゃれは意図されていません。:)しかし、そうです、私は同意します。TINYINT(1)の方が簡単だったことも覚えています。なぜなのか思い出せません。他の誰かがこれについて考えていますか?BIT(1)は、表面的には0または1に制限できるため、より良いように見えます。一方、TINYINTは数値のように扱われました。
BMiner

2
@BMiner-はは、それは本当に意図されていなかった、それに気づかなかった:)しかし、確かに、私がビットフィールドを何かバイナリとして解釈したことを正しく覚えていれば、tinyintは数値として扱う方が簡単で、そのため、 (ブール)式で使用します。
M-Peror 2011

34

この質問には回答済みですが、$ 0.02を投入すると思いました。私は頻繁に使用するCHAR(0)場合は、'' == true and NULL == false

mysql docsから:

CHAR(0)2つの値のみを取ることができる列が必要な場合も非常に便利ですCHAR(0) NULL。1ビットのみを占有し、値NULL''(空の文字列)のみを取ることができると定義されている列。


16
うーん、これは私としてあなたに迷惑をかけるようなものです。つまり、言語によっては、NULLと ''の違いを見つけるのが簡単ではない場合があります(たとえば、PHP)。
Roland Bouman、

3
スペース(ブール値を表すために使用されるバイト数)の節約という観点からは、このアプローチは明らかに勝者です。これにより、TINYINTより1バイトが節約されます。(一部のコメントが指摘するように)欠点は、一部のクライアントがNULLと空の文字列を区別することが難しい場合があることです。一部のリレーショナルデータベース(Oracleなど)でも、長さゼロの文字列とNULLを区別しません。
spencer7593

3
これはとても賢いです!以前は巧妙なコードを書いていたが、今はペストのようにそれを避けている。私のコードには、正しい動作だけでなく、非常に明確な意図が必要です。私のアドバイス?コード/データベースをサポートする必要がある人を混乱させたい場合にのみ、これを行ってください。たとえば、PHPでは''nullはどちらも偽の値です。
CJデニス

1
@CJDennisリポジトリパターンの背後にあるデータベースレイヤーを抽象化した場合は、このソリューションのあいまいさについて心配する必要はありません。
プログラハンマー


17

多くのブール型フィールドがある場合、ビットはさまざまなバイトオプション(tinyint、enum、char(1))よりも有利です。1ビットフィールドは、依然として1バイトを占めます。2つのビットフィールドが同じバイトに収まります。3、4、5、6、7、8。その後、次のバイトを埋め始めます。結局、節約は非常に小さいので、焦点を当てるべき他の何千もの最適化があります。膨大な量のデータを処理している場合を除いて、これらの数バイトを合計してもそれほど多くはありません。PHPでビットを使用している場合は、入出力する値を型キャストする必要があります。


1
型キャストコメントの+1。プログラミング言語で作業するときにこれに追加するには、一貫性を優先して遅延プログラミング手法を使用しないでください。等しいだけでなく、同じ演算子を使用します。PHPの場合、if($ var == "")は、0、false、null、未定義、および ""に対してtrueになります。すべての値をテストするには、未定義のエラーも回避できるため、if(true === empty($ var))を使用するのが最善の方法です。if(is_int($ var)&& $ var === 0)を使用してデータ型を検証するか、型キャストして、タスクの特定のデータ型(int)$ varにする必要があります。
fyrye 2014年

@トールは、MSSQLに当てはまるのと同じ程度にMySQLにも当てはまりますか?まだ本番環境に入っていない新しいアプリケーションをMSSQLからMySQLに移行しています。私はPHPを使用していませんが、C#をJava 8に変換しています。Javaが強く型付けされた言語であることを考えると、型処理については心配していません... 1バイトから最大8個のフラグに移動するすべてのビットフラグTINYINT(1)が指定された各フラグは1バイト。MySQLのこのトピックに関するドキュメントを知っていますか?
ザックヤンセン、2016

1
@Thorより詳細な調査を行うと、答えがどうあるべきかは明らかです。変更が発生し、この処理に改善が見られました。アプリケーション層/データアクセス層に含まれる言語を理解し、ライブラリがサポートしていることを理解します。私は現在Javaを使用しており、HybernateなどのライブラリとJDBCの使用には現時点でBIT(1)をお勧めします。ここにURLがある[参照テーブル5.2]:dev.mysql.com/doc/connector-j/en/...
ザックJannsen

12

MySQLがビットデータ型を実装するまで、大量のトランザクションなどで処理が本当にスペースや時間を必要とする場合はbit_flags、すべてのブール変数に対して呼び出されるTINYINTフィールドを作成し、SQLで必要なブールビットをマスクしてシフトしますクエリ。

たとえば、左端のビットがブールフィールドを表し、右端の7ビットが何も表していない場合、bit_flagsフィールドは128(バイナリ10000000)になります。右端の7ビットをマスク(非表示)し(ビットごとの演算子を使用&)、8番目のビットを7スペース右にシフトして、末尾を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ビットであるため、1バイトから8つのブール変数が潜在的に存在します。将来の一部のプログラマーは常に次の7ビットを使用するため、マスクする必要あります。ただシフトしないでください。そうしないと、将来、自分や他の人のために地獄を作ります。MySQLでマスキングとシフトを実行するようにしてください。これは、Webスクリプト言語(PHP、ASPなど)で実行するよりもはるかに高速です。また、フィールドのMySQLコメントフィールドにコメントを入力してくださいbit_flags

これらのサイトは、このメソッドを実装するときに役立ちます。


7
これは、将来のプログラマーの意図を難読化する恐ろしい方法のようです。確かに(あなたがその単一のテーブル内のすべての8 boolsを使用していると仮定し!)7つのバイトを保存するために多くの問題のように思える
うん

@はい、難読化はまったくありません!表の各フィールドを説明するドキュメントとMySQLのコメントを(答えが言及しているように)書いてください!提案されているMySQLのマスキング解除戦略は堅固に見え、2つの列だけで最大16の異なるブールフィールド保存する方が、16を使用するよりも優れています。ビット操作を使用して混乱しすぎて、Webスクリプト言語を使用して各ブール値を取得したい場合は、それをとして保存し、コードでマスク解除手順を実行します(8つのフィールドに制限する必要もありません)。 ...VARCHAR
CPHPython 2018年

BITタイプが存在します。参照してくださいdev.mysql.com/doc/refman/8.0/en/bit-type.html
ドルメン

10

私はゼロ、NULL、および '' PHP、MySql、およびPOST値のループを正確に丸めることを試みることにうんざりしているので、「はい」と「いいえ」を使用します。

これは問題なく動作し、明白で簡単ではない特別な処理は必要ありません。


17
これだけのスペースを無駄にしてパフォーマンスを犠牲にしたい場合は、少なくともYおよびNオプションを指定してCHAR(1)を実行することができます。
ILikeTacos 2013

3
ほとんどの現実世界の状況では、「ノー」と単なる情報の欠如の間に実際の違いがあります。たとえば、ユーザーがまだ実際に「いいえ」と言っていない場合は、デフォルトでチェックボックスをオンにすることができます。正確にどれだけのスペースを節約していると思いますか、また、偽とNULLを区別する必要があるたびにどのくらいの処理を行いますか?保存された画像とデジタルビデオの世界では、スペースの節約の1つまたは2つはまったく関係ありませんが、明快さと処理の削減は現実のものです。
Geoff Kendall

8
この答えはうまくいくので間違いではありませんし、人々がそれを信用するほど悪くはありません。ほとんどのプロジェクト(つまり、テーブルサイズ<1mil行)の場合、提供されるソリューション間のパフォーマンスの違いは無視できます。クエリが7ミリ秒から5ミリ秒で返されても不満はありません...公平を期すために、テーブルが10mil行以上に成長している場合、これはおそらく推奨されるソリューションではありません。
ブラッド

1
ENUMデータ型を使用するための私からの+1。私は個人的にこの表記を好む:ENUM( 'y'、 'n')。コンパクト(長さ1バイト)、直観的、すべてのブールフラグのアプリケーションレベルの規則として見栄えが良いです。HTMLフォームフィールドで直接使用できます。たとえばPHPの場合:<select name = "production"> <option value = "y" <?= $ production === 'y'?'selected = "selected"': ''?>>はい</ option> <option value = "n" <?= $ production === 'n'?'selected = "selected"': ''?>>いいえ</ option> </ select>
Vlado

2
笑これは私の目を惹きましたが、@ GeoffKendallは正しいと言わざるを得ません。多くの場合、最適なパフォーマンスの必要はなく、あなたのために仕事をする方法はどれも正しい方法です。
Madmenyo

6

Mysqlでこのリンクブールデータ型を参照する と、アプリケーションの使用法に応じて、0または1のみを格納する場合は、bit(1)の方が適しています。


6
or 値BIT(1)のみを保存できるのは本当です。データ型の最大の問題は、さまざまなクライアントライブラリがデータ型をさまざまに不安定に処理することです。さまざまなSQLツール(SQLyog、TOAD for MySQL、SQL Developer)、データベースモデルを「リバースエンジニアリング」するツール、JDBC、PHP、Perl DBIなどのさまざまなクライアントの動作をチェックアウトし、いくつかのORMフレームワーク( Hibernate、Mybatis、JPA)。使いやすさの点では、ツール/フレームワークの互換性/ネイティブサポートが勝者です。b'0'b'1'BITTINYINT(1)
spencer7593

はい。これは、アプリで検討されているフレームワークに応じて完了します。たとえば、PHPのPhalconフレームワークはビットデータ型を処理しません
Vidz '28

ちなみに、MyBatisはとの両方BITをサポートしていTINYINTます。MyBatisのJdbcTypeクラスを参照してください。mybatis.org/ mybatis
Lucky

1
@Vidz私はあなたにBIT(1)について言及するためにプラス1を与えますが、これを読んでいる開発者にも指摘します-アプリケーション層/データアクセス層になる言語を理解し、ライブラリサポートを知っています。私は現在Javaを使用しており、HybernateなどのライブラリとJDBCの使用には現時点でBIT(1)をお勧めします。ここにURLがある[参照テーブル5.2]:dev.mysql.com/doc/connector-j/en/...
ザックJannsen

6

MySQL(8.0.16)とMariaDB(10.2.1)の両方がCHECK制約を実装したので、今は

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

あなただけの店のことができるようになり01またはNULL、同様に変換できる値として01のようなエラーが発生することなく'1'0x00b'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))

db <> fiddleデモ


enum(0、1)についてはどう
ですか

3
@santiagoarizti ENUM(そうでなければなりませんenum('0', '1')-注意:これらは文字列です)は良い考えではありません。内部での格納方法と非文字列値の処理方法が原因で、問題多すぎます。例えば。0FALSE 保存することはできません。1TRUEなる'0'。と2なる'1'
Paul Spiegel

ベストアンサー... MySQL 8+を使用している方へ
ドルメン

2

ここで答えを読んだ後、私は使用することを決めたbit(1)とはい、それは空間/時間で何とか優れている、しかし私は私の心を変え、私は再びそれを使用することは決してありませんしながら、後に。準備されたステートメント、ライブラリなど(php)を使用すると、開発がかなり複雑になりました。

それ以来、私は常にを使用しtinyint(1)、十分に思えます。


3
それがあなたの開発をどのように複雑にしたかを説明するのを気にしていますか
Chazy Chaz

@ChazyChaz SQL Serverのような他のdbとは異なり、1/0ではなくtrue / falseを期待します。これにより、trueに設定していると思われるが実際には発生しないという奇妙な状況が発生する場合があります。
maembe

0

ブール値の格納には、BOOL、BOOLEANデータ型を使用できます。

これらのタイプはTINYINT(1)の同義語です

ただし、BIT(1)データ型はブール値(true [1]またはfalse [0])を格納する方が理にかなっていますが、TINYINT(1)は、データの出力、クエリなどを行うときに簡単に操作できます。 MySQLと他のデータベース間の相互運用性を実現します。この回答またはスレッドを確認することもできます

MySQLはまた、BOOL、BOOLEANデータ型をTINYINT(1)に変換します。

さらに、ドキュメントを読む

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.