MySQL 5.6 リファレンスマニュアル  /  ...  /  CHAR および VARCHAR 型

11.4.1 CHAR および VARCHAR 型

CHAR 型と VARCHAR 型は似ていますが、格納および取得方法が異なります。また、最大長と、末尾のスペースが保持されるかどうかという点でも異なります。

CHAR 型と VARCHAR 型には、格納する最大文字数を表す長さが宣言されています。たとえば、CHAR(30) には最大 30 文字を格納できます。

CHAR カラムの長さは、テーブルを作成したときに宣言した長さに修正されます。この長さには、0 から 255 までの任意の値を指定できます。CHAR 値は格納されると、指定された長さになるように右側がスペースで埋められます。PAD_CHAR_TO_FULL_LENGTH SQL モードが有効になっていないかぎり、CHAR 値が取り出されるときに、末尾のスペースが削除されます。

VARCHAR カラム内の値は可変長の文字列です。長さは 0 から 65,535 までの値で指定できます。VARCHAR カラムの有効な最大長は、最大行サイズ (65,535 バイト、すべてのカラムで共有される) と使用される文字セットによって決まります。セクションD.10.4「テーブルカラム数と行サイズの制限」を参照してください。

CHAR とは対照的に、VARCHAR 値は、1 バイトまたは 2 バイト長のプリフィクスの付いたデータとして格納されます。長さプリフィクスは、値に含まれるバイト数を示します。255 バイト以下の値を格納するカラムでは 1 バイト長のプリフィクスを使用し、255 バイトよりも大きい値を格納するカラムでは 2 バイト長のプリフィクスを使用します。

厳密な SQL モードが有効でない場合に、CHAR または VARCHAR カラムにその最大長を超える値を割り当てると、その値はカラムの最大長に合わせて切り捨てられ、警告メッセージが表示されます。スペース以外の文字の切り捨てに関しては、厳密な SQL モードを使用することで、警告ではなくエラーを発生させて、その値の挿入を抑制できます。セクション5.1.7「サーバー SQL モード」を参照してください。

VARCHAR カラムの場合、使用している SQL モードに関係なく、カラム長を超える末尾のスペースは挿入前に切り捨てられ、警告メッセージが表示されます。CHAR カラムの場合、SQL モードに関係なく、超過した末尾のスペースは通知なしに挿入される値から切り捨てられます。

VARCHAR 値は格納されるときに埋められません。標準 SQL に従い、値を格納し取り出すときに末尾のスペースは保持されます。

次の表は、CHAR(4) カラムと VARCHAR(4) カラムにさまざまな文字列値を格納した結果を表示して、CHARVARCHAR の違いを示しています (カラムには latin1 などのシングルバイト文字セットを使用するものとします)。

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 内のすべての CHARVARCHAR、および TEXT 値が、末尾のスペースに関係なく比較されることを意味します。このコンテキストでの比較には、末尾のスペースが意味を持つ LIKE パターンマッチング演算子は含まれません。例:

mysql> CREATE TABLE names (myname CHAR(10));
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO names VALUES ('Monty');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT myname = 'Monty', myname = 'Monty  ' FROM names;
+------------------+--------------------+
| myname = 'Monty' | myname = 'Monty  ' |
+------------------+--------------------+
|                1 |                  1 |
+------------------+--------------------+
1 row in set (0.00 sec)

mysql> SELECT myname LIKE 'Monty', myname LIKE 'Monty  ' FROM names;
+---------------------+-----------------------+
| myname LIKE 'Monty' | myname LIKE 'Monty  ' |
+---------------------+-----------------------+
|                   1 |                     0 |
+---------------------+-----------------------+
1 row in set (0.00 sec)

これは MySQL のすべてのバージョンに当てはまり、サーバーの SQL モードの影響は受けません。

注記

MySQL の文字セットおよび照合順序の詳細は、セクション10.1「文字セットのサポート」を参照してください。ストレージ要件の追加情報については、セクション11.7「データ型のストレージ要件」を参照してください。

末尾の埋め込み文字が取り除かれたり、比較で無視されたりする場合では、一意の値を必要とするインデックスがカラムに含まれていれば、末尾の埋め込み文字の個数だけが異なるカラム値への挿入は、重複キーエラーになります。たとえば、テーブルに 'a' が含まれている場合、'a ' を格納しようとすると、重複キーエラーが発生します。


User Comments
  Posted by Julian Morrison on July 14, 2006
Note that using CHAR will only speed up your access if the whole record is fixed size. That is, if you use any variable size object, you might as well make all of them variable size. You gain no speed by using a CHAR in a table that also contains a VARCHAR.
  Posted by Kirby Wirby on April 9, 2007
Keep in mind that defining a column as VARCHAR will only save space if the data in a particular column is variable in length. I've worked on plenty of data sets where data in a given column is fixed in size -- e.g., code values or indicator/flag fields. In these cases, it's more space-efficient to use CHAR. Consider the case of an indicator field where the value is either 'Y' or 'N'. If defined as a CHAR, the field requires only one byte. However, if defined as a VARCHAR, the field requires two bytes. I worked on a multi-terabyte project at Bank of America where the DBAs actually went to the trouble to rebuild some tables that contained numerous flag or indicator fields because the fields were originally defined as VARCHAR(1) instead of CHAR(1).
  Posted by San jeet on May 7, 2007
"Before MySQL 5.0.3, trailing spaces are removed from values when they are stored into a VARCHAR column; this means that the spaces also are absent from retrieved values."

Post mySQL 5.0.3, if you are stuck with trailing whitespace in a VARCHAR column, you can remove it through a two step process:

1) alter column type to char
2) alter column type back to varchar.

  Posted by Philip Gollucci on September 15, 2008
in regards to the above (stripping trailing whitespace)

update table t
set c = rtrim(c);

or you can use trim(), or ltrim()

  Posted by Michał Sierzchuła on July 21, 2009
When I try to save IP of visitor to VARCHAR (12) I noticed that, saving IP with dots and ending 0, like 87.10.231.110 is writed like FLOAT without 0 on end of number, 87.10.231.11

It takes me 8h to resolve this simple problem ;) and save value in other type :)
  Posted by Andrew Deighton on July 22, 2009
In reply to Michał Sierzchuła above:
This is because you have 13 characters you are trying to put into a varchar(12) field, not because of the trailing 0. You need 15 characters to store an IP address, 12 digits and 3 dots.
  Posted by Alex Palmer on July 23, 2009
Yes, you do need a maximum of 15 characters to store an IP address as a string.
Alternatively you can save a lot of space by storing your IPs as 4-byte unsigned integers. Then use ip2long(), long2ip() string conversions in your application layer.
  Posted by Matt Simerson on September 11, 2009
The best way to store an IP addresses in a RDBMS is by converting it into an INT.
MySQL is especially nice because it will do the conversion between INT and
dotted quad for you. See the INET_ATON and INET_NTOA functions. You'll find
queries like this all over in my code:
SELECT INET_NTOA(ip) from ips;
or
INSERT INTO ips SET ip=INET_ATON('1.1.1.1');
  Posted by Bill Meier on June 18, 2012
Note that if you use the built in IP functions the column must be declared as UNSIGNED INT so IP addresses 128.0.0.0 and up are handled correctly.
Sign Up Login You must be logged in to post a comment.