リレーションを貼ってみるナリ

現状のデータベースはちょっとつまらないです。テーブルが一つだけでリレーションは張っていません。せっかくリレーショナルデータベースを使うのだから、やっぱりリレーションが張ってあるテーブルをいじってみたいなぁ。でもリレーションなんて難しいことやってみたことないしなぁ。できるのかなぁ…。

(いろいろ調べちゅう)

ということで、1時間くらいネットを徘徊したところで早速リレーションを張ってみたいと思います。

リレーションて何

リレーションというのは関連づけということです。例えばこんなテーブルを考えてみます。

nameemail
age
city
company
co_location 
a
a@hoge.com
28
shibuya
hoge
chiba
b@hoge.com
37
minatohoge
chiba 
cc@hoge.com55
meguro
hogechiba
dd@fuga.com33yokohama
fugakanagawa
ee@fuga.com41totsuka fugakanagawa
このテーブルにはそれほどレコードが無いのであまり不自由は感じませんが、これが100件、200件というふうに増えてくると「company」「co_location」を別管理にした方がよいということがわかります。次のように人間についてのレコードを管理するテーブルと、会社についてのレコードを管理するテーブルを別々にした方が入力や修正が簡単になるでしょう。

nameemail
age
city
co_id
a
a@hoge.com
28
shibuya
1
b@hoge.com
37
minato
cc@hoge.com55
meguro
1
dd@fuga.com33yokohama
2
ee@fuga.com41totsuka 2
co_id
company
co_location 
1
hoge
chiba
2fuga
kanagawa

ここでこの二つのテーブルを関連づけているのは「co_id」というフィールドです。すなわちこのフィールドを接着剤にして二つのテーブルをリンクさせている(リレーションを張っている)わけです。

リレーションいろいろ

リレーションを張るときに大切なのは、どんなリレーションにするかということです。リレーションの種類として代表的なのは次のようなものです。

1対1の関係
例えばお菓子テーブルとバーコードテーブルという二つのテーブルを考えてみると、それぞれのレコードは1対1の関係にあります。この二つのテーブルは1対1のリレーションにあります。
1対多の関係
例えばお菓子テーブルとメーカーテーブルという二つのテーブルを考えてみると、メーカーテーブルのレコード1つに対して、お菓子テーブルのレコードが複数対応します(例えばメーカーAは商品Aも商品Bも商品Cも製造している、など)。一方お菓子テーブルのレコード1つに対するメーカーテーブルのレコードは1つだけです(例えば商品Aを製造しているのはメーカーAだけである、など。共同開発とか特殊な事情は考えません)。このときこの二つのテーブルは1対多のリレーションにあります。
多対多の関係
例えばお菓子テーブルと販売店テーブルという二つのテーブルを考えてみると、お菓子テーブルのレコード1つに対して、販売店テーブルのレコードが複数対応します(例えば商品Aは販売店Aでも販売店Bでも売っている、など)。一方販売店テーブルのレコード1つに対してもお菓子テーブルのレコードが複数対応します(販売店Aでは商品Aも商品Bも売っている、など)。このときこの二つのテーブルは多対多のリレーションにあります。

Turbogearsプロジェクトのテーブルを増やしてリレーションを張る

以上をふまえて、現在のデータベースに新たにテーブルを作成し、既存のテーブルとリレーションを張ってみたいと思います。

テーブルの変更と追加

現在データベースにはお菓子に関するテーブルがあります。

