我正在Postgresql中编写触发器,以基于咨询表上的插入内容动态更新收入表中特定列的内容。 [编辑]这是我的表格的样子
SELECT * FROM psy_revenues;
id | owner_id | January | February | March | April | etc | etc
---+----------+---------+----------+-------+-------+-----+----
2 | 1 |0 | 0 | 0 | 0 | |
SELECT * FROM psy_consultations;
id | first_name | last_name | date | payed | owner_id
---+------------+-----------+-----------------------------+-------+---------
3 | Gérard | Bouchard |2018-12-05 04:49:26.064397+01| 80 |1
4 | Pasti | Lami |2018-12-05 23:23:52.454849+01| 60 |2
我正在寻找一种简单的解决方案,以仅设置与 consults 上添加的NEW行的时间戳相对应的列(月)。根据psql中的时间戳获取月份名称非常容易:to_char(2018-12-05 04:42:11.66867 + 01,'Month')==>十二月
[问题]但是,我不知道如何使用它来指示psql应该更新哪一列。这是我正在寻找的一般想法。主要问题是我正在使用值来表示字段(请参阅SET行)。有没有解决方法,所以我可以直接选择相关字段? (我尝试了几件事,但不是很成功)
CREATE OR REPLACE FUNCTION update_revenues()
RETURNS trigger AS
$BODY$
BEGIN
UPDATE psy_revenues
SET to_char(NEW.date, 'Month') = (
SELECT SUM(payed)
FROM psy_consultations
WHERE (
owner_id = NEW.owner_id
AND to_char(date, 'Month')=to_char(NEW.date, 'Month')
)
);
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;
CREATE TRIGGER update_revenues
AFTER INSERT
ON psy_consultations
FOR EACH ROW
EXECUTE PROCEDURE update_revenues();
答案 0 :(得分:1)
您需要在触发函数中使用动态sql:生成包含正确的SQL代码的字符串,然后使用EXECUTE
关键字来运行它。
以下代码应该可以解决问题:
CREATE OR REPLACE FUNCTION update_revenues()
RETURNS trigger AS
$BODY$
DECLARE
new_month text;
new_owner_id integer;
BEGIN
new_month := to_char(NEW.date, 'Month');
new_owner_id := NEW.owner_id;
EXECUTE
'UPDATE psy_revenues
SET ' || new_month || ' = (
SELECT SUM(payed) FROM psy_consultations
WHERE (
owner_id = ' || new_owner_id || '
AND to_char(date, ''Month'') = ' || new_month || '
)
)';
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;
答案 1 :(得分:1)
您应该使用动态SQL。请避免串联以避免SQL注入,请使用format
函数和位置参数
CREATE OR REPLACE FUNCTION update_revenues()
RETURNS trigger AS
$BODY$
DECLARE
BEGIN
EXECUTE format (
'UPDATE psy_revenues
SET %I = (
SELECT SUM(payed) FROM psy_consultations WHERE
owner_id = $1 AND to_char(date, ''MM-YYYY'') = $2
)'
,to_char(NEW.date, 'FMMonth') ) --column name to update(%I)
USING NEW.owner_id , to_char(NEW.date, 'MM-YYYY');--values for owner_id & month
RETURN NEW;
END;
$BODY$ LANGUAGE plpgsql;
编辑:似乎TO_CHAR()
用空格填充了月份字符串,我添加了FM修饰符(如@horse建议)将其删除。
看到这个:
knayak=# select '|'||to_char(current_date,'Month')||'|' as mon ;
mon
-------------
|December |
(1 row)