データベース用語集
【概要】
本用語集は,データベースシステムの基礎から応用までを体系的に整理した技術資料である.データベースの基本概念,データモデリング,リレーショナルデータベース理論,SQL言語,物理的実装,SQLite固有の機能までの全8章で構成される.各用語は相互参照リンクにより関連概念と結びつけられている.データベース管理システムの理論的基盤と実装技術の両面から知識の習得を支援する.大学の情報工学課程における教材として,またデータベース技術者の参考資料として利用できる.
【目次】
- 1. データベースの基本概念
- 2. データモデルとデータベース設計
- 3. リレーショナルデータベースの理論
- 4. データベース管理システム
- 5. SQL言語
- 6. データベースの物理的実装とパフォーマンス
- 7. SQLite特有の概念と操作
- 8. データベースの応用
【サイト内の関連ページ】
1. データベースの基本概念
ファイル:ファイル名を持ち,デジタルデータを保存する基本単位である.主要な操作には,オープン,クローズ,読み出し,書き込みがある.
データベース:複数のエンドユーザやアプリケーションプログラムによって共有され,継続的に利用されるデータの集合体である.実世界の特定の側面をデータとして表現し,通常は二次記憶装置(ハードディスクなど)に格納される.必要に応じてメインメモリにキャッシュされ,アクセスが行われる.
例:大学の学生情報データベースでは,学生ID,氏名,所属学部,履修科目などの情報が複数のテーブルに格納され,学生課や各学部の教職員が共有して利用する.
データベースの正しさ:データベースは実世界の状態を正確に表現することが求められる.構造設計は現実世界の多様性に対応できる柔軟性を持ち,データには誤りや矛盾がない状態が求められる.柔軟性の欠如や誤記録,重複登録は,システムの信頼性と運用効率を低下させる.
問い合わせ(クエリ,query):データベースから必要な情報を抽出するために実行される命令である.データの検索,抽出,集計などの操作を指定し,その結果としてデータを取得する.リレーショナルデータベースでは,SQLを用いて問い合わせを記述し,データベース管理システムに送信する.
2. データモデルとデータベース設計
データモデル:実世界の情報をデータベースとして記述するためのフレームワークである.データベースのデータ構造を定義する規約,データに対する操作体系の定義,データの一貫性制約を規定するための規約体系から構成される.
データモデリング:概念モデルと論理モデルを設計するプロセスである.実世界のデータベース化は,通常,概念モデルから論理モデルへと段階的に進められる.実世界の要求を反映させるため,ユーザや関係者との要件分析が前提となる.
概念モデル:データベース化対象の実世界について,データ構造と一貫性制約を抽象的に記述したモデルである.特定の論理モデルやデータベース管理システムに依存しない設計手法である.
論理モデル:リレーショナル,ネットワーク,階層型,オブジェクト指向などの種類があり,データベース管理システムの特性に応じて選択される.概念モデルが確立されていれば,その構造を論理モデルへと変換できる.
実体関連モデル:概念モデルを記述するための方法論である.実世界を実体型と関連型で表現し,それぞれに属性を付与する.さらに,主キーによる一貫性制約などの規則を定義する.
例:大学のデータベース設計では,「学生」「教員」「科目」などが実体型となり,「履修」が学生と科目を結ぶ関連型となる.学生には学籍番号や氏名という属性があり,学籍番号が主キーとなる.
実体:実世界において独立して認識可能な対象である.
実体関連図:実体関連モデルによる概念モデルを視覚的に表現する図式表現である.実体型は四角形,関連型は菱形,属性は楕円で表され,主キーには下線が付される.主キーを持たず他の実体型に依存する弱実体型は二重枠の四角形で示される.実体型と関連型を結ぶ線分上には,1,N,Mの記号で関係の多重度を示す.
3. リレーショナルデータベースの理論
3.1 基本概念
リレーショナルデータベース:データを表(テーブル)形式で管理するデータベースシステムであり,各テーブルは行(レコード,タプル)と列(属性)から構成される.複数のテーブル間の関連付けを扱い,テーブル間の結合や分解が可能である.SQLを用いたデータ操作や検索を行い,データフォーマット,データ操作体系,データ型の定義方法,一貫性制約の規定方法が標準化されている.テーブル定義,一貫性制約,トランザクション,実行計画,二次索引などの概念が基礎となり,MySQL,PostgreSQL,SQLiteなどが代表的な実装例である.
例:学生情報を管理するデータベースでは,「students」テーブル(学籍番号,氏名,生年月日),「classes」テーブル(科目コード,科目名,単位数),「enrollment」テーブル(学籍番号,科目コード,成績)の複数のテーブルでデータを管理する.
リレーショナルデータモデル:データベースをテーブルの集合として記述し,データ操作の体系をリレーショナル代数やタプルリレーショナル論理に基づいて行うデータモデルである.主キー制約,一意制約,非空制約,ドメイン制約,参照整合性制約などの一貫性制約が存在する.
リレーショナルデータベース管理システム:リレーショナルデータモデルの機能を実装したデータベース管理システムである.MySQL,PostgreSQL,SQLiteなどが該当し,データの格納,検索,更新,管理を行うための機能を提供する.一貫性制約を記述する機能や,制約に違反する更新を拒否する機能を実装している.
3.2 データ構造
ドメイン:データ項目が取りうる値の集合である(a set of permitted values).例えば,「年齢」というデータ項目のドメインは,整数値の集合 {0, 1, 2, …, 120} のように定義される.データベースの各列に対してドメインを設定することで,データの整合性を確保する基盤となる.
単純値:分解不可能な値である.数値,文字,文字列,時刻,日付,論理値などを指す.「みかん」は単純値であるが,{みかん, りんご}のような集合は単純値ではない.属性名「family name」と「given name」の直積集合やドメイン要素のべき集合など,構造化された値や直積集合の要素は単純値とはみなされない.
直積集合:n個の集合S1, S2, …, Snが与えられたとき,各集合から1つずつ要素を取り出して作る組をすべて集めた集合である.S1 × S2 × … × Snと記す.例えば,S1 = {1, 2}, S2 = {a, b, c}のとき,S1 × S2 = {(1, a), (1, b), (1, c), (2, a), (2, b), (2, c)}となる.順序が重要であり,S2 × S1は異なる集合となる.
リレーション:ドメインD1, D2, …, Dnの直積集合「D1×D2×…×Dn」の有限部分集合である.id,年月日,顧客名,商品ID,単価,数量などの複数の属性とそれぞれのドメインで構成される情報の集合がリレーションとなる.リレーショナルデータベースの基本的な構成要素である.
タプル:直積集合の各要素,またはリレーションの各要素である.順序付けされた値の組み合わせとして,リレーションの構成要素となる.データベースのテーブルでは,1つの行(レコード)がタプルに相当する.
例:学生テーブルの1行「(1001, '山田太郎', '工学部', '2002-05-15')」が1つのタプルである.
多重集合(multi-set):要素の重複を許す集合である.リレーショナルデータベースでは,例えば得点データ {85, 75, 90, 85, 75} などを集計するために用いられる.単なる集合では {85, 75, 90} となり平均点が正しく計算できないが,多重集合では重複を考慮して計算できる.
テーブル(table):リレーショナルデータベースの構成要素で,行(レコード)と列(属性)から構成される二次元の表形式のデータ構造である.多重集合を基礎とする体系であり,同じ値を持つ行が複数現れることが許される.ヘッダ(属性名が配置される部分)と本体(属性のドメインの直積集合の要素からなる多重集合)から構成され,本体にはリレーションのほか,重複値を持つ多重集合も格納できる.物理的には,各行がテーブルに格納されている1つの実体を表す.例えばscoresテーブルはname,teacher_name,student_name,scoreなどの列を持つ.
属性(attribute):リレーショナルデータベースのテーブルにおいて,各列が1つの属性を構成する.テーブル内の列を表す要素で,データ型とドメインを持つ.属性名は各列に付けられた名前であり,テーブルのヘッダに記述される.id,年,月,日,顧客名,商品ID,単価,数量などが属性名となる.point3テーブルのx,y,z属性は実数型の座標値を格納する例である.テーブルのタプルが更新されても,属性名は不変である.
第一正規形:ドメインとして,分解不可能な単純値のみを対象とすることである.リレーショナルデータベースの設計指針の1つで,データを単純な形式に保つことで操作と管理を容易にする.第一正規形を満たすことで,データの冗長性を減らし,整合性を高める.
3.3 スキーマとキー
リレーション/テーブルスキーマ:テーブル名とその属性(列)名の集合で構成され,テーブルの構造を定義するものである.Rをリレーション名,A1, A2, …, Anを属性名とするとき,「R(A1, A2, …, An)」のように表記される.例えば「point3(id, x, y, z, created_at)」や「scores(id, name, teacher_name, student_name, score)」のように表記する.各属性にはドメインが定義され,テーブルの構造が規定される.テーブルのタプルが挿入・削除・変更されてもリレーションスキーマ自体は不変である.
データベーススキーマ:データベース全体の構造を定義する情報であり,テーブル定義,制約,索引などの情報が含まれる.SQLiteではsqlite_masterテーブルに格納され,ルート・ページなどの情報も含まれる.
キー(key):テーブルのタプルを一意に識別するために使用できる属性または属性の組のうち,極小なものである(極小とは,その一部分だけではキーの役割を果たせないという意味).候補キーとも呼ばれる.テーブルの2つ以上のタプルが同一のキー属性値を持つことはない.例として,学生テーブルでは学籍番号がキーとなり,図書館の本ではISBNコードがキーとなる.
主キー(primary key):テーブル内の各行を一意に識別するための属性または属性の組み合わせである.リレーションスキーマの複数の候補キーから,データベース管理者が選定し,かつ空値をとることがない1つを選んだものである.テーブル定義時に「PRIMARY KEY」として指定され,キーが1種類しか存在しない場合は,それが自動的に主キーとなる.値の重複やNULL値を許さず,通常は自動的に索引が作成される.SQLiteでは,INTEGER型のPRIMARY KEY列に対してAUTOINCREMENTを指定できる.
例:
create table students ( student_id integer primary key, name text not null, department text, email text unique );ここでstudent_idが主キーとなり,各学生を一意に識別する.
外部キー(foreign key):あるリレーションの属性が,別のリレーションの主キーを参照するように設定されている場合の属性である.例えば,リレーションR(…, Ai, …)の属性AiがリレーションS(…, Bj, …)の主キーBjを参照する場合,Aiは外部キーとなる.この参照は,AiがBjの値と一致するか空値である必要があり,テーブル間の関連付けを可能にする.データの参照整合性を維持する役割を持つ.
例:
create table enrollments ( id integer primary key, student_id integer, course_id integer, grade text, foreign key (student_id) references students(student_id), foreign key (course_id) references courses(course_id) );ここでstudent_idとcourse_idが外部キーとなり,それぞれstudentsテーブルとcoursesテーブルを参照している.
UNIQUE制約(一意制約):指定した列または列の組み合わせが,テーブル内で重複しないことを保証する制約である.productsテーブルのproduct_name列にUNIQUE制約を設定し,製品名の重複を防ぐ.PRIMARY KEYとは異なり,NULL値を許可する.
自動インクリメント(AUTOINCREMENT):主キーとして使用される整数値を自動的に増加させる機能である.テーブル定義時に「AUTOINCREMENT」として指定すると,新しい行が挿入されるたびに,指定された列の値が自動的に増加する.SQLiteではINTEGER PRIMARY KEY列は自動的に増加するが,AUTOINCREMENTキーワードを追加すると,行IDの割り当てアルゴリズムが変更され,削除された値が再利用されない動作となる.
3.4 関数従属性と正規化
正規化(normalization):データの冗長性を減らし,データの整合性を向上させるための手法である.情報無損失の原則があり,正規化後のテーブル群から元のテーブルを復元できる.
例:注文テーブルが「注文ID, 顧客ID, 顧客名, 商品ID, 商品名, 価格, 数量」のような構造の場合,顧客名や商品名,価格などが重複して格納される.これを「注文(注文ID, 顧客ID, 商品ID, 数量)」「顧客(顧客ID, 顧客名)」「商品(商品ID, 商品名, 価格)」の3つのテーブルに分割することで正規化できる.
関数従属性:リレーションスキーマの属性間の依存関係を表すものである.社員テーブルにおいて社員番号→氏名, 部署のように,ある属性集合の値が決まれば,別の属性集合の値が一意に決まる関係を示す.リレーションスキーマの任意のインスタンスで満たされる必要がある.
更新時異状:データベースの更新時に発生する問題である.修正時異状,挿入時異状,削除時異状の3種類があり,正規化によって更新時異状を解消できる.
修正時異状:リレーションのタプルの属性値の修正において発生する問題である.教授の所属学部が変更された場合に,その教授の全ての講義に関するタプルを更新する必要があるなど,実世界の変化を反映させるために複数のタプルを同時に更新しなければならない状況で発生する.
挿入時異状:リレーションへのタプルの挿入において発生する問題である.学生が履修科目を持たない場合に学生と科目の関係を表すテーブルに学生情報を登録できないなど,非空制約やキー制約がある属性の属性値が空値であるようなタプルは挿入できない.
削除時異状:リレーションからのタプルの削除において発生する問題である.ある科目の最後の履修者が履修を取りやめた場合にその科目自体の情報も失われるなど,実世界の変化を反映させるためにタプルを削除すると,他の情報も同時に失われる可能性がある.
ボイス・コッド正規形:リレーションスキーマの正規形の1つである.リレーションスキーマが持つ任意の関数従属性X→Yについて,Xがそのスキーマのキー(スーパーキー)になっていることを要求する.情報無損失分解によりボイス・コッド正規形にすることで更新時異状が解消されるが,分解前の関数従属性を維持できないこともある.
テーブルの分解:あるテーブルを属性集合の部分集合による射影で置き換えるプロセスである.scoresテーブルをA(name, teacher_name)とB(id, name, student_name, score)に分解するように,元の属性集合の全てを含むように複数の部分集合に分割する.
情報無損失分解:分解されたテーブルから元のテーブルを復元できる分解である.あるリレーションがその分解成分の自然結合をとると元の形に復元できるときの分解を指す.A(name, teacher_name)とB(id, name, student_name, score)から元のscoresテーブルを復元できる場合などが該当する.
結合と分解:リレーショナルデータベースにおいて,複数のテーブルを結合したり,1つのテーブルを複数のテーブルに分解したりする操作である.JOIN操作やビューを使用して実現し,データの正規化や検索効率に関わる.
3.5 制約と空値
一貫性制約:データベース内のデータが矛盾なく保たれるための条件である.リレーショナルデータモデルでは,主キー制約(PRIMARY KEY),外部キー制約(FOREIGN KEY, REFERENCES),一意制約(UNIQUE),非空制約(NOT NULL),ドメイン制約,チェック制約(CHECK,「score >= 0 AND score <= 100」などの条件式で指定)などがある.例として「月の値は1から12の範囲内」「氏名欄の必須入力」「誕生年に3009などの実現不可能な値を禁止」などの条件を設定できる.これらにより,データの整合性を保証し,無効なデータの挿入や更新を防止する.一貫性制約を満たしていても,生年月日の年の誤入力などの人為的ミスは防げない.
例:
create table products ( id integer primary key, product_name text unique not null, price numeric check (price > 0), stock integer default 0, category_id integer references categories(id) );この例では,以下の制約がある:
- idは主キー制約(重複不可,NULL不可)
- product_nameは一意制約と非空制約(重複不可,NULL不可)
- priceはチェック制約(0より大きい値のみ許可)
- category_idは外部キー制約(categoriesテーブルのid列を参照)
空値(NULL):値が存在しない,未定,値が未知などの状態を表すための特別な値である.例えば,自由席の「予約座席番号」,担当者が未定の授業,あるいは存在するが未把握の住所などで使用される.SQLiteにおいて空値を表し,特定のカラムに「NOT NULL」制約を設けることでNULLを許容しないよう指定できる.データベースの設計において,空値の扱いは検討する必要がある.
4. データベース管理システム
データベース管理システム:データベースを管理し,利用環境を提供するソフトウェアシステムである.データベース定義機能,データベース操作機能,問い合わせ最適化機能,大量データへのアクセス機能,一貫性制約維持機能,アクセス権限と機密保護機能などを実装している.PostgreSQL,MySQL,SQLiteなどが該当し,それぞれのシステムによってサポートするデータ型や機能が異なる.
Microsoft Access:リレーショナルデータベースを作成・管理するためのソフトウェアであり,GUIベースのツールを備えている.
Accessのビュー:Microsoft Accessにおける画面表示の形式で,データシートビュー,デザインビュー,SQLビューの3種類がある.
組み込み型データベース管理システム:アプリケーションプログラムに直接統合され,独立プロセスとしては動作しないシステムである.同時アクセス制御や権限管理機能が簡略化される代わりに,軽量に動作する.
トランザクション(transaction):データベース操作の論理的な単位であり,複数のデータベース操作をまとめて1つの処理単位として扱う機能である.「begin transaction;」で開始し,「commit;」で確定または「rollback;」で取り消すことができる.ACID特性(原子性,一貫性,独立性,永続性)を持ち,すべての操作が成功するか,すべて失敗するかのいずれかになる.アプリケーションプログラムの異常終了時でもデータベースの一貫性を維持する機能,複数ユーザによる同時アクセス環境下でのデータ整合性保証,データの消失を防止する永続性保証機能を含む.
例:銀行の振込操作では,「出金アカウントからの引き落とし」と「入金アカウントへの入金」が1つのトランザクションとして扱われる.
begin transaction; -- 山田さんの口座から1000円引き落とす update accounts set balance = balance - 1000 where account_id = '1001'; -- 鈴木さんの口座に1000円入金する update accounts set balance = balance + 1000 where account_id = '2001'; commit;操作のどちらかが失敗した場合,rollbackが実行され,どちらの口座残高も変更前の状態に戻る.これにより,残高が消失したり,二重に処理されたりする問題を防ぐ.
ACID特性:トランザクションの信頼性を保証する4つの特性.
- 原子性(Atomicity):トランザクションに含まれる操作は,すべて実行されるか,まったく実行されないかのいずれかであることを保証する特性.例えば銀行振込では,出金と入金が両方成功するか,両方失敗するかのどちらかとなる.
- 一貫性(Consistency):トランザクションの実行前後でデータベースが一貫性制約を満たした状態を維持することを保証する特性.トランザクション実行前にデータベースが正しい状態であれば,トランザクション実行後も正しい状態が保たれる.すなわち,全ての一貫性制約(主キー制約,外部キー制約,チェック制約など)が維持される.
- 独立性(Isolation):複数のトランザクションが同時に実行される場合でも,各トランザクションは他のトランザクションの影響を受けずに実行されるように見える特性.
- 永続性(Durability):成功したトランザクションの結果は,システム障害が発生しても永続的に保存されることを保証する特性.COMMIT後のデータは消失しない.
BEGIN TRANSACTION:トランザクションの開始を宣言する文である.これ以降の操作はCOMMITかROLLBACKまで1つの処理単位として扱われる.
ROLLBACK:トランザクション内のすべての操作を取り消す文である.データベースはトランザクション開始前の状態に戻る.
ジャーナルファイル:トランザクション中の変更を一時的に記録するファイルである.mydbデータベースの場合は「mydb-journal」という名前で,システム障害時の回復やROLLBACKの際に使用される.
5. SQL言語
SQL(Structured Query Language):リレーショナルデータベースを操作するための標準的な言語である.英文として読み下せるように設計されている.CREATE TABLE,INSERT,SELECT,UPDATE,DELETEなどの文を用いて,データの定義,挿入,検索,更新,削除を行う.データ操作に加え,データベーススキーマの定義やトランザクション管理などの機能も提供する.「select * from E where score > 80;」のような問い合わせ(クエリ)と呼ばれる命令文の形式で記述し,テーブルを扱い,同一値の行の重複も許可する.例として「select name, score from students where score > 80 order by score desc;」は成績が80点を超える学生を点数の高い順に表示する.SQL文のキーワードは大文字小文字を区別しないが,テーブル名やカラム名は区別する場合がある.
5.1 テーブル定義とデータ型
テーブル定義:データベース内のテーブル構造を規定する操作である.テーブル名,各列の名前,データ型,制約条件などを指定し,SQLではCREATE TABLE文を使用して行う.PRIMARY KEY,REFERENCES(外部キー参照),UNIQUEなどの一貫性制約も同時に設定できる.
データ型(data type):SQLで扱うデータの種類を定義するものである.SQLiteには,NULL,INTEGER,REAL,TEXT,BLOBの5つのストレージクラスがある.NULL(空値),INTEGER(符号付き整数,値の大きさに応じて1〜8バイトのいずれかで格納),REAL(浮動小数点値,8バイトのIEEE浮動小数点数),TEXT/CHAR(文字列,可変長,最大長をchar(n)のように宣言可能.ただしSQLiteはこの長さ制限を強制しない.データベースのエンコーディング(UTF-8,UTF-16BE,UTF-16LE)で保存される),datetime(日付や時刻.SQLiteには日時専用のストレージクラスはなく,本資料の例のようにdatetime関数でISO8601形式の文字列を生成する場合はTEXT型として格納される),BLOB(バイナリデータ.画像やオーディオファイルなど,入力データがそのままの形で格納される)などがある.productsテーブルでは,idはINTEGER型,product_nameはTEXT型などを使用する.SQLiteは動的型付けを採用しており,列に宣言された型と異なる型の値も格納できる.
CREATE TABLE文:新しいテーブルを作成するためのSQL文である.「create table products (...)」のように記述し,テーブル名,列定義,各列のデータ型,制約条件などを指定する.
5.2 データ操作とクエリ
SELECT文:データベースからデータを取得するためのSQL文である.「select * from products where id = 123;」のように記述し,取得したい列を指定して条件に合致するデータを抽出できる.「select A1, A2, ..., An」のように複数の列を指定する場合はカンマで区切る.「*」を使用すると全ての列を取得でき,「テーブル名.*」で特定テーブルの全列を指定できる.WHERE句やORDER BY句と組み合わせて使用される.
例:
-- 全学生の情報を取得 select * from students; -- 工学部に所属する学生の氏名と学年を取得 select name, grade from students where department = '工学部'; -- 成績が80点以上の学生を成績の高い順に取得 select name, score from grades where score >= 80 order by score desc;FROM句:SQL問い合わせにおいて,データを取得するテーブルを指定する部分である.「from T1, T2, ..., Tm」のように複数のテーブルを指定する場合はカンマで区切る.テーブル参照リスト内で「社員 X, 社員 Y」のようにタプル変数を定義することも可能で,テーブルの別名として使用できる.
WHERE句:SQL問い合わせにおいて,抽出条件を指定する部分である.「where id = 123」や「where X.部長 = Y.社員番号 AND X.給与 > Y.給与」のように,比較演算,論理演算,各種述語(BETWEEN,IN,LIKE,IS NULL,EXISTSなど)を使用して条件を表現する.複数の条件を論理演算子ANDやORで組み合わせることもできる.
INSERT文:SQLでデータベースにデータを挿入するための文である.「insert into E values('Database', 80, 'KK', datetime('now', 'localtime'), NULL)」のようにVALUES句で直接値を指定する方法とSELECT文の結果を挿入する方法がある.テーブルに新しい行(レコード)を追加する操作を行う.
例:
-- 学生テーブルに新しい学生を追加(全列指定) insert into students values (1005, '田中太郎', '情報学部', 2, 'tanaka@example.com'); -- 列名を明示的に指定して学生を追加 insert into students (student_id, name, department) values (1006, '佐藤花子', '経営学部'); -- 別のテーブルから選択したデータを挿入 insert into graduated_students select * from students where grade = 4;DELETE文:SQLでデータベースから条件に合致する行を削除するための文である.「delete from E where name = 'Database' AND student_name = 'AA'」のようにWHERE句で削除条件を指定する.
例:
-- 特定の学生IDのレコードを削除 delete from students where student_id = 1001; -- 特定の条件に合致する複数レコードを削除 delete from grades where score < 60 and term = '前期';UPDATE文:SQLでデータベース内の既存データを更新するための文である.「update E set score=90, updated_at=datetime('now', 'localtime') where name = 'Database' AND student_name = 'KK'」のようにSET句で更新内容を,WHERE句で更新対象を指定する.
例:
-- 特定の学生のメールアドレスを更新 update students set email = 'new.email@example.com' where student_id = 1003; -- 複数の列を同時に更新 update products set price = price * 1.1, last_updated = datetime('now', 'localtime') where category = 'electronics';DISTINCT指定:SQLにおいて問い合わせ結果から重複行を除去するための指定である.「select distinct name, teacher_name from scores」のように,SELECTと選択リストとの間に「DISTINCT」と記述することで,結果に重複行がある場合に1つを残して他を除去する.
ORDER BY句:問い合わせ結果をソートするためのSQL句である.「order by product_name」でproduct_nameの昇順に,「order by product_name desc」で降順に並べ替える.指定した列の値に基づいて昇順(ASC,デフォルト)または降順(DESC)にソートでき,複数の列を指定することで複合的なソート条件を適用できる.
COUNT関数:SQL集計関数の1つで,指定した条件に合致する行数を計算する.「count(*)」で条件に合致する全行数を,「count(substr(product_name, 1, 1))」で対応する値の数をカウントできる.単独で使用するか,GROUP BY句と組み合わせて各グループの行数を求めることができる.
SUM関数:SQL集計関数の1つで,指定した列の値の合計を計算する.「sum(price)」で商品価格の合計を求めるなど,数値データの集計に使用される.
AVG関数:SQL集計関数の1つで,指定した列の値の平均を計算する.「avg(score)」でテストの平均点を求めるなど,数値データの平均値算出に使用される.
MAX関数:SQL集計関数の1つで,指定した列の最大値を返す.「max(price)」で最高価格を,「max(date)」で最新の日付を求めるなど,様々なデータ型で使用できる.
MIN関数:SQL集計関数の1つで,指定した列の最小値を返す.「min(price)」で最低価格を,「min(date)」で最も古い日付を求めるなど,様々なデータ型で使用できる.
GROUP BY句:指定した列の値でグループ化を行い,各グループに対して集計関数を適用するSQL句である.「group by substr(product_name, 1, 1)」のように記述し,product_nameの先頭文字でグループ化して各グループの行数をカウントできる.複数の列を指定することで多次元のグループ化も可能である.
例:
-- 学部ごとの学生数を集計 select department, count(*) as student_count from students group by department; -- 科目ごとの平均点と最高点を算出 select course_name, avg(score) as average, max(score) as highest from grades group by course_name;HAVING句:GROUP BY句によってグループ化された結果に対して条件を適用するためのSQL句である.「having count(substr(product_name, 1, 1)) > 24」のように記述し,先頭文字ごとにグループ化した結果のうち,行数が24を超えるグループのみを抽出できる.WHERE句がグループ化前の行に対して条件を指定するのに対し,HAVING句はグループ化後の集計結果に対して条件を指定する点が異なる.
比較演算子:SQLにおける2項述語として機能する演算子である.「<」(より小さい),「<=」(以下),「=」(等しい),「>=」(以上),「>」(より大きい),「<>」(等しくない)の6種類がある.「price > 25」のような条件式で使用される.
論理演算子:複数の条件を組み合わせるための演算子である.AND(論理積),OR(論理和),NOT(論理否定)がある.NULL値を含む行を抽出するためのIS NULLや,文字列パターンマッチングのためのLIKE(「%」や「_」のワイルドカードを使用)なども条件式で使用される.
LIKE演算子(パターンマッチ):文字列のパターンマッチングを行うための演算子である.「where type like '%AA%'」のように記述し,typeの値に「AA」を含む行を検索できる.ワイルドカード文字「%」(任意の0文字以上の文字列)と「_」(任意の1文字)を使用して文字列検索を実現する.SQLiteのデフォルト動作では,ASCII文字に限り大文字小文字を区別せずにマッチングを行う(Unicode文字は大文字小文字を区別する).「like 'B%'」は先頭が「B」または「b」の文字列,「like '%C'」は末尾が「C」または「c」の文字列にマッチする.
例:
-- 「田中」で始まる名前を検索 select * from students where name like '田中%'; -- メールアドレスが「gmail.com」で終わるレコードを検索 select * from contacts where email like '%@gmail.com'; -- 名前に「太」を含む学生を検索 select * from students where name like '%太%'; -- 3文字目が「子」である製品名を検索 select * from products where product_name like '__子%';文字列定数:SQLにおいて,文字列はシングルクオーテーションマーク「'」で囲む.日本語などの多バイト文字を含む場合,NATIONAL CHARACTER型(NCHAR型とも表記)として定義し,比較時には「専攻 = N'情報知能工学'」のように定数の前にプレフィックス文字「N」を付加する.
入れ子型質問:SQL問い合わせの中に別のSQL問い合わせ(副問い合わせ)を含む形式である.「属性名 IN <副問い合わせ>」または「値 IN <副問い合わせ>」の形で使用する.結果集合(x1, x2, ..., xn)に対して「x IN (x1, x2, ..., xn)」は「x = x1 OR x = x2 OR ... OR x = xn」と同値になる.
例:
-- 情報学部に所属する教員が担当する科目を取得 select * from courses where instructor_id in ( select id from instructors where department = '情報学部' ); -- 平均点より高い点数を取った学生を取得 select student_name, score from grades where score > (select avg(score) from grades);
5.3 関数と特殊操作
now関数:SQLiteで現在の日時を取得するための指定である.datetime関数などの引数として「'now'」の形で指定する.
datetime関数:SQLiteで日時データを「YYYY-MM-DD HH:MM:SS」形式の文字列に変換する関数である.「datetime('now', 'localtime')」のように使用する.
5.4 リレーショナル代数
リレーショナル代数:集合論に基づくデータベース操作の理論体系である.集合演算(和集合,差集合,共通集合,直積集合)とリレーショナル代数固有の演算(射影,選択,結合,商)で構成される.これらの演算は独立ではなく,例えば結合演算は直積演算と選択演算の組み合わせで実現できる.
直積演算:2つのリレーション(テーブル)のすべての行の組み合わせを生成する演算である.R(A1, A2, …, An)とS(B1, B2, …, Bm)の直積演算「R×S」は,RとSのすべてのタプルの組み合わせからなる新しいリレーションを生成する.SQLでは「from R, S」の形式で記述する.
θ-結合演算:2つのリレーションの直積集合から,指定された条件を満たす要素のみを選択する演算である.「R[AiθBj]S」と表記し,RのAi属性とSのBj属性に対して比較演算子θが成り立つ組み合わせを選択する.SQLでは「select * from R, S where R.AiθS.Bj」の形式で実現できる.
商演算:2つのリレーションR(A1, A2, …, An-m, B1, B2, …, Bm)とS(B1, B2, …, Bm)の関係を表す演算である.「R÷S」と表記し,「R÷S = { t | t ∈R[A1, A2, …, An-m] ∧ (∀u∈S) ((t, u) ∈R )}」と定義される.「すべて」の条件を表現するために使用される.
射影:テーブルから特定の列(属性)だけを選択する操作である.R[A, B]のように表記され,リレーションRから属性AとBのみを選択する.結果として得られるテーブルは選択された属性のみを含み,重複行がある場合は1つだけが残される.
タプルリレーショナル論理:一階述語論理に基づいてリレーションを宣言的に記述する形式である.「R(u)」(リレーション),「u[Ai]θv[Bj]」(属性値比較),「u[Ai]θc」(値比較)などのアトムと式を組み合わせる.全称記号(∀)や存在記号(∃)による変数定義(例:「(∃u)Φ(u)」)も可能である.
結合属性:2つのリレーションの共通属性である.学生(学生ID, 名前, 学科ID)と学科(学科ID, 学科名)の結合属性は「学科ID」となる.2つのリレーションにおいて,共通する属性集合が結合属性となり,各属性について元のリレーションにおけるドメインが等しい必要がある.
自然結合演算:2つのリレーションを結合属性の値が等しいタプルどうしで結合する演算である.結合演算と射影演算を使って表現でき,結果として得られるリレーションは両リレーションの全ての属性を含むが,結合属性は重複せず1つとして表現される.
テーブル結合(table join):複数のテーブルを特定の条件に基づいて1つにまとめる操作である.SQLのINNER JOINとON句などを使用して実行される.
例:
-- 内部結合(inner join)でstudentsとgradesテーブルを結合 select students.name, grades.course_name, grades.score from students inner join grades on students.student_id = grades.student_id; -- 左外部結合(left join)ですべての学生と履修科目(履修していない学生も含む)を取得 select students.name, enrollments.course_id from students left join enrollments on students.student_id = enrollments.student_id;
6. データベースの物理的実装とパフォーマンス
6.1 データベースファイルと物理構造
データベースファイル:データベースの内容が物理的に保存されるファイルである.SQLiteでは単一のファイルにデータベース全体が格納され,/home/ubuntuuser/mydbやC:\SQLite\mydbなどのパスで指定される.特定の物理構造を持ち,テーブルやレコードといったデータベースの要素が格納されている.
データページ:SQLiteデータベースファイル内のデータを格納する基本単位である.サイズは設定可能で,本資料の例では1024バイトであり,複数のレコードが格納される.データページ内には未使用部分も存在する.
レコード:データベース内のデータを格納する基本単位である.テーブルの1行に相当し,複数のフィールド値で構成される.バイナリエディタで確認すると,path,val,created_atなどのフィールド値をバイト列として確認できる.
レコードヘッダ:レコードの先頭に位置する領域で,レコードの長さやキー値などのメタデータが格納されている.例えばレコードの長さが「2E」や「2C」,キー値が「01」「02」「03」などの16進数で表示される.
キー値:レコードを識別するための値である.idフィールドなど,主キーとして定義されたフィールドの値に対応し,レコードヘッダに「01」「02」「03」などの値として格納される.
データベースファイルの物理構造:SQLiteデータベースファイルの内部構成である.SQLite 3ではデータベースヘッダがあり,データページのサイズは設定可能で,本資料の例では1024バイト(16進数で400)であり,レコードを単位としたストレージシステムとなっている.
バイナリエディタ:ファイルの内容をバイト単位で表示・編集できるツールである.UbuntuではGHex,WindowsではBzなどが利用でき,データベースファイルの物理構造を16進数表示とテキスト表示で確認できる.
テキスト・エンコーディング:データベースで文字データを格納する際の形式である.SQLiteでは,UTF-8,UTF-16BE(big-endian UTF-16),UTF-16LE(little-endian UTF-16)から選択可能である.エンコーディングの設定はデータベース作成時に行い,後から変更する場合は「PRAGMA encoding=UTF-16le;」のようなコマンドを実行する.
6.2 索引とパフォーマンス
索引:レコードを効率よく検索するためのデータ構造である.レコードデータの更新時には索引の維持が必要となるため,索引を増やしすぎると処理効率が低下する可能性がある.更新操作のたびに索引も更新する必要があるためである.
例:顧客テーブルに1000万件のデータがあり,氏名での検索が頻繁に行われる場合,氏名列に索引を作成することで検索速度が向上する.索引がない場合は全テーブルスキャンが必要となるが,索引があれば対象レコードへ直接アクセスできる.
主索引:主キーの値とレコードとを直接結びつける索引構造である.各テーブルに1つだけ存在し,テーブル定義時に「PRIMARY KEY」と指定した属性が主キーになる.point3テーブルではid属性に対する主索引が自動的に作成される.
二次索引:主索引のキー以外の属性による索引構造である.1つのテーブルに対して任意の数を作成でき,追加・削除が可能である.問い合わせの検索性能を向上させるための補助的なデータ構造である.「create index idx1 on point3(x)」というSQL文でx属性に対する二次索引を作成できる.二次索引がない場合はテーブルの全ての行を1行ずつ処理する必要がある.
索引エントリ:索引内の各項目で,元のテーブルの各行に対応する.キー値と,対応するレコードへの参照(ポインタ)で構成される.二次索引idx1では,x値とそれに対応するレコードへの参照で構成されている.
CREATE INDEX:二次索引を生成するためのSQL文である.「create index <索引名> on <テーブル名> (<列名の並び>)」の形式で使用し,指定した列に基づいて索引を作成する.「create index idx1 on point3(x)」はpoint3テーブルのx列に対する二次索引idx1を作成するコマンドである.
例:
-- 学生テーブルの氏名に索引を作成 create index idx_student_name on students(name); -- 複合索引(複数の列を組み合わせた索引)の作成 create index idx_department_grade on students(department, grade); -- ユニーク索引(重複を許さない索引)の作成 create unique index idx_unique_email on users(email);DROP INDEX:既存の二次索引を削除するためのSQL文である.「drop index <索引名>;」の形式で使用し,指定した名前の索引を削除する.「drop index idx1;」を実行するとidx1という名前の二次索引が削除される.
索引名:二次索引に付けられる識別子である.例えば「idx2」は索引名で,「drop index idx2」のように,索引の管理(削除など)に使用される.
6.3 実行計画とオペコード
実行計画(SQL問い合わせ計画):データベース管理システムがSQL問い合わせを実行する際の処理手順を示す計画である.SQLをコンパイルして作成され,データベースの基本的なオペレータの並びで表現される.索引の使用方法や結合の順序などを含み,問い合わせのパフォーマンス最適化に役立つ.SQLiteではEXPLAIN文(「explain select * from point3 where x < 1000000000;」など)で確認でき,索引の有無により実行効率が変わる.
例:
-- 索引なしの検索の実行計画を確認 explain select * from students where name = '山田太郎';このSQLの実行計画は,以下のようなオペコード列で表示される.
addr opcode p1 p2 p3 p4 p5 comment ---- ------------- ---- ---- ---- ------------- ---- ------------- 0 Init 0 12 0 00 Start at 12 1 OpenRead 0 2 0 3 00 root=2 tbl=students 2 Rewind 0 11 0 00 3 Column 0 1 1 00 r[1]=students.name 4 Ne 1 10 2 collseq(BINARY) name='山田太郎' 5 Rowid 0 3 0 00 r[3]=rowid 6 Column 0 0 4 00 r[4]=students.id 7 Column 0 2 5 00 r[5]=students.department 8 Column 0 3 6 00 r[6]=students.email 9 ResultRow 3 4 0 00 output=r[3..6] 10 Next 0 3 0 01 11 Halt 0 0 0 00 12 Transaction 0 0 1 0 01 13 Goto 0 1 0 00この例では,テーブルスキャン(全レコード走査)が行われているが,nameに索引があると実行計画が変わり効率的になる.
SQLコンパイル:データベース管理システムがSQL文を解析し,実行できる形式に変換する処理である.実行計画の生成につながり,SQLiteではSQLite Virtual Machine Opcodesとして表現される.
オペコード:SQLiteなどのデータベース管理システムの内部処理を指示する命令コードである.OpenRead,Rewind,Column,Next,Goto,Rowid,ResultRow,Neなどがあり,SQLの実行時に使用される.SQLiteの仮想マシンが実行する基本命令として機能する.
カーソル:データベーステーブルや索引内の特定の位置を指し示すポインタである.オペコードによって操作され,データベース操作時に現在処理中のレコードや索引エントリの位置を追跡するために使用される.OpenReadオペコードによって初期化され,テーブル内の行を順に処理するために使われる.Rewindオペコードでカーソルをテーブルの先頭に移動させる.
OpenRead:SQLiteのオペコードの1つで,指定されたテーブルに対して読み取り用のカーソルを作成する.オペランドP1にはカーソル番号,P2にはルートページ番号が設定される.
Rewind:SQLiteのオペコードの1つで,カーソルをテーブルの先頭行に位置づける.テーブルが空の場合は指定されたアドレスにジャンプする.問い合わせ計画では「Rewind P2 = 13」のように表示される.
Column:SQLiteのオペコードの1つで,カーソルが指し示すレコードの特定の列からデータを取り出し,指定されたレジスタに格納する.列番号は0から始まり,問い合わせ計画では「Column P3 = 1」などと表示される.
Rowid:SQLiteのオペコードの1つで,カーソルが指し示すレコードの主キーの値を,指定されたレジスタに格納する.問い合わせ計画では「Rowid P1 = 1, P2 = 1」のように表示される.
ResultRow:SQLiteのオペコードの1つで,指定された範囲のレジスタの値を1行として出力する.問い合わせの結果行を生成するために使用され,「ResultRow P1 = 1, P2 = 7」は7つのレジスタ値を出力する.
Next:SQLiteのオペコードの1つで,カーソルをテーブルの次の行に進める.末端に達した場合は次の命令に進み,そうでない場合は指定されたアドレスにジャンプする.「Next P2 = 4」は次行がある場合,アドレス4に戻る.
条件付きジャンプ:オペコードの一種で,特定の条件が満たされた場合にのみ,指定されたアドレスに制御を移す命令である.SQLiteの「Ne」(等しくない場合にジャンプ)や「Ge」(以上の場合にジャンプ)などのオペコードがこれにあたる.「Ge P1 = 1, P2 = 17, P3 = 2」はレジスタ1の値がレジスタ2の値以上の場合にアドレス17にジャンプする操作を表す.
レジスタ:SQLiteのような仮想マシンで使用される一時的なデータ格納領域である.オペコードの実行中に,中間結果や操作対象の値を保持するために使用される.「Integer P1 = 1000000000, P2 = 1」というオペコードはレジスタ1に値1000000000をセットする操作を表す.
ルート・ページ(ルート・ページ番号):テーブルや索引の最上位のページである.テーブルや索引へのアクセスの起点となり,データベース管理システムによって自動的に割り当てられ,sqlite_masterテーブルのrootpageフィールドに格納される.本資料の例では,point3テーブルのルート・ページ番号は12,二次索引idx1のルート・ページ番号は46である.
7. SQLite特有の概念と操作
SQLite:軽量で組み込み可能な,サーバレスなリレーショナルデータベース管理システムである.単一のファイルにデータベース全体を格納し,ファイルベースのデータベース管理を行う.CREATE TABLE,INSERT,SELECTなどのSQL文を使用してテーブル定義,データ挿入,問い合わせなどの操作が可能である.SQL問い合わせ計画の表示や,仮想マシンのオペコードの実行などの機能を持ち,Windows環境やUbuntu環境で利用でき,データ型としてNULL,INTEGER,REAL,TEXT,BLOBの5つのストレージクラスをサポートしている.モバイルアプリケーションや小規模なウェブアプリケーションで使用されている.
例:
-- SQLiteデータベースファイルを開く(コマンドライン) sqlite3 mydatabase.db -- テーブル作成 create table users ( id integer primary key, name text not null, email text unique, created_at datetime default current_timestamp ); -- データ挿入 insert into users (name, email) values ('山田太郎', 'yamada@example.com'); -- データ取得 select * from users;Pythonからデスクトップアプリに組み込む例を以下に示す.
import sqlite3 conn = sqlite3.connect('mydatabase.db') cursor = conn.cursor() cursor.execute('select * from users') for row in cursor.fetchall(): print(row) conn.close()Sqliteman:SQLiteデータベースを管理するためのグラフィカルユーザインターフェース(GUI)ツールである.「File」→「Open」メニューからデータベースファイルを開くことができ,データベースファイルの作成や既存データベースの開閉,「Run SQL」ボタンでのSQL問い合わせの実行,テーブルの内容確認,データの閲覧や編集などの操作を行うことができる.UbuntuやWindowsなど複数のプラットフォームで利用可能である.
オブジェクト・ブラウザ:Sqlitemanなどのデータベース管理ツールで提供される,データベース内のオブジェクトを階層的に表示する機能である.「Tables」を展開するとテーブル一覧が表示され,テーブルやビューなどを選択できる.
システムカタログ:データベース管理システムが内部で管理しているシステムテーブルの集合である.Sqlitemanで「System Catalogue」を展開することで閲覧可能で,データベースの構造を確認できる.
sqlite_master:SQLiteのシステムテーブルで,TEMPORARYテーブル以外のデータベーススキーマが格納されている(SQLiteの標準名は「sqlite_schema」であり,「sqlite_master」は歴史的経緯による別名として利用できる).type,name,tbl_name,rootpage,sqlの各列を持つ.「select * from sqlite_master;」でテーブル一覧を取得できるが,DROP TABLE,UPDATE,INSERT,DELETEなどの直接の更新操作は許可されていない.
例:
-- sqlite_masterテーブルからデータベース内のすべてのテーブル情報を取得 select name, type, sql from sqlite_master where type = 'table'; -- 特定のテーブルに関する情報を確認 select * from sqlite_master where tbl_name = 'users'; -- 索引情報を取得 select name, tbl_name from sqlite_master where type = 'index';一括実行:複数のSQL文を連続して実行する機能である.「Run multiple SQL statements...」ボタンでトランザクション内の複数操作を一度に実行する際に使用される.
文法エラー:SQLの構文が正しくない場合に発生するエラーである.未定義の値を使用した場合などで,トランザクション内で発生した場合はエラーの対応方法によってトランザクションの続行可否が決まる.
埋め込みSQL:プログラミング言語の中にSQL文を組み込んで使用する技術である.C,Java,Pythonなどの言語からアプリケーションでデータベースを操作する際に用いられる.文字列としてSQL命令を定義し,データベース接続オブジェクトのメソッドを通じて実行するプログラミング手法である.
例:Pythonでの埋め込みSQL
import sqlite3 # データベース接続 conn = sqlite3.connect('school.db') cursor = conn.cursor() # 埋め込みSQLの実行 student_id = 1001 cursor.execute(''' select s.name, c.course_name, g.score from students s join grades g on s.student_id = g.student_id join courses c on g.course_id = c.course_id where s.student_id = ? ''', (student_id,)) # 結果の取得と処理 for name, course, score in cursor.fetchall(): print(f"学生名: {name}, 科目: {course}, 成績: {score}") # 接続を閉じる conn.close()
8. データベースの応用
データウェアハウス(data warehouse):過去のデータを蓄積・分析するためのシステムである.時間の経過に伴うデータの変化を記録し,日時情報を付加して管理する.
例:小売企業では,日々の販売データ,在庫データ,顧客データなどが店舗システムから定期的にデータウェアハウスに集約される.このデータを基に,季節ごとの売上傾向分析,商品カテゴリ別の需要予測,顧客セグメント分析などを行い,経営戦略やマーケティング施策に活用する.