常常咱们会碰到这种需求:html
须要记录一下用户的浏览过哪些商品;或者搜索历史,每次搜索时须要更新搜索历史;...
一般这些需求咱们须要先建立一个相关历史的表his_table,在每次insert以前须要检索下这条数据是否已存在。
繁琐的点在于每次insert都须要query,才能够肯定接下来的inser or update操做。
甚至更复杂的业务,修改A表的后又须要修改B表的数据,这样的话就须要操做两个表,使咱们的代码更加臃肿。
而数据库触发器就能够解决这类问题,今天就来介绍一下SQLite3数据库触发器在Android的使用。
复制代码
Show your code!!!git
比方说咱们的数据建表语句是这样的github
CREATE TABLE db_list_table (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
item_id INTEGER NOT NULL,
date TimeStamp DEFAULT (datetime('now','localtime'))
);
复制代码
// 插入时间戳yyyy-MM-dd HH:mm:ss,更多请查看文章末尾SQLite时间函数
// 时间函数是基本能够知足常见的格式
date TimeStamp DEFAULT (datetime('now','localtime'))
复制代码
你觉得这样就结束了?(ಡωಡ)(ಡωಡ)sql
CREATE TRIGGER auto_remove BEFORE INSERT
ON db_list_table
BEGIN
DELETE FROM db_list_table WHERE NEW.user_id=user_id AND NEW.item_id=item_id;
END;
复制代码
这句SQL的意思就是建立了一个触发器,在每次插入数据以前删除和此次插入数据相同的旧数据。下面会分别解释各个字段什么意思。数据库
咱们能够拆解一下这条建立触发器SQLbash
CREATE TRIGGER // 建立触发器
auto_remove // 触发器名称,后期能够用来查询和移除触发器
BEFORE // 在事件以前触发,改成AFTER就是以后触发
INSERT // 在插入事件触发,还支持DELETE、UPDATE
ON db_list_table // 操做哪一个表
BEGIN // 触发语句开始
// 触发语句,删除db_list_table表中和当前插入数据的user_id、item_id相同的数据
DELETE FROM db_list_table WHERE user_id=NEW.user_id AND item_id=NEW.item_id;// 不要忘了分号
// 由于触发事件是INSERT,因此表单数据要用NEW.column-name引用;
// 可能比较绕,你品品,你细品,是否是颇有道理(ಡωಡ)
END; // 触发语句结束
复制代码
NEW 和OLD 关键字的英文文档函数
Both the WHEN clause and the trigger actions may access elements of the row being inserted, deleted or updated using references of the form "NEW.column-name" and "OLD.column-name",
where column-name is the name of a column from the table that the trigger is associated with.
OLD and NEW references may only be used in triggers on events for which they are relevant, as follows:
INSERT NEW references are valid // 插入时NEW有效
UPDATE NEW and OLD references are valid // 均有效
DELETE OLD references are valid // 删除时OLD有效
// 这里的INSERT,UPADATE,DELETE指的是触发动做类型,不是触发语句类型。就是BEFOR/AFTER后面的操做
复制代码
建立完这个触发器以后每次插入新数据前就会自动检索已存在的数据,存在的话就会删除,而后再插入。 这样的话咱们就不须要维候插入和更新的逻辑,所有交由触发器自动管理。ui
固然咱们也可使用触发器更新其余表的数据,好比这里作了一下数据库数据的备份,记录主表全部的插入记录。spa
// 建立备份表
CREATE TABLE db_list_backup_table (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id TEXT NOT NULL,
item_id INTEGER NOT NULL,
date TimeStamp NOT NULL
);
// 建立备份触发器
CREATE TRIGGER back_up AFTER INSERT
ON db_list_table
BEGIN
INSERT INTO db_list_backup_table (user_id,item_id,date) VALUES (NEW.user_id,NEW.item_id,NEW.date);
// 这里触发动做是INSERT,使用NEW关键字引用value
END;
复制代码
插入一些数据看一下备份效果 code
你们可能已经发现了,BEGIN 和END中间的触发语句就是一条SQL的删除语句,没错触发语句就是一条普通的删除语句,也能够插入一些默认值(好比更详细的时间戳),甚至使用更复杂的SQL来完成更高级的功能。可是它也有一些限制:
好比,产品经理又加了 一个插入数据时自动删除失效数据 的需求,不慌只须要修改一下触发器。不过触发器不支持修改,只能删除后新建
drop trigger trigger_name // 根据触发器名称删除
复制代码
CREATE TRIGGER auto_remove BEFORE INSERT
ON db_list_table
BEGIN
DELETE FROM db_list_table WHERE
strftime('%s','now') - strftime('%s',date) >= 30 // 30s之前的数据算失效
OR
(NEW.user_id=user_id AND NEW.item_id=item_id);
END;
复制代码
// 将当前时间转换为秒数
strftime('%s','now')
复制代码
// 经过sqlite_master 查询,不是查询咱们本身的代表
SELECT name FROM sqlite_master WHERE type = 'trigger';
复制代码
执行多条SQL时记得使用事务,保证语句的在预期内执行
db.beginTransaction()
try {
db.execSQL("sql a")
db.execSQL("sql b")
// 数据库事务成功
db.setTransactionSuccessful()
} catch (e: SQLException) {
e.printStackTrace()
// todo 异常处理
} finally {
db.endTransaction()
}
复制代码
若是有什么错误或者不足的地方,欢迎指正