关联名称和伪记录

OLD、NEW和PARENT

行级触发器可以访问它通过关联名称正在处理的行的数据,默认的关联名称是OLD、NEW和PARENT。

如果触发器是基于内嵌到视图中的表而创建,则OLD和NEW指的是内嵌表的当前行,PARENT指的是父表的当前行; 如果触发器是基于表或视图创建,那么OLD和NEW指的是表和视图的当前行,而此时的PARENT未定义。

由于OLD、NEW和PARENT拥有记录的结构,但是相比记录而言在内容上有所限制,因此它们也被称为伪记录。

伪记录的结构

伪记录的结构为table_name%ROWTYPE,对于OLD和NEW而言,table_name表示触发器创建时所基于的表,对于PARENT而言,则是相应的父表。

在简单的触发器中的trigger_body在复合触发器中的tps_body中,关联名称是一个和参数绑定的占位符,其基本语法如下:

:pseudorecord_name.field_name

在条件触发器的WHEN条件限定语句中,由于关联名称不是作为一个和参数绑定的占位符,因此应省略上面语法中的冒号。

OLD 与 NEW 的取值

下表列出了对于触发器语句正在处理的行的OLD和NEW的值:

Triggering Statement OLD.fieldValue NEW.fieldValue
INSERT NULL Post-insert value
UPDATE Pre-update value Post-update value
DELETE Pre-delete value NULL

特殊变量

在一个PLOSCAR触发器调用的时候,系统会在顶层的声明段里自动创建如下表所示几个特殊变量。

变量名 数据类型 含义
TG_NAME NAME 触发器名称。
TG_WHEN text 一个由触发器定义决定的字符串。 取值为 'BEFORE' 或者 'AFTER'。
TG_LEVEL text 一个由触发器定义决定的字符串。 取值为 'ROW' 或者 'STATEMENT'。
TG_OP text 一个说明触发事件的字符串。 取值为 'INSERT' 、 'UPDATE' 或者 'DELETE'。
TG_RELID OID 激活触发器调用的表的对象标识(OID)。
TG_RELNAME NAME 激活触发器调用的表的名称。

示例

示例1: 使用触发器中的特殊变量

--  清理环境
DROP TRIGGER trg4;
DROP TRIGGER trg3;
DROP TRIGGER trg2;
DROP TRIGGER trg1;
DROP TABLE tab1 CASCADE;


--  创建表
CREATE TABLE tab1 (a varchar(20), b varchar(20));


--  创建 BEFORE INSERT 语句级触发器(使用特殊变量)
CREATE TRIGGER trg1 BEFORE INSERT ON tab1
FOR EACH STATEMENT
BEGIN
    RAISE NOTICE 'trg1 called: action = %, when = %, level = %',
                TG_OP, TG_WHEN, TG_LEVEL;
END;
/

--  创建 AFTER INSERT 语句级触发器(使用特殊变量)
CREATE TRIGGER trg2 AFTER INSERT ON tab1
FOR EACH STATEMENT
BEGIN
    RAISE NOTICE 'trg2 called: action = %, when = %, level = %',
                TG_OP, TG_WHEN, TG_LEVEL;
END;
/


--  触发 TRIGGER
INSERT INTO tab1 VALUES('1', '100');
1
NOTICE, trg1 called: action = INSERT, when = BEFORE, level = STATEMENT
NOTICE, trg2 called: action = INSERT, when = AFTER, level = STATEMENT
INSERT INTO tab1 VALUES('2', '200');
1
NOTICE, trg1 called: action = INSERT, when = BEFORE, level = STATEMENT
NOTICE, trg2 called: action = INSERT, when = AFTER, level = STATEMENT


SELECT * FROM tab1 ORDER BY a, b;
A(varchar)      |B(varchar)      |
--------------------------------
1               |100             |
--------------------------------
2               |200             |
总数目:2


--  创建 BEFORE UPDATE 行级触发器(使用伪记录和特殊变量)
CREATE TRIGGER trg3 BEFORE UPDATE ON tab1
FOR EACH ROW
BEGIN
    RAISE NOTICE 'trg3 called: action = %, when = %, level = %',
                TG_OP, TG_WHEN, TG_LEVEL;
    RAISE NOTICE 'trg3 called: OLD.a = %, OLD.b = %, NEW.a = %, NEW.b = %',
                :OLD.a, :OLD.b, :NEW.a, :NEW.b;
END;
/

--  创建 AFTER UPDATE 行级触发器(使用伪记录和特殊变量)
CREATE TRIGGER trg4 AFTER UPDATE ON tab1
FOR EACH ROW
BEGIN
    RAISE NOTICE 'trg4 called: action = %, when = %, level = %',
                TG_OP, TG_WHEN, TG_LEVEL;
    RAISE NOTICE 'trg4 called: OLD.a = %, OLD.b = %, NEW.a = %, NEW.b = %',
                :OLD.a, :OLD.b, :NEW.a, :NEW.b;
END;
/


--  触发 TRIGGER
UPDATE tab1 SET a = '5' WHERE b = '100';
1
NOTICE, trg3 called: action = UPDATE, when = BEFORE, level = ROW
NOTICE, trg3 called: OLD.a = 1, OLD.b = 100, NEW.a = 5, NEW.b = 100
NOTICE, trg4 called: action = UPDATE, when = AFTER, level = ROW
NOTICE, trg4 called: OLD.a = 1, OLD.b = 100, NEW.a = 5, NEW.b = 100
UPDATE tab1 SET a = '6', b = '600';
2
NOTICE, trg3 called: action = UPDATE, when = BEFORE, level = ROW
NOTICE, trg3 called: OLD.a = 5, OLD.b = 100, NEW.a = 6, NEW.b = 600
NOTICE, trg3 called: action = UPDATE, when = BEFORE, level = ROW
NOTICE, trg3 called: OLD.a = 2, OLD.b = 200, NEW.a = 6, NEW.b = 600
NOTICE, trg4 called: action = UPDATE, when = AFTER, level = ROW
NOTICE, trg4 called: OLD.a = 5, OLD.b = 100, NEW.a = 6, NEW.b = 600
NOTICE, trg4 called: action = UPDATE, when = AFTER, level = ROW
NOTICE, trg4 called: OLD.a = 2, OLD.b = 200, NEW.a = 6, NEW.b = 600


SELECT * FROM tab1 ORDER BY a, b;
A(varchar)      |B(varchar)      |
--------------------------------
6               |600             |
--------------------------------
6               |600             |
总数目:2


--  删除触发器和表
DROP TRIGGER trg4;
DROP TRIGGER trg3;
DROP TRIGGER trg2;
DROP TRIGGER trg1;
DROP TABLE tab1;