简体   繁体   English

PostgreSQL 相同的触发器函数将 INSERT 上的 UPDATE 更新到不同的表中(使用相同的模式)

[英]PostgreSQL same trigger function to UPDATE on INSERT into different tables (using the same schema)

I have 100s of tables having the same schema and I have a trigger function to UPDATE some column whenever data is INSERTed into that table.我有 100 个具有相同架构的表,并且我有一个触发器函数可以在数据插入该表时更新某些列。

Table Schema:表架构:

CREATE TABLE symbol_daily_ohlc (
 cdate date,
 open numeric(8,2),
 high numeric(8,2),
 low numeric(8,2),
 close numeric(8,2),
 sma8 numeric(8,2)
);

Trigger function:触发功能:

create or replace function update_sma8() RETURNS TRIGGER AS
$$
BEGIN
UPDATE symbol_daily_ohlc d SET sma8 = s.simple_mov_avg 
FROM
(
 SELECT  sec.cdate,AVG(sec.close)  
 OVER(ORDER BY sec.cdate ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS 
 simple_mov_avg FROM symbol_daily_ohlc sec
)s where s.cdate = NEW.cdate  --The newly inserted cdate
 AND d.cdate = s.cdate;   
RETURN NULL;
END $$ language plpgsql;

Trigger setup on table:表上的触发器设置:

CREATE TRIGGER trig_update_sma
AFTER INSERT ON symbol_daily_ohlc
FOR EACH ROW
EXECUTE PROCEDURE update_sma8();

This is working well for the given table ie symbol_daily_ohlc.这适用于给定的表,即 symbol_daily_ohlc。 I would like to use the same trigger function ie update_sma8() to be used with any table having the same schema (I don't want to rewrite the same function for different tables).我想使用相同的触发器函数,即 update_sma8() 与具有相同模式的任何表一起使用(我不想为不同的表重写相同的函数)。

I tried replacing the table name (ie symbol_daily_ohlc) with TG_TABLE_NAME, but that didn't work - thrown errors.我尝试用 TG_TABLE_NAME 替换表名(即 symbol_daily_ohlc),但这不起作用 - 抛出错误。 So how to do that?那么怎么做呢?

Reference: SQL trigger function to UPDATE daily moving average upon INSERT参考: 在插入时更新每日移动平均线的 SQL 触发器函数

You can have a same procedure that executes and returns a Trigger for all the tables, but you can't have a same Trigger for all your tables.您可以使用相同的过程为所有表执行并返回触发器,但不能为所有表使用相同的触发器。

Here's a block that dynamically creates a Trigger with table name suffix ( using EXECUTE format )这是一个动态创建带有表名后缀的触发器的块(使用EXECUTE format

DO $$
declare
tabs RECORD;
BEGIN
for tabs IN
(select table_name,table_schema
   from information_schema.tables where table_name 
   like 'symbol_daily_ohlc%' 
  -- and table_schema like '%'
) LOOP
EXECUTE format('CREATE TRIGGER check_update_%I
    AFTER INSERT ON %I.%I
    FOR EACH ROW
EXECUTE PROCEDURE update_sma8()',tabs.table_name,
 tabs.table_schema
,tabs.table_name);
END LOOP;
END $$;

And here's your Trigger, which takes the table name dynamically from TG_TABLE_NAME这是您的触发器,它从TG_TABLE_NAME动态获取表名

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

EXECUTE format ('UPDATE %I d SET sma8 = s.simple_mov_avg 
FROM
(
 SELECT  sec.cdate,AVG(sec.close)  
   OVER(ORDER BY sec.cdate ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS 
    simple_mov_avg FROM %I sec
)s where s.cdate = %L  --The newly inserted cdate
     AND d.cdate = s.cdate',TG_TABLE_NAME,TG_TABLE_NAME,NEW.cdate);   
RETURN NULL;

END $$ language plpgsql;

Demo 演示

As others have suggested, it's not a good idea to have multiple tables with the same structure.正如其他人所建议的那样,拥有多个具有相同结构的表并不是一个好主意。 You should consider combining them into one table.您应该考虑将它们合并到一张表中。

I think you'll probably have to use SQL to generate SQL, then run the generated SQL.我认为您可能必须使用 SQL 来生成 SQL,然后运行生成的 SQL。 Something like:就像是:

select CONCAT('create or replace function update_sma8() RETURNS TRIGGER AS
  $$
  BEGIN
  UPDATE ', table_name, '  d SET sma8 = s.simple_mov_avg 
  FROM
  (
   SELECT  sec.cdate,AVG(sec.close)  
   OVER(ORDER BY sec.cdate ROWS BETWEEN 7 PRECEDING AND CURRENT ROW) AS 
   simple_mov_avg FROM ', table_name, '
  )s where s.cdate = NEW.cdate  --The newly inserted cdate
  AND d.cdate = s.cdate;   
  RETURN NULL;
  END $$ language plpgsql;
') from information_schema.tables

But really you should consider Gordon's advice (and my followup) and put all your data back in one table:但实际上,您应该考虑 Gordon 的建议(以及我的后续行动)并将所有数据放回一张表中:

SELECT CONCAT('INSERT INTO all_hist SELECT ''', table_name, ''', t.* FROM ', table_name) FROM information_schema.tables

This will generate a bunch of sqls that put all the table data into all_hist, a table that should have an identical schema to the other thousands, except for an additional column "symbol" or whatever..这将生成一堆将所有表数据放入 all_hist 的 sql,该表应该与其他数千个表具有相同的架构,除了附加列“符号”或其他任何内容。

You can use a similar trick to create yourself a bunch of views to recreate the thousands-table approach if you really want..如果你真的想要,你可以使用类似的技巧为自己创建一堆视图来重新创建千表方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM