2011-09-14 50 views
1

大きな画像をSQLAlchemyモデルの設定とすると誰かが参考になるので、すべてのレベルで参照整合性が保証されますか?参照整合性 - SQLAlchemyの設定方法?

DBによって参照整合性が表現され、強制されなければならないというアイデアが浮かび上がってきました。私は必要と思うすべての制約を持つスキーマ(現在Postgresqlにあります)を作成しました。 。

私はSQLAlchemy(0.7)を宣言モードで使用して、このDBの上にアプリケーションを構築します。

を検索し、ビットを読んだ、私は私が設定できることを学びました:私の列()の定義に

  • にonUpdate/ondeleteルール。
  • 私の関係()定義のカスケードオプション、
    これらはSQLAlchemyのセッションレベルで動作するようです。
  • 私のrelationship()定義のためのpassive_deletesとpassive_updatesオプション。

これらのオプションにはデフォルト値があります。

しかし、SQLAlchemyがセッション中にDBとその制約と同期していないことを確認するために、SQLAlchemyモデルで実際にどのくらいのことをする必要があるのか​​混乱しています。

SQLAlchemyのColumns()定義で 'onupdate'などを設定すると、正確に何が達成されていますか?

また、カスケードとパッシブデリート/パッシブアップデートのルールでは、私はリレーションシップ()を設定できます。私はここで何が必要なのですか?なぜですか?

私の質問に言い換えると、SQLAlchemyはDBスキーマに設定されている制約をどのように拡張し、どのように拡張する必要がありますか?

私が知っておくべきことは何ですか? :)

答えて

4

SQLAlchemyは基本的にデータベースの制約について何かを知る必要はありません。データベースに制約が設定されていれば、基本的には完了です。アプリケーションは、データベースが想定していない何かを実行することを許可しません。

SQLAlchemyの主なテーマは、実際にあなたが話すことだけです。したがって、SQLAlchemyがデータをフラッシュする(INSERTステートメントを発行する)時点で、親Widget()への参照を必要とするSubWidget()オブジェクトを永続化しようとすると、操作は失敗しますデータベースによって発行された制約違反で、トランザクションがロールバックされます。

したがって、「ウィジェット」を参照する「サブウィジェット」のFKを想定すると、アプリケーションはデータが正しい構造であることを保証する必要があります。これを行うには2つの方法があります。 1つは、外部キー参照を含む列を手作業で維持し、INSERTまたはUPDATEの時点で適切な値を持つことを確認することです。もう1つは、relationship()を使用して外部キー属性を管理することです。代わりに、SubWidget()オブジェクトの作成に、親Widget()オブジェクトを関連付ける操作を伴うことを確認します別途作成および/または取得されます。

カスケードについては、必須ではありませんが、ON DELETE CASCADEが適用される外部キーに使用することをお勧めします。 SQLAlchemy側では、relationship()を使用すると、ORMに、パッシブ削除フラグ(http://www.sqlalchemy.org/docs/orm/collections.html?highlight=passive_deletes#using-passive-deletes)を介してデータベースがカスケード削除するというヒントが与えられることが通常ありますが、これは通常パフォーマンスの向上です。 SQLAlchemyを使用すると、relationship()の従属側にあるすべてのオブジェクトがメモリにロードされ、適切に処理されます。つまり、外部キー属性をNULL(デフォルト)に設定するか、 「カスケード」を「all、delete-orphan」に設定すると、http://www.sqlalchemy.org/docs/orm/session.html#cascadesを参照してください)。

ON UPDATEカスケードはあまり一般的ではありません。ナチュラルプライマリキーは、最近では一般的なプラクティスではありません。これらのキーは、プレーン整数のプライマリキーと実際には同じように機能しないため、他の方法では面倒かもしれません。 SQLAlchemyはこれらもサポートしていますが、SQLAはデフォルトでPKの突然変異が発生したときに更新カスケードが実行されると仮定しているため、一般的に注意が必要です。詳細はhttp://www.sqlalchemy.org/docs/orm/relationships.html#mutable-primary-keys-update-cascadesを参照してください。

多少の実験でgrokを書くのは簡単かもしれませんが、基本的な考え方は、一度設定したSQLの動作の多くが自動化されているにもかかわらず、SQLAlchemyはあなたに指示しているSQLだけを放出しているということです。 relationship()は、データベースに存在する制約に関してデータが永続化、変更、または削除されたときに、どのように動作させるかについての詳細を設定する必要があります。 SQLAlchemyのを作るために

+0

zzzeekこんにちは、 は、私の頭の中に霧の一部を持ち上げるしようとしていただきありがとうございます。そして、SQLAlchemyのために! :) 自分の質問に「回答」を追加しました。そこでは、私が学んだと思っていることを要約しています。 うまくいけば、私は正しい軌道に乗っている... – herira

1

だから、私の最初の質問の後いじり/勉強zzzeeks答えに構築し、そして私自身の...

積極は、DB状態の中、セッションビューは何からそらすことができを防ぎますあなたがフラッシュ/コミットするときにDBが許可する場合、SQLAlchemyモデルのDBスキーマにあるすべての制約をミラーリングする必要があります。

、これはの形の列定義を介して行われる:制約が及ぶ場合について

__table_args__ = (
     ForeignKeyConstraint(['id'], ['remote_table.id']), 
     UniqueConstraint('foo'), 
     ) 

:同様に、__table_args__の可能含めて、

ForeignKey(..., onupdate='', ondelete='') 
primary_key=True 
unique=True 

など複数の列。一方

relationship() 

及びその関連引数、のように:

cascade 
cascade_backrefs 
foreign_keys 
passive_deletes 
passive_updates 

というように、あなたに少しの努力であなたのモデルで作業することができます(重要)便利な機能です可能な限り、しかし究極のものであることを意味するものではありません参照整合性を破ることを防ぐ。

Column()(および__table_args__)機能は、データベース内のすべての一般的な制約を表すことができません。

一方、上記の引数のいくつか(またはそれが最も理にかなっているところのデフォルト値)を使ってリレーションシップ()を設定すると、SQLAlchemyは自動的にタスクを実行します。最終的には参照整数関連するそうでなければ、通常は周囲のコードで論理によって表現される必要があります。

SQLAlchemyによって不要なSQL文が発行されることを避けるために、関係()の最適な設定が行われることもあります。この総和はやや正確である

希望...

+0

簡単にスキミングは私にとってはうまくいくようだ – zzzeek

関連する問題