* クラス名は先頭大文字の方がよさげなので「snack」→「Snack」と変更し、またnameフィールドに64文字の制限をつけました(´ω`)

#model.pyの中身
class Snack(SQLObject):
    name = UnicodeCol(length=64)
    eval = IntCol()
    comment = UnicodeCol()

ここにメーカーに関するデータのフィールドを加えていきたいと思います。とりあえず何も考えずにメーカーの名前を入れるフィールドを追加することにします。

#model.pyの中身
class Snack(SQLObject):
    name = UnicodeCol(length=64)
    eval = IntCol()
    comment = UnicodeCol()
maker = UnicodeCol() ←メーカーの名前が入るフィールド

この段階では、ただ単にフィールドを増やしただけです。リレーションは張っていません。

リレーションを張る前にメーカーに関するデータを入れるテーブルを用意しなければいけませんね。メーカーテーブルには、メーカーの名前とそのメーカーが製造したお菓子のフィールドを用意することにします。こちらも何も考えずテーブルを書きます。

class Maker(SQLObject):
name = UnicodeCol(length=64)
snacks = UnicodeCol()

この段階では、ただ単にテーブルを追加しただけでリレーションは張っていません。

リレーションを張る

テーブルが二つできたところで双方にリレーションを張ってみたいと思います。このSnackとMakerの関係は「1対多」です。Maker(1)に対してSnack(多)のデータがあります。

Snackテーブルに注目してみると、makerフィールドというのが他のテーブル(Maker)からデータを引っ張ってきたい部分です(現時点では便宜上UnicodeCol()としてあります)。ここにはMakerテーブルから引っ張ってきたメーカーの名前が「1」個だけ入ってほしいところですので、外からのデータ(ForeignKey:外部キー)が入りますよということで、

maker = ForeignKey('Maker')

と書いてあげます。

今度はMakerテーブルに注目してみると、snacksフィールドというのが他のテーブル(Snack)からデータを引っ張ってきたい部分です(現時点では便宜上UnicodeCol()としてあります)。ここにはSnackテーブルから引っ張ってきたお菓子の名前が「多」個入ってきて欲しいところですので、複数個のデータが入りますよということで、

snacks = MultipleJoin('Snack')

と書いてあげます。

* 当初の計画ではメーカーに関するデータ表示などの機能は考慮にいれていませんでしたが、計画に追加することにします。

まとめると、「1対多」の関係の場合は、

  • そのフィールドに他のテーブルから1個のデータが入る→ForeignKey('他のテーブル名')
  • そのフィールドに他のテーブルから複数個のデータが入る→MultipleJoin('他のテーブル名')

という関係になりましょうか(ホントかな…)。

ということで、最終的にmodel.pyは以下のようになりました。

from sqlobject import *
from turbogears.database import PackageHub

hub = PackageHub("snack")
__connection__ = hub

class Snack(SQLObject):
    name = UnicodeCol(length=64)
    eval = IntCol()
    comment = UnicodeCol()
    maker = ForeignKey('Maker')

class Maker(SQLObject):
    name = UnicodeCol(length=64)
    snacks = MultipleJoin('Snack')

うーん、すごく自信ないんですが、これでいいんでしょうか。

カテゴリ
Turbogears Turbogears
トラックバック用URL:
http://nagosui.org/Nagosui/COREBlog2/make-relation/tbping
コメントを追加

下のフォームに記入してコメントを追加できます。平文テキスト形式。

(必須)
(必須)
(必須)
(Required)
Enter the word

このBlogについて
Plone, Zope, Pythonなどのトピックについてのメモです。
カテゴリ
Plone (98)
Plone Products (23)
COREBlog2 (31)
COREBlog1 (29)
ReadingCOREBlog (7)
Zope (66)
Turbogears (18)
Django (12)
Python (25)
Linux (30)
Nagosui (12)
Design (33)
Misc (48)
moblog (5)
最近のエントリ
浜松ブラスバンド定期演奏会2008 nyusuke 2008年11月24日
Glossy Horizontal Menuを使う nyusuke 2008年11月17日
第3回Python東海終了 nyusuke 2008年11月17日
Universalじゃない件 nyusuke 2008年11月15日
最近のコメント
Re:WebデザイナーのためのDjangoはじめの一歩 nyusuke 2007年06月01日
Re:WebデザイナーのためのDjangoはじめの一歩 pateo 2007年05月31日
Re:東海Python Workshop 01終了 nyusuke 2007年05月31日
Re:東海Python Workshop 01終了 kfuruhata 2007年05月30日