# 39.1.触发行为概述

触发器是一种规范,每当执行某种类型的操作时,数据库应自动执行特定的功能。触发器可以附加到表(分区或非分区)、视图和外部表。

在表和外部表上,可以定义触发器在任何插入,使现代化删去操作,每个修改的行一次,或每个SQL语句一次。使现代化此外,只有在中提到某些列时,才能将触发器设置为激发设置合同条款使现代化陈述触发器也可以触发截断声明。如果触发事件发生,将在适当的时间调用触发器的函数来处理该事件。

在视图上,可以定义触发器来执行,而不是插入,使现代化删去操作。这样的而不是对于视图中需要修改的每一行触发一次触发器。触发器的功能负责对视图的基础基表执行必要的修改,并在适当的情况下返回修改后的行,使其在视图中显示。视图上的触发器也可以定义为在每个SQL语句之前或之后执行一次插入,使现代化删去操作。然而,只有在同时存在而不是在视图上触发。否则,任何针对视图的语句都必须重写为影响其基础基表的语句,然后将触发的触发器是附加到基表的触发器。

必须先定义触发器函数,然后才能创建触发器本身。触发器函数必须声明为不带参数且返回类型的函数触发(触发器函数通过特殊传递的触发数据结构,而不是普通函数参数的形式。)

一旦创建了一个合适的触发函数,就可以使用创建触发器.相同的触发器功能可用于多个触发器。

PostgreSQL提供了这两种功能每行触发器和每份声明触发器。对于每行触发器,对于受触发触发器的语句影响的每一行,都会调用一次触发器函数。相反,当执行适当的语句时,每语句触发器只被调用一次,而不管该语句影响的行数是多少。特别是,影响零行的语句仍然会导致执行任何适用的per语句触发器。这两种触发器有时被称为行级触发器和语句级分别触发。触发截断只能在语句级别定义,不能按行定义。

触发器也根据是否触发进行分类之前, 之后而不是手术。这些被称为之前触发器,之后触发器,以及而不是分别触发。语句级之前触发器在语句开始执行任何操作之前自然触发,而语句级别之后在语句的最后触发触发。这些类型的触发器可以在表、视图或外部表上定义。行级之前在对特定行进行操作之前立即触发火灾,而行级别之后触发器在语句末尾(但在任何语句级别之前)触发之后触发器)。这些类型的触发器只能在表和外部表上定义,不能在视图上定义。而不是触发器只能在视图上定义,并且只能在行级别定义;当视图中的每一排都被确定为需要操作时,它们会立即开火。

处决之后如果触发器被定义为约束触发器。在所有情况下,触发器都是作为触发它的语句的同一事务的一部分执行的,因此,如果该语句或触发器中的任何一个导致错误,则两者的影响都将回滚。

以继承或分区层次结构中的父表为目标的语句不会触发受影响子表的语句级触发器;只触发父表的语句级触发器。但是,任何受影响的子表的行级触发器都将被激发。

如果插入包含一个关于冲突,请更新子句中,行级别的影响之前 插入触发器和行级别之前 使现代化这两个触发器的应用方式都可以从更新行的最终状态明显看出,如果排除列被引用。不需要有一个排除两组行级别的列引用之前不过,它会触发执行。当两者同时存在时,应考虑意外结果的可能性之前 插入之前 使现代化行级触发器,用于更改正在插入/更新的行(即使修改或多或少是等效的,如果它们不是幂等的,这也会有问题)。注意语句级别使现代化触发器在以下情况下执行:关于冲突,请更新指定,而不管任何行是否受使现代化(而且无论替代方案使现代化曾经走过的路)。一插入带着关于冲突,请更新子句将在语句级别执行之前 插入先触发,然后是语句级之前 使现代化触发器,后跟语句级之后 使现代化触发器,最后是语句级之后 插入触发器。

如果使现代化在一个分区表上,当一行移动到另一个分区时,它将作为删去从原始分区,然后是插入进入新的分区。在本例中,所有行级别之前 使现代化触发器和所有行级别之前 删去触发器在原始分区上触发。然后所有的行水平之前 插入触发器在目标分区上触发。当所有这些触发因素都影响正在移动的行时,应考虑意外结果的可能性。远至赛后就触发因素而言,之后 删去之后 插入触发器被应用;但是之后 使现代化触发器不会被应用,因为使现代化已转换为删去还有插入.就语句级触发器而言删去插入即使发生行移动,也会触发触发器;只有使现代化在中使用的目标表上定义的触发器使现代化声明将被解雇。

