2

履歴を念頭に置いてデータベースを作成しようとしています (経験から、これをいつか行う必要があることがわかります)。

ここでdatabase-design-how-to-handle-the-archive-problem に質問しましたが、ここのリンクよりも優れた答えはありません。

私の問題は、コードをどこで実行するか、技術的にはどのようにするかです (MySQL は頭痛の種です)。まず、Php でこれを開始しました。挿入を行う前に、レコードを複製して「廃止」としてマークし、レコードを変更します。

ただし、テーブルに付属するすべての依存関係と更新を (何らかの方法で) コーディングすることを意味する依存関係の問題 (manytomany および manytoone の関連付けも更新する必要があります) があります (これは受け入れられません)。

そこで、データベースサーバー側ですべての作業を行うことを考えています。これにより、私の PHP コードが大幅に簡素化されます。

問題は、現在のレコードを変更する前に「アーカイブ」する必要があることです。これを行うには、コードが"before update" トリガー内にある必要があります。

これが私のコードです:

DELIMITER ;;

DROP TRIGGER IF EXISTS produit_trigger_update_before;

CREATE TRIGGER produit_trigger_update_before
BEFORE UPDATE ON produit
  FOR EACH ROW BEGIN
    /* */
    INSERT INTO produit SET 
      id_origine      = OLD.id_origine,
      date_v_creation = OLD.date_v_creation,
      date_v_start    = OLD.date_v_debut,
      date_v_end      = NOW(),
      ...
      last_record     = OLD.last_record;

    /* Dependancies : */
    SET @last=LAST_INSERT_ID();
    UPDATE categorie_produit SET id_produit=@last
    WHERE id_produit = OLD.id;
    UPDATE produit_attribut SET id_produit=@last
    WHERE id_produit = OLD.id;
  END;;

DELIMITER ;;

このコードが機能するようになれば、問題はすべて解消されます。しかし、いまいましい、それは機能していません:

mysql> update produit set importance=3;
ERROR 1442 (HY000): Can't update table 'produit' in stored function/trigger because it is already used by statement which invoked this stored function/trigger.
mysql> Bye

このページINSTEAD OF UPDATEには、トリガーで句を使用する実際のサンプルがあります。MySQL はこれをサポートしていないようです。

したがって、私の質問は概念的(=機能する可能性のある他の「原則」がありますか)および/または技術的(=このトリガーを機能させることができますか)の両方です。

4

2 に答える 2

0

このコードが機能するようになれば、問題はすべて解消されます。しかし、いまいましい、それは機能していません:

原則として、テーブル A にトリガーを挿入することはできません。これは、無限ループが発生する可能性があるためです。(オラクル用語でミューテーションのトリガー)

個人的には、トリガーを使用してこれを行うことはありません。トリガーは「監査ログ」を実行できますが、これはここで必要なことではありません。

「ModifyProduit」のようなものを呼び出すPHP関数またはMySQLストアドプロシージャ(好みに関係なく)を使用して、プログラムで解決することをお勧めします。

コードは基本的に、上記のトリガーで実行したことを実行します。(現在の行にコード セット date_v_end を設定してから、完全に新しい行を挿入する方が簡単な場合があります。そうすれば、参照テーブルの更新をいじる必要がなくなります)

于 2012-06-15T19:26:37.887 に答える
0

このような補助テーブルを使用してテーブルの履歴を作成できます (mysql の多くのテーブルでこれを実行しましたが、速度は非常に優れています)。

  • tableは、 + 2 つの追加の列produit_historyと同じ構造を持っています: "history_start DATETIME NOT NULL" および "history_stop DATETIME DEFAULT NULL"。produit
  • produitテーブル には 3 つのトリガーがあります。
    • produit_historyAFTER INSERT: このトリガーでは、 history_start = NOW() および history_stop = NULL (NULL は現在の行が有効であることを意味します) を使用して、同じデータを単純に挿入します。
    • AFTER UPDATE: このトリガーは 2 つのクエリを実行します。最初は、次のような un update です。
      UPDATE produit_historyset history_stop = NOW() WHERE id_origin = OLD.id_origin AND history_stop IS NULL;
      2 番目のクエリは、AFTER INSERT トリガーと同じ挿入です。
    • AFTER DELETE: これは、AFTER UPDATE と同じ単純な更新をトリガーします。

次に、次の where 条件を使用して、この履歴テーブルにクエリを実行し、必要なときにいつでもスナップショットを取得できます。

WHERE (history_start <= "interesting_time" AND (history_stop IS NULL OR history_stop > "interesting_time"))
于 2012-12-17T15:08:16.827 に答える