SQLite 觸發(fā)器(Trigger)是數(shù)據(jù)庫(kù)的回調(diào)函數(shù),它會(huì)在指定的數(shù)據(jù)庫(kù)事件發(fā)生時(shí)自動(dòng)執(zhí)行/調(diào)用础芍。
觸發(fā)條件
SQLite 的觸發(fā)器(Trigger)可以指定在特定的數(shù)據(jù)庫(kù)表發(fā)生 DELETE灸叼、INSERT 或 UPDATE 時(shí)觸發(fā)神汹,或在一個(gè)或多個(gè)指定表的列發(fā)生更新時(shí)觸發(fā)。
特性
SQLite 只支持 FOR EACH ROW 觸發(fā)器(Trigger)古今,沒(méi)有 FOR EACH STATEMENT 觸發(fā)器(Trigger)屁魏。
>for each row 是操作語(yǔ)句每影響到一行的時(shí)候就觸發(fā)一次,也就是刪了 10 行就觸發(fā) 10 次捉腥,
而for each statement一條操作語(yǔ)句就觸發(fā)一次氓拼,有時(shí)沒(méi)有被影響的行也執(zhí)行。
sqlite 只實(shí)現(xiàn)了 for each row 的觸發(fā)但狭。for each row 用法是這樣的(when 后接條件):
另外披诗,我們可以選擇在觸發(fā)前或觸發(fā)后做記錄。
使用觸發(fā)器
1立磁、新增數(shù)據(jù)時(shí)觸發(fā)
比如,我們對(duì)供應(yīng)商表中的數(shù)據(jù)進(jìn)行監(jiān)控剥槐,當(dāng)供應(yīng)商數(shù)據(jù)增加的時(shí)候記錄一下
- 創(chuàng)健變化數(shù)據(jù)的記錄表
CREATE TABLE "supplier_data_change" (
`id` INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
`info` TEXT,
`updateTime` TEXT NOT NULL )
- 創(chuàng)建觸發(fā)器
CREATE TRIGGER supplier_change_trigger
AFTER INSERT
ON supplier_new
BEGIN
insert into supplier_data_change (info,updateTime)
values (-- 記錄供應(yīng)商變化的時(shí)間和id
'新增供應(yīng)商ID='||(select max(id) from supplier_new),
datetime());
END;
- 插入一條供應(yīng)商信息
insert into supplier_new (supplier,supplierAddress,supplierTel,supplierEmail,supplierContact)
values ('杭州有機(jī)農(nóng)副產(chǎn)品經(jīng)銷(xiāo)','文二西路113號(hào)','15865432549','organicVegetable@126.com','周琪')
-
記錄表中的數(shù)據(jù)
2唱歧、修改數(shù)據(jù)時(shí)觸發(fā)
上面是供應(yīng)商數(shù)據(jù)增加時(shí)才記錄,我們可以再加一個(gè)當(dāng)供應(yīng)商數(shù)據(jù)變化的時(shí)候也記錄粒竖,我們?cè)诠?yīng)商表中增加一個(gè)信息更新時(shí)間的字段(updateTime)颅崩,記錄插入或更新信息的時(shí)間
(如果沒(méi)有時(shí)間做篩選的,我們只能記錄對(duì)應(yīng)的表在什么時(shí)間做過(guò)修改蕊苗,無(wú)法判斷是那條記錄被修改過(guò)沿后,所以為了演示我這里增加了一個(gè)updateTime的字段)
-
創(chuàng)建更新的觸發(fā)器
利用select id from supplier_new order by updateTime desc limit 1
來(lái)獲取最新修改的記錄
CREATE TRIGGER supplier_update_trigger
AFTER UPDATE
ON supplier_new
FOR EACH ROW
BEGIN
insert into supplier_data_change (info,updateTime)
values (-- 記錄供應(yīng)商變化的時(shí)間和id
'供應(yīng)商信息變更,ID='||(select id from supplier_new order by updateTime desc limit 1),
datetime());
END;
-
更新數(shù)據(jù) 不要忘記了更新
updateTime
值
update supplier_new
set supplierContact = supplierContact||'_'||id ,updateTime = datetime()
where id = 2
3朽砰、刪除數(shù)據(jù)時(shí)觸發(fā)
刪除數(shù)據(jù)的時(shí)候尖滚,我們記錄被刪除的供應(yīng)商名稱以及刪除的時(shí)間
- 創(chuàng)建觸發(fā)器
CREATE TRIGGER supplier_delete_before_trigger
BEFORE delete
on supplier_new
BEGIN
insert into supplier_data_change (info,updateTime)
values (-- 記錄供應(yīng)商變化
'供應(yīng)商刪除前,供應(yīng)商ID:'||(select group_concat(id) from supplier_new order by updateTime desc),
datetime());
END;
CREATE TRIGGER supplier_delete_trigger
AFTER delete
ON supplier_new
BEGIN
insert into supplier_data_change (info,updateTime)
values (-- 記錄供應(yīng)商變化
'供應(yīng)商刪除后,供應(yīng)商ID:'||(select group_concat(id) from supplier_new order by updateTime desc),
datetime());
END;
- 刪除數(shù)據(jù)
delete from supplier_new
where id = 3
- 刪除記錄成功
通過(guò)記錄信息我們可以看到id=3
的供應(yīng)商是在2018-10-25 12:32:57
被刪除的苗傅。
試一下將上面的 select id from supplier_new order by updateTime desc
進(jìn)行列轉(zhuǎn)行
獲取觸發(fā)器
- 獲取數(shù)據(jù)庫(kù)中的觸發(fā)器
SELECT name FROM sqlite_master
WHERE type = 'trigger';
- 獲取特定表中的觸發(fā)器使用 AND 子句連接表名
SELECT name FROM sqlite_master
WHERE type = 'trigger' and tbl_name = 表名;
實(shí)際使用
SELECT name FROM sqlite_master
WHERE type = 'trigger' and tbl_name = 'supplier_new';
刪除觸發(fā)器
DROP TRIGGER trigger_name;
實(shí)際使用
DROP TRIGGER supplier_change_trigger;
說(shuō)明
如果你創(chuàng)建觸發(fā)器的SQL寫(xiě)的不夠嚴(yán)謹(jǐn)薪铜,可能會(huì)操作你正常的插入/更新SQL無(wú)法執(zhí)行
例如,我創(chuàng)建觸發(fā)器的SQL為:
CREATE TRIGGER supplier_update_trigger
AFTER UPDATE
ON supplier_new
FOR EACH ROW
BEGIN
insert into supplier_data_change (info,updateTime)
values (-- 記錄供應(yīng)商變化的時(shí)間和id
'供應(yīng)商信息變更弄砍,ID='||id,
datetime());
END;
我在 supplier_data_change 的插入語(yǔ)句使用了id造锅,這樣寫(xiě)是錯(cuò)誤(我實(shí)際是想取變化的供應(yīng)商的id)撼唾。
這里的no such column: id
就是你在創(chuàng)建觸發(fā)器的時(shí)候使用的id
。
這個(gè)id正確的獲取方法是select max(id) from supplier_new