スペック早見表

SQLデータ型 比較早見表|MySQL・PostgreSQL・SQL Server・SQLite

主要RDBMS4種(MySQL・PostgreSQL・SQL Server・SQLite)のデータ型を横断比較。整数型のバイト数と範囲、DECIMALとFLOATの使い分け、VARCHAR/TEXTの上限、DATETIME/TIMESTAMPのタイムゾーン挙動、BOOLEAN・バイナリ・JSONの対応差、そしてDB間移行のハマりどころまで、テーブル設計と移行作業で必要な確定値を一覧表示します。

📌 まずこれだけ|最頻出の確定値

知りたいこと答え
INT の範囲-2,147,483,648 〜 2,147,483,647(4バイト・約±21億)
BIGINT の範囲-9,223,372,036,854,775,808 〜 9,223,372,036,854,775,807(8バイト)
金額を入れる型DECIMAL / NUMERIC(FLOAT・DOUBLEは丸め誤差が出るため不可)
MySQL TIMESTAMP の上限2038-01-19 03:14:07 UTC(2038年問題。以降はDATETIMEを使用)
MySQL の BOOLEANTINYINT(1) の別名(TRUE=1 / FALSE=0)
SQL Server の timestamp日時型ではない(rowversionの旧称。日時は datetime2)

このページについて

SQLの型名はISO/IEC 9075(SQL標準)で大枠が決まっていますが、サイズ・上限・内部表現はRDBMSごとに異なります。本ページではMySQL・PostgreSQL・SQL Server・SQLiteの公式リファレンスで確認できる確定値のみを、整数・小数・文字列・日付時刻・その他(真偽値/バイナリ/JSON)の5分類で比較します。

「INTはいくつまで入る?」「金額はDECIMALとFLOATどっち?」「PostgreSQLにTINYINTはある?」「移行したらTIMESTAMPが壊れた」といった、テーブル設計・DB移行・ORM設定で頻発する疑問に即答できる構成です。

型名や数値の一部を入力すると、下の比較表(5表)の行が絞り込まれます。空欄に戻すと全行表示されます。

1. 整数型の比較

範囲は符号付きの値。SQLiteのINTEGERは値の大きさに応じて1〜8バイトで可変格納され、最大8バイト符号付き整数(BIGINT相当)まで扱えます。

バイト数範囲(符号付き)MySQLPostgreSQLSQL ServerSQLite
TINYINT1-128 〜 127×(SMALLINTで代用)△ 0〜255の符号なしのみINTEGERで代用
SMALLINT2-32,768 〜 32,767INTEGERで代用
MEDIUMINT3-8,388,608 〜 8,388,607××INTEGERで代用
INT / INTEGER4-2,147,483,648 〜 2,147,483,647INTEGER(最大8バイト)
BIGINT8-9,223,372,036,854,775,808 〜 9,223,372,036,854,775,807INTEGERで対応

UNSIGNED(符号なし)修飾はMySQL固有です(例: INT UNSIGNED = 0〜4,294,967,295)。PostgreSQLに符号なし整数型はなく、SQL ServerのTINYINTは符号なし(0〜255)しかありません。

2. 小数型の比較

DECIMAL/NUMERICは10進の正確値、FLOAT/DOUBLE/REALは2進の近似値(IEEE 754)。金額・数量などの業務データはDECIMALを使います。

性質MySQLPostgreSQLSQL ServerSQLite
DECIMAL / NUMERIC10進・正確最大65桁(小数部は最大30桁)整数部131,072桁・小数部16,383桁まで最大38桁専用型なし(NUMERIC親和性で近似格納)
単精度浮動小数(4バイト)2進・近似FLOATreal(精度6桁程度)real(=float(24))×(REALは8バイト)
倍精度浮動小数(8バイト)2進・近似DOUBLEdouble precision(精度15桁程度)float(53)REAL
通貨専用型×(DECIMALを使用)money(8バイト)money / smallmoney×

通貨専用型よりも、桁数を明示できるDECIMAL(例: DECIMAL(10,2))での設計が一般的です。

3. 文字列型の比較

上限の単位に注意。MySQLとSQL Serverはバイト数基準の制限があり、PostgreSQLのvarchar(n)のnは文字数です。

MySQLPostgreSQLSQL ServerSQLite
CHAR(固定長)最大255文字character(n)。1フィールド約1GBまでchar(n)は最大8,000バイトTEXT扱い(固定長なし)
VARCHAR(可変長)最大65,535バイト(行全体の上限65,535バイトと共有)varchar(n)のnは文字数。1フィールド約1GBまでvarchar(n)は最大8,000バイト。varchar(max)は最大2GB(2³¹-1バイト)TEXT扱い(長さ指定は無視)
TEXT(長文)TINYTEXT 255B / TEXT 65,535B / MEDIUMTEXT 16MB / LONGTEXT 4GBtext(長さ上限の指定なし・約1GBまで)varchar(max)を使用(text型は旧式)TEXT(既定の上限は10億バイト)
Unicode専用型不要(列ごとに文字セット指定)不要(UTF-8データベースで対応)nchar(n)/nvarchar(n)は最大4,000文字。nvarchar(max)は最大2GB不要(TEXTはUTF-8/UTF-16)

