2.7. 自己参照型フィールドの注意点¶
自己参照フィールドとは、所属するテーブルを参照するフィールドのことです。
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()
も参照してください。