删除之前删除相关记录触发postgresql

时间:2016-11-24 03:00:00

标签: sql postgresql triggers

我需要创建触发器,这将删除相关表中的相关行。是的,我知道ON DELETE CASCADE,但问题是我需要使用触发器。我谷歌它几个小时,但没有找到Postgesql的解决方案。我使用postgresql 9.4,pgAdmin III。

我有以下表格:

CREATE TABLE "Customer"
(
    "Id" serial NOT NULL,
    "ContactPerson" text NOT NULL,
    "Address" text NOT NULL,
    "PhoneNumber" "PhoneNumber" NOT NULL,
    CONSTRAINT "CustomerId (PK)" PRIMARY KEY ("Id")
)
WITH (
    OIDS=FALSE
);

CREATE TABLE "Order"
(
    "Id" serial NOT NULL,
    "OrderDate" date NOT NULL DEFAULT ('now'::text)::date,
    "Amount" integer NOT NULL DEFAULT 1,
    "CustomerId" integer NOT NULL,
    "GoodId" integer NOT NULL,
    CONSTRAINT "OrderId (PK)" PRIMARY KEY ("Id"),
    CONSTRAINT "CustomerId (FK)" FOREIGN KEY ("CustomerId")
        REFERENCES "Customer" ("Id") MATCH SIMPLE
        ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT "GoodId (FK)" FOREIGN KEY ("GoodId")
        REFERENCES "Good" ("Id") MATCH SIMPLE
        ON UPDATE NO ACTION ON DELETE NO ACTION,
    CONSTRAINT "AmountCheck" CHECK ("Amount" > 0),
    CONSTRAINT "OrderDateCheck" CHECK ("OrderDate" <= 'now'::text::date)
)
WITH (
    OIDS=FALSE
);

我使用此查询创建触发器:

CREATE FUNCTION DeleteCustomerWithOrders() RETURNS trigger AS $DeleteCustomerWithOrders$
    BEGIN
        DELETE FROM "Order"
        WHERE "Order"."CustomerId" = (SELECT "Id" FROM "Customer");
        RETURN "Customer";        
    END;
$DeleteCustomerWithOrders$ LANGUAGE plpgsql;

CREATE TRIGGER DeleteCustomerWithOrders BEFORE DELETE ON "Customer"
    EXECUTE PROCEDURE DeleteCustomerWithOrders();

查询运行良好,但后来我尝试从Customer删除行,它出错:

column "Customer" does not exists

(“客户”栏不存在)

文档中只有ON INSERT或UPDATE触发器的示例,它们使用RETURN NEW。我也看到在sql-server中使用OLD。在我的情况下,它没有任何帮助。 WHERE也可能存在错误。

更新

感谢帕特里克。这解决了第一个问题,但又导致了另一个问题。

another problem

错误:记录old未分配值。细节:对于未分配记录的cortege结构未定义。

1 个答案:

答案 0 :(得分:1)

您的代码有两个小问题。

触发器在表"Customer"上运行,但在触发器功能中,您引用要使用预定义参数OLD删除的此表的行。另外,不要从该行中选择id,而只是引用它(子查询实际上从表中检索了所有id,这也是错误的。)

触发器功能应如下所示:

CREATE FUNCTION DeleteCustomerWithOrders() RETURNS trigger AS
$DeleteCustomerWithOrders$
BEGIN
    DELETE FROM "Order"
    WHERE "Order"."CustomerId" = OLD."Id";
    RETURN OLD;        
END;
$DeleteCustomerWithOrders$ LANGUAGE plpgsql;

您收到的错误来自声明RETURN "Customer";。 RETURN语句需要trigger参数,但要查找标识符。系统然后将此解释为将返回trigger对象的SELECT语句,但该语句显然不完整:"Customer"在选择列表中,因此被解释为列名,但没有行源(FROM ...)完成语句,因此无法解析列名。