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"()会进行更新并因此触发第二个触发器,该触发器以错误结束:
Run Code Online (Sandbox Code Playgroud)ERROR: record "new" has no field "field1"
我怎样才能避免这种情况?
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。当从另一个触发器调用时,该值较高且不执行触发器函数。
如果您不希望在插入触发器中调用更新触发器时执行更新触发器,则可以将语句包围在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/