恥ずかしながら「整数型の表示幅消えてるやん!」ということに今更気づいたので、簡単に調べてまとめておきました。
表示幅とは
INT(11)
のような表記で見かける「(11)」の部分、これが「表示幅」と呼ばれるものです。これと、例えばVARCHAR(255)
のような文字列型の定義とは異なり、実際のデータが格納される桁数を指定しているわけではありません。
では、INT(4)
と指定したら、すべての値が4桁で表示されるのかというとそうではなく、表示幅が反映されるのは、ZEROFILL
(ゼロ埋め)の設定がされている場合だけです。
ZEROFILL
が有効な場合は指定された桁数未満の数字は0で埋められますが、ZEROFILL
の指定がない場合はほとんど意味がありません。
この紛らわしい見た目から、表示幅がデータ長の制約と勘違いしたことがある人も多いはずです。
この表示幅は、MySQL8.0.17以降では非推奨となり、8.0.19以降では一部の例外を除いて指定が無視されるようになりました。この変更は、INT
だけでなく、BIGINT
やSMALLINT
など他の整数型にも共通しています。
実際の挙動
MySQL8.0.16以前
まず、8.0.16以前のバージョンでの表示幅の挙動を確認してみます。
mysql> CREATE TABLE `sample` (
-> `default_int_column` int(11) NOT NULL AUTO_INCREMENT,
-> `zerofill_int_column` int(4) zerofill NOT NULL,
-> `not_zerofill_int_column` int(4) NOT NULL,
-> PRIMARY KEY (`default_int_column`)
-> );
Query OK, 0 rows affected (0.11 sec)
mysql> DESC sample;
+-------------------------+--------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------------+--------------------------+------+-----+---------+----------------+
| default_int_column | int(11) | NO | PRI | NULL | auto_increment |
| zerofill_int_column | int(4) unsigned zerofill | NO | | NULL | |
| not_zerofill_int_column | int(4) | NO | | NULL | |
+-------------------------+--------------------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)
mysql> INSERT INTO `sample` VALUES (12, 12, 12);
Query OK, 1 row affected (0.04 sec)
mysql> INSERT INTO `sample` VALUES (1234567, 1234567, 1234567);
Query OK, 1 row affected (0.08 sec)
mysql> select * FROM `sample`;
+--------------------+---------------------+-------------------------+
| default_int_column | zerofill_int_column | not_zerofill_int_column |
+--------------------+---------------------+-------------------------+
| 12 | 0012 | 12 |
| 1234567 | 1234567 | 1234567 |
+--------------------+---------------------+-------------------------+
2 rows in set (0.01 sec)
このように、ZEROFILL
が有効な場合のみ、指定された表示桁数に達するまで0埋めされることがわかります。一方で、INT(4)という表示幅の指定があっても、5桁以上の数字をそのまま保存でき、表示幅によって桁数が強制的に制限されるわけではありません。
MySQL8.0.17
次に表示幅の指定が非推奨となった8.0.17の挙動を見ていきます。
mysql> CREATE TABLE `sample` (
-> `default_int_column` int(11) NOT NULL AUTO_INCREMENT,
-> `zerofill_int_column` int(4) zerofill NOT NULL,
-> `not_zerofill_int_column` int(4) NOT NULL,
-> PRIMARY KEY (`default_int_column`)
-> );
Query OK, 0 rows affected, 4 warnings (0.02 sec)
mysql> SHOW WARNINGS;
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
| Warning | 1681 | Integer display width is deprecated and will be removed in a future release. |
| Warning | 1681 | The ZEROFILL attribute is deprecated and will be removed in a future release. Use the LPAD function to zero-pad numbers, or store the formatted numbers in a CHAR column. |
| Warning | 1681 | Integer display width is deprecated and will be removed in a future release. |
| Warning | 1681 | Integer display width is deprecated and will be removed in a future release. |
+---------+------+---------------------------------------------------------------------------------------------------------------------------------------------------------------------------+
4 rows in set (0.00 sec)
mysql> DESC sample;
+-------------------------+--------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------------+--------------------------+------+-----+---------+----------------+
| default_int_column | int(11) | NO | PRI | NULL | auto_increment |
| zerofill_int_column | int(4) unsigned zerofill | NO | | NULL | |
| not_zerofill_int_column | int(4) | NO | | NULL | |
+-------------------------+--------------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
表示幅とZEROFILL
が非推奨であるという警告が出ていますが、表示幅の指定自体はまだ有効です。
MySQL8.0.19以降
最後に、MySQL 8.0.19以降での挙動を確認します。
mysql> CREATE TABLE `sample` (
-> `default_int_column` int(11) NOT NULL AUTO_INCREMENT,
-> `zerofill_int_column` int(4) zerofill NOT NULL,
-> `not_zerofill_int_column` int(4) NOT NULL,
-> PRIMARY KEY (`default_int_column`)
-> );
Query OK, 0 rows affected, 4 warnings (0.01 sec)
mysql> DESC sample;
+-------------------------+--------------------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------------+--------------------------+------+-----+---------+----------------+
| default_int_column | int | NO | PRI | NULL | auto_increment |
| zerofill_int_column | int(4) unsigned zerofill | NO | | NULL | |
| not_zerofill_int_column | int | NO | | NULL | |
+-------------------------+--------------------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
MySQL8.0.19以降はZEROFILL
属性が付いている列とTINYINT(1)
を除いて表示幅の指定が完全に無視されるようになっています。
MySQL 8.0.19リリースノート
まとめ
整数型の表示幅は、MySQL8.0.17から非推奨となり、8.0.19以降では一部を除いて無視されるようになりました。ZEROFILL
も非推奨になっているので、データの見た目を制御したい場合は、LPAD()
関数などで対応しましょう。