メインコンテンツへスキップ

VillageSQL is a drop-in replacement for MySQL with extensions.

All examples on this page work on VillageSQL. Install Now →
MySQL にはブール型がありません。BOOL と BOOLEAN は TINYINT(1) の別表記であり、1 バイトに収まる任意の数値を格納します。この列は 0 や 1 と同じように 5 や -1 も保持し、入れた値をそのまま返します。VillageSQL の vsql_boolean 拡張機能は、2 つの値だけを保持し、それ以外をすべて拒否する STRICTBOOL 列型を追加します。

TINYINT(1) が問題になる理由

MySQL が提供する列に、4 行を挿入した例を示します。
何も拒否されませんでした。次に、同じ質問を 2 通りの方法で尋ねます。
3 行が真と評価され、1 行が TRUE と等しくなります。どちらのクエリも正しく見えますが、結果は一致しません。TRUE はリテラルの 1 であり、WHERE active はゼロ以外の任意の値を調べるためです。5 を保持する行は、一方のクエリではアクティブで、もう一方では非アクティブです。スキーマには 5 の書き込みを止めるものが何もなかったため、この不一致は後になって、数字の合わないレポートによって発見されます。

STRICTBOOL 列

この列は、文字列 'true'/'false'、't'/'f'、'yes'/'no'、'on'/'off'、および '1'/'0' を、大文字小文字を問わず受け入れます。文字列として渡してください。数値をそのまま渡すと拒否されます。どの表記で入力しても、返されるのは true または false です。
行 5 は値を指定しなかったため、列のデフォルト値を取りました。受け入れられる表記以外のものは、あるべき場所、つまり挿入時に拒否されます。
値で絞り込むときは、書き込んだときと同じ方法で指定します。

集計

この型には 2 つの集計関数が付属します。boolean_sum は true の行を数え、boolean_avg はその割合を返します。
どちらの集計関数も NULL を無視するため、割合は回答のあった行を分母として計算されます。
3 行のうち、2 件の回答に対して 1 件が yes なので、割合は 0.5 です。NULL を false として数えたい場合は、集計関数がそう解釈することを期待するのではなく、クエリで明示してください。

インデックス

STRICTBOOL 列には、他の列と同じようにインデックスを作成できます。
そのインデックスに価値があるかどうかは、いつもの問題です。2 つの値しか持たない列の選択性が高くなるのは、一方の値が稀な場合だけです。たとえば、ほとんど何もロックされないアカウントテーブルの locked フラグがそうです。

既存の列の移行

TINYINT 列をその場で変換することはできません。サーバーはこれを拒否します。
代わりに、2 つ目の列を追加して値を入れます。
この 2 つのステートメントは、それぞれリテラルを代入しています。値を計算するステートメントは拒否されます。STRICTBOOL 列は文字列式を受け取らないためです。
エラーが求める明示的な変換とは、この型自身の関数です。そのため、1 つのステートメントで実行できます。
移行は、5 や -1 の行が何を意味していたかを決める機会でもあります。上の例では、ゼロ以外はすべて true になりました。これは WHERE active が返していた結果と同じです。システム内のどこかのレポートが代わりに active = 1 を使用していたなら、そのレポートは一致していなかったことになり、今がそれに気づくときです。 新しい列が正しくなったら、古い列を削除して名前を変更します。

トラブルシューティング

関連項目