4D v14.3

リレーションのタイプ

ホーム

 
4D v14.3
リレーションのタイプ

リレーションのタイプ  


 

 

最も一般的なリレーションはNテーブルと1テーブル間で使用されるもので、N対1リレーションと呼ばれます。しかしN対Nや1対1リレーションを作成することもできます。すべてのリレーションはマニュアルあるいは自動リレーションにできます。

リレーションは自動またはマニュアルで使用できます。

自動リレーションでは、リレートしたテーブルのレコードがカレントになると、4Dは対応するレコードをカレントセレクションにします。カレントセレクションになった一連のレコードは表示、印刷、更新、そして検索や並び替えの対象として使用できます。プログラミングは必要ありません。

マニュアルリレーションでは、開発者が4Dに対し、対応するレコードをメモリにロードするかどうかを指示します。この制御を行うにはメソッドを使用します。リレートしたテーブルを制御するメソッドを作成するための情報は4Dランゲージリファレンスマニュアルを参照してください。

すべての対応するレコードを毎回ロードする必要がないようなアプリケーションでは、パフォーマンスを最適化するためにマニュアルリレーションを選択するでしょう。例えば3つ以上のテーブルが互いにリレートしているようなストラクチャーでは、リレートしたレコードのメモリへのロードを制御したくなるでしょう。また2つのテーブル間で2つの異なるリレーションを行う際も、マニュアルリレーションを使用する必要があります。2つのテーブル間では1つの自動リレーションしか存在できません。対してマニュアルリレーションはいくつでも存在できます。

2つのテーブル間でリレーションを作成する場合、リレーションで主キーを含むテーブルを1テーブル、外部キーを含むテーブルをNテーブルと呼びます。1テーブル中の1レコードがNテーブル中のNレコードにリレートし、Nテーブル中のNレコードが1テーブル中の1レコードにリレートするため、それぞれ1テーブル、Nテーブルと呼ばれます。このタイプのリレーションはN対1リレーションと呼ばれます。

従業員と会社間のリレーションにおいて、[Companies]テーブルは1テーブルであり、[Employees]テーブルはNテーブルです。1つの会社レコードは複数の従業員レコード (例: 会社に勤めるすべての従業員) にリレートし、複数の従業員が1つの会社 (例: 彼らが働く会社) にリレートします。例えば[Companies]テーブルにAcmeレコードが1つだけあり、Acmeに勤務する従業員のレコードが複数[Employees]テーブルに登録されることがあります。

[Employees]テーブル中のいずれかのレコードがカレントになると、4Dは[Companies]テーブルから対応するレコードを1つロードします。[Companies]テーブル中のフィールドがフォーム上に配置されていれば、その値が自動で表示されます。
下図では、[Employees]テーブルのレコードが1つロードされたときに[Companies]テーブルのレコードが特定され、[Employees]テーブルレコードのフォーム上に会社の所在地と電話番号が表示されている様子を示しています:

対して[Companies]テーブルのレコードが1つカレントになると、4Dは[Employees]テーブルレコードのセレクションを作成し、フォーム上に表示します。このリレーションは他のテーブルの複数のレコードを指定するため、複数の従業員の名前や役職が表示されます。フォームに表示されているレコードだけがメモリにロードされます。

下図では、[Companies]テーブルのレコードが1つロードされたときに複数の[Employees]テーブルのレコードが特定され、[Companies]テーブルレコードのフォーム上に、その会社で働く従業員の名前と役職がリスト表示されている様子を示しています:

1テーブルとNテーブルの区別は、リレーションごとに異なります。あるテーブルはあるリレーションにおいては1テーブルとなり、別なリレーションではNテーブルとなることがあります。リレーションにおいてテーブルは1つだけしか主キーをもつことができませんが、外部キーは複数持つことができます。

例えば[Employees]テーブル中の全員に製品サンプルを送付するとしましょう。[Postal Rates]テーブルを作成し、郵便番号と、郵便番号ごとの配送料を登録します。このストラクチャーを使用すると、従業員ごとに送付のための料金を含む住所ラベルを印刷することができます。下図はデータベースストラクチャーに追加された[Postal Rates]テーブルを示しています。

