ルールは避け、代わりにトリガーを使用する と記載されていることがよくあります。ルールシステムには危険が見えますが、確かにルールには有効な使い方がありますよね?彼らは何ですか?
私はこれを一般的な関心から求めています。私はデータベースにあまり慣れていません。
たとえば、以前は特定のデータをロックダウンする必要があったので、次のようなことをしました。
CREATE OR REPLACE RULE protect_data AS
ON UPDATE TO exampletable -- another similar rule for DELETE
WHERE OLD.type = 'protected'
DO INSTEAD NOTHING;
次に、保護されたデータを編集する場合:
START TRANSACTION;
ALTER TABLE exampletable DISABLE RULE protect_data;
-- edit data as I like
ALTER TABLE exampletable ENABLE RULE protect_data;
COMMIT;
私はこれがハッキーであることに同意しますが、この場合、データベースにアクセスするアプリケーションを変更できませんでした(またはエラーをスローすることさえありました)。したがって、ボーナスポイントこれがルールシステムの危険/無効な使用である理由を見つけるために、しかし、ではないこれがなぜ悪いデザインであるのか。
RULESの使用例の1つは更新可能なビューです(ただし、9.1での変更により、そのバージョンではビューにINSTEAD OFトリガーが導入されています)
別の良い説明がマニュアルにあります:
両方で実装できるものについては、データベースの使用方法によって異なります。影響を受ける行に対してトリガーが1回起動されます。ルールはクエリを操作するか、追加のクエリを生成します。したがって、1つのステートメントで多数の行が影響を受ける場合、1つの追加コマンドを発行するルールは、すべての行に対して呼び出され、その操作を何度も実行する必要があるトリガーよりも高速になる可能性があります。ただし、トリガーアプローチは、概念的にはルールアプローチよりもはるかに単純であり、初心者が正しく理解する方が簡単です。
(以下から取得: http://www.postgresql.org/docs/current/static/rules-triggers.html )
ルールに関するいくつかの問題を次に示します: http://www.depesz.com/index.php/2010/06/15/to-rule-or-not-to-rule-that-is-the- question / (たとえば、random()がクエリに含まれている場合、2回実行されて異なる値を返す可能性があります)。
ルールの最大の欠点は、人々がそれらを理解しない理解できないことです。
たとえば、次のルールがあると考えるかもしれません。
CREATE OR REPLACE RULE protect_data AS
ON UPDATE TO exampletable -- another similar rule for DELETE
WHERE OLD.type = 'protected'
DO INSTEAD NOTHING;
私が発行する場合は、
update exampletable set whatever = whatever + 1 where type = 'protected'
クエリは実行されません。それは真実ではありません。クエリが実行されますが、条件が追加された変更バージョンで実行されます。
さらに、ルールは非常に便利なものを壊します。つまり、return句です。
$ update exampletable set whatever = whatever + 1 where type = 'normal' returning *;
ERROR: cannot perform UPDATE RETURNING on relation "exampletable"
HINT: You need an unconditional ON UPDATE DO INSTEAD rule with a RETURNING clause.
それをラップするには-本当に、本当に、積極的に書き込み可能なビューを使用する必要があり、9.1より前のPostgreSQLを使用している場合-ルールを使用する正当な理由があります可能性があります。
他のすべての場合-たとえあなたがすぐにそれを見なくても、あなたはおそらく足で自分を撃っているでしょう。
私は、揮発性関数を処理するときにルールでいくつかの苦い経験をしました(メモリが機能する場合、depeszのブログ投稿はそれらのいくつかを強調しています)。
また、fkeyトリガーが起動されるタイミングのため、それらを使用するときに参照整合性を壊しました。
CREATE OR REPLACE RULE protected_example AS
ON DELETE TO example
WHERE OLD.protected
DO INSTEAD NOTHING;
...次に別のテーブルを追加し、on deleteカスケード外部キーでそのテーブルを参照する例を作成します。次に、そのテーブルから*を削除し...ホラーで反動します。
上記の問題をバグとして報告しましたが、機能/必要なEdgeケースとして却下されました。それがなぜなのかを理解したのはたった数か月後です。つまり、fkeyトリガーが機能し、ルールが実行されて独自に機能しますが、fkeyトリガーは、パフォーマンス上の理由でそのジョブが適切に実行されたことを確認しません。 。
私がまだルールを使用している実際の使用例は、データを事前に操作するBEFORE
トリガー(SQL標準では許可されていませんが、Postgresは喜んで義務付けられます)が影響を受ける行を事前に操作し、したがって、ctidを変更します(つまり、更新は2回行われるか、更新によって削除が無効になったために削除されません)。
これにより、Postgresは影響を受ける行の数を正しく返さなくなります。これは、後続のステートメントを発行する前にその数を監視するまでは大きな問題ではありません。
この場合、戦略的に配置されたルールを1つまたは2つ使用すると、問題のあるステートメントを事前に実行できるため、Postgresが影響を受ける行の正しい数を返すことがわかりました。
これはどうですか:ビューに変更する必要があるテーブルがあります。上記のテーブルに挿入するレガシーアプリケーションをサポートするために、「挿入」を基になるテーブルへの新しいビューにマップするルールが作成されます。