确定触发器函数内的更新是不是导致另一个触发器触发
Posted
技术标签:
【中文标题】确定触发器函数内的更新是不是导致另一个触发器触发【英文标题】:Determining whether an update inside a trigger function caused another trigger to fire确定触发器函数内的更新是否导致另一个触发器触发 【发布时间】:2015-05-10 02:28:23 【问题描述】:我想知道是否从另一个触发器函数内部调用了插入/更新/删除操作,以便我可以在不允许插入/更新/删除操作的表 X 上应用触发器,除非该操作正在执行表 Y 上的触发函数。
换句话说,我希望在发出插入/更新/删除操作时在表 Y 上有一个触发器,检查是否从表 X 触发器调用了该操作,如果是,则继续 - 否则,拒绝行动。
我还相信,根据触发器的层次结构,让触发器函数可用的“请求源”信息可能有助于调试。
【问题讨论】:
【参考方案1】:您在此处提出的建议与启用或拒绝访问数据库中数据的标准方式背道而驰。通常,您可以通过GRANT
ing 表和函数的权限来解决此问题。您的情况可以这样解决:
首先,创建具有特定角色(= 用户、组)的表,例如“管理员”。
CREATE TABLE x (...);
ALTER TABLE x OWNER to admin; -- Not necessary if "admin" created the table
CREATE TABLE y (...);
ALTER TABLE y OWNER to admin;
此时只有角色“admin”可以访问表。如果您希望其他用户(例如角色“app_user”)从表x
中进行选择,并从表y
中选择、插入、更新和删除,那么您应该明确地GRANT
这些权限:
GRANT SELECT ON x TO app_user;
GRANT SELECT, INSERT, UPDATE, DELETE ON y TO app_user;
然后在表y
上定义一个触发器,并在触发器函数中将更改级联到表x
;我假设你已经解决了这个问题。这里的技巧是让“admin”用户作为触发器函数的所有者(这是合乎逻辑的,因为只有“admin”可以CREATE TRIGGER
在表y
上)然后使用SECURITY DEFINER
。这意味着即使“app_user”执行了一个调用触发器的INSERT INTO y ...
,对表x
进行级联操作的触发器函数也会以用户“admin”的权限执行:
CREATE FUNCTION my_trigger_func RETURNS trigger AS $$
BEGIN
-- Perform some operation on x
RETURN NEW; -- or OLD
END;
$$ LANGUAGE plpgsql SECURITY DEFINER;
ALTER FUNCTION my_trigger_func OWNER TO admin; -- If needed
REVOKE ALL ON FUNCTION my_trigger_func FROM public;
CREATE TRIGGER my_trigger
BEFORE INSERT, UPDATE, DELETE ON y -- or AFTER, depending on your needs
FOR EACH ROW EXECUTE PROCEDURE my_trigger_func();
请注意,您不必在触发器函数上使用GRANT EXECUTE
:因为“app_user”对调用运行触发器函数的触发器的表y
具有权限,因此允许“app_user”执行触发器函数。
按照这个过程,“app_user”可以修改表x
的唯一方法是通过表y
。使用“admin”可以直接修改表x
,但是作为表和触发器所有者这个角色应该比直接修改表x
更清楚。
【讨论】:
以上是关于确定触发器函数内的更新是不是导致另一个触发器触发的主要内容,如果未能解决你的问题,请参考以下文章