[Postal Rates]テーブルのZip Codeフィールドは主キーであり、[Postal Rates]テーブルは1テーブルです。[Companies] テーブルのZipフィールドはリレーションの外部キーフィールドです。Zipフィールドは外部キーなので、重複した値を登録することができます。つまり[Companies]テーブルは[Postal Rates]テーブルに対するNテーブルです。

そんなわけで、あるテーブルが1テーブルかNテーブルかは他のテーブルに対するリレーションで決定されます。[Companies]テーブルは[Postal Rates]テーブルとのリレーションではNテーブルであり、[Employees] テーブルとのリレーションでは1テーブルです。

1対1リレーションは特別なケースで使用されます。通常1対1リレーションはひとつのテーブルに合成できます。

以下は1対1リレーションを使用するいくつかの理由です:

  • あまりにも多くのフィールドをテーブルに定義する必要があるため、論理的にそれらをグループ分けしたほうがデータベースの動作が速くなり、管理も容易になるケース。
  • 特定のフィールドへのアクセスを制限したいケース。分離したテーブルを使用すれば、それぞれのテーブルごとにことなくアクセス権を割り当てることができます。

時にはあるテーブルのNレコードと他のテーブルのNレコードをリレートさせる必要があります。これはN対N (あるいは多対多) リレーションと呼ばれます。

N対Nリレーションの例に、受講履歴のデータベースがあります。データベースに2つのテーブル[Students]と[Classes]があるとします。ひとりの生徒は複数の講座を受講し、ひとつの講座には複数の生徒が在籍します。ひとりの生徒が受講するすべての講座を見る必要があり、ある講座を受講するすべての生徒を見る必要もあります。

N対Nリレーションの例はほかにもあります:

  • [Suppliers]と[Products]: 問屋は多くの製品を扱い、各製品は複数の問屋から提供されます。
  • [Employees]と[Account]: 各従業員は複数の取引を扱い、各取引は複数の従業員により処理されます。
  • [Movies]と[Actors]: 各映画には複数の出演者がいて、各出演者は複数の映画に出演します。

4Dを使用して自動N対Nリレーションを作成できます。キーは関連する2つのテーブルとそれぞれ1対Nでリレートする中間テーブルを作成することにあります。そのうえで、すべての必要なレコード追跡と表示を行うリストフォームと詳細フォームを作成することができます。この節ではN対Nリレーションを処理するために自動リレーションを使用する方法を説明します。

下図は生徒の受講状態を管理するためのデータベースに定義された3つのテーブル[Students], [Classes], [Joining]を示しています。このデータベースストラクチャーはこの節でN対Nリレーションを説明するために通しで使用されます。

[Students]テーブルは1テーブルで、各生徒ごとに1つのレコードが作成され、名前、専攻、GPA (成績平均点) が格納されます。StudentIDフィールドにより生徒はユニークに識別されます。
[Classes]テーブルも1テーブルです。各講座ごとに1つのレコードが作成され、講座名と講師名が格納されます。CatalogTitleフィールドにより、講座がユニークに識別されます。
中間テーブルである[Joining]は他の2つのテーブルに対してNテーブルとなります。このテーブルにはN件の学生とN件の講座レコードが登録されます。このテーブルのフォームは他の両テーブルのデータを入力するため、および他の両テーブルの情報を表示するために使用されます。
3つのテーブルを使用することで、データが効率的に格納されます。生徒の完全なデータは1つのレコードのみに格納され、講座の完全なデータも1つのレコードにのみ格納されます。生徒の各受講データは一度だけ格納されますが、結果すべての組み合わせを表現することができます。

中間テーブル (この例題では[Joining]テーブル) を使用して、他の両テーブルからの情報を入力および表示します。[Joining]テーブルに入力できる各レコードはリレートしている他のテーブル (生徒と講座) です。[Joining]テーブルのレコードにはリレーションを実行するための2つの情報、studentIDとcatalogTitleだけが格納されます。以下は[Joining]テーブルに作成された新しいレコードの例です。

