関係データベースの構成要素とスキーマ設計
リレーショナルデータベースは、構造化された情報を格納・管理するために設計されています。主要な構成要素は以下の通りです。
- テーブル (Table): データを格納する基本単位。データベース内で一意な名前を持つ必要があります。
- カラム (Column): テーブル内の属性やフィールドを表します。
- 行 (Row): 各レコードに対応するデータの集合です。
- データ型 (Data Type): 各カラムに格納可能な値の種類を制限し、ストレージ最適化や正しいソート順序を保証します。
- 主キー (Primary Key): 行を一意に識別するためのカラム(またはカラムの組み合わせ)。
主キーの制約と設計指針
主キーを定義する際には、以下の条件を厳密に遵守する必要があります。
- すべての行に値が存在するため、
NULLは許可されません。 - テーブル内で値の重複は発生しません。
運用上の推奨事項として、主キーの値は設定後に更新しない、再利用しない、およびビジネスロジックの変更に伴う値(例:メールアドレスや電話番号)を使用しないことが挙げられます。
対話型シェルと基本取得コマンド
MySQLクライアントでの作業では、プロンプトmysql>に続けてコマンドを入力します。ステートメントはセミコロン(;)または\gで終了する必要があり、単にEnterキーを押すだけでは実行されません。ヘルプはhelpまたは\h、セッションの終了はquitまたは\exitで実行できます。
データベースの構造を確認するための主要なコマンドは以下の通りです。
-- データベース一覧の表示
SHOW DATABASES;
-- 現在のデータベースにあるテーブル一覧を取得
SHOW TABLES;
-- 特定テーブルの構造定義を確認(DESCRIBEと同義)
SHOW COLUMNS FROM product_catalog;
-- 作成時の完全なDDL文を出力
SHOW CREATE TABLE product_catalog;
SHOW CREATE DATABASE inventory_db;
-- サポートされているストレージエンジンの確認
SHOW ENGINES;
データ取得の基本構文では、特定カラムの指定や全カラムの取得(*)、重複排除、および出力件数の制限が可能です。
-- 特定カラムの抽出
SELECT item_code, product_name, price FROM product_catalog;
-- 重複値の除去(指定した全カラムの組み合わせで重複判定される)
SELECT DISTINCT category FROM product_catalog;
-- LIMITによる件数制限(0番目から5件取得)
SELECT item_code FROM product_catalog LIMIT 5;
-- LIMITの開始位置と件数を指定(2番目から5件)
SELECT item_code FROM product_catalog LIMIT 5 OFFSET 2;
-- データベース名とテーブル名を明示的に修飾
SELECT sku FROM inventory_db.product_catalog;
データの並び替えと条件フィルタリング
結果セットの順序を制御するにはORDER BY句を使用します。デフォルトは昇順(ASC)であり、降順にはDESCを指定します。日本語文字列のソート順序は照合順序(Collation)の設定に依存します。
SELECT item_code, price, stock_status
FROM product_catalog
ORDER BY price ASC, stock_status DESC;
行の抽出条件を定義するにはWHERE句を用います。比較演算子と組み合わせて条件式を構築します。
SELECT * FROM product_catalog
WHERE price BETWEEN 1500 AND 8000
ORDER BY price DESC;
| 演算子 | 意味 |
|---|---|
= | 等しい |
<> または != | 等しくない |
< / <= | 小さい / 以下 |
> / >= | 大きい / 以上 |
BETWEEN A AND B | 範囲内(A以上B以下) |
BETWEENは数値および文字列の範囲指定に使用でき、境界値を含みます。また、欠損値の判定にはIS NULLを使用します。空文字列やゼロ値とは明確に区別されることに注意してください。
-- 文字列のマッチングはデフォルトで大文字小文字を区別しない
SELECT sku, product_name FROM product_catalog WHERE category = 'ELECTRONICS';
-- NULL値を持つレコードの抽出
SELECT sku, serial_number FROM product_catalog
WHERE warranty_expires IS NULL
LIMIT 5;
複合条件と集合演算子の優先順位
複数の条件を組み合わせる場合、ANDとOR演算子を使用します。MySQLはANDを先に評価するため、意図しない結果を避けるために括弧による明示的なグループ化が必須です。
-- ANDのみ:両方の条件を満たす場合
SELECT sku, price FROM product_catalog
WHERE stock_status = 'available' AND price >= 2000;
-- OR:いずれかの条件を満たす場合
SELECT sku, category FROM product_catalog
WHERE category = 'BOOK' OR category = 'MAGAZINE';
括弧を使用しない場合と使用した場合で、評価順序が変化し、結果セットが大きく異なる点に留意してください。
-- 括弧なし(ANDが優先): status='discontinued'かつprice<500、またはcategory='SALE'
SELECT sku FROM product_catalog
WHERE stock_status = 'discontinued' AND price < 500 OR category = 'SALE';
-- 括弧あり(明示的優先): (status='discontinued'またはprice<500) かつ category='SALE'
SELECT sku FROM product_catalog
WHERE (stock_status = 'discontinued' OR price < 500) AND category = 'SALE';
複数の一致候補を指定する場合は、IN演算子を用いると記述が簡潔になり、実行計画が最適化されることが多いです。また、サブクエリをネストして動的な条件生成にも利用できます。
SELECT sku, product_name, price
FROM product_catalog
WHERE category IN ('AUDIO', 'VIDEO', 'CAMERA');
NOT演算子は条件を否定します。IN、BETWEEN、EXISTSなどの句と組み合わせ可能です。
SELECT sku, category FROM product_catalog
WHERE category NOT IN ('BOOK', 'MAGAZINE');
パターン検索:LIKEと正規表現
曖昧な文字列検索にはLIKEとREGEXPが使用されます。LIKEはカラム全体の値とマッチングを行うのに対し、REGEXPはカラム内の部分文字列に一致するパターンを検出します。
-- %:任意の文字(0文字以上)
-- _:任意の1文字
SELECT product_name FROM product_catalog
WHERE product_name LIKE '%Adapter_' ;
正規表現検索では、REGEXPキーワードの後に標準的なパターン構文を記述します。MySQLのデフォルトでは大文字小文字を区別しませんが、BINARYを追加することで区別できます。
-- ORマッチング(|)
SELECT sku, serial_number FROM product_catalog
WHERE serial_number REGEXP 'A|B|C';
-- 文字セット[]によるOR同等の表現
SELECT sku FROM product_catalog
WHERE serial_number REGEXP 'SN[012]';
| 構文 | 説明 |
|---|---|
[^abc] | 指定文字以外にマッチ |
[a-z] または [0-9] | 範囲指定 |
*, +, ? | 0回以上, 1回以上, 0回または1回 |
{n}, {n,}, {n,m} | 正確n回, n回以上, n回からm回 |
[:digit:], [:alpha:], [:alnum:] | 文字クラス(数字, アルファベット, 英数字) |
MySQL環境では、正規表現内の特殊文字やバックスラッシュ自体をエスケープするために、二重バックスラッシュ(\\)が必要です。
-- 数字が連続して出現するパターンの抽出
SELECT sku, price FROM product_catalog
WHERE price REGEXP '^[[:digit:]]{4}$';
-- 単語境界とアンカーの活用
-- ^: 文字列の先頭, $: 末尾, [[:<:]]: 単語の開始, [[:>:]]: 単語の終了
SELECT product_name FROM product_catalog
WHERE product_name REGEXP '^[[:alnum:]]{3}[[:digit:]]';
算出フィールドとエイリアスの定義
クエリ実行時に既存カラムを加工して新しい値を生成する際は、文字列関数や数値関数を使用します。複数の文字列を結合するにはCONCAT()関数が標準的です。他のDBMSでは||演算子が使われることもありますが、MySQLでは関数呼び出し形式が推奨されます。
-- 文字列結合
SELECT CONCAT(product_name, ' [', category, ']') AS display_info
FROM product_catalog
LIMIT 3;
結合前に不要な空白を除去するには、TRIM()(両端)、LTRIM()(左端)、RTRIM()(右端)を適用します。
SELECT CONCAT(TRIM(product_name), ': ', price) AS formatted_price
FROM product_catalog
ORDER BY price DESC;
生成された算出カラムや集計結果には、ASキーワードを使用して別名(エイリアス)を割り当てることができます。これにより、アプリケーション側でのデータ参照が容易になります。
SELECT
CONCAT(RTRIM(category), '_', sku) AS item_id,
price * stock_count AS total_value
FROM product_catalog
WHERE stock_count > 0
ORDER BY total_value DESC;