2

触发功能与“常规”功能有何不同?创建触发器是否绝对必要?

例如,在这种情况下:

-- Trigger function
CREATE FUNCTION update_record_trigger_function() RETURNS trigger
LANGUAGE plpgsql
AS $update_record_trigger_function$
BEGIN
  PERFORM update_record(NEW.oid); -- helper function ... 
  RETURN NEW;
END
$update_record_trigger_function$;

-- Trigger for updating latest clicks for posts
CREATE TRIGGER update_latest_record
AFTER INSERT OR UPDATE ON record
FOR EACH ROW
EXECUTE PROCEDURE update_record_trigger_function();

会不会更简单(或者是否可以这样做):

-- Trigger for updating latest clicks for posts
CREATE TRIGGER update_latest_record
AFTER INSERT OR UPDATE ON record
FOR EACH ROW
PERFORM update_record(NEW.oid); -- syntactically not right but along this idea

我找不到任何包含“跳过触发功能”示例的文档或解释触发功能对触发器的特殊性和必要性的文档?

4

1 回答 1

4

PostgreSQL 将“触发器函数”从触发器定义中分离出来的原因有很多:

  • 触发器函数可以写成通用函数,可以作用于许多不同的表,因此您可以将相同的触发器函数作为触发器添加到许多不同的表中。这便于维护。

  • 触发器函数可以采用参数,使它们能够适应特定的列名或应用它们的表的其他特征。这使得编写通用的、可重用的触发器函数变得切实可行,否则您将无法这样做,因此您通常不需要在多个地方重复代码。参见EXECUTE ... USINGformat函数及其%L%I格式说明符。

  • PostgreSQL 非常努力地不在乎你的函数是用什么编程语言编写的。它们可以是 PL/PgSQL、Python、Perl、C 或 MyWackyPluginLanguage。如果它没有将触发器功能与触发器定义分开,这将更难实现。

PostgreSQL 不支持您描述的速记,尽管其他一些数据库系统提供的东西与您所展示的非常相似。您本质上希望能够将触发器函数定义为内联表达式。这不受支持。从来没有迫切需要它,所以没有人实施它。

如果将来添加了这样的功能-我不知道有任何计划这样做-可能会使用DO上下文解释为触发器的 PL/PgSQL 块来完成,例如(不是合法的语法):

CREATE TRIGGER update_latest_record
AFTER INSERT OR UPDATE ON record
FOR EACH ROW DO $$ PERFORM update_record(NEW.oid); RETURN NEW; $$;

这样解析器就不需要理解 PL/PgSQL 结构,我们只需要教它理解FOR EACH ROW DO [string literal body of function]作为替代方案FOR EACH ROW EXECUTE PROCEDURE proc_name(args),然后调用 PL/PgSQL 子系统来处理触发器文字。

在实践中,Pg 可能只是生成一个普通的触发器函数并从触发器中添加对它的引用,因此如果触发器被删除,它就会被删除,这使得它成为一个方便的宏,就像一个带有 a和 aSERIAL的字段的便利宏生成由具有该字段的表拥有。特别是,可能会像定义一个单独的触发器函数和触发器一样输出它,而不是使用速记。INTEGERDEFAULT nextval(...)SEQUENCESERIALpg_dump

老实说,我怀疑这样的东西会不会被添加,但如果你能提供足够令人信服的用例,如果你真的很幸运的话,你可能会对它感兴趣。如果您愿意为实施该功能所需的时间提供资金支持,那么您很可能只会通过这样的提议(“允许将 DO 块用作触发程序”)获得任何结果。

于 2013-02-14T16:18:24.247 回答