CHAR
と VARCHAR
タイプは似ていますが、格納、検索される方法が異なります。また、最大長さと、末尾のスペースが保持されるかどうかという点でも異なります。格納と検索の最中にレターケースの変換は行われません。
CHAR
と VARCHAR
タイプには、格納したい最大文字数を表す長さが宣言されています。例えば、CHAR(30)
は最大30文字まで持つ事ができます。
CHAR
カラムの長さは、テーブルを作成した時に宣言した長さに修正されます。長さは0から255までのどの長さにもなり得ます。CHAR
値が格納された時、指定された長さになるよう、右側が詰められます。CHAR
値が検索された時、後続スペースは削除されます。
VARCHAR
カラム内の値は可変長の文字列です。長さは0から65,535の値で指定できます。(VARCHAR
の最大有効長さは、最大行サイズと利用される文字サイズによって決まります。最大カラム長さは65,532バイトの行サイズによります。)
CHAR
とは対照的に、VARCHAR
値は必要な文字数と、長さを記録する為の1バイト(255よりも長いカラムは2バイト)だけを利用して格納できます。
VARCHAR
値は格納される時に詰められません。スタンダードSQLに適合して、値が格納、検索される時に後続スペースは保持されます。
CHAR
や VARCHAR
カラムに、その最大長を超える値を指定すると、その値は切り捨てられます。切り捨てられた文字がスペースで無い場合には警告メッセージが表示されます。スペース以外の文字の切捨てに関しては、ストリクトSQLモードを利用する事で警告ではなくエラーを表示させ、その値の挿入を食い止める事ができます。項4.2.6. 「SQL モード」を参照してください。
次のテーブルは、CHAR(4)
と
VARCHAR(4)
カラムに様々な文字列値を格納した結果を表示する事で、CHAR
と VARCHAR
の違いを表しています。
値 | CHAR(4) |
要求ストレージ | VARCHAR(4) |
要求ストレージ |
'' |
' ' |
4バイト | '' |
1バイト |
'ab' |
'ab ' |
4 バイト | 'ab' |
3バイト |
'abcd' |
'abcd' |
4 バイト | 'abcd' |
5バイト |
'abcdefgh' |
'abcd' |
4バイト | 'abcd' |
5バイト |
テーブルの最終行に格納されたと表示されている値は、ストリクトモードを利用していない時だけ 適応される事を覚えておいて下さい。もしMySQLがストリクトモードで起動していると、カラム長を超える値は 格納されず エラーになります。
もし規定の値が CHAR(4)
と
VARCHAR(4)
カラムに格納されると、CHAR
カラムが検索される時に後続スペースが削除されるので、カラムから検索された値は必ずしも同じとは限りません。次の例はこれらの点を例示しています。
mysql>CREATE TABLE vc (v VARCHAR(4), c CHAR(4));
Query OK, 0 rows affected (0.01 sec) mysql>INSERT INTO vc VALUES ('ab ', 'ab ');
Query OK, 1 row affected (0.00 sec) mysql>SELECT CONCAT('(', v, ')'), CONCAT('(', c, ')') FROM vc;
+---------------------+---------------------+ | CONCAT('(', v, ')') | CONCAT('(', c, ')') | +---------------------+---------------------+ | (ab ) | (ab) | +---------------------+---------------------+ 1 row in set (0.06 sec)
CHAR
と VARCHAR
カラムの中の値は、そのカラムに指定された
文字セットの照合に従って格納、比較されます。
全てのMySQL照合は PADSPACE
タイプの物だと覚えておいてください。これは、MySQLの中の全ての
CHAR
と VARCHAR
値が後続スペースを無視して比較されるという事を意味します。例:
mysql>CREATE TABLE names (myname CHAR(10), yourname VARCHAR(10));
Query OK, 0 rows affected (0.09 sec) mysql>INSERT INTO names VALUES ('Monty ', 'Monty ');
Query OK, 1 row affected (0.00 sec) mysql>SELECT myname = 'Monty ', yourname = 'Monty ' FROM names;
+--------------------+----------------------+ | myname = 'Monty ' | yourname = 'Monty ' | +--------------------+----------------------+ | 1 | 1 | +--------------------+----------------------+ 1 row in set (0.00 sec)
これは全てのMySQLバージョンに当てはまり、サーバのSQLモードに影響されないという事を覚えておいて下さい。
後続文字が剥ぎ取られたり、比較がそれらを無視する場合は、もしカラムが固有の値を要求するインデックスを持っていたら、後続文字数だけが異なるカラム値への挿入は重複キーエラーになります。例えば、もしテーブルが
'a'
を含んでいると、'a '
を格納しようとした時重複キーエラーになります。