SQLのCHAR型とは?CHARとVARCHARの違い・性能・実装差を徹底解説
はじめに
データベースのスキーマ設計で悩むポイントの一つが文字列型の選択です。特に「CHAR(または CHARACTER)」型は「固定長」の文字列を扱うため、用途によっては非常に有効ですが、誤った理解のまま使うとストレージや検索結果に予期しない影響を与えます。本稿では SQL の CHAR 型について基礎から実装差、性能面、運用上の注意点まで詳しく解説します。
SQL の CHAR 型とは
CHAR(別名 CHARACTER)は「固定長(fixed-length)」の文字列型を表します。宣言時に長さ n を指定し(例:CHAR(10))、その長さまで空白(スペース)で右詰め(パディング)されて保存されるのが基本概念です。SQL 標準でも CHAR は「ブランク(空白)パディングされた」文字列型として定義されています。
CHAR と VARCHAR の基本的な違い
- 格納長
CHAR は常に指定長で格納される(不足分は空白で埋められる)。VARCHAR(可変長)は実際に格納する文字数分だけ記憶される(内部に長さ情報を持つ)。
- 用途
固定長のコードやステータス(国コード、性別コードなど)に適する。可変長の文や可変長フィールドには VARCHAR が適する。
- パフォーマンス
ページレイアウトや行の固定化によりアクセスが有利になるケースがある一方、無駄な空白でストレージ効率が下がる場合もある。
格納方式とパディング(空白詰め)の挙動
CHAR 型の基本動作は「右側をスペースで埋めて定長にする」ことです。例えば CHAR(10) カラムに 'abc' を挿入した場合、内部的には 'abc ' のように 7 個のスペースで埋められます。ただし、実際の取り出しや比較の挙動は実装によって差があります(後述)。
比較・検索時のトレーリングスペース(末尾空白)の扱い
SQL 標準では多くの場合、末尾の空白は比較時に無視されます。つまり 'a' と 'a ' は等しいとみなされます。各データベース製品もこれに準拠することが多いですが、表示や取り出し時に末尾スペースが残るかどうか、比較時の厳密さなどに違いがあります。実際の運用ではトリム(TRIM)や LIKE 比較の振る舞いにも注意が必要です。
文字コード・バイト数と長さの取り扱い
- 長さの単位
CHAR(n) の n は通常「文字数(characters)」で指定しますが、一部設定や古い実装ではバイト数として扱われることがあります(特にマルチバイト文字セットを使う環境で注意)。
- 実際の占有バイト数
使用される文字セット(例:UTF-8、UTF-8MB4、UTF-16、Shift_JIS など)により 1 文字あたりのバイト数が異なります。CHAR(10) を UTF-8 のマルチバイト文字で使うと、格納時に n × 最大バイト数分を確保する実装もあるため、ストレージ設計時に留意が必要です。
- NCHAR / NVARCHAR
Unicode を直接扱う場合、SQL Server の NCHAR/NVARCHAR、Oracle の NCHAR など「N プレフィックス」を持つ型があり、これは内部で Unicode(たとえば UTF-16)を使うことを想定しています。N 型は文字数単位での指定やバイト数に注意が必要です。
主要データベース製品ごとの差異(実務上の注意)
以下は代表的な RDBMS のドキュメントに基づく実装上の差異の要点です。
- MySQL
CHAR は固定長で右パディングされます。MySQL のドキュメントでは、CHAR は固定長で格納され、取り出すときに末尾の空白が取り除かれることが記載されています(比較時もトレーリングスペースは無視されます)。なお、CHAR(n) の「n」は文字数で指定され、utf8mb4 等の設定では内部的なバイト占有に注意が必要です。
- PostgreSQL
character(n)(または CHAR(n))は指定長にスペースでパディングして格納されます。length の単位は文字です。PostgreSQL は SQL 標準に近い挙動を取り、比較時の末尾空白の扱いなどは標準に準拠しています。注意点として、text や varchar を使うことが推奨される場面が多い点が挙げられます。
- Microsoft SQL Server
char(n) は固定長で、内部的にバイト単位(エンコーディングにより異なる)で格納します。比較時はトレーリングブランクが無視されるなど標準挙動に沿います。Unicode を扱う場合は nchar を使用します(これは UTF-16 ベース)。
- Oracle
CHAR は固定長でブランクパディングされます。Oracle はデフォルトでバイト長での最大長指定が行われやすかったり、NLS パラメータで char/byte semantics を切り替えたりできる点で注意が必要です。最近の Oracle では CHAR の代わりに VARCHAR2(可変長)を推奨することが多いです。
なぜ CHAR を使うのか — 利点と適用例
- 定型のコードや固定長キー
国コード(JP, US 等)、状態コード、固定長の識別子(10 桁固定など)は CHAR の天然の利用先です。固定長なのでデータの整合性が保ちやすく、アプリ側でもバリデーションが簡単になります。
- パフォーマンス上の利点
行長が固定化されるとページ内のオフセット計算が簡略化され、特定のワークロードでは読み取り性能やキャッシュの一次効果が向上する場合があります。ただしこれはワークロードとストレージレイアウト次第です。
- アラインメントやハードウェア最適化
固定長は CPU キャッシュや I/O の観点で有利になることがありますが、これは一般論であり実際の効果は DBMS に依存します。
欠点・注意点
- 無駄なストレージ消費
可変長データに対して CHAR を使うとスペースで埋まる分だけ容量が増えるため、ディスクやメモリの無駄遣いになります。
- 末尾空白の取り扱いでバグを生む可能性
アプリ側でトリムの有無を想定していないと、比較や表示で不整合が起きます(例:ユーザー表示で末尾空白が見える/見えないの差)。
- マルチバイト文字との相性
CHAR(n) をバイト単位で理解している設定だと、マルチバイト文字で指定長を超えたり足りなくなったりする問題が生じます。必ず DBMS の「長さが文字ベースかバイトベースか」を確認してください。
インデックスや検索への影響
固定長のカラムはインデックスキーとして一定の効果を持つことが多いですが、キー長が長すぎるとインデックスサイズが大きくなりパフォーマンスが落ちます。CHAR の場合、無駄なパディングがインデックスにも反映される実装があるため、実際のインデックスサイズや AFP(セレクティビティ)を考慮して選択してください。
実務的なベストプラクティス
- 固定長に本当に意味があるかを検討する
見た目が固定長でも、実務要件として本当に固定長である必要があるか(例:外部システムとの連携、ファイルフォーマット)を確認する。
- 国際化を考慮する
Unicode を使う場合は NCHAR/NVARCHAR の採用や、文字数指定とバイト数指定の違いに注意する。MySQL なら CHAR(n) は文字数単位だが、内部バイト占有を把握する。
- 表示・比較の一貫性を担保する
アプリ側で INSERT/UPDATE 前に TRIM を行うか、DB 側で比較時に TRIM を使うなど、末尾スペースの扱いを明確に設計書に残す。
- テストで実装差を検証する
開発環境と本番環境の DBMS が異なる場合、CHAR の取り扱い(格納、検索、取り出し時のスペース)を必ずテストする。
よくある誤解とQ&A
- 「CHAR は常に高速」— 誤り
固定長が有利になるケースはあるが、無駄なストレージで I/O が増えると逆に遅くなることがある。
- 「末尾スペースは必ず保存されない」— 誤解
保存時にパディングされる実装が一般的だが、取り出し時に DBMS が自動でトリムする場合や残す場合があるため、個別の実装を確認する必要がある。
- 「CHAR = バイト数で指定」— 条件付き
現代の主要 DBMS は多くが文字数で指定するが、NLS や設定によりバイト単位扱いになることがあるため注意。
具体例(SQL)
以下はイメージのための簡単な挙動例です(DBMS によって表示や取り扱いは異なります)。
CREATE TABLE t1 (c CHAR(5));
INSERT INTO t1 VALUES ('ab'); -- 内部は 'ab ' として格納され得る
SELECT LENGTH(c), c FROM t1; -- LENGTH の返し方(バイト/文字)や表示は実装差あり
まとめ(結論)
CHAR 型は「固定長」を前提にした有用なデータ型ですが、文字コード、比較時の末尾空白、ストレージ占有など実装依存の挙動を正しく理解して使うことが重要です。固定長が要求される外部仕様や固定長コードの管理には有効ですが、可変長の文字列には一般的に VARCHAR 系を使うのが安全です。実務では利用する DBMS の公式ドキュメントを参照し、開発・本番で挙動の差がないかを検証してください。


