1. 语法
创建触发器语句
隐藏
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
删除语句
显示
WITH
RECURSIVE
common-table-expression
,
DELETE
FROM
qualified-table-name
returning-clause
expr
WHERE
通用表表达式
显示
table-name
(
column-name
)
AS
NOT
MATERIALIZED
(
select-stmt
)
,
限定表名
显示
schema-name
.
table-name
AS
alias
INDEXED
BY
index-name
NOT
INDEXED
返回子句
显示
RETURNING
expr
AS
column-alias
*
,
表达式
显示
literal-value
bind-parameter
schema-name
.
table-name
.
column-name
unary-operator
expr
expr
binary-operator
expr
function-name
(
function-arguments
)
filter-clause
over-clause
(
expr
)
,
CAST
(
expr
AS
type-name
)
expr
COLLATE
collation-name
expr
NOT
LIKE
GLOB
REGEXP
MATCH
expr
expr
ESCAPE
expr
expr
ISNULL
NOTNULL
NOT
NULL
expr
IS
NOT
DISTINCT
FROM
expr
expr
NOT
BETWEEN
expr
AND
expr
expr
NOT
IN
(
select-stmt
)
expr
,
schema-name
.
table-function
(
expr
)
table-name
,
NOT
EXISTS
(
select-stmt
)
CASE
expr
WHEN
expr
THEN
expr
ELSE
expr
END
raise-function
过滤子句
显示
函数参数
显示
DISTINCT
expr
,
*
ORDER
BY
ordering-term
,
排序项
显示
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
字面量值
显示
CURRENT_TIMESTAMP
numeric-literal
string-literal
blob-literal
NULL
TRUE
FALSE
CURRENT_TIME
CURRENT_DATE
OVER 子句
显示
OVER
window-name
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
窗口规范
显示
GROUPS
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
RANGE
ROWS
UNBOUNDED
PRECEDING
expr
PRECEDING
CURRENT
ROW
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
EXCLUDE
CURRENT
ROW
EXCLUDE
GROUP
EXCLUDE
TIES
EXCLUDE
NO
OTHERS
排序项
显示
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
引发函数
显示
RAISE
(
ROLLBACK
,
error-message
)
IGNORE
ABORT
FAIL
类型名称
显示
name
(
signed-number
,
signed-number
)
(
signed-number
)
带符号数字
显示
插入语句
显示
WITH
RECURSIVE
common-table-expression
,
REPLACE
INSERT
OR
ROLLBACK
INTO
ABORT
FAIL
IGNORE
REPLACE
schema-name
.
table-name
AS
alias
(
column-name
)
,
VALUES
(
expr
)
,
,
upsert-clause
select-stmt
upsert-clause
DEFAULT
VALUES
returning-clause
通用表表达式
显示
table-name
(
column-name
)
AS
NOT
MATERIALIZED
(
select-stmt
)
,
返回子句
显示
RETURNING
expr
AS
column-alias
*
,
UPSERT 子句
显示
ON
CONFLICT
(
indexed-column
)
WHERE
expr
DO
,
conflict target
UPDATE
SET
column-name-list
=
expr
WHERE
expr
NOTHING
,
column-name
列名列表
显示
索引列
显示
column-name
COLLATE
collation-name
DESC
expr
ASC
选择语句
显示
WITH
RECURSIVE
common-table-expression
,
SELECT
DISTINCT
result-column
,
ALL
FROM
table-or-subquery
join-clause
,
WHERE
expr
GROUP
BY
expr
HAVING
expr
,
WINDOW
window-name
AS
window-defn
,
VALUES
(
expr
)
,
,
compound-operator
select-core
ORDER
BY
LIMIT
expr
ordering-term
,
OFFSET
expr
,
expr
通用表表达式
显示
table-name
(
column-name
)
AS
NOT
MATERIALIZED
(
select-stmt
)
,
复合运算符
显示
UNION
UNION
INTERSECT
EXCEPT
ALL
连接子句
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
连接约束
显示
USING
(
column-name
)
,
ON
expr
连接运算符
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
排序项
显示
expr
COLLATE
collation-name
DESC
ASC
NULLS
FIRST
NULLS
LAST
结果列
显示
expr
AS
column-alias
*
table-name
.
*
表或子查询
显示
schema-name
.
table-name
AS
table-alias
INDEXED
BY
index-name
NOT
INDEXED
table-function-name
(
expr
)
,
AS
table-alias
(
select-stmt
)
(
table-or-subquery
)
,
join-clause
窗口定义
显示
(
base-window-name
PARTITION
BY
expr
,
ORDER
BY
ordering-term
,
frame-spec
)
窗口规范
显示
GROUPS
BETWEEN
UNBOUNDED
PRECEDING
AND
UNBOUNDED
FOLLOWING
RANGE
ROWS
UNBOUNDED
PRECEDING
expr
PRECEDING
CURRENT
ROW
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
expr
PRECEDING
CURRENT
ROW
expr
FOLLOWING
EXCLUDE
CURRENT
ROW
EXCLUDE
GROUP
EXCLUDE
TIES
EXCLUDE
NO
OTHERS
更新语句
显示
WITH
RECURSIVE
common-table-expression
,
UPDATE
OR
ROLLBACK
qualified-table-name
OR
REPLACE
OR
IGNORE
OR
FAIL
OR
ABORT
SET
column-name-list
=
expr
column-name
,
FROM
table-or-subquery
,
join-clause
WHERE
expr
returning-clause
列名列表
显示
通用表表达式
显示
table-name
(
column-name
)
AS
NOT
MATERIALIZED
(
select-stmt
)
,
连接子句
显示
table-or-subquery
join-operator
table-or-subquery
join-constraint
连接约束
显示
USING
(
column-name
)
,
ON
expr
连接运算符
显示
NATURAL
LEFT
OUTER
JOIN
,
RIGHT
FULL
INNER
CROSS
限定表名
显示
schema-name
.
table-name
AS
alias
INDEXED
BY
index-name
NOT
INDEXED
返回子句
显示
RETURNING
expr
AS
column-alias
*
,
表或子查询
显示
schema-name
.
table-name
AS
table-alias
INDEXED
BY
index-name
NOT
INDEXED
table-function-name
(
expr
)
,
AS
table-alias
(
select-stmt
)
(
table-or-subquery
)
,
join-clause
2. 描述
CREATE TRIGGER 语句用于向数据库模式添加触发器。触发器是在发生指定数据库事件时自动执行的数据库操作。
每个触发器必须指定它将针对以下操作之一触发:DELETE 、INSERT 、UPDATE 。对于每个被删除、插入或更新的行,触发器都会触发一次。如果使用了“UPDATE OF column-name ”语法,则只有当 column-name 出现在 UPDATE 语句的 SET 子句中某个项的左侧时,触发器才会触发。
由于历史上的疏忽,在“UPDATE OF”子句中命名的列实际上不必存在于要更新的表中。无法识别的列名会被静默忽略。如果 SQLite 在“UPDATE OF”子句中的任何名称不是表中的列时,使 CREATE TRIGGER 语句失败,会更有帮助。但是,由于这个问题是在 SQLite 广泛部署多年后才发现的,因此我们一直抵制修复该问题,以免破坏旧版应用程序。
目前,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 引用有效
UPDATE
NEW 和 OLD 引用有效
DELETE
OLD 引用有效
如果提供了 WHEN 子句,则只有在 WHEN 子句为真时才会执行指定的 SQL 语句。如果没有提供 WHEN 子句,则每次触发器触发时都会执行 SQL 语句。
BEFORE 或 AFTER 关键字决定相对于关联行的插入、修改或删除何时执行触发器操作。当不存在这两个关键字时,BEFORE 为默认值。
可以在触发器主体内的 UPDATE 或 INSERT 操作的一部分中指定 ON CONFLICT 子句。但是,如果在导致触发器触发的语句的一部分中指定了 ON CONFLICT 子句,则使用外部语句的冲突处理策略。
当与其关联的表(table-name 表)被 删除 时,触发器会自动 删除 。但是,如果触发器操作引用其他表,则如果这些其他表被 删除 或 修改 ,触发器不会被删除或修改。
使用 DROP TRIGGER 语句删除触发器。
2.1. 触发器内 UPDATE、DELETE 和 INSERT 语句的语法限制
触发器内的 UPDATE 、DELETE 和 INSERT 语句不支持 UPDATE 、DELETE 和 INSERT 语句的完整语法。适用以下限制
3. INSTEAD OF 触发器
BEFORE 和 AFTER 触发器仅适用于普通表。INSTEAD OF 触发器仅适用于视图。
如果视图上存在 INSTEAD OF INSERT 触发器,则可以对该视图执行 INSERT 语句。不会发生实际的插入。而是运行触发器中包含的语句。INSTEAD OF DELETE 和 INSTEAD OF UPDATE 触发器对视图上的 DELETE 和 UPDATE 语句的工作方式相同。
请注意,sqlite3_changes() 和 sqlite3_total_changes() 接口不会计算 INSTEAD OF 触发器的触发次数,但 count_changes pragma 会计算 INSTEAD OF 触发器的触发次数。
4. 一些触发器示例
假设客户记录存储在“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';
有关 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 字段。请注意,分配给视图的值如何在触发器主体内的特殊“NEW”表中作为字段提供。
5. 使用 BEFORE 触发器的注意事项
如果 BEFORE UPDATE 或 BEFORE DELETE 触发器修改或删除了要更新或删除的行,则后续更新或删除操作的结果未定义。此外,如果 BEFORE 触发器修改或删除了行,则这些行上本来应该运行的 AFTER 触发器是否会实际运行是未定义的。
在 BEFORE INSERT 触发器中,如果未将 rowid 显式设置为整数,则 NEW.rowid 的值未定义。
由于上述行为,鼓励程序员优先使用 AFTER 触发器而不是 BEFORE 触发器。
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 触发器。此类触发器仅在定义触发器的应用程序对目标表进行更改时触发。修改数据库的其他应用程序将无法看到 TEMP 触发器,因此无法运行该触发器。
在非 TEMP 表上定义 TEMP 触发器时,务必指定保存非 TEMP 表的数据库。例如,在以下语句中,务必使用“main.tab1”而不是“tab1”
CREATE TEMP TRIGGER ex1 AFTER INSERT ON main. tab1 BEGIN ...
如果未在目标表上指定模式名称,则每当发生任何模式更改时,TEMP 触发器可能会重新附加到另一个数据库中具有相同名称的表。这可能会导致问题。
此页面上次修改于 2024-08-03 15:33:40 UTC