MySQL テーブルの作成とデータ制約
データベースを作成した後の次のステップは、具体的な情報を保存するための「構造」を構築することです。この構造はテーブル (Tables) によって定義されます。テーブルはデータを行(Row)と列(Column)に整理します。これは Excel などのスプレッドシートによく似ています。
テーブルを正しく設計するには、カラムの定義、データ型の割り当て、そしてデータの整合性と関連性を保証するための制約 (Constraints) の適用方法を理解する必要があります。
1. テーブル構造とデータ型の定義
テーブル作成のプロセスには、テーブル名を指定し、各カラムに一意の名前と適切なデータ型を定義することが含まれます。前章「MySQL データ型」で学んだように、データ型はカラムがどのような値(数値、テキスト、日付など)を保存できるか、およびどの程度のストレージ容量を必要とするかを決定します。ストレージ効率とデータの正確性を向上させるには、正しいデータ型を選択することが極めて重要です。
1.1 CREATE TABLE の基本構文
テーブルを作成するための基本的な SQL 構文は以下の通りです。
CREATE TABLE table_name (
column1_name DATATYPE [CONSTRAINTS],
column2_name DATATYPE [CONSTRAINTS],
column3_name DATATYPE [CONSTRAINTS],
-- ... さらなるカラム
[TABLE_CONSTRAINTS]
);- table_name: 新しいテーブルに指定する名前。
- column_name: テーブル内の各カラムの名前。
- DATATYPE: そのカラムの具体的なデータ型(例:
INT,VARCHAR(255),DATE)。 - CONSTRAINTS(カラムレベル制約): 単一のカラムに適用され、そのカラムに保存できるデータの種類を制限するルール。
- TABLE_CONSTRAINTS(テーブルレベル制約): テーブル全体に適用されるルールで、通常は複数のカラムに関係します。
1.2 例:Customers(顧客)テーブルの作成
オンライン書店のデータベースを構築すると仮定しましょう。最も基礎的なテーブルの一つは、顧客情報を保存する Customers です。
CREATE TABLE Customers (
customer_id INT, -- 各顧客の一意識別子
first_name VARCHAR(50), -- 顧客の名
last_name VARCHAR(50), -- 顧客の姓
email VARCHAR(100), -- 顧客のメールアドレス
registration_date DATE -- 顧客の登録日
);この Customers テーブルでは、数値 ID には INT、氏名やメールアドレスのような可変長文字列には VARCHAR、登録日には DATE というデータ型を使用しています。
2. 主キー (Primary Key):一意識別の保証
主キー (Primary Key) は、テーブル内の各行(レコード)を一意に識別するための特別なカラム(またはカラムのセット)です。主キーの存在により、テーブル内のすべてのレコードを重複なく、確実に見つけ出すことができます。一つのテーブルに設定できる主キーは一つだけです。
主キーの主な特徴:
- 一意性 (Uniqueness): 主キーカラム内の各値はすべて異なっていなければなりません。2つの行が同じ主キー値を持つことはできません。
- 非NULL (Non-NULL): 主キーカラムに
NULL(空)を含めることはできません。すべてのレコードは具体的な主キー値を持つ必要があります。
2.1 カラムレベルの主キー
PRIMARY KEY 制約を使用して、特定のカラムを主キーに指定できます。カラム定義の直後に記述する場合、これをカラムレベル制約と呼びます。
CREATE TABLE Products (
product_id INT PRIMARY KEY, -- product_id を主キーに設定
product_name VARCHAR(100),
price DECIMAL(10, 2),
stock_quantity INT
);この Products(製品)テーブルでは、product_id が主キーとして宣言されています。つまり、各製品は一意の product_id を持つ必要があり、NULL は許可されません。
2.2 テーブルレベルの主キー
主キーが複数のカラムで構成される場合(複合主キー)、またはコードの可読性を高めるために、テーブルの最後に主キーを定義することがあります。これをテーブルレベル制約と呼びます。
CREATE TABLE OrderItems (
order_id INT,
product_id INT,
quantity INT,
price_per_item DECIMAL(10, 2),
PRIMARY KEY (order_id, product_id) -- 複合主キー
);ここでは、order_id と product_id の組み合わせが注文内の各アイテムを一意に識別します。個別の order_id は重複する可能性があり(一つの注文に複数の製品が含まれる)、個別の product_id も重複する可能性があります(異なる注文で同じ製品が購入される)。しかし、(order_id, product_id) というペアは、各行において必ず一意でなければなりません。
2.3 主キーのオートインクリメント属性 (AUTO_INCREMENT)
数値型の主キーでは、通常 AUTO_INCREMENT を使用します。この属性は、テーブルに新しい行が挿入されるたびに、一意で連続した数値を自動的に生成します。これによりデータ入力が大幅に簡略化され、絶対的な一意性が保証されます。注意点として、AUTO_INCREMENT カラムは主キーまたは UNIQUE インデックスの一部である必要があります。
CREATE TABLE Employees (
employee_id INT PRIMARY KEY AUTO_INCREMENT, -- 新しい従業員に ID を自動採番
first_name VARCHAR(50),
last_name VARCHAR(50),
hire_date DATE
);Employees(従業員)テーブルにデータを挿入する際、通常 INSERT 文で employee_id を省略すれば、MySQL が自動的に次の利用可能な数値を割り当てます。
3. その他の主要なデータ制約
制約はデータテーブルに強制的に適用されるルールです。これらはデータの正確性と信頼性を確保します。主キー以外にも、よく使われる制約として NOT NULL、UNIQUE、DEFAULT、CHECK があります。
3.1 非NULL制約 (NOT NULL)
NOT NULL 制約は、カラムに NULL 値を保存できないようにします。つまり、新しい行を挿入したり既存の行を更新したりする際、そのカラムに具体的な値を必ず提供しなければなりません。
CREATE TABLE Publishers (
publisher_id INT PRIMARY KEY AUTO_INCREMENT,
publisher_name VARCHAR(100) NOT NULL, -- 出版社名は NULL 不可
city VARCHAR(50)
);この Publishers(出版社)テーブルでは、publisher_name は常に値を持つ必要があります。publisher_name なしでデータを挿入しようとしたり、NULL に更新しようとすると、システムはエラーを返します。これは重要な情報の完全性を保つために不可欠です。
3.2 ユニーク制約 (UNIQUE)
UNIQUE 制約は、そのカラム内のすべての値が互いに異なることを保証します。主キーも一意性を保証しますが、一つのテーブルに複数の UNIQUE 制約を設定できるのに対し、主キーは一つだけです。また、UNIQUE カラムは NULL 値を含むことができます(MySQL では、複数の NULL 値は互いにコンフリクトしないとみなされるのが一般的です)。
CREATE TABLE Users (
user_id INT PRIMARY KEY AUTO_INCREMENT,
username VARCHAR(50) UNIQUE NOT NULL, -- ユーザー名は一意かつ入力必須
email VARCHAR(100) UNIQUE, -- メールアドレスは一意である必要があるが、NULL は許可
password_hash VARCHAR(255) NOT NULL
);ここでは、username は一意かつ NOT NULL である必要があります。email を入力する場合は一意である必要がありますが、未入力(NULL)のままにすることも可能です。これはメールアドレスや身分証番号など、一意であるべきだが提供されない場合もあるフィールドに最適です。
3.3 デフォルト値制約 (DEFAULT)
INSERT 操作で値が明示的に指定されなかった場合、DEFAULT 制約はそのカラムに規定の値を設定します。
CREATE TABLE Orders (
order_id INT PRIMARY KEY AUTO_INCREMENT,
customer_id INT NOT NULL,
order_date DATE DEFAULT (CURRENT_DATE()), -- 指定がない場合は今日の日付
status VARCHAR(20) DEFAULT 'Pending' -- デフォルトステータスを 'Pending' (保留中) に設定
);Orders(注文)テーブルに新しいレコードが追加される際、order_date が提供されなければ自動的に今日の日付がセットされます。同様に、status もデフォルトで 'Pending' になります。これによりデータの整合性が保たれ、頻繁に使用される値の手入力の手間が省けます。
3.4 チェック制約 (CHECK)
CHECK 制約を使用すると、カラムのすべての値が満たすべき条件を定義できます。挿入または更新しようとする値がその条件に違反する場合、操作は失敗します。
CREATE TABLE ProductsInventory (
product_id INT PRIMARY KEY AUTO_INCREMENT,
product_name VARCHAR(100) NOT NULL,
price DECIMAL(10, 2) CHECK (price >= 0), -- 価格は負数不可
stock_quantity INT CHECK (stock_quantity >= 0) -- 在庫数は負数不可
);ProductsInventory(製品在庫)では、price と stock_quantity は 0 以上である必要があります。この制約により、負の価格や負の在庫といった無効なデータがデータベースに混入するのを防ぎます。
4. 総合実践デモンストレーション
これらのコンセプトを実際のシナリオに適用してみましょう。大学の学生管理システムのためのデータベーステーブルを作成します。
まず、正しいデータベースを使用していることを確認してください。以前に university_db を作成している場合は、それを有効化します。
USE university_db;実践 1:Students (学生) テーブル
Students テーブルは各学生の基本情報を保存します。
CREATE TABLE Students (
student_id INT PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE NOT NULL,
enrollment_date DATE DEFAULT (CURRENT_DATE()),
major VARCHAR(50)
);- student_id:
INT PRIMARY KEY AUTO_INCREMENTにより、各学生に一意の ID が自動割り当てされます。 - first_name, last_name:
NOT NULLにより氏名の入力が必須となります。 - email:
UNIQUE NOT NULLにより、メールアドレスの重複と空値を禁止します。 - enrollment_date: 未入力の場合、自動的に現在の日付が設定されます。
- major: 専攻は任意入力(制約なし、デフォルトで
NULL許可)。
実践 2:Courses (コース) テーブル
Courses テーブルは開講される各コースの詳細を保存します。
CREATE TABLE Courses (
course_id VARCHAR(10) PRIMARY KEY, -- コース ID は文字列 ('CS101' など)
course_title VARCHAR(100) NOT NULL UNIQUE,
credits INT NOT NULL CHECK (credits > 0 AND credits <= 6), -- 単位数は 1 から 6 の間
department VARCHAR(50) NOT NULL
);- course_id: カスタム文字列を主キーとして使用します。
- course_title: コース名は必須かつ一意です。
- credits: 単位数が 1 から 6 の間の正の整数であることを強制します。
- department: 所属学部が必須であることを保証します。
実践 3:Instructors (講師) テーブル
Instructors テーブルは大学の教職員情報を保存します。
CREATE TABLE Instructors (
instructor_id INT PRIMARY KEY AUTO_INCREMENT,
first_name VARCHAR(50) NOT NULL,
last_name VARCHAR(50) NOT NULL,
email VARCHAR(100) UNIQUE,
hire_date DATE DEFAULT (CURRENT_DATE()),
salary DECIMAL(10, 2) CHECK (salary >= 30000.00) -- 最低給与を 30,000 に設定
);- instructor_id: 一意の自動採番 ID を提供します。
- email: 一意である必要がありますが、空値(
NULL)も許可されます。 - salary: 最低給与基準を強制適用します。
これらの例を通して、さまざまな制約を組み合わせることで、現実世界のビジネスルールを忠実に反映した堅牢なテーブル構造を構築できることがわかります。