このレコードはJeffrey T. SpauldingがJournalism講座を受講していることを示しています。このレコードは実際には2つのテーブルからの情報を表示しているにすぎません。

同様のレコードが、各生徒が受講するすべての講座に対して作成されます。実際にはStudentIDとCatalogTitleだけが[Joining]テーブルに格納されます。各レコードには特定の生徒が受講する特定の講座が保存されます

注: [Joining]テーブルのレコードがロードされると、リレートしたテーブルのレコードセレクションが自動で作成されます。この場合セレクションは対応する生徒と講座レコードで構成されます。ここで他のテーブルのセレクションを表示すると、1つのレコードだけが表示されます。すべてのレコードを表示するにはクエリーメニューからすべてを表示を選択します。

このレコードの入力フォームは以下のようになります。フォーム中に[Students]および[Classes]テーブルのフィールドが含まれている点に留意してください。

データはStudentIDとCatalogTitleフィールドにのみ入力されます。StudentIDが入力されると、4Dはリレートした[Students]テーブルから対応する情報を探し、それをLast Name、First Name、Majorフィールドに表示します。同様にCatalogTitleが入力されると4Dは講座を[Classes]テーブル内で検索し、その情報を表示します。

これら3つのテーブルの情報をサブフォームを使用して表示することができます。生徒のレコードでは生徒が受講するすべての講座のリストを表示でき、講座レコードではその講座を受講するすべての生徒のリストを表示できます。

生徒のレコードに講座のリストを表示するには、サブフォームを使用します。サブフォームの作成に関する情報はサブフォームの作成と設定を参照してください。

上図は[Students]テーブルのレコードです。レコードの上部には生徒に関する情報が表示されています。この生徒が受講している2つの講座の情報が下部に表示されていますが、これは受講情報が格納された[Joining]テーブルのデータが使用されています。

サブフォームは[Joining]テーブルのものであり、[Classes]テーブルではない点に留意してください。[Joining]テーブルは生徒のレコードから講座のレコードにリレートする情報を格納しています。サブフォームには[Classes]テーブルのClassNameフィールドが置かれています。[Joining]と[Classes]テーブル間のリレーションのために、4Dは自動で正しい講座名を表示します。

以下はある講座とその講座を受講する生徒を表示するレコードです:


これは[Classes]テーブルのレコードで、講座の情報と、それを受講する生徒のリストが表示されています。生徒の情報もまた[Joining]テーブルから表示されます。

このサブフォームの例題で、表示されたすべてのフィールドにデータを入力することができます。例えば講座レコードに新しい学生を入力するには、サブフォームに表示された最後の生徒レコードに移動し、Ctrl+Shift+/ (Windows) または Command+Shift+/ (Mac OS) を押して新しいレコードを作成します (ショートカットはデータベース設定で変更できます、を参照)。適切なStudentIDを入力すると、レコードの他の情報が表示されます。

データベースに設定されたリレーションはデータベースの動作において重要な役割を持ち、テーブル間の情報フローを制御します。

自動リレーションが設定されたレコードが詳細フォームを使用してディスクからロードされると、リレートしたテーブルの対応するレコードがカレントセレクションになります。リレーションが1つだけレコードを選択した場合、そのレコードがディスクからロードされます。リレーションにより複数のレコードが選択されると、レコードの新しいカレントセレクションがそのテーブルに作成され、カレントセレクションの先頭レコードがディスクからロードされます。ディスクからロードされたレコードはそのテーブルのカレントレコードと呼ばれます。

この節の例題では、リレーションは3つのテーブル間だけで設定されていました。実際のアプリケーションでは、リレーションは複数のテーブル間で作成され、チェーンのように次々とアクティブ化されます。リレーションがアクティブ化されるたびに、4Dはリレートしたテーブルのレコードセレクションを作成し、レコードをディスクからロードします。ディスクからロードされたレコードはそのテーブルのカレントレコードとなり、そのテーブルがさらに自動リレーションを持てば、4Dは次のリレートしたテーブルのセレクションを作成しカレントレコードをロードします。