每语句触发器调用的触发器函数应始终返回无效的.每行触发器调用的触发器函数可以返回表行(类型为一堆)如果他们愿意的话,给打电话的遗嘱执行人。在操作具有以下选项之前触发的行级触发器:

  • 它可以回来无效的跳过当前行的操作。这指示执行器不要执行调用触发器的行级操作(插入、修改或删除特定表行)。

  • 行级别插入使现代化仅触发器时,返回的行将成为要插入的行或将替换正在更新的行。这允许触发器函数修改正在插入或更新的行。

    一排之前不打算导致这两种行为的触发器必须小心返回传入的同一行(即划船插入使现代化触发器古老的划船删去触发器)。

    一排而不是触发器应该返回无效的指示它没有修改视图基础基表中的任何数据,或者它应该返回传入的视图行(划船插入使现代化行动,或古老的划船删去操作)。非空返回值用于表示触发器在视图中执行了必要的数据修改。这将导致受命令影响的行数的计数增加。对于插入使现代化仅限操作时,触发器可能会修改在归还之前先划船。这将更改插入返回更新返回,并且在视图显示的数据与提供的数据不完全相同时非常有用。

    对于在操作后激发的行级触发器,返回值被忽略,因此它们可以返回无效的.

    一些注意事项适用于生成的列。存储的生成列在之前触发和之前之后触发器。因此,生成的值可以在之后触发器。在里面之前触发器古老的行包含旧生成的值,正如人们所料,但行尚未包含新生成的值,因此不应访问该行。在C语言界面中,此时未定义列的内容;更高级的编程语言应该阻止访问存储在排成一排之前触发对中生成的列的值所做的更改之前触发器被忽略并将被覆盖。

    如果为同一关系上的同一事件定义了多个触发器,则将按触发器名称的字母顺序触发这些触发器。就之前而不是触发器,每个触发器返回的可能修改的行成为下一个触发器的输入。如果有的话之前而不是触发返回无效的,则该行的操作被放弃,且后续触发器不会(针对该行)触发。

    触发器定义也可以指定布尔值什么时候条件,将对其进行测试,以确定是否应触发触发器。行内级别触发什么时候条件可以检查行中列的旧值和/或新值。(语句级触发器也可以具有什么时候条件,尽管该功能对它们不太有用。)在一个之前扳机什么时候条件是在函数被执行或将被执行之前计算的,所以使用什么时候与在触发功能开始时测试相同条件没有实质性区别。然而,在一个之后扳机什么时候在行更新发生后立即计算条件,它确定是否将事件排队以在语句末尾触发触发器。所以当之后扳机什么时候条件不返回true,不需要对事件排队,也不需要在语句末尾重新获取行。如果只需要为少数几行触发触发器,这可能会导致修改许多行的语句的速度显著加快。而不是触发器不支持什么时候条件

    通常,行级别之前触发器用于检查或修改将插入或更新的数据。例如,一个之前触发器可用于将当前时间插入时间戳列,或检查行的两个元素是否一致。行级之后触发器最明智地用于将更新传播到其他表,或对其他表进行一致性检查。这种分工的原因是之后触发器可以确定它看到的是行的最终值,而之前触发不能;可能还有其他原因之前触发后开火。如果你没有特定的理由触发之前之后这个之前case更有效,因为在语句结束之前不必保存有关操作的信息。

    如果触发器函数执行SQL命令,那么这些命令可能会再次触发触发器。这被称为级联触发器。级联级别的数量没有直接限制。级联可能导致对同一触发器的递归调用;例如插入触发器可能会执行一个命令,在同一个表中插入另一行,从而导致插入再次触发。在这种情况下,触发器程序员有责任避免无限递归。

定义触发器时,可以为其指定参数。在触发器定义中包含参数的目的是允许具有类似需求的不同触发器调用相同的函数。例如,可能有一个通用触发器函数,它将两个列名作为参数,将当前用户放在其中一个,将当前时间戳放在另一个。如果编写得当,这个触发器函数将独立于它所触发的特定表。所以同样的功能也可以用于插入事件,以自动跟踪事务表中记录的创建。如果定义为使现代化触发

每种支持触发器的编程语言都有自己的方法,用于使触发器输入数据可供触发器函数使用。该输入数据包括触发事件的类型(例如。,插入使现代化)以及在创建触发器.对于行级触发器,输入数据还包括划船插入使现代化触发器和/或古老的划船使现代化删去触发器。

默认情况下,语句级触发器无法检查由语句修改的各行。但是事后陈述触发器可以请求过渡表被创建以使受影响的行集可供触发器使用。赛后触发器还可以请求转换表,以便查看表中的全部更改以及当前触发的单个行中的更改。再次检查转换表的方法取决于所使用的编程语言,但典型的方法是使转换表的行为类似于只读临时表,可以通过触发器函数中发出的SQL命令来访问。