Sql 更新Postgres 9中当前日期的触发器

Sql 更新Postgres 9中当前日期的触发器,sql,database,postgresql,triggers,Sql,Database,Postgresql,Triggers,我有两个表,分别是sale和customer。我想创建一个触发器,在sale表中的每个新插入上更新customer表中的last\u purchase列 表客户:客户id、姓名、上次销售,… 表销售:销售id、客户id、日期等 CREATE TRIGGER update_last_sale BEFORE INSERT ON sale FOR EACH ROW EXECUTE... 我已经开始写了,但我不知道怎么写。 有人能帮我吗 CREATE FUNCTION update_customer_

我有两个表,分别是
sale
customer
。我想创建一个触发器,在
sale
表中的每个新插入上更新
customer
表中的
last\u purchase

表客户:客户id、姓名、上次销售,…
表销售:销售id、客户id、日期等

CREATE TRIGGER update_last_sale BEFORE INSERT ON sale FOR EACH ROW EXECUTE...
我已经开始写了,但我不知道怎么写。
有人能帮我吗

CREATE FUNCTION update_customer_last_sale() RETURNS TRIGGER AS $$
BEGIN
    UPDATE customer SET last_sale=now() WHERE cutomer_id=NEW.customer_id;
    RETURN NEW;
END; $$
LANGUAGE plpgsql;
然后


NEW
是即将插入销售表的行。(对于更新行,更新后该行的外观应为
NEW
,更新前该行的外观应为
OLD

我想您需要这里的规则

CREATE RULE therule AS ON INSERT TO sale DO ALSO
    (UPDATE customer SET customer.last_sale = now()
           WHERE customer.customer_id=NEW.customer_id);

编辑:但请参见评论中的讨论。

基本上,我认为存储冗余数据不是一个好主意。customers中的最后一列只是max(sales.sale\u date)的总和

如果我们使用now()来联系客户,情况会变得更糟。如果我们需要重新插入一些历史记录(如重新计算去年的税收),会发生什么。这就是存储冗余数据时得到的结果

-- modelled after Erwin's version
SET search_path='tmp';

-- DROP TABLE customers CASCADE;
CREATE TABLE customers
    ( id INTEGER NOT NULL PRIMARY KEY
    , name VARCHAR
    , last_sale DATE
    );

-- DROP TABLE sales CASCADE;
CREATE TABLE sales
    ( id INTEGER NOT NULL PRIMARY KEY
    , customer_id INTEGER REFERENCES customers(id)
    , saledate DATE NOT NULL
    );


CREATE OR REPLACE FUNCTION update_customer_last_sale() RETURNS TRIGGER AS $meat$
BEGIN
    UPDATE customers cu
    -- SET last_sale = now() WHERE id=NEW.customer_id
    SET last_sale = (
        SELECT MAX(saledate) FROM sales sa
        WHERE sa.customer_id=cu.id
        )   
    WHERE cu.id=NEW.customer_id
    ;
    RETURN NEW;
END; $meat$
LANGUAGE plpgsql;

CREATE TRIGGER update_last_sale
    AFTER INSERT ON sales
    FOR EACH ROW
    EXECUTE PROCEDURE update_customer_last_sale();


INSERT INTO customers(id,name,last_sale) VALUES(1, 'Dick', NULL),(2, 'Sue', NULL),(3, 'Bill', NULL);


INSERT INTO sales(id,customer_id,saledate) VALUES (1,1,'1900-01-01'),(2,1,'1950-01-01'),(3,2,'2011-12-15');

SELECT * FROM customers;

SELECT * FROM sales;
结果是:

 id | name | last_sale  
----+------+------------
  3 | Bill | 
  1 | Dick | 1950-01-01
  2 | Sue  | 2011-12-15
(3 rows)

 id | customer_id |  saledate  
----+-------------+------------
  1 |           1 | 1900-01-01
  2 |           1 | 1950-01-01
  3 |           2 | 2011-12-15
(3 rows)

规则非常棘手,你必须很好地理解它们才能正确使用它们。使用“复制”插入数据时,它也不起作用@弗兰克海肯斯,必须理解你所使用的东西并不少见,我想说理解触发器也没有坏处;-)规则有点不受欢迎,Postgres团队明确建议使用触发器。@a_horse_和_no_名字,愿意透露来源吗?@MichaelKrelin hacker:例如,在关于
创建规则的章节中:“如果您确实希望为每个物理行单独触发一个操作,则可能需要使用触发器“。现在我们有了
而不是
视图触发器,几乎没有任何理由使用它们。此外,它们也比触发器慢。看到这里的最后一句话:触发器创建不起作用,最后一行需要。。。对于每一行,执行更新_customer_last_sale()的过程;至少对于博士后10。
 id | name | last_sale  
----+------+------------
  3 | Bill | 
  1 | Dick | 1950-01-01
  2 | Sue  | 2011-12-15
(3 rows)

 id | customer_id |  saledate  
----+-------------+------------
  1 |           1 | 1900-01-01
  2 |           1 | 1950-01-01
  3 |           2 | 2011-12-15
(3 rows)