1

私は6つのテーブルを持っています:

 Staff ( StaffID, Name )
 Product ( ProductID, Name )
 Faq ( FaqID, Question, Answer, ProductID* )
 Customer (CustomerID, Name, Email)
 Ticket ( TicketID, Problem, Status, Priority, LoggedTime, CustomerID* , ProductID* )
 TicketUpdate ( TicketUpdateID, Message, UpdateTime, TicketID* , StaffID* )

回答する質問: 製品 ID を指定して、その製品のレコードを削除します。製品が削除されると、関連するすべての FAQ がデータベースに残る可能性がありますが、ProductID フィールドには null 参照が含まれている必要があります。ただし、製品を削除すると、関連するチケットとその更新も削除されます。完全を期すために、削除されたチケットとその更新は、製品、チケット、および更新に関する履歴データを保持する監査テーブルまたは一連のテーブルにコピーする必要があります。(ヒント: この監査情報を維持し、製品が削除されたときに削除されたチケットとチケットの更新を自動的にコピーするには、追加のテーブルまたはセットまたはテーブルを定義する必要があります)。監査テーブルには、削除を要求したユーザーと削除操作のタイムスタンプを記録する必要があります。

追加のmaintain_auditテーブルを作成しました:

CREATE TABLE maintain_audit(
 TicketID INTEGER NOT NULL,
 TicketUpdateID INTEGER NOT NULL,
 Message VARCHAR(1000),
 mdate TIMESTAMP NOT NULL,
 muser VARCHAR(128),
 PRIMARY KEY (TicketID, TicketUpdateID)
  ); 

さらに、1 つの関数とトリガーを作成しました。

    CREATE OR REPLACE FUNCTION maintain_audit()
      RETURNS TRIGGER AS $BODY$
      BEGIN
      INSERT INTO maintain_audit (TicketID,TicketUpdateID,Message,muser,mdate)
     (SELECT Ticket.ID,TicketUpdate.ID,Message,user,now() FROM Ticket, TicketUpdate WHERE             Ticket.ID=TicketUpdate.TicketID AND Ticket.ProductID = OLD.ID);
      RETURN OLD;
      END;
     $BODY$
      LANGUAGE plpgsql; 


 CREATE TRIGGER maintain_audit
     BEFORE DELETE
     ON Product
     FOR EACH ROW
     EXECUTE PROCEDURE maintain_audit()

     DELETE FROM Product WHERE Product.ID=30; 

これをすべて実行すると、次のようになります。

    ERROR:  null value in column "productid" violates not-null constraint
   CONTEXT:  SQL statement "UPDATE ONLY "public"."faq" SET "productid" = NULL WHERE $1     OPERATOR(pg_catalog.=) "productid""

皆さん、この問題を解決するのを手伝ってくれませんか?

4

2 に答える 2

2

おそらく必要なのはトリガーです。どの RDBMS を使用しているかはわかりませんが、そこから始めるべきです。私はゼロから始めて、1 時間以内にトリガーを起動し、多少似たような状況で実行しました。

ご存じないかもしれませんが、トリガーは、挿入、更新、削除など、特定の種類のクエリがテーブルで発生した後に何かを実行します。あらゆる種類のクエリを実行できます。

もう 1 つのヒントとして、データの整合性が損なわれる可能性があるため、何も削除しないでください。「アクティブな」ブールフィールドを追加し、アクティブを false に設定してから、システムのほとんどのクエリでそれらを除外することができます。または、関連付けられたレコードを、同じ構造を持つ Products_archive テーブルに移動することもできます。簡単にできること:

select * into destination from source where 1=0

それでも、トリガーは非常に自動化されているため、トリガーを使用して必要な作業を行います。

于 2012-04-18T22:47:58.170 に答える
1
  1. ON DELETE CASCADE を持つ Ticket.product_id と TicketUpdate.Ticket_id の外部キーを作成します。これにより、製品を削除すると、すべてのチケットとチケットの更新が自動的に削除されます。

  2. product_id、ユーザー、およびタイムスタンプを使用して、製品の削除者の監査テーブルを作成します。ticket、ticketUpdate の監査テーブルは、それらを正確に反映する必要があります。

  3. チケットを監査テーブルにコピーするテーブル Ticket の BEFORE DELETE TRIGGER を作成します。

  4. TicketUpdate についても同じことを行います

  5. 製品の AFTER DETETE トリガーを作成して、製品監査テーブルで製品の削除を要求したユーザーを取得します。

  6. テーブルFAQで、ON DELETE SET NULLを使用してProduct_idを外部キーとして作成します

于 2012-04-18T23:01:02.830 に答える