创建触发器

创建触发器的语法格式如下图:

 

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

 

 

 

 

    

 

 

 

posted @ 2020-06-30 18:55  Luo大哥  阅读(804)  评论(0编辑  收藏  举报