【问题标题】:Need some help in creating a query in SQL?在 SQL 中创建查询时需要一些帮助吗?
【发布时间】:2012-04-30 10:21:02
【问题描述】:

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

我创建了额外的维护审核表:

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""

各位,能帮我解决一下这个问题吗?

【问题讨论】:

    标签: sql postgresql cascading-deletes audit-logging


    【解决方案1】:

    您可能想要的是触发器。不确定您使用的是什么 RDBMS,但这就是您应该开始的地方。我从零开始,在一个小时内启动并运行了类似情况的触发器。

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

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

    select * into destination from source where 1=0
    

    不过,我还是会使用触发器完成您需要完成的工作,因为它们非常自动化。

    【讨论】:

    • 谢谢贾斯汀!;-)这很有帮助!
    【解决方案2】:
    1. 为 Ticket.product_id 和具有 ON DELETE CASCADE 的 TicketUpdate.Ticket_id 创建外键。这将在您删除产品时自动删除所有票证和票证更新。

    2. 使用 product_id、用户和时间戳为产品删除者创建一个审计表。工单的审计表,ticketUpdate 应该完全反映它们。

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

    4. 对 TicketUpdate 执行相同操作

    5. 在产品上创建一个 AFTER DETETE 触发器,以在产品审核表中捕获谁请求删除产品。

    6. 在FAQ表中创建Product_id作为外键,ON DELETE SET NULL

    【讨论】:

    • 非常感谢大卫!;-) 这很有帮助!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-03-26
    • 1970-01-01
    • 1970-01-01
    • 2018-10-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多