テーブルリレーションが正しく設定されていないと、テーブル間の情報の流れは混乱し、壊れてしまいます。注意すべきリレーション構造を以下に紹介します。

循環リレーションは情報が無限にループするように設定されたリレーションです。下図は循環リレーションの例であり、[Employees]テーブルが[Company]テーブルにリレートし、[Company]テーブルは[Insurer]テーブルにリレートし、[Insurer]テーブルは[Employee]テーブルに戻ってリレートしています。

[Employee]テーブルのレコードがディスクからロードされると、4Dはリレートする[Company]テーブルのレコードをロードします。このレコードは[Company]テーブルのカレントレコードとなります。これによりリレートする[Insurer]テーブルのレコードがロードされます。

もしテーブルリレーションがこのまま続行されると、[Insurer]テーブルにリレートする[Employee]テーブルのレコード (会社により保険が掛けられたすべての従業員) が選択され、先頭レコードがカレントレコードになります。このカレントレコードは、このリレーションチェーンが開始された元の従業員レコードとは異なるかもしれません。この状況では、4Dはどのレコードが実際のカレントレコード化を知るすべがありません。

4Dはこの種の循環リレーションを検知すると、チェーンの最後のテーブルでリレーションが停止します。この場合、[Insurer]と[Employee]テーブル間のリレーションは実行されません。


カレントレコード間での同様の衝突が、同じテーブルに複数のリンクがある場合にも発生します。
1つのテーブルに対して一度に複数のカレントレコードを持つことはできないため、同じテーブルに対す複数のテーブルからの自動リレーションを管理することはできません。
以下のストラクチャーは同じテーブルにリレートするテーブルとそのサブテーブルを表しています。

ユーザーが[Employees]テーブルで作業しているとき、[Insurance]テーブルのリレートしてレコードがロードされ、それがこのテーブルのカレントレコードとなります。
しかし[Children]と[Insurance]テーブル間にもリレーションがあります。つまり、[Children]テーブルのカレントセレクションの先頭レコードに基づく[Insurance]テーブルのリレートしたレコードもロードされることを意味します。親の保険会社と子の保険会社が異なる場合、このリレーション構造は問題となります。この場合4Dはリレーションの続行を停止しません。両方のリレーションが実行されますが同時ではありません。
この種のストラクチャーを使用したい場合はマニュアルテーブルリレーションを使用し、4Dランゲージリファレンスマニュアルで説明されているコマンドを使用してリレーションを制御しなければなりません。

自動リレーションでは管理できないリレーション構造のもう一つの例は、2つのテーブル間で複数のリレーションが設定されているケースです。1テーブルのリレートしたフィールドのデータを更新するたびに、他のテーブルのカレントレコードが変更されてしまします。この状況では自動リレーションを使用することはできません。

テーブルには1つだけカレントレコードが存在できるため、セレクション中のレコードすべてにリレーションが実行されるわけではありません。以下のストr買う茶ーのような請求書システムを考えてみましょう:

[Invoices]テーブルのレコードが使用されると、その請求書の請求明細である[InvoiceLines]テーブルのセレクションが作成されます。しかし[InvoiceLines]テーブルの先頭レコードに対応する[Items]テーブルのレコードだけが選択されます。[Items]テーブルのセレクションは請求書のすべての項目の情報を含むわけではありません。

しかし、[InvoiceLines]を[Invoices]テーブルのサブフォームとして配置した場合は、4Dは請求明細を呼び出すたびに項目へのリレーションを実行して、項目名を各行に表示させることができます。

 
プロパティ 

プロダクト: 4D
テーマ: データベースストラクチャーの作成

 
ARTICLE USAGE

デザインリファレンス ( 4D v14 R2)
デザインリファレンス ( 4D v12.4)
デザインリファレンス ( 4D v13.4)
デザインリファレンス ( 4D v14 R3)
デザインリファレンス ( 4D v14.3)
デザインリファレンス ( 4D v14 R4)