如何防止 PostgreSQL 触发器被另一个触发器触发?

dd_*_*d_a 11 postgresql trigger plpgsql postgresql-9.3

我在一张桌子上有 2 个触发器;一种适用于插入:

CREATE TRIGGER "get_user_name"
AFTER INSERT ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "add_info"();
Run Code Online (Sandbox Code Playgroud)

这会更新表中的一些值。
还有一个用于更新(填充历史表):

CREATE TRIGGER "set_history"
BEFORE UPDATE ON "field_data"
FOR EACH ROW EXECUTE PROCEDURE "gener_history"();
Run Code Online (Sandbox Code Playgroud)

问题是,当我在表中插入新行时,该过程"add_info"()会进行更新并因此触发第二个触发器,该触发器以错误结束:

ERROR:  record "new" has no field "field1"
Run Code Online (Sandbox Code Playgroud)

我怎样才能避免这种情况?

Erw*_*ter 19

(在触发逻辑明显的错误一边。)
在Postgres的9.2或更高版本,使用该函数pg_trigger_depth()的是@Akash已经提到的上的触发条件本身(而不是触发功能的机构),使得触发功能是连从另一个触发器调用时执行(包括它自己 - 因此也可以防止循环)。
这通常性能更好,更简单、更干净:

CREATE TRIGGER set_history
BEFORE UPDATE ON field_data
FOR EACH ROW 
WHEN (pg_trigger_depth() < 1)
EXECUTE PROCEDURE gener_history();
Run Code Online (Sandbox Code Playgroud)

输入触发器函数之前pg_trigger_depth() < 1计算表达式。所以它在第一次调用时评估为 0。当从另一个触发器调用时,该值较高且不执行触发器函数。


Aka*_*ash 5

如果您不希望在插入触发器中调用更新触发器时执行更新触发器,则可以将语句包围在pg_trigger_depth()返回深度的条件中,当您直接/间接从另一个触发器运行触发器时该条件不会为 0 .

所以,在你的函数中gener_history(),你可以做这样的事情

IF pg_trigger_depth() = 1 THEN
.. your statements..
END IF;
Run Code Online (Sandbox Code Playgroud)

这是另一个例子:http : //www.depesz.com/2012/02/01/waiting-for-9-2-trigger-depth/