创建触发器的语法格式如下图:
CREATE TRIGGER语句用于将触发器添加到数据库中。 所谓触发器是指在发生指定的数据库事件时自动执行的数据库操作。通常情况下,触发器必须指定一个关联表,当这个关联表发生了触发器指定的操作时,触发器就将自动进行定义的操作。
例如:
CREATE TRIGGER tri_t1 before insert on t1 Begin …… End.
通常情况下,触发器有三个要素:
- 时机,即什么时候启动触发器。
- 条件,即启动触发器的条件。
- 关联表,这个是触发器关联的数据表,当数据表删除时,也会自动删除创建的触发器;
在SQLITE中,时机部分是可忽略的(默认是before),而条件是不允许省略的,每个触发器必须指定将针对以下操作之一触发:DELETE,INSERT,UPDATE。 触发器为删除,插入或更新的每一行触发一次。
如果BEFORE UPDATE或BEFORE DELETE触发器修改或删除了将要更新或删除的行,则后续更新或删除操作的结果很难确定。 此外,如果BEFORE触发器修改或删除了一行,则不确定是否会触发在其他行上的AFTER触发器。因此,如果使用BEFORE,则尽量不要对改行数据进行删除或更改。
此外,在INSERT操作中使用BEFORE操作时,如果表中没有显示的ID栏,则不会更改NEW.rowid的值。当然,通常情况下,此时的NEW.rowid值通常情况下也不重要。事实上,如果定义了非空的ID值,而在插入数据前并不知道这个值时,使用BEFORE INSERT的触发器其实挺方便有效的。
例如,每次插入数据时,设置NEW.ID为max(ID)+1,即可以避免缺少非空值的缺乏而报警,又能避免ID值重复。
通过在CREATE TRIGGER语句中指定INSTEAD OF,可以在视图以及普通表上创建触发器。 如果在视图上定义了一个或多个ON INSERT,ON DELETE或ON UPDATE触发器,那么分别在视图上执行INSERT,DELETE或UPDATE语句就不会出错。 而是在视图上执行INSERT,DELETE或UPDATE会引发关联的触发器。 视图基础的实际表不会被修改(可能由触发程序明确修改除外)。
如果使用“ UPDATE OF column-name”语法,则仅当column-name(指定的列)出现在UPDATE语句的SET子句中某个术语的左侧时,触发器才会触发。
有意思的是,由于历史上的疏忽,“ UPDATE OF”子句中命名的列实际上不必存在于要更新的表中, 无法识别的列名将被自动忽略。当然如果之后你在表中增加了该名称的列,则触发器又会自动生效。
目前,SQLite仅支持FOR EACH ROW触发器,不支持FOR EACH STATEMENT触发器。 因此,显式指定FOR EACH ROW是可选的。 FOR EACH ROW表示可以对引起触发器触发的语句插入,更新或删除的每个数据库行执行触发器中指定的SQL语句(取决于WHEN子句)。
WHEN子句和触发操作都可以使用“ NEW.column-name”和“ OLD.column-name”形式的引用来访问要插入,删除或更新的行的元素,其中column-name是 与触发器关联的表中的列。 OLD(表示原数据)和NEW(表示新数据)引用只能在与其相关的事件的触发器中使用,如下所示:
- insert时,只有NEW
- delete时,只有OLD
- 而UPDATA时,既有NEW,也有OLD
最后,让我们来看几个例子:
例子1.假设客户记录存储在“customers”表中,而订单记录存储在“orders”表中,则以下UPDATE触发器可确保在客户更改其地址时重定向所有关联的订单:
CREATE TRIGGER update_customer_address UPDATE OF address ON customers BEGIN UPDATE orders SET address = new.address WHERE customer_name = old.name; END;
当创建此触发器后,如果执行下面的语句:
UPDATE customers SET address = '1 Main St.' WHERE name = 'Jack Jones';
则自动导致下面的操作:
UPDATE orders SET address = '1 Main St.' WHERE customer_name = 'Jack Jones';
例子2,使用INSTEAD OF的触发器。假定我们使用下面的语句建立了表、视图和触发器:
CREATE TABLE customer( cust_id INTEGER PRIMARY KEY, cust_name TEXT, cust_addr TEXT ); CREATE VIEW customer_address AS SELECT cust_id, cust_addr FROM customer; CREATE TRIGGER cust_addr_chng INSTEAD OF UPDATE OF cust_addr ON customer_address BEGIN UPDATE customer SET cust_addr=NEW.cust_addr WHERE cust_id=NEW.cust_id; END;
则下面的语句:
UPDATE customer_address SET cust_addr=$new_address WHERE cust_id=$cust_id;
导致为customer.cust_id等于$ cust_id参数的特定客户条目更新customer.cust_addr字段。
最后说一句,删除触发器的语法是:
drop trigger tablename