Small. Fast. Reliable.
Choose any three.
创建触发器

1.语法

create-trigger-stmt:

CREATE TEMP TEMPORARY TRIGGER IF NOT EXISTS schema-name . trigger-name BEFORE AFTER INSTEAD OF DELETE INSERT UPDATE OF column-name , ON table-name FOR EACH ROW WHEN expr BEGIN update-stmt ; END insert-stmt delete-stmt select-stmt

delete-stmt:

expr:

insert-stmt:

select-stmt:

update-stmt:

2.说明

CREATE TRIGGER语句用于将触发器添加到数据库模式。触发器是在发生指定的数据库事件时自动执行的数据库操作。

每个触发器必须指定将针对以下操作之一触发:DELETEINSERTUPDATE。触发器针对删除,插入或更新的每一行触发一次。如果使用“ UPDATE OF column-name ”语法,则仅当column-name出现在UPDATE语句的SET子句中某个术语的左侧时,触发器才会触发 。

由于历史上的疏忽,“ UPDATE OF”子句中命名的列实际上不必存在于要更新的​​表中。无法识别的列名将被静默忽略。如果“ UPDATE OF”子句中的任何名称都不是表中的列,如果SQLite使CREATE TRIGGER语句失败,则将更有用。但是,由于此问题是在SQLite广泛部署多年后才发现的,因此我们担心会破坏旧版应用程序而拒绝解决该问题。

目前,SQLite仅支持FOR EACH ROW触发器,不支持FOR EACH STATEMENT触发器。因此,显式指定FOR EACH ROW是可选的。FOR EACH ROW表示可以对引起触发器触发的语句插入,更新或删除的每个数据库行执行触发器中指定的SQL语句(取决于WHEN子句)。

无论是当被插入子句和触发器操作可以访问该行的元素,删除或使用的形式“NEW。的引用更新列名”和“OLD。列名”,其中 列名是一个的名称与触发器关联的表中的列。OLD和NEW引用只能在与其相关的事件的触发器中使用,如下所示:

新引用有效
更新 NEW和OLD参考有效
删除 OLD参考有效

如果提供了WHEN子句,则仅在WHEN子句为true时才执行指定的SQL语句。如果未提供WHEN子句,则每次触发触发器时都将执行SQL语句。

BEFORE或AFTER关键字确定何时相对于关联行的插入,修改或删除执行触发动作。当两个关键字都不存在时,BEFORE是默认设置。

可以将ON CONFLICT子句指定为 触发器主体内的UPDATEINSERT操作的一部分。但是,如果将ON CONFLICT子句指定为导致触发器触发的语句的一部分,则将使用外部语句的冲突处理策略。

触发器自动下降 时,他们正在与(相关联的表表名表) 下降。但是,如果触发动作引用其他表,触发器不会删除或修改,如果这些其他表丢弃修改

使用DROP TRIGGER语句删除触发器

2.1。触发器内的UPDATE,DELETE和INSERT语句的语法限制

触发器内的UPDATEDELETEINSERT语句不支持UPDATEDELETEINSERT语句的完整语法。适用以下限制:

3. INSTEAD OF触发器

通过在CREATE TRIGGER语句中指定INSTEAD OF,可以在视图以及普通表上创建触发器。如果在视图上定义了一个或多个ON INSERT,ON DELETE或ON UPDATE触发器,那么分别在视图上执行INSERT,DELETE或UPDATE语句就不会出错。相反,在视图上执行INSERT,DELETE或UPDATE会引发关联的触发器。视图基础的实际表不会被修改(可能由触发程序明确修改除外)。

请注意,sqlite3_changes()sqlite3_total_changes()接口不计入INSTEAD OF触发器触发,但 count_changes编译指示确实计入INSTEAD OF触发器触发。

4.一些示例触发器

假设客户记录存储在“客户”表中,而订单记录存储在“订单”表中,则以下UPDATE触发器可确保在客户更改其地址时重定向所有关联的订单:

创建触发器update_customer_address客户的地址更新 
  开始
    UPDATE订单SET地址= new.address WHERE customer_name = old.name;
  结尾;

安装此触发器后,执行以下语句:

更新客户SET地址='1 Main St.' WHERE name ='Jack Jones';

使以下内容自动执行:

UPDATE命令SET地址='1 Main St.' WHERE customer_name ='杰克·琼斯';

有关INSTEAD OF触发器的示例,请考虑以下架构:

创建表客户(
  cust_id INTEGER主键,
  cust_name TEXT,
  cust_addr文字
);
创建视图customer_address AS
   从客户中选择cust_id,cust_addr;
创建触发器cust_addr_chng
对customer_address的cusd_addr进行更新
开始
  更新客户SET cust_addr = NEW.cust_addr
   在哪里cust_id = NEW.cust_id;
结尾;

使用上面的模式,以下形式的语句:

更新customer_address SET cust_addr = $ new_address,其中cust_id = $ cust_id;

导致为customer.cust_id等于$ cust_id参数的特定客户条目更新customer.cust_addr字段。请注意,如何在触发器主体内的特殊“ NEW”表中将分配给视图的值用作字段。

5.使用前触发器的注意事项

如果BEFORE UPDATE或BEFORE DELETE触发器修改或删除了将要更新或删除的行,则后续更新或删除操作的结果是不确定的。此外,如果BEFORE触发器修改或删除了一行,则不确定是否会运行在这些行上的AFTER触发器。

在未将行ID显式设置为整数的BEFORE INSERT触发器中,未定义NEW.rowid的值。

由于上述行为,鼓励程序员比AFTER触发器更喜欢AFTER触发器。

6. RAISE()函数

特殊的SQL函数RAISE()可以在触发器程序中使用,语法如下

提升功能:

RAISE ( ROLLBACK , error-message ) IGNORE ABORT FAIL

在触发程序执行期间调用RAISE(ROLLBACK,...),RAISE(ABORT,...)或RAISE(FAIL,...)之一时,将执行指定的ON CONFLICT处理,并且当前查询终止。SQLITE_CONSTRAINT的错误代码将与指定的错误消息一起返回给应用程序。

调用RAISE(IGNORE)时,将放弃当前触发程序的其余部分,导致触发程序执行的语句以及将要执行的所有后续触发程序。没有数据库更改会回滚。如果导致触发程序执行的语句本身是触发程序的一部分,则该触发程序将在下一步开始时恢复执行。

7.非TEMP表上的TEMP触发器

触发器通常与CREATE TRIGGER语句中以“ ON”关键字命名的表存在于同一数据库中。除此之外,可以在另一个数据库的表上创建TEMP TRIGGER。仅当定义触发器的应用程序对目标表进行更改时,才会触发此类触发器。其他修改数据库的应用程序将无法看到TEMP触发器,因此无法运行该触发器。

在非TEMP表上定义TEMP触发器时,重要的是指定保存非TEMP表的数据库。例如,在下面的语句中,重要的是说“ main.tab1”而不是仅仅“ tab1”:

电源上插入后创建温度触发ex1 tab1开始...

如果未在目标表上指定架构名称,则可能在任何架构更改发生时将TEMP触发器重新附加到另一个数据库中具有相同名称的表。