[英]PostgreSQL same trigger function to UPDATE on INSERT into different tables (using the same schema)
我有 100 個具有相同架構的表,並且我有一個觸發器函數可以在數據插入該表時更新某些列。
表架構:
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)
);
觸發功能:
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;
表上的觸發器設置:
CREATE TRIGGER trig_update_sma
AFTER INSERT ON symbol_daily_ohlc
FOR EACH ROW
EXECUTE PROCEDURE update_sma8();
這適用於給定的表,即 symbol_daily_ohlc。 我想使用相同的觸發器函數,即 update_sma8() 與具有相同模式的任何表一起使用(我不想為不同的表重寫相同的函數)。
我嘗試用 TG_TABLE_NAME 替換表名(即 symbol_daily_ohlc),但這不起作用 - 拋出錯誤。 那么怎么做呢?
您可以使用相同的過程為所有表執行並返回觸發器,但不能為所有表使用相同的觸發器。
這是一個動態創建帶有表名后綴的觸發器的塊(使用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 $$;
這是您的觸發器,它從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;
正如其他人所建議的那樣,擁有多個具有相同結構的表並不是一個好主意。 您應該考慮將它們合並到一張表中。
我認為您可能必須使用 SQL 來生成 SQL,然后運行生成的 SQL。 就像是:
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
但實際上,您應該考慮 Gordon 的建議(以及我的后續行動)並將所有數據放回一張表中:
SELECT CONCAT('INSERT INTO all_hist SELECT ''', table_name, ''', t.* FROM ', table_name) FROM information_schema.tables
這將生成一堆將所有表數據放入 all_hist 的 sql,該表應該與其他數千個表具有相同的架構,除了附加列“符號”或其他任何內容。
如果你真的想要,你可以使用類似的技巧為自己創建一堆視圖來重新創建千表方法。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.