在 plpgsql 触发器函数中用 "array_to_string" 填充变量
Fill a variable with "array_to_string" in a plpgsql trigger function
我正在使用 PostgreSQL 9.5。
我正在 PL/pgSQL 中创建一个触发器,它在 table (synthese_poly
) 中添加一条记录,当 INSERT
在第二个 table (operation_poly
),与其他 tables 数据。
触发器运行良好,除了一些未填充的变量(尤其是我尝试使用 array_to_string()
函数填充的变量)。
这是代码:
-- Function: bdtravaux.totablesynth_fn()
-- DROP FUNCTION bdtravaux.totablesynth_fn();
CREATE OR REPLACE FUNCTION bdtravaux.totablesynth_fn()
RETURNS trigger AS
$BODY$
DECLARE
varoperateur varchar;
varchantvol boolean;
BEGIN
IF (TG_OP = 'INSERT') THEN
varsortie_id := NEW.sortie;
varopeid := NEW.operation_id;
--The following « SELECT » queries take data in third-party tables and fill variables, which will be used in the final insertion query.
SELECT array_to_string(array_agg(DISTINCT oper.operateurs),'; ')
INTO varoperateur
FROM bdtravaux.join_operateurs oper INNER JOIN bdtravaux.operation_poly o ON (oper.id_joinop=o.id_oper)
WHERE o.operation_id = varopeid;
SELECT CASE WHEN o.ope_chvol = 0 THEN 'f' ELSE 't' END as opechvol INTO varchantvol
FROM bdtravaux.operation_poly o WHERE o.operation_id = varopeid;
-- «INSERT» query
INSERT INTO bdtravaux.synthese_poly (soperateur, schantvol) SELECT varoperateur, varchantvol;
RAISE NOTICE 'varoperateur value : (%)', varoperateur;
RAISE NOTICE 'varchantvol value : (%)', varchantvol;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION bdtravaux.totablesynth_fn()
OWNER TO postgres;
这就是触发器:
-- Trigger: totablesynth on bdtravaux.operation_poly
-- DROP TRIGGER totablesynth ON bdtravaux.operation_poly;
CREATE TRIGGER totablesynth
AFTER INSERT
ON bdtravaux.operation_poly
FOR EACH ROW
WHEN ((new.chantfini = true))
EXECUTE PROCEDURE bdtravaux.totablesynth_fn();
varchantvol
变量已正确填充,但 varoperateur
仍然空无一物(NULL 值)(synthese_poly
table 中的相应字段以此类推) .
注:
SELECT array_to_string(…) ...
查询本身(使用 pgAdmin 启动,没有 INTO varoperateur
并用值替换 varopeid
)运行良好,returns 一个字符串。
我尝试更改 array_to_string()
函数和变量的数据类型(使用 ::varchar
或 ::text
…),没有任何效果。
你知道会发生什么吗?
我有根据的猜测:你有一个触发器 BEFORE INSERT ON bdtravaux.operation_poly
。而operation_id
就是它的serial
PK栏目。
在这种情况下,带有 WHERE o.operation_id = varopeid
的查询
(其中 varopeid
已填充 NEW.operation_id
)永远找不到任何行,因为该行不在 table 中。
array_agg()
在此没有任何作用。
可以使用触发器 AFTER INSERT ON bdtravaux.operation_poly
。但是如果 id_oper
来自同一个插入行,你可以简化为:
SELECT array_to_string(array_agg(DISTINCT oper.operateurs),'; ')
INTO varoperateur
FROM bdtravaux.join_operateurs oper
WHERE oper.id_joinop = NEW.id_oper;
并保留 BEFORE
触发器。
整个功能可能会更简单,一个查询就可以完成。
使用array_agg
您可以将 array_to_string(array_agg(DISTINCT oper.operateurs),'; ')
替换为
string_agg(DISTINCT oper.operateurs,'; ')
您可以使用 order by 对聚合中的文本进行排序
string_agg(DISTINCT oper.operateurs,'; ' ORDER BY oper.operateurs)
我正在使用 PostgreSQL 9.5。
我正在 PL/pgSQL 中创建一个触发器,它在 table (synthese_poly
) 中添加一条记录,当 INSERT
在第二个 table (operation_poly
),与其他 tables 数据。
触发器运行良好,除了一些未填充的变量(尤其是我尝试使用 array_to_string()
函数填充的变量)。
这是代码:
-- Function: bdtravaux.totablesynth_fn()
-- DROP FUNCTION bdtravaux.totablesynth_fn();
CREATE OR REPLACE FUNCTION bdtravaux.totablesynth_fn()
RETURNS trigger AS
$BODY$
DECLARE
varoperateur varchar;
varchantvol boolean;
BEGIN
IF (TG_OP = 'INSERT') THEN
varsortie_id := NEW.sortie;
varopeid := NEW.operation_id;
--The following « SELECT » queries take data in third-party tables and fill variables, which will be used in the final insertion query.
SELECT array_to_string(array_agg(DISTINCT oper.operateurs),'; ')
INTO varoperateur
FROM bdtravaux.join_operateurs oper INNER JOIN bdtravaux.operation_poly o ON (oper.id_joinop=o.id_oper)
WHERE o.operation_id = varopeid;
SELECT CASE WHEN o.ope_chvol = 0 THEN 'f' ELSE 't' END as opechvol INTO varchantvol
FROM bdtravaux.operation_poly o WHERE o.operation_id = varopeid;
-- «INSERT» query
INSERT INTO bdtravaux.synthese_poly (soperateur, schantvol) SELECT varoperateur, varchantvol;
RAISE NOTICE 'varoperateur value : (%)', varoperateur;
RAISE NOTICE 'varchantvol value : (%)', varchantvol;
END IF;
RETURN NEW;
END;
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION bdtravaux.totablesynth_fn()
OWNER TO postgres;
这就是触发器:
-- Trigger: totablesynth on bdtravaux.operation_poly
-- DROP TRIGGER totablesynth ON bdtravaux.operation_poly;
CREATE TRIGGER totablesynth
AFTER INSERT
ON bdtravaux.operation_poly
FOR EACH ROW
WHEN ((new.chantfini = true))
EXECUTE PROCEDURE bdtravaux.totablesynth_fn();
varchantvol
变量已正确填充,但 varoperateur
仍然空无一物(NULL 值)(synthese_poly
table 中的相应字段以此类推) .
注:
SELECT array_to_string(…) ...
查询本身(使用 pgAdmin 启动,没有 INTO varoperateur
并用值替换 varopeid
)运行良好,returns 一个字符串。
我尝试更改 array_to_string()
函数和变量的数据类型(使用 ::varchar
或 ::text
…),没有任何效果。
你知道会发生什么吗?
我有根据的猜测:你有一个触发器 BEFORE INSERT ON bdtravaux.operation_poly
。而operation_id
就是它的serial
PK栏目。
在这种情况下,带有 WHERE o.operation_id = varopeid
的查询
(其中 varopeid
已填充 NEW.operation_id
)永远找不到任何行,因为该行不在 table 中。
array_agg()
在此没有任何作用。
可以使用触发器 AFTER INSERT ON bdtravaux.operation_poly
。但是如果 id_oper
来自同一个插入行,你可以简化为:
SELECT array_to_string(array_agg(DISTINCT oper.operateurs),'; ')
INTO varoperateur
FROM bdtravaux.join_operateurs oper
WHERE oper.id_joinop = NEW.id_oper;
并保留 BEFORE
触发器。
整个功能可能会更简单,一个查询就可以完成。
使用array_agg
您可以将 array_to_string(array_agg(DISTINCT oper.operateurs),'; ')
替换为
string_agg(DISTINCT oper.operateurs,'; ')
您可以使用 order by 对聚合中的文本进行排序
string_agg(DISTINCT oper.operateurs,'; ' ORDER BY oper.operateurs)