触发函数可在INSERT上向上更新一列

时间:2019-03-28 01:56:19

标签: sql postgresql

我想为postgresql表设置一个触发函数,该函数应使用从另一列派生的数据更新一列。

表格:

CREATE TABLE day (
symbol varchar(20) REFERENCES another_table(symbol),
date date,
open NUMERIC(8,2),
high NUMERIC(8,2),
low  NUMERIC(8,2),
close NUMERIC(8,2),
sma8 NUMERIC(8,2),
PRIMARY KEY(symbol, date));

注意:复合主键。

示例插入:

INSERT INTO day VALUES('ABC', '2019-03-19', 102.3, 110.0, 125.3, 120.4, 0);
INSERT INTO day VALUES('ABC', '2019-03-20', 112.3, 109.0, 119.3, 118.4, 0);
INSERT INTO day VALUES('DEF', '2019-03-19', 1112.3, 1100.0, 1155.3, 1120.4, 0);
INSERT INTO day VALUES('DEF', '2019-03-20', 1202.3, 1180.0, 1205.3, 1190.4, 0);

以此类推。

当“日期”列是唯一的主键,并且该表仅包含与一个“符号”有关的数据时(例如,该表包含各个唯一日期的一个特定符号的数据),以下触发器功能可以正常工作。

create or replace function update_sma8() RETURNS TRIGGER AS
$$
 BEGIN

 UPDATE day d SET sma8 = s.simple_mov_avg 
 FROM
 (
  SELECT  sec.date,AVG(sec.close)  
    OVER(ORDER BY sec.date ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS 
     simple_mov_avg FROM day sec
 )s where s.date = NEW.date  --The newly inserted date
      AND d.date = s.date;   
 RETURN NULL;

 END $$ language plpgsql;

引用:SQL trigger function to UPDATE daily moving average upon INSERT

我想用通过平均一个特定交易品种的当前“关闭”值和最后7个“关闭”值得出的值来更新“ sma8”列(“日期”有所不同,即过去的数据)。其他符号也是如此。

请引导我。谢谢。

2 个答案:

答案 0 :(得分:0)

您需要知道如何通过“符号”过滤行。

  1. 添加WHERE子句进行过滤。
WHERE sec.symbol = NEW.symbol
  1. 然后,您注册触发器。
CREATE TRIGGER day_insert
    AFTER INSERT ON day
    FOR EACH ROW
    EXECUTE PROCEDURE update_sma8();
  1. 确保在插入行时将更新“ sma8”列。

这里是完整代码。


DROP FUNCTION public.update_sma8();

CREATE FUNCTION public.update_sma8()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF 
AS $BODY$
 BEGIN

 UPDATE day d SET sma8 = s.simple_mov_avg 
 FROM
 (
  SELECT  sec.date,AVG(sec.close)  
    OVER(ORDER BY sec.date ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS 
     simple_mov_avg FROM day sec WHERE symbol = NEW.symbol
 )s where s.date = NEW.date  --The newly inserted date
      AND d.date = s.date ;   
 RETURN NULL;

 END $BODY$;

ALTER FUNCTION public.update_sma8()
    OWNER TO postgres;

答案 1 :(得分:0)

您可以添加PARTITION BY symbol,然后在where子句中使用它来计算每个符号。

create or replace function update_sma8() RETURNS TRIGGER AS
$$
 BEGIN

 UPDATE day d SET sma8 = s.simple_mov_avg 
 FROM
 (
  SELECT  sec.date,sec.symbol,AVG(sec.close)  
    OVER( partition by symbol ORDER BY sec.date ROWS BETWEEN 
                          7 PRECEDING AND CURRENT ROW) AS 
     simple_mov_avg FROM day sec
 )s where s.date = NEW.date  --The newly inserted date
      AND d.date = s.date   
      AND d.symbol = s.symbol;
  RETURN NULL;
 END $$ language plpgsql;

DEMO