◀ 5.

MySQL データ型一覧|数値・文字列・日付型の範囲と選び方

▶
この記事の要点
  • MySQL / MariaDB のデータ型は大きく「数値」「文字列」「日付・時刻」「バイナリ」「JSON など」に分かれる
  • 整数は TINYINT / SMALLINT / MEDIUMINT / INT / BIGINT。UNSIGNED を付けると負の数を捨てて上限が約 2 倍になる
  • 金額など誤差が許されない値は DECIMAL。FLOAT / DOUBLE は近似値なので比較や合計で誤差が出る
  • 文字列は CHAR(固定長)/ VARCHAR(可変長)/ TEXT 系(長文)。長さは「バイト」ではなく「文字数」で指定する
  • 日時は DATETIME と TIMESTAMP の違い(タイムゾーン変換・2038 年問題)を理解して選ぶ
  • INT(10) の (10) は桁数の上限ではない。MySQL 8.0.17 以降は非推奨

MySQL / MariaDB のデータ型とは

テーブルを作るとき、各カラムには「どんな種類の値を、どれくらいの大きさまで入れるか」を表すデータ型を指定します。データ型を適切に選ぶと、ストレージの節約、検索の高速化、不正な値の混入防止につながります。逆に、何でも VARCHAR(255) にしたり、金額を FLOAT にしたりすると、後から並び順がおかしい・合計が合わないといった不具合の原因になります。

MySQL と MariaDB は共通の祖先を持つため、基本的なデータ型はほぼ同じです。以下は 2026 年時点の MySQL 8.x / MariaDB 10.x〜11.x を前提にしています。

主要なデータ型一覧(早見表)

分類データ型内容・範囲主な用途
整数TINYINT1 バイト。-128〜127(UNSIGNED で 0〜255)フラグ、小さな区分値
整数SMALLINT2 バイト。-32768〜32767(UNSIGNED で 0〜65535)件数の少ないマスタの ID
整数MEDIUMINT3 バイト。-8388608〜8388607中規模の数値
整数INT4 バイト。約 -21 億〜21 億(UNSIGNED で 0〜約 42 億)一般的な ID、数量
整数BIGINT8 バイト。約 ±922 京大量データの ID、ミリ秒の時刻値
固定小数点DECIMAL(M,D)全体 M 桁(最大 65)、小数部 D 桁(最大 30)を正確に保持金額、税率
浮動小数点FLOAT / DOUBLE4 バイト / 8 バイトの近似値測定値、座標、統計
文字列CHAR(M)固定長。最大 255 文字。短い値は末尾を空白で埋めて保存都道府県コードなど長さが一定の値
文字列VARCHAR(M)可変長。最大 65,535 バイト(行全体の上限と共有)名前、メールアドレス、タイトル
文字列TEXT 系TINYTEXT(255 バイト)/ TEXT(約 64KB)/ MEDIUMTEXT(約 16MB)/ LONGTEXT(約 4GB)本文、ログ
日付DATEYYYY-MM-DD。1000-01-01〜9999-12-31誕生日、締め日
時刻TIMEHH:MM:SS。-838:59:59〜838:59:59時刻、経過時間
日時DATETIMEYYYY-MM-DD HH:MM:SS。1000 年〜9999 年予約日時、イベント日時
日時TIMESTAMPUTC で保存。1970-01-01 00:00:01〜2038-01-19 03:14:07(UTC)作成日時、更新日時
年YEARYYYY。1901〜2155年度
列挙ENUM / SET定義した候補から 1 つ(ENUM)または複数(SET)状態、区分
バイナリBINARY / VARBINARY / BLOB 系文字コードを持たないバイト列ハッシュ値、UUID のバイナリ表現
JSONJSONMySQL は専用のバイナリ形式で保存。MariaDB では LONGTEXT の別名(JSON 妥当性チェック付き)可変な属性、設定値

数値型の選び方

整数型と UNSIGNED

数値のデータ型の後に UNSIGNED を付けると負の数を格納できなくなり、その分だけ正の数の上限が約 2 倍に広がります。たとえば INT は最大 2,147,483,647 ですが、INT UNSIGNED なら 4,294,967,295 まで入ります。ID や個数など負にならない値に向いています。

ただし UNSIGNED 同士の引き算で結果が負になるとエラー(BIGINT UNSIGNED value is out of range)になる点には注意が必要です。また MySQL 8.0.17 以降、FLOAT / DOUBLE / DECIMAL に対する UNSIGNED は非推奨になっています。

CREATE TABLE products (
  id        INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
  stock     SMALLINT UNSIGNED NOT NULL DEFAULT 0,
  price     DECIMAL(10,2) NOT NULL,          -- 金額は DECIMAL
  weight_kg DOUBLE NULL,                     -- 近似値で良い測定値
  is_active TINYINT(1) NOT NULL DEFAULT 1    -- BOOLEAN は TINYINT(1) の別名
);

DECIMAL と FLOAT / DOUBLE の違い

FLOAT / DOUBLE は 2 進数の近似値なので、0.1 のような値を正確に表せません。合計や等価比較で 0.30000000000000004 のような誤差が出ることがあります。金額・ポイント・税率のように 1 円のずれも許されない値は DECIMAL を使います。

文字列型の選び方

  • VARCHAR(M) の M は文字数です。utf8mb4(絵文字も保存できる 4 バイト文字コード)では 1 文字最大 4 バイトなので、VARCHAR の実質的な上限は約 16,000 文字になります
  • CHAR は長さが常に一定の値に使います。可変長の値に CHAR を使うと末尾の空白が取り除かれて返るため、意図しない比較結果になることがあります
  • TEXT 系はインデックスを張るときにプレフィックス長(先頭何文字か)の指定が必要です。検索や並び替えに使うカラムは VARCHAR が扱いやすいです
  • 文字コードと照合順序(collation)によって大文字・小文字や全角・半角の区別が変わります。比較結果が想定と違う場合はテーブルの照合順序を確認します

日付・時刻型:DATETIME と TIMESTAMP の違い

項目DATETIMETIMESTAMP
保存方法入力値をそのまま保存UTC に変換して保存し、取得時にセッションのタイムゾーンへ戻す
範囲1000 年〜9999 年1970 年〜2038 年 1 月 19 日(UTC)
向いている用途予約日時など「その地域の時刻」として意味がある値レコードの作成・更新日時など「ある瞬間」を表す値

TIMESTAMP は 2038 年 1 月 19 日を超える値を保存できません(いわゆる 2038 年問題)。有効期限や長期の予定など将来の日時を扱うカラムは DATETIME を選びます。どちらも DATETIME(3) のように指定すると小数秒(最大 6 桁、マイクロ秒)まで保存できます。

INT(10) の数字は何を意味するか

INT(10) の (10) は「表示幅」で、格納できる桁数や範囲には影響しません。INT(1) でも INT(11) でも保存できる値は同じです。この表示幅は ZEROFILL(ゼロ埋め表示)と組み合わせたときにしか意味がなく、MySQL 8.0.17 以降は TINYINT(1) を除いて非推奨となり、SHOW CREATE TABLE でも表示されなくなりました。新しく書く DDL では INT とだけ書けば十分です。

よくある落とし穴

  • 範囲外の値: 厳格モード(STRICT_TRANS_TABLES、MySQL 5.7 以降の既定)では範囲外の値はエラーになります。厳格モードを外した環境では最大値に丸められて黙って保存されるため、環境によって挙動が違います
  • 電話番号や郵便番号を INT にする: 先頭の 0 が消えます。計算しない番号は VARCHAR に入れます
  • ENUM の候補追加: 候補の追加は ALTER TABLE が必要です。頻繁に増える区分は別テーブル(マスタ)にした方が運用しやすくなります
  • JSON 型の互換性: MySQL と MariaDB で内部の扱いが異なります。両方で動かす前提なら JSON 関数の挙動を事前に確認します

データ型の確認方法

既存テーブルのカラムの型は次のコマンドで確認できます。

-- カラム一覧と型
DESC products;

-- テーブル定義をそのまま表示
SHOW CREATE TABLE products\G

-- 特定スキーマの全カラムの型を一覧
SELECT table_name, column_name, column_type, is_nullable, column_default
FROM information_schema.columns
WHERE table_schema = 'mydb'
ORDER BY table_name, ordinal_position;

関連

Post Share
子ページ

子ページはありません

同階層のページ
  1. ダウンロード&インストール方法(Windows)
  2. インストール方法(Linux)
  3. コマンド一覧
  4. SQL
  5. データ型
  6. 関数
  7. 管理ツール
  8. 設定
  9. パフォーマンスチューニング関連
  10. エクスポートおよびインポート
  11. エラー&トラブル
  12. 文字コードの確認
  13. 実行中の SQL の状態確認およびプロセスキルの方法
  14. パスワードの無効化設定
  15. root ユーザーの初期パスワード確認方法
  16. rootユーザーのパスワード変更方法
  17. LIMIT, OFFSET の始まりと挙動
  18. mysqlのバージョン確認方法
  19. MySQLで実行計画を表示する方法
  20. レプリケーションのステータス確認方法
  21. 中央値の導き方(バージョン8未満)
  22. 階層SQL(バージョン8未満)
  23. パーセンタイルの導き方
  24. 特定スキーマの全テーブルの全カラム情報を取得する方法