備忘録的プログラミングリファレンス

リレーショナルデータベースについて

 リレーショナルデータベース、 Relational Database Management System(RDMS)とは関連している複数のテーブル(表)で構成されるデータベースの一種です。

 テーブル(表)を使ったデータの保存をする方法に表計算ソフトがあります。

表計算

 表計算ソフトとデータベースの違いは、表計算ソフトは見ながら作成できますが、データベースは SQL プログラム言語で概念的に定義、操作するところです。

CREATE TABLE example (
	id	SERIAL,		/* ID */
	name	VARCHAR(30),	/* name */
	...
);

SELECT * FROM example;

 表計算ソフトは汎用性に乏しいのですが、データベースはリレーションという技術で複数のテーブル(表)を関連付けることができ在庫データと売上データを連動させることができるといった汎用性をもっています。
 さらに、データベースには web アプリケーションや他のプログラムと連携するといったことができ、大規模なシステムに向いています。

 テーブルというと食事をするための机を指しますが、コンピュータの世界でのテーブルは行列のある表のことを指します。テーブルの上に拡げられた一覧表というイメージでしょうか。

テーブル(表)の作成

 データベースでは関連する複数のテーブル(表)で構成されます。
 1つのテーブルをみてみると、表計算ソフトにみられるような行列の形態をしています。しかし、表計算ソフトのように目に見える形をしておらず、SQL というプログラム言語で操作することが基本となります。

 表計算ソフトとデータベースでの違いを作成方法からみてみます。
 例えば、売上管理の表を作成するとします。項目名は、日付、商品名、単価、数量、金額、合計金額が考えられます。
 売上管理を表計算ソフトで作成する際には、以下のように作成するのではないしょうか。

合計金額( =sum(金額) )
番号日付商品名単価数量金額
/ / ( =個数✕単価 )
/ / ( =個数✕単価 )
/ / ( =個数✕単価 )
売上管理

 この例では慣例として行ごとに番号をふるので番号という列を設けています。

 表計算ソフトでは行列に並んだマス目を利用しますが、データベースでは項目を定義して実際のデータは後で追加していきます。

 上記の売上管理の表で例えるなら、データベースの表の作成においては先に項目名を抜粋します。

列名の部分

 そして、SQL 文で以下のようなテーブルを定義します。カラムとして項目名とそのデータ型を定義しています。

CREATE TABLE transfer_slip (
	number		SERIAL,				/* 番号 */
	date_time	DATE DEFAULT current_date,	/* 日付 */
	goods_name	VARCHAR(30),			/* 商品名 */
	unit_price	INT,				/* 単価 */
	amount		INT,				/* 数量 */
	price	BIGINT GENERATED ALWAYS AS ( amount * unit_price ) STORED  /* 金額 */
);

 データは作成したテーブルに SQL で入力操作を行います。例えば上記で作成したテーブルにデータを入力するには以下のような INSERT 文を使用します。

INSERT INTO transfer_slip( date_time, goods_name, unit_price, amount );
	   VALUES ( '2023/6/1', 'candy', 3, 100 );

 このように SQL を利用したデータベースの運用はプログラムという概念が先行しますので難解であることが欠点です。さらに、運用するには API やインターフェイスを用意しなければならないといった手間が増えます。
 しかし、データベースは処理速度が速く汎用性をもっており、大規模なデータの運用に向いています。

 ここではデータベースの作成や管理について触れていません。データベースの作成について知りたい方はデータベースの作成を参照してください。

リレーショナル

 リレーショナルデータベースの特徴は、関連データの参照ができることです。

 上記の例でいえば、入力される売上データの商品名が自由に入力できます。自由に入力できると同じ商品であるにも関わらず複数の商品名で記録されることになります。
自由に商品名を記録できると何の商品を指しているのかを誰もが分かるという状態ではないという欠点が生じます。
 この欠点を解消するために商品名もテーブルとして記録し、さらにそのテーブルが参照できたら便利です。

 以下のように商品データを記録するためのテーブルを用意します。

CREATE TABLE goods (
	id		SERIAL,				/* 番号 */
	goods_name	VARCHAR(30),			/* 商品名 */
	unit_price	INT				/* 単価 */
);

 用意した商品テーブルを売上テーブルから FOREIGN KEY で参照できるようにします。

CREATE TABLE transfer_slip (
	number		SERIAL,				/* 番号 */
	date_time	DATE DEFAULT current_date,	/* 日付 */
	goods_name	VARCHAR(30),			/* 商品名 */
	unit_price	INT,				/* 単価 */
	amount		INT,				/* 数量 */
	price	BIGINT GENERATED ALWAYS AS ( amount * unit_price ) STORED,  /* 金額 */

	FOREIGN KEY(goods_name) REFERENCES goods(goods_name)
);

 FOREIGN KEY で該当するテーブルを参照できるようにすれば、自由にデータを入力することはできません。
 自由にデータを入力できないようにすることによってデータの整合性を保つことができます。

 このような商品テーブルを作成し、売上テーブルから参照できるようにするといった関連するデータで構成されたデータベースをリレーションデータベースといいます。

 上記の例の場合は、単価も商品テーブルから参照できるようにし、金額は都度計算するようにします。そのためには VIEW を使用します。

 まずは transfer_slip テーブルを編集し直します。

CREATE TABLE transfer_slip (
	number		SERIAL,				/* 番号 */
	date_time	DATE DEFAULT current_date,	/* 日付 */
	goods_name	VARCHAR(30),			/* 商品名 */
--	unit_price	INT,				/* 単価 */
	amount		INT,				/* 数量 */
--	price	BIGINT GENERATED ALWAYS AS ( amount * unit_price ) STORED,  /* 金額 */

	FOREIGN KEY(goods_name) REFERENCES goods(goods_name)
);

 次に VIEW を作成します。

VIEW の作成
CREATE VIEW transfer_slip_view AS
	SELECT
		slip.number	AS number,	/* 番号 */
		slip.date_time	AS date_time,	/* 日付 */
		slip.goods_name	AS goods_name,	/* 商品名 */
		goods.unit_price AS unit_price,	/* 単価 */
		slip.amount	AS amount,	/* 数量 */
		price	BIGINT GENERATED ALWAYS AS ( slip.amount * goods.unit_price ) STORED,  /* 金額 */
	FROM transfer_slip AS slip INNER JOIN goods AS goods on slip.goods_name=goods.goods_name;

 VIEW を参照することでも複数のテーブル(表)を関連付けた形で参照することができます。

 このようにリレーショナルデータベースは複数のテーブル(表)と関連付けることができます。例えば売上、商品、顧客といったデータを関連付けてデータを保存することができます。