我一直试图弄清楚如何创建一个触发器/函数,它将在更新表行时计算一个值。这是我正在创建的DVD租赁数据库。我有一些数据库经验,但我只开始使用触发器和函数。我想要发生的是,当员工插入电影返还日期时,它将采用租用日期并从返回日期中减去它,然后将每天的差价乘以1.99美元。我有计算它的表达式。我想要一个触发器来运行表达式并将结果插入到该表中。
例如:
客户返回电影,员工将返回日期输入到Rent表中,当此行更新时,触发器将运行计算欠款的表达式,并将结果插入到amount_owed列的Rent表行中。
以下是我一直在尝试的一些事情,触发器执行该功能,但之后我收到错误。
功能代码:
BOOST_LOG_TRIVIAL
触发码:
CREATE OR REPLACE FUNCTION update_cus_balance(integer)
RETURNS void AS
$BODY$
BEGIN
UPDATE rent
SET amount_owed=subquery.balance
FROM (SELECT date_part('day'::text, rent.return_date - rent.rent_date) * 2.99::double precision AS balance
from rent) AS subquery
WHERE rent.rent_id=rent_id;
END
$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
ALTER FUNCTION update_cus_balance(integer)
OWNER TO postgres;
PGadmin III只是说"发生错误"当我尝试添加return_date并保存更改时。
答案 0 :(得分:0)
update
表上的rent
会触发trigger
,触发器会更新租借表。租借表上的更新会触发一个触发器,一个触发器......
这就是您收到stack depth limit exceeded
错误的原因。
可以轻松修复添加
AND amount_owed<>subquery.balance
触发器中查询的WHERE
子句。但是,您可以更好地将触发器更改为BEFORE UPDATE
,为了保持一致性,它甚至应该BEFORE INSERT OR UPDATE
触发,以检查return_date
是否已填充。
看起来像练习练习,所以请自行尝试触发前。
答案 1 :(得分:0)
就像Jakub所说,你需要一个BEFORE UPDATE
触发器来完成这项工作。这种触发器有两个重要特征:
OLD
和一个NEW
变量,它包含更新前行的值以及更新后的内容。您可以操作NEW
变量,然后这些更改将保存到表中。根据您的情况,触发器功能看起来像这样:
CREATE OR REPLACE FUNCTION update_cus_balance(integer)
RETURNS void trigger AS -- A trigger function should ALWAYS return trigger
$BODY$
BEGIN
-- Calculate rent if the return date is set or changed
IF NEW.return_date <> OLD.return_date THEN
IF NEW.return_date = NEW.rent_date THEN -- Same day returns
NEW.amount_owed := 2.99;
ELSE
NEW.amount_owed := (NEW.return_date - NEW.rent_date) * 2.99;
END IF;
END IF;
-- Trigger function should ALWAYS return NEW to succeed.
-- Return NULL to make the update fail.
RETURN NEW;
END
$BODY$ LANGUAGE plpgsql;
触发器应为:
CREATE TRIGGER update_balance
BEFORE UPDATE ON rent
FOR EACH ROW EXECUTE PROCEDURE update_cus_balance();
请注意,我假设rent_date
和return_date
的类型为date
(顾名思义)。如果它们是timestamp
,您可以创建两个变量并EXTRACT()
出租日期并返回到这些变量。
PostgreSQL中的触发器和函数并不是很复杂,但请仔细阅读excellent manual。