前回紹介した基本的なテーブルの関連付けでは、条件に一致したレコードだけが表示されます。従って、「テーブルには記録されているのに結果には表示されないレコード」が存在することになります。
- WHERE句による条件の指定 - 商品を記録した「商品_mr」とその仕入先を記録した「仕入先_mr」の2つのテーブルを関連付け「商品ID 品名 仕入単価 仕入先ID 仕入先名」の各フィールドを抽出する方法として、前回は以下のようなSQLを紹介しました。
SELECT 商品_mr.商品ID, 商品_mr.品名, 商品_mr.仕入単価, 商品_mr.仕入先ID, 仕入先_mr.仕入先名 FROM 商品_mr, 仕入先_mr WHERE 商品_mr.仕入先ID = 仕入先_mr.仕入先ID
WHERE句で双方のテーブルから関連付けたいテーブル同士を=演算子でつなぐことによって、
商品_mrの仕入先IDと等しい(=)値を 仕入先_mrの仕入先IDから探して結びつける
という処理が行われます。
さらに、テーブルに別名を充てることで、上記のSQLは以下のように簡略化できました。
SELECT A.商品ID, A.品名, A.仕入単価, A.仕入先ID, B.仕入先名 FROM 商品_mr AS A, 仕入先_mr AS B WHERE A.仕入先ID = B.仕入先ID
これが、最も基本的な関連付けの形です。
- 表示されないレコード - 上記SQLの実行結果をもう一度見ておきましょう。気が付いた方もいると思いますが、クエリアナライザの結果ペインに表示された実行結果では、「商品_mr」に記録されている商品のレコードはすべて表示されていますが、「仕入先_mr」に記録された仕入先の中には、表示されていないレコードが存在します。
Enterprise Managerで「商品_mr」の全レコードを見れば、仕入先ID=305の「テイコー産業」から仕入れている商品(「仕入先ID」フィールドの値が“305”のレコード)が存在しません。そのためSQLの実行結果で、「テイコー産業」の名前はどこにも表示されないのです。
現時点で取引をしていない仕入先が仕入先を記録するマスターテーブルに存在することは、実務では十分あり得ます。ですから、基本的な関連付けの状態では、このことに何の問題もありません。
このような表示結果となるのは、WHERE句の条件式で双方のテーブルの「仕入先ID」が等しいレコードだけを抽出するよう設定しているからです(WHERE A.仕入先ID = B.仕入先ID)。
このように、双方のテーブルからフィールドの値が等しい組み合わせだけを抽出する関連付けの形態を「等結合」あるいは「等価結合」と呼びます。
- 一致するレコードだけを抽出する - 等結合では、条件式で指定したフィールド同士の値が等しくない(一致しない)レコードが切り捨てられ、一致するレコードだけが抽出(結果として表示)されます。
上の場合とは逆に、間違った仕入先(「仕入先_mr」に存在しない仕入先IDの値)を記録されたレコードが「商品_mr」に存在してしまうことも(本来はあってはならないのですが、何かの間違いで)、あり得るでしょう。そのような場合には、間違った仕入先IDを持つ「商品_mr」側のレコードが表示されなくなります。
但し、サンプルのデータベースでは、「商品_mr」のあるレコードの「仕入先ID」を存在しない値(例えば“9001”など)にした場合、テーブルを保存しようとした時点で「参照整合性制約に反するので記録できない」旨の警告が表示され、書き換えた値は書き換える前の(正当な)値に戻されます。これは、「第10回 テーブルの関連付けとサブクエリによる条件の抽出」で紹介したダイヤグラム(各テーブルの関連付けの状態を予め記録したオブジェクト)によって、互いに矛盾する値を記録できないよう設定してあるためです。参照整合性については、回を追って説明します。
ここでは例を示しませんが、試す場合は「商品_mr」と同じ構造でレコードを持つ「商品_dmy」を使ってください。「商品_dmy」を作るには、クエリアナライザで以下のSQLを実行します ※1。
SELECT * INTO 商品_dmy FROM 商品_mr
なお「商品_dmy」の作り方とSELECT INTO命令については、本コラムの第8回(データの加工命令(2))~レコードの削除と削除処理の注意点)で紹介しています。
※1 サンプルのex00.sqlに同じ内容のSQLが記録されているので、クエリアナライザでそれを開いて実行しても構いません
|
|
|