GreenPlum. Ошибка в триггерной функции
Есть 3 таблицы fact_amount со структурой:
CREATE TABLE fact_amount (
id serial4 NOT NULL,
fdate date NULL,
type_activity_id int4 NULL,
status_id int4 NULL,
CONSTRAINT fact_amount_pk_1 PRIMARY KEY (id),
CONSTRAINT fact_amount_fk_1 FOREIGN KEY (category_id) REFERENCES mdv_db.spr_category(category_id),
CONSTRAINT fact_amount_fk_2 FOREIGN KEY (status_id) REFERENCES mdv_db.spr_status(status_id),
CONSTRAINT fact_amount_fk_3 FOREIGN KEY (type_activity_id) REFERENCES mdv_db.spr_type_activity(type_activity_id)
);
spr_status:
CREATE TABLE spr_status (
status_id serial4 NOT NULL,
status_name varchar NULL,
CONSTRAINT spr_status_pk PRIMARY KEY (status_id)
);
spr_type_activity:
CREATE TABLE spr_type_activity (
type_activity_id serial4 NOT NULL,
type_activity_name varchar NULL,
CONSTRAINT spr_type_activity_pk PRIMARY KEY (type_activity_id)
);
Надо создать представление с данными из таблицы fact_amount и транспонированной spr_type_activity и значениями из spr_status. Сначала создал функцию, которая все это преобразовывала. Все прекрасно работало, кроме того, чтобы при изменении в справочнике spr_type_activity обновлялось представление. В итоге преобразовал ее в триггерную функцию:
CREATE TRIGGER tr_spr_type_activity
AFTER INSERT OR DELETE OR UPDATE
ON spr_type_activity FOR EACH ROW EXECUTE PROCEDURE c_crosstab();
Триггерная функция:
CREATE OR REPLACE FUNCTION c_crosstab()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
DECLARE
casesql varchar;
dynsql varchar;
r record;
eavsql_inarg varchar;
resview varchar;
rowid varchar;
colid varchar;
val varchar;
BEGIN
eavsql_inarg = 'SELECT fa.id,
sb.id_branch,
sb.parent_branch_id,
fa.fdate,
sb.branch_name,
ss.status_name,
fa.type_activity_id,
sa.type_activity_name
FROM mdv_db.fact_amount fa
LEFT JOIN mdv_db.branch sb ON fa.id_branch = sb.id_branch
LEFT JOIN mdv_db.spr_category sc ON fa.category_id = sc.category_id
LEFT JOIN mdv_db.spr_status ss ON fa.status_id = ss.status_id
LEFT JOIN mdv_db.spr_type_activity sa ON fa.type_activity_id = sa.type_activity_id';
resview = 'v_crosstab';
rowid = 'id';
colid = 'type_activity_name';
val = 'status_name';
dynsql = '';
FOR r IN SELECT * FROM pg_views
WHERE lower(viewname) = lower(resview)
LOOP
EXECUTE 'DROP VIEW IF EXISTS ' || resview;
END LOOP;
casesql = 'SELECT DISTINCT ' || colid || ' AS v from (' || eavsql_inarg || ') eav ORDER BY ' || colid;
FOR r IN EXECUTE casesql LOOP
dynsql = dynsql || ', ' || 'CASE WHEN ' || colid || '=''' || r.v || ''' THEN ' || val || ' ELSE NULL END AS ' || r.v;
END LOOP;
dynsql = 'CREATE VIEW ' || resview || ' AS SELECT ' || rowid || dynsql || ' from (' || eavsql_inarg || ') eav ORDER BY ' || rowid;
RAISE NOTICE 'dynsql %1', dynsql;
EXECUTE dynsql;
END;
$function$
Выходит следующая ошибка:
Error synchronizing data with database
Причина:
SQL Error [0A000]: ERROR: function cannot execute on a QE slice because it issues a non-SELECT statement (seg5 172.23.133.194:6002 pid=32075)
Где: SQL statement "DROP VIEW IF EXISTS v_crosstab"
PL/pgSQL function c_crosstab() line 34 at EXECUTE statement
Созданием процедур/функций раньше не занимался. В чем ошибка и как ее исправить? Может можно решить задачу иным способом? Без триггеров и функции?
Источник: Stack Overflow на русском