2.7. 自己参照型フィールドの注意点

自己参照フィールドとは、所属するテーブルを参照するフィールドのことです。

../../_images/web2py_dal_024r.JPG

DALではこのような参照フィールドを設定することが可能です。しかし、いくつか注意点があります。

1.定義上の注意点

自己参照型フィールド定義で、Tableクラスのインスタンスを指定しますとエラーが発生します。

db.define_table('bom',
    Field('item'),
    Field('assembly', db.bom))  # この部分でエラー発生

これはbomテーブルの定義が完了していないのに、assemblyフィールドでbomテーブルに参照しようとするからです。 エラー回避のためには、次のように referenceキーワードで記述します。

db.define_table('bom',
    Field('item'),
    Field('assembly', 'reference bom')) # referenceキーワードに変更

referenceキーワードについては Fieldクラスtypeパラメータ を参照ください。

2.利用上の注意点

自己参照型フィールドがあるテーブルで、同じテーブル同士を テーブル結合(join) する場合は、一方のテーブル(同一テーブルですが)に 別名設定しないと動きません。DALではTableクラスのwith_aliasメソッドを利用します。これはSQL文で言えば、AS演算子を使用するのと同じ意味です。

上記のテーブル定義を利用したサンプルを示してみます。

personテーブルのデータです。

>>> print db(db.bom).select()
bom.id,bom.item,bom.assembly
1,Antle,0
2,Lines,1
3,Every,1
4,Granu,3
5,Roame,3

with_alias メソッドを利用して、join命令を発行してみます。

>>> def_assem = db.bom.with_alias('assem')
>>> rows = db().select(db.bom.item, def_assem.item,
... left=(def_assem.on(def_assem.id==db.bom.assembly)))

joinの結果を確認してみます。

>>> print rows
bom.item,assem.item
Antle,<NULL>
Lines,Antle
Every,Antle
Granu,Every
Roame,Every

同じテーブル同士でjoinできたことが確認できました。

with_alias はSQL文に別名のテーブルを設定します。別名が設定されたTableクラスのインスタンスが、def_assemになります。 このため、def_assemを利用してleft(join)を指定すれば、別名のテーブルで設定したことになります。

最後にjoin命令のSQL文を見てみます。

>>> print db._lastsql
SELECT  bom.item, assem.item FROM bom LEFT
JOIN bom AS assem ON (assem.id = bom.assembly);

SQL文ではAS演算子が使われていることがわかります。

with_aliasメソッドについては with_alias() も参照してください。

参考: Self-Reference and Aliases自己参照と別名