在SQL中创建查询需要一些帮助吗?

时间:2012-04-18 22:26:08

标签: sql postgresql cascading-deletes audit-logging

我有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字段中应该有一个空引用。但是,删除产品还应删除任何相关的故障单及其更新。为了完整性,应将已删除的票证及其更新复制到审计表或一组表中,以维护产品,票证和更新的历史数据。 (提示:您需要定义一个或多个表或一组或多个表来维护此审核信息,并在删除产品时自动复制任何已删除的故障单和故障单更新)。您的审计表应记录请求删除的用户和删除操作的时间戳。

我创建了额外的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""

GUYS,你能帮我解决这个问题吗?

2 个答案:

答案 0 :(得分:2)

你可能想要的是触发器。不确定您使用的是哪种RDBMS,但这是您应该从哪里开始的。我从零开始,在一小时内触发并在一个类似的情况下运行。

如果您还不知道,触发器会在表上发生特定类型的查询后执行某些操作,例如插入,更新或删除。您可以进行任何类型的查询。

我会给你的另一个提示是不删除任何内容,因为这可能会破坏数据的完整性。您可以添加一个“活动”布尔字段,将active设置为false,然后在系统的大多数查询中过滤掉这些字段。或者,您可以将关联的记录移动到具有相同结构的Products_archive表。容易做到:

select * into destination from source where 1=0

尽管如此,我还是会使用触发器来完成你需要完成的工作,因为它们是如此自动化。

答案 1 :(得分:1)

  1. 为Ticket.product_id创建外键,并为具有ON DELETE CASCADE的TicketUpdate.Ticket_id创建外键。这将在您删除产品时自动删除所有故障单和故障更新。

  2. 使用product_id,user和timestamp为Product deleters创建一个审计表。对于故障单的审计表,ticketUpdate应该完全镜像它们。

  3. 为表Ticket创建一个BEFORE DELETE TRIGGER,它将票证复制到审计表。

  4. 对TicketUpdate

  5. 执行相同操作
  6. 在产品上创建AFTER DETETE触发器,以捕获在产品审核表中请求删除产品的人。

  7. 在表格FAQ中,将Product_id创建为具有ON DELETE SET NULL的外键