データ型
データ型
収納ボックスにはさまざまなサイズがあるように — 耳飾り用の小さな仕切り、腕時計用の中サイズ、マフラー用の大サイズ — データベースの各列にもデータに合った「ボックス」が必要です。適切な型を選択すれば、データは安全で省スペースになります。間違えれば、ストレージの浪費や精度の低下につながります。
1. 基本概念
| 概念 | 説明 |
|---|---|
| 数値型 | 整数と小数を格納。INT、BIGINT、DECIMAL、FLOATなど |
| 文字列型 | テキストデータを格納。CHAR、VARCHAR、TEXT |
| 日付型 | 日付と時刻を格納。DATE、DATETIME、TIMESTAMP |
| ブール型 | 真/偽の値を格納。SQLiteはINTEGER(0/1)を使用 |
| NULL | 「不明」または「欠損」を表す — 空文字列でもゼロでもない |
| 型選択の原則 | データ範囲、精度要件、ストレージ効率に基づいて最適な型を選択 |
2. 基本構文
数値型
| 型 | 説明 | 範囲/精度 | 最適な用途 |
|---|---|---|---|
INTEGER / INT |
整数 | ±21億 | ID、数量、年齢 |
BIGINT |
大きな整数 | ±9.2×10¹⁸ | 大量データのID、ファイルサイズ |
DECIMAL(p,s) / NUMERIC(p,s) |
正確な小数 | p = 全桁数、s = 小数桁数 | 金額、価格(精度低下なし) |
FLOAT / REAL |
浮動小数点 | 有効桁数約7桁 | 科学計算、近似値 |
DOUBLE |
倍精度浮動小数点 | 有効桁数約15桁 | 高精度の近似計算 |
-- DECIMALで正確な金額を保存
CREATE TABLE accounts (
id INTEGER PRIMARY KEY,
balance DECIMAL(12, 2) -- 最大12桁、小数2桁
);
-- FLOATで近似的に保存
CREATE TABLE measurements (
id INTEGER PRIMARY KEY,
temperature REAL -- 近似値、小さな誤差がある可能性
);
0.1 + 0.2は0.30000000000000004になる可能性があり、金融シナリオでは致命的です。
文字列型
| 型 | 説明 | 最大長 | 最適な用途 |
|---|---|---|---|
CHAR(n) |
固定長文字列 | 255バイト | 固定長データ(例:性別M/F、ステータスコード) |
VARCHAR(n) |
可変長文字列 | 65535バイト | 名前、メールアドレス、タイトル |
TEXT |
長いテキスト | 無制限 | 記事本文、メモ、説明 |
CREATE TABLE articles (
id INTEGER PRIMARY KEY,
title VARCHAR(200), -- タイトル、最大200文字
status CHAR(1), -- ステータス:D=下書き、P=公開済み
content TEXT -- 本文、無制限
);
日付型
| 型 | 説明 | 形式 | 最適な用途 |
|---|---|---|---|
DATE |
日付 | YYYY-MM-DD |
誕生日、入社日 |
DATETIME |
日付と時刻 | YYYY-MM-DD HH:MM:SS |
作成時刻、予約時間 |
TIMESTAMP |
タイムスタンプ | 自動管理 | レコード更新時刻、タイムゾーンをまたぐシナリオ |
CREATE TABLE events (
id INTEGER PRIMARY KEY,
event_name TEXT,
event_date DATE, -- 日付のみ
created_at DATETIME DEFAULT CURRENT_TIMESTAMP -- 作成時刻を自動記録
);
TEXT(ISO 8601形式、例:'2024-01-15')またはINTEGER(Unixタイムスタンプ)として保存されます。SQLiteの組み込み日付関数(DATE()、DATETIME()など)はこれらの形式を正しく処理できます。
ブール型
| 型 | 説明 | 保存方法 |
|---|---|---|
BOOLEAN |
真/偽 | SQLiteではINTEGERとして保存:0=偽、1=真 |
BIT |
ビット値 | MySQL/SQL Serverで使用 |
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name TEXT,
is_active BOOLEAN DEFAULT 1 -- 1=有効、0=無効
);
-- ブール値を挿入
INSERT INTO users (name, is_active) VALUES ('John', TRUE); -- 1として保存
INSERT INTO users (name, is_active) VALUES ('Jane', FALSE); -- 0として保存
-- ブール値でクエリ
SELECT * FROM users WHERE is_active = 1;
TRUEは1に、FALSEは0に等しいです。ただし、コードの可読性のため、数字を直接書く代わりにTRUE/FALSEを使用することを推奨します。
NULLの意味
NULLは「不明」または「欠損」を表します — 空文字列''ではなく、数値0ではなく、もちろんFALSEでもありません。
-- NULLを含むすべての演算の結果はNULL
SELECT NULL + 1; -- 結果:NULL
SELECT NULL || 'hello'; -- 結果:NULL
-- NULLを確認するには、IS / IS NOTを使用
SELECT * FROM employees WHERE department_id IS NULL; -- ✅ 正しい
SELECT * FROM employees WHERE department_id = NULL; -- ❌ 常に空を返す
SELECT * FROM employees WHERE department_id IS NOT NULL; -- ✅ 正しい
ISを使用し、=は使わない; ②NULLを含むすべての演算の結果はNULLになる。
型選択のベストプラクティス
| シナリオ | 推奨型 | 理由 |
|---|---|---|
| 主キーID | INTEGER PRIMARY KEY AUTOINCREMENT |
整数は文字列より高速。自動採番が便利 |
| 金額/価格 | DECIMAL(10,2) |
正確な保存、丸め誤差なし |
| ユーザー名/タイトル | VARCHAR(100) |
可変長でスペース節約。長さ制限で悪用を防止 |
| 記事本文 | TEXT |
無制限の長さ、大きなテキストに適している |
| 日付 | DATE / DATETIME |
明確なセマンティクス、組み込み日付関数のサポート |
| はい/いいえフラグ | BOOLEAN |
明確なセマンティクス、コンパクトな保存 |
| 列挙ステータス | CHAR(1) または INTEGER |
ENUM型より柔軟 |
3. コード例
例:商品テーブルの作成と型制約の確認(難易度⭐)
商品テーブルを作成して、さまざまなデータ型の動作を体験します。
-- 指定された列型で商品テーブルを作成
CREATE TABLE products_demo (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) NOT NULL,
stock INTEGER DEFAULT 0,
description TEXT,
is_active BOOLEAN DEFAULT 1,
created_at DATE
);
-- さまざまな型のデータを挿入
INSERT INTO products_demo (name, price, stock, description, is_active, created_at)
VALUES ('メカニカルキーボード', 299.50, 100, 'ブルースイッチ87キー、タイピングに最適', TRUE, '2024-01-15');
INSERT INTO products_demo (name, price, stock, description, is_active, created_at)
VALUES ('ワイヤレスマウス', 89.00, 200, NULL, TRUE, '2024-02-20');
-- データと型の動作を確認
SELECT name, price, stock, description, is_active, created_at
FROM products_demo;
出力:
name price stock description is_active created_at
---------------- ------- ----- --------------------------------------------- --------- ----------
メカニカルキーボード 299.50 100 ブルースイッチ87キー、タイピングに... 1 2024-01-15
ワイヤレスマウス 89.00 200 (NULL) 1 2024-02-20
例:NULLの算術特性を確認(難易度⭐⭐)
実際のクエリを通じてNULLの特別な動作を理解します。
-- テストテーブルを作成
CREATE TABLE null_test (
id INTEGER PRIMARY KEY,
value INTEGER
);
INSERT INTO null_test VALUES (1, 10);
INSERT INTO null_test VALUES (2, NULL);
INSERT INTO null_test VALUES (3, 20);
-- 算術演算でのNULL
SELECT id, value, value + 100 AS add_result
FROM null_test;
出力:
id value add_result
-- ----- ----------
1 10 110
2 (NULL) (NULL)
3 20 120
-- NULLの確認:IS vs =
SELECT id, value,
CASE WHEN value IS NULL THEN 'NULLです' ELSE 'NULLではありません' END AS check_result
FROM null_test;
出力:
id value check_result
-- ----- ------------
1 10 NULLではありません
2 (NULL) NULLです
3 20 NULLではありません
-- NULLと集計関数:COUNTはNULLを除外、SUM/AVGはNULLを無視
SELECT COUNT(value) AS count_val, -- 2(NULLをカウントしない)
COUNT(*) AS count_all, -- 3(すべての行をカウント)
SUM(value) AS sum_val, -- 30(NULLを無視)
AVG(value) AS avg_val -- 15(30/2、30/3ではない)
FROM null_test;
出力:
count_val count_all sum_val avg_val
--------- --------- ------- -------
2 3 30 15.0
4. 主な応用シナリオ
シナリオ1:ユーザー登録テーブルの設計
ビジネス要件に基づいて適切な型を選択します:
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username VARCHAR(50) NOT NULL UNIQUE, -- ユーザー名、一意でNULL不可
email VARCHAR(100) NOT NULL UNIQUE, -- メールアドレス
password_hash CHAR(64) NOT NULL, -- SHA256ハッシュ、固定64文字
age INTEGER CHECK (age >= 0 AND age <= 150), -- 年齢、妥当な範囲チェック
balance DECIMAL(12, 2) DEFAULT 0.00, -- 口座残高、セントまで正確
bio TEXT, -- 自己紹介、無制限
is_verified BOOLEAN DEFAULT 0, // メール認証済みかどうか
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
シナリオ2:デフォルト値でのNULL処理
COALESCE関数を使用してNULLにデフォルト値を提供します:
-- 従業員情報をクエリし、部署がNULLの場合は「未割り当て」と表示
SELECT e.name,
COALESCE(d.name, '未割り当て') AS department,
COALESCE(e.salary, 0) AS salary
FROM employees e
LEFT JOIN departments d ON e.department_id = d.id;
❓ よくある質問
質問:DECIMAL(10,2)とFLOATの両方で小数を保存できます。違いは何ですか? 回答: DECIMALは正確な値を保存し、金額など精度が重要なシナリオに適しています。FLOATは近似値を保存し、計算は速いものの小さな誤差があります。シンプルなルール:金額にはDECIMAL、科学計算にはFLOATを使用します。
質問:CHARとVARCHARのどちらを選べばいいですか? 回答: データ長が固定の場合(例:性別M/F、MD5ハッシュ)、CHARの方が効率的です。長さが異なる場合(例:名前、タイトル)、VARCHARがよりスペースを節約します。実際にはVARCHARがより多く使用されます。
質問:NULLと空文字列''の違いは何ですか? 回答: NULLは「不明/値なし」を意味し、空文字列は「値は既知で空である」を意味します。例えば、「ミドルネーム」列:外国人にはミドルネームがない場合(NULL)、中国人にはあるが空文字列('')の場合があります。集計関数では、COUNT(列)はNULLをカウントしませんが、空文字列はカウントします。
質問:SQLiteの型システムは他のデータベースとどう違いますか? 回答: SQLiteは動的型システムを使用しています — 列の型宣言は厳密な制約というより「提案」に近いです。INTEGER列に文字列を挿入できます(非推奨ですが)。MySQL、PostgreSQLなどは厳密な型システムを使用しており、型の不一致はエラーを引き起こします。コードの移植性のため、型を正しく使用してください。
📖 まとめ
- 数値型:整数にはINT/BIGINT、正確な小数にはDECIMAL(金額には必須)、近似値にはFLOAT
- 文字列型:固定長にはCHAR、可変長にはVARCHAR、大きなテキストにはTEXT
- 日付型:DATEは日付を保存、DATETIMEは日付と時刻を保存、TIMESTAMPは自動管理
- ブール型:BOOLEANはTRUE/FALSEを保存。SQLiteでは実際にはINTEGERの0/1
- NULLは「不明」を意味する。
= NULLではなくIS NULLで確認。NULLを含む演算の結果はNULL - 型選択の原則:データ範囲、精度要件、ストレージ効率を考慮。金額には必ずDECIMALを使用
📝 演習
演習1(⭐)
以下のフィールドを持つ「図書館貸出」テーブルを設計し、適切なデータ型を選択してください:
- 貸出ID(主キー)
- 書籍タイトル(最大200文字)
- ISBN(固定13文字)
- 借り手の名前
- 貸出日
- 返却期限
- 返却済みかどうか
- 備考(NULL可)
演習2(⭐⭐)
演習1のテーブルを作成し、5件のレコードを挿入してから、クエリを書いてください:
- 未返却の貸出レコードをすべてクエリ
- 備考がNULLのレコードをクエリ
- 未返却レコードの総数をカウント(NULL処理に注意)



