数値型
整数や小数などの数値を格納するデータ型です。格納可能な値の範囲およびデータサイズなどは下記URLを参照してください。
10.2. 数値タイプ
型名 | データ型 | 桁数指定 | オプション |
BIT | ビット | 桁数 | なし |
TINYINT | 整数 | 桁数 | UNSIGNED, ZEROFILL |
SMALLINT | 整数 | 桁数 | UNSIGNED, ZEROFILL |
MEDIUMINT | 整数 | 桁数 | UNSIGNED, ZEROFILL |
INT | 整数 | 桁数 | UNSIGNED, ZEROFILL |
INTEGER | 整数 | 桁数 | UNSIGNED, ZEROFILL |
BIGINT | 整数 | 桁数 | UNSIGNED, ZEROFILL |
REAL | 浮動小数 | 点数 | UNSIGNED, ZEROFILL |
DOUBLE | 浮動小数 | 点数 | UNSIGNED, ZEROFILL |
FLOAT | 浮動小数 | 点数 | UNSIGNED, ZEROFILL |
DECIMAL | 固定小数 | 点数 | UNSIGNED, ZEROFILL |
NUMERIC | 固定小数 | 点数 | UNSIGNED, ZEROFILL |
オプションのUNSIGNEDは、0と正の数だけを格納可能とし、格納可能な正の数の範囲もほぼ倍となります。TINYINTの場合、UNSIGNED無しだと格納可能なのは-127から128ですが、UNSIGNEDを使用すると0から255が格納可能範囲となります。
なお、MySQL独特の挙動として、格納可能範囲外の値が挿入された場合は自動的に値を「丸め」ます。例えばUNSIGNED無しのTINYINTが指定された列に、格納可能範囲外の128を挿入すると127に変更され、-129を挿入すると-128に変更されて格納されます。なお、値が自動的に変更された場合にはWarningが出力されます。¥Wを実行してWarningが自動的に表示される状態でテストした例です。1行目の値-129および7行目の値128が「Out of range value(格納可能範囲外の値)」となっており、自動的にそれぞれ-128と127に変更されて格納されています。
mysql> ¥W Show warnings enabled. mysql> CREATE TABLE r1(c1 TINYINT); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO r1 VALUES(-129), (-128), (-127), (0), (126), (127), (128); Query OK, 7 rows affected, 2 warnings (0.00 sec) Records: 7 Duplicates: 0 Warnings: 2 Warning (Code 1264): Out of range value for column 'c1' at row 1 Warning (Code 1264): Out of range value for column 'c1' at row 7 mysql> SELECT * FROM r1; +------+ | c1 | +------+ | -128 | | -128 | | -127 | | 0 | | 126 | | 127 | | 127 | +------+ 7 rows in set (0.00 sec)
プログラミング言語や他のデータデータベースでも共通するポイントですが、浮動小数点の丸め誤差の問題はMySQLでも注意が必要です。
精度を求められる数値演算には固定小数点型であるDECIMALやNUMERICを利用します。下記の例では2進数では循環小数でしか表現できない値-0.1を格納した場合に、浮動小数点型では誤差のある値が格納されており、それぞれの列の値が異なっていることを確認している例です。
mysql> CREATE TABLE r2(c1 FLOAT(60,10), c2 DECIMAL(60,10)); Query OK, 0 rows affected (0.01 sec) mysql> INSERT INTO r2 VALUES(-0.1, -0.1); Query OK, 1 row affected (0.00 sec) mysql> SELECT c1*10000000000, c2*10000000000 FROM r2; +------------------------+------------------------+ | c1*10000000000 | c2*10000000000 | +------------------------+------------------------+ | -1000000014.9011612000 | -1000000000.0000000000 | +------------------------+------------------------+ 1 row in set (0.00 sec) mysql> SELECT IF(c1 = c2,'TRUE','FALSE') FROM r2; +----------------------------+ | IF(c1 = c2,'TRUE','FALSE') | +----------------------------+ | FALSE | +----------------------------+ 1 rows in set (0.00 sec)