Postgresql 根据值更新特定字段(触发器)
Postgresql update specific fields based on a value (trigger)
我正在 Postgresql 中编写一个触发器,根据 咨询 收入 table 中的特定列动态更新特定列的内容 table。 [编辑] 这是我的 table 的样子
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
我正在寻找一种直接的解决方案,仅设置与 咨询 上添加的新行的时间戳对应的列(月)。根据 psql 中的时间戳获取月份名称相当容易:to_char(2018-12-05 04:42:11.66867+01, 'Month') ==> December
[问题] 但是,我不知道如何使用它来指示 psql 应该更新哪一列。这是我正在寻找的内容的总体思路。主要问题是我使用 value 来表示 field(参见 SET 行)。是否有解决方法,以便我可以直接 select 相关字段? (我尝试了好几样东西,但都不是很成功)
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();
您需要在触发器函数中使用动态 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;
你应该使用动态 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 = AND to_char(date, ''MM-YYYY'') =
)'
,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)
我正在 Postgresql 中编写一个触发器,根据 咨询 收入 table 中的特定列动态更新特定列的内容 table。 [编辑] 这是我的 table 的样子
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
我正在寻找一种直接的解决方案,仅设置与 咨询 上添加的新行的时间戳对应的列(月)。根据 psql 中的时间戳获取月份名称相当容易:to_char(2018-12-05 04:42:11.66867+01, 'Month') ==> December
[问题] 但是,我不知道如何使用它来指示 psql 应该更新哪一列。这是我正在寻找的内容的总体思路。主要问题是我使用 value 来表示 field(参见 SET 行)。是否有解决方法,以便我可以直接 select 相关字段? (我尝试了好几样东西,但都不是很成功)
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();
您需要在触发器函数中使用动态 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;
你应该使用动态 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 = AND to_char(date, ''MM-YYYY'') =
)'
,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)