MySQLのVARCHAR(n)のnは文字数指定ですが、格納上限はバイト数で決まるため、utf8mb4(1文字最大4バイト)では実質約16,383文字が上限になります。

4. 日付時刻型の比較

SQLiteに日付時刻の専用型はなく、TEXT(ISO 8601)・REAL(ユリウス日)・INTEGER(Unix時間)のいずれかで格納し日付関数で操作します。

MySQLPostgreSQLSQL ServerSQLite
DATE1000-01-01 〜 9999-12-31紀元前4713年 〜 西暦5874897年0001-01-01 〜 9999-12-31専用型なし
TIME-838:59:59 〜 838:59:59(経過時間も表現可)00:00:00 〜 24:00:0000:00:00.0000000 〜 23:59:59.9999999専用型なし
DATETIME(TZなし)DATETIME: 1000-01-01 00:00:00 〜 9999-12-31 23:59:59timestamp: 紀元前4713年 〜 西暦294276年datetime: 1753年〜9999年(精度約3.33ms) / datetime2: 0001年〜9999年(精度100ns)専用型なし
TIMESTAMP1970-01-01 00:00:01 UTC 〜 2038-01-19 03:14:07 UTC。UTCで保存しセッションTZで表示timestampはTZなし型(TZ付きは下段)日時型ではない(rowversionの旧称)専用型なし
タイムゾーン付き日時×(TIMESTAMPの自動変換のみ)timestamptz: UTCで保存し表示時に変換datetimeoffset: UTCオフセットを値ごとに保持専用型なし

5. 真偽値・バイナリ・JSON型の比較

MySQLPostgreSQLSQL ServerSQLite
BOOLEANTINYINT(1)の別名(TRUE=1/FALSE=0)boolean(1バイト・真の論理型)bit(0・1・NULL)専用型なし(INTEGERの0/1)
バイナリBINARY(最大255B)/VARBINARY、BLOB系(TINYBLOB 255B〜LONGBLOB 4GB)bytea(約1GBまで)binary/varbinary(n)は最大8,000バイト。varbinary(max)は最大2GBBLOB
JSONJSON型あり(5.7.8以降・バイナリ形式で格納)json(テキスト保持)とjsonb(バイナリ・インデックス可)の2種専用型なし(nvarcharに格納しJSON関数で操作・2016以降)専用型なし(TEXT+JSON関数。3.38.0以降は標準組込)
UUID専用型なし(BINARY(16)やCHAR(36)で代用)uuid型ありuniqueidentifier型あり専用型なし

6. DB間移行のハマりどころ

落とし穴何が起きるか対策
TINYINT(1)とBOOLEANMySQLのBOOLEANは実体がTINYINT(1)。0/1以外も格納でき、PostgreSQLの真のboolean型へ移行すると2以上の値が変換エラーや意図しない真偽値になる移行前に0/1以外の値を洗い出す。ドライバのtinyint→boolean自動変換設定も確認
TIMESTAMPの2038年問題MySQLのTIMESTAMPは2038-01-19 03:14:07 UTCが上限。契約満了日など未来日付が入らない未来日時を扱う列はDATETIMEにする。既存列は計画的に型変更
SQL Serverのtimestamp名前に反して日時型ではなくrowversion(更新順のバイナリ値)。日時のつもりでSELECTすると16進値が返る日時にはdatetime2/datetimeoffsetを使用。移行ツールのマッピング定義を確認
SQLiteの動的型列の型宣言は「型親和性」の判定にしか使われず、どの列にも任意の型の値が入る。長さ制限も無視されるアプリ側でバリデーションする。SQLite 3.37.0以降ならSTRICTテーブルで型を強制
UNSIGNEDはMySQL固有INT UNSIGNED(上限約42.9億)をPostgreSQLのintegerへ移すと上限超過の恐れ符号なし列はBIGINTなど1段大きい型へマッピング
VARCHAR(n)のnの意味PostgreSQLは文字数、SQL Serverのvarcharはバイト数。マルチバイト文字で「同じn」でも入る文字数が違う日本語データはSQL Serverではnvarcharを使うか、バイト数換算で長さを再設計

使い方・選び方のポイント

使用場面

テーブル設計(CREATE TABLE)・DB移行・ORMのスキーマ定義・レビュー時の型チェックに使います。迷ったら「格納したい値の範囲と性質(正確値か近似値か)」から逆引きします。

よくある間違い

①金額にFLOAT/DOUBLEを使う(丸め誤差が蓄積)②連番IDをINTにして約21億で枯渇 ③MySQLのTIMESTAMP列に2038年以降の日付を入れようとする ④SQL Serverのtimestampを日時型と誤解 ⑤SQLiteで型宣言や長さ指定が強制されると思い込む、が定番です。

選び方のコツ

①整数は範囲で選ぶ(迷ったらINT、大規模テーブルの主キーはBIGINT)②金額・数量など正確さが必要な数値はDECIMAL、科学計算はDOUBLE ③文字列は上限を見積もってVARCHAR、長文はTEXT系 ④日時はタイムゾーン要件で選ぶ(複数TZならPostgreSQLはtimestamptz、SQL Serverはdatetimeoffset)。

