2

学校のプロジェクトでは、冗長な情報を取得し、トリガーを使用して更新する必要があります。「評価」(0 ~ 100 の数字)を含む「recipe_ratings」というテーブルがあります。「レシピ」テーブルには、その特定のレシピの平均評価を含む「評価」と呼ばれる冗長な行があります。

次のような Oracle トリガーを作成しようとしました。

CREATE OR REPLACE TRIGGER trigger_rating 
AFTER UPDATE 
  ON recipe_ratings 
  FOR EACH ROW

DECLARE 
  average_rating NUMBER;

BEGIN
  SELECT ROUND(AVG(rating))
  INTO average_rating
  FROM recipe_ratings
  WHERE rid = :new.rid;

  UPDATE recipe SET rating = average_rating
  WHERE rid = :new.rid 

END;

ORA-04091: table name is mutating, trigger/function may not see it. 「自律トランザクション」を実験していますが、トリガーから離れているように感じます。

このトリガーを機能させるにはどうすればよいでしょうか。

4

3 に答える 3

4

教授が、無効​​なデータ モデルを使用することに加えて、自律型トランザクションの恐ろしい誤用となる自律型トランザクションを使用する道にあなたを導いていないことを願っています。

現実の世界では、この種のことが機能するためには、

  • RID 値のコレクションを含むパッケージ
  • このコレクションを初期化する before ステートメント トリガー
  • :new.rid 値をコレクションに挿入する行レベルのトリガー
  • RECIPE_RATINGSコレクションを読み取り、テーブルの更新を発行する after ステートメント トリガー

明らかに、そのようなことはすぐに非常に面倒になります。そのため、冗長データの保存が非常に問題になります。

挿入のみを処理する必要があり、INSERT ... VALUES を使用してすべての挿入が単一行の挿入であることを保証できる場合は、クエリでRECIPE_RATINGSテーブルをクエリできます。これは現実の世界では機能しませんが、教室では十分かもしれません。

単一の行が更新されるたびにすべてのレシピの平均評価を再計算することを気にしない場合RECIPE_RATINGS(実際には壊滅的ですが、十分に小さいデータ セットで機能する可能性があります)、after ステートメント トリガーを使用できます。テーブルのすべての行で相関更新を行いRECIPEます。

于 2011-05-03T22:55:47.667 に答える
2

あなたのデータモデルはどの程度柔軟ですか?

レシピの平均評価を保存するのではなく、すべての評価と評価の数の合計を保存できますか。

評価に対する挿入トリガーは、値または新しい行を取得して親レシピ行を更新し、評価を合計に追加し、評価の数/カウントに 1 を追加します。

更新トリガーは、:NEW 値と :OLD 値の差を合計に追加します (カウントは更新しません)。

どちらのトリガーも評価テーブルの他の行をクエリする必要はなく、テーブルの変更エラーを防止し、複数の同時ユーザーがいる環境での使用をより安全にします。

クエリ (またはビューまたは派生列) は、単純に合計をカウントで割ることによって平均を決定します。

于 2011-05-04T00:25:13.493 に答える
1

この記事では、これらのエラーを回避する1つの方法を説明します。

別の考え-ここでは、FOR EACH ROWトリガーよりも「通常の」トリガーの方が適しているでしょうか?1つのステートメントに同じレシピのrecipe_ratingの更新が複数ある場合は、それ以外の場合は平均を複数回計算しています(したがって、ミューテーションの警告)。

于 2011-05-03T22:51:49.023 に答える