MySQL 入門

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_idproduct_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 NULLUNIQUEDEFAULTCHECK があります。

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(製品在庫)では、pricestock_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: 最低給与基準を強制適用します。

これらの例を通して、さまざまな制約を組み合わせることで、現実世界のビジネスルールを忠実に反映した堅牢なテーブル構造を構築できることがわかります。