よくある質問

Q1. 金額を保存するのに最適な型は?

A. DECIMAL(NUMERIC)型です。10進数を正確に保持するため丸め誤差が出ません。FLOATやDOUBLEは2進浮動小数点のため0.1のような値を正確に表現できず、金額計算に使うと誤差が蓄積します。例えば税込計算はDECIMAL(10,2)のように小数部の桁数を明示して行います。

Q2. INTとBIGINTはどちらを使うべき?

A. INTの上限は2,147,483,647(約21億)です。連番IDが21億件を超える可能性のあるテーブル(ログ・取引履歴など)は最初からBIGINT(上限約922京)にします。運用途中でINTからBIGINTへ変更する作業は、大規模テーブルでは長時間ロックの原因になります。

Q3. MySQLのDATETIMEとTIMESTAMPの違いは?

A. DATETIMEは書き込んだ値をそのまま保存し(範囲は1000年〜9999年)、TIMESTAMPはUTCに変換して保存しセッションのタイムゾーンに変換して表示します。TIMESTAMPの上限は2038-01-19 03:14:07 UTC(2038年問題)のため、それ以降の日時を扱う列にはDATETIMEを使います。

Q4. MySQLにBOOLEAN型はある?

A. BOOLEAN(BOOL)はTINYINT(1)の別名で、独立した型ではありません。TRUEは1、FALSEは0として格納されます。0と1以外の値も格納できてしまう点がPostgreSQLの真のboolean型との違いで、DB間移行やORM設定での注意点です。

Q5. SQL ServerのTIMESTAMP型に日時は保存できる?

A. できません。SQL Serverのtimestampはrowversion(行の更新順を示すバイナリ値)の旧称で、日付時刻型ではありません。日時にはdatetime2やdatetimeoffsetを使います。MySQLやPostgreSQLから移行するときの代表的な落とし穴です。

Q6. SQLiteでVARCHAR(50)と書いたら50文字に制限される?

A. 制限されません。SQLiteは動的型で、列の型宣言は型親和性(TEXT/INTEGERなど)の判定に使われるだけで、長さ指定は無視されます。列に型を厳密に強制したい場合は、SQLite 3.37.0以降で使えるSTRICTテーブルを利用します。

Q7. VARCHAR(255)がよく使われるのはなぜ?

A. MySQLでは長さ255バイト以下のVARCHAR値は長さ情報を1バイトで格納でき、それを超えると2バイト必要になる境界が255だからです。歴史的な慣習として広まりましたが、現在は用途に必要な長さを見積もって指定するのが基本です。

なぜ同じ「SQL」なのに型が違うのか

SQLの型体系はISO/IEC 9075(SQL標準)がINTEGER・NUMERIC・CHARACTER VARYINGといった型の枠組みを定義していますが、バイト数・上限値・内部表現は「実装定義」とされている部分が多く、各RDBMSが独自に決めています。MySQLのMEDIUMINT(3バイト)やUNSIGNED修飾、PostgreSQLのjsonb、SQL Serverのdatetimeoffsetは、それぞれの製品が歴史的に積み上げてきた方言です。同じ「INTEGER」という宣言でも中身が同一とは限らない、というのがDB移行の難しさの根源です。

数値型の分類で重要なのが正確値(exact numeric)と近似値(approximate numeric)の区別です。DECIMALは10進の桁をそのまま保持するため「0.1 + 0.2 = 0.3」が正確に成り立ちますが、FLOAT/DOUBLEはIEEE 754の2進浮動小数点であり、0.1は2進数では循環小数になるため厳密には表現できません。1回の計算では誤差が見えなくても、集計や乗算を繰り返すと差が現れるため、会計・在庫のような業務データは正確値の型で持つのが原則です。

SQLiteだけが大きく異なるのは、型を列ではなく値そのものに持たせる動的型(manifest typing)を採用しているためです。格納クラスはNULL・INTEGER・REAL・TEXT・BLOBの5種のみで、列の型宣言は「型親和性」というゆるやかな変換ヒントとして扱われます。組込み用途で軽量・柔軟であることを優先した設計ですが、サーバー型RDBMSと同じ感覚でスキーマに型チェックを期待すると裏切られるため、3.37.0で追加されたSTRICTテーブルやアプリ側の検証で補います。

関連する早見表

関連規格・出典

  • MySQL リファレンスマニュアル「Data Types」— 整数・DECIMAL・文字列・日付時刻型の範囲と上限
  • PostgreSQL 公式ドキュメント「Chapter 8. Data Types」— numeric・文字型・日付時刻型・jsonb
  • SQL Server Transact-SQL リファレンス「データ型」— int/bigint・decimal・varchar(max)・datetime2・rowversion
  • SQLite 公式ドキュメント「Datatypes In SQLite」「STRICT Tables」— 型親和性・格納クラス
  • ISO/IEC 9075(SQL標準)— 型体系の枠組み(参考)

最終更新: 2026-07-02