1.语法
create-trigger-stmt:
delete-stmt:
common-table-expression:
限定表名称:
返回条款:
expr:
过滤器子句:
文字值:
子句:
框架规格:
订购期限:
提升功能:
类型名称:
签名编号:
insert-stmt:
common-table-expression:
返回条款:
附加条款:
列名列表:
索引栏:
select-stmt:
common-table-expression:
复合运算符:
加盟条款:
连接约束:
加入运营商:
订购期限:
结果栏:
表或子查询:
update-stmt:
列名列表:
common-table-expression:
加盟条款:
连接约束:
加入运营商:
限定表名称:
返回条款:
表或子查询:
2.说明
CREATE TRIGGER语句用于将触发器添加到数据库模式。触发器是在发生指定的数据库事件时自动执行的数据库操作。
每个触发器必须指定将针对以下操作之一触发:DELETE,INSERT,UPDATE。触发器针对删除,插入或更新的每一行触发一次。如果使用“ 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子句指定为
触发器主体内的UPDATE或INSERT操作的一部分。但是,如果将ON CONFLICT子句指定为导致触发器触发的语句的一部分,则将使用外部语句的冲突处理策略。
触发器自动下降
时,他们正在与(相关联的表表名表)
下降。但是,如果触发动作引用其他表,触发器不会删除或修改,如果这些其他表丢弃或修改。
使用DROP TRIGGER语句删除触发器。
2.1。触发器内的UPDATE,DELETE和INSERT语句的语法限制
触发器内的UPDATE,DELETE和INSERT语句不支持UPDATE,DELETE和INSERT语句的完整语法。适用以下限制:
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,...),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触发器重新附加到另一个数据库中具有相同名称的表。