SQLite学习:触发器、视图、索引和子查询


1. 前言 & 环境启动

在上一篇《SQLite语法学习:HAVING、DISTINCT、JOIN、UNION子句》 中,讲解了 SQLite的HAVING、DISTINCT、JOIN、UNION子句语法,在本篇博客中,将继续讲解 SQLite 触发器、视图、索引和子查询的基本语法。

同学们将学习到:

  • SQLite 触发器语法
  • SQLite 视图语法
  • SQLite 索引语法
  • SQLite 子查询语法

请同学们参考《SQLite3快速入门:SQLite 是什么?如何用好 TA?》 ,完成 SQLite 的环境启动,具体命令如下。

cd 你的 SQLite 目录
sqlite3
.open test.db

启动成功后,如下图所示。

在这里插入图片描述
请同学初始化本次博客中需要用到的数据,命令如下。

CREATE TABLE student(
   code CHAR(100)  PRIMARY KEY,
   name CHAR(100),
   age INT(100),
   mobile CHAR(100),
   honor TEXT
);
INSERT INTO student VALUES ('002', '李四', 18,'17800000002','期中进步生');
INSERT INTO student VALUES ('003', '王五', 19,'17800000003','蓝桥杯省级三等奖');
INSERT INTO student VALUES ('004', '赵六', 20,'17800000004','程序设计竞赛一等奖');
INSERT INTO student VALUES ('005', '郑七', 19,'17800000005','蓝桥杯省级一等奖');
INSERT INTO student VALUES ('006', '皱八', 21,'17800000006','数学竞赛二等奖');
INSERT INTO student VALUES ('007', '龚九', 19,'17800000007','蓝桥杯省级二等奖');
INSERT INTO student VALUES ('008', '桑十', 22,'17800000008','蓝桥杯省级三等奖');
INSERT INTO student VALUES ('009', '武十一', 18,'17800000009','数学建模竞赛三等奖');
INSERT INTO student VALUES ('010', '揣十二', 17,'17800000010','蓝桥杯省级二等奖');
INSERT INTO student VALUES ('011', '周十三', 23,'17800000011','蓝桥杯省级参与奖');
INSERT INTO student VALUES ('012', '钟十四', 27,'17800000012','蓝桥杯省级一等奖');
INSERT INTO student VALUES ('013', '孟十五', 30,'17800000013','蓝桥杯省级参与奖');
INSERT INTO student VALUES ('014', '梁十六', 15,'17800000014','蓝桥杯省级三等奖');
CREATE TABLE achievement(
   id INTEGER PRIMARY KEY AUTOINCREMENT ,
   code CHAR(100),
   examination CHAR(100),
   grade DOUBLE,
   date CHAR(100)
);
INSERT INTO achievement VALUES (1, '001', '高等数学A', 91.5,'2023-01-28');
INSERT INTO achievement VALUES (2, '002', '高等数学A', 88.0,'2023-01-28');
INSERT INTO achievement VALUES (3, '003', '高等数学A', 70,'2023-01-28');
INSERT INTO achievement VALUES (4, '004', '高等数学A', 55.5,'2023-01-28');
INSERT INTO achievement VALUES (5, '001', 'C语言程序设计', 71.5,'2023-01-28');
INSERT INTO achievement VALUES (6, '002', 'C语言程序设计', 51.5,'2023-01-28');
INSERT INTO achievement VALUES (7, '003', 'C语言程序设计', 91.5,'2023-01-28');
INSERT INTO achievement VALUES (8, '004', 'C语言程序设计', 81.5,'2023-01-28');
CREATE TABLE log(
   id INTEGER PRIMARY KEY AUTOINCREMENT,
   mobile CHAR(100),
   time CHAR(100)
);

上面的命令创建了学生表,拥有学号( c o d e code code)、姓名( n a m e name name)、年龄( a g e age age)、手机号( m o b i l e mobile mobile)、荣誉( h o n o r honor honor)这五个字段,并初始化了 14 14 14 条数据。

创建了学生成绩表,拥有成绩 ID( i d id id)、学号( c o d e code code)、考试名称( e x a m i n a t i o n examination examination)、成绩( g r a d e grade grade)、录入日期( d a t e date date)这五个字段,并初始化了 8 8 8 条数据。

另外也创建了日志表,拥有日志 ID( i d id id)、手机号( d a t a data data)、记录时间( t i m e time time)这三个字段。

初始化结果如下图所示。

在这里插入图片描述


2 触发器

SQLite 的触发器是数据库的回调函数,它会在指定的数据库事件发生时自动执行/调用。

简单来说,触发器就是 sqlite 数据的监听事件,当被触发后可以做一定事情。

触发器的基本语法如下所示。

CREATE TRIGGER 触发器名称 [BEFORE|AFTER] 事件类型
ON 表名
BEGIN
 -- 执行的事件
END;

同学们需要注意以下几点:

  • 触发器只能在 DELETE、INSERT 或 UPDATE 时被触发,或在一个或多个指定表的列发生更新时触发。
  • SQLite 只支持 FOR EACH ROW 触发器,不支持 FOR EACH STATEMENT 触发器。
  • WHEN 子句和触发器动作可能访问使用表单 NEW.column-name 和 OLD.column-name 的引用插入、删除或更新的行元素,其中 column-name 是从与触发器关联的表的列的名称。
  • 如果提供 WHEN 子句,则只针对 WHEN 子句为真的指定行执行 SQL 语句;如果没有提供 WHEN 子句,则针对所有行执行 SQL 语句。
  • 事件类型就是 BEFORE 或 AFTER,判断是在插入、修改或删除之前或者之后执行触发器。
  • 当触发器相关联的数据表被删除时,系统会自动删除触发器。
  • 要修改的表必须存在于同一数据库中,作为触发器被附加的表或视图,且必须只使用 tablename,而不是 database.tablename。
  • 一个特殊的 SQL 函数 RAISE() 可用于触发器程序内抛出异常。

例题1:在新增学生的数据时,需要自动将输入手机号存储在日志表,则需要定义以下触发器。

CREATE TRIGGER mobile_log AFTER INSERT 
ON student 
BEGIN 
   INSERT INTO log(mobile, time) VALUES (new.mobile, datetime('now'));
END;

在这里插入图片描述

请注意:命令需要逐行执行,不能一次全部复制执行!

触发器创建完成后,首先查询一次日志表,命令如下。

SELECT * FROM log;

在这里插入图片描述

查询发现没有数据,接着新增一位学生,请同学们执行以下插入命令。

INSERT INTO student VALUES ('001', '张三', 17,'17800000001','市三好学生');

此时再次查询日志表的数据,命令如下。

SELECT * FROM log;

在这里插入图片描述

发现日志数据已生成,如下图所示,说明触发器已成功执行。


3 视图

在实战开发中,数据库的设计往往追求 高内聚低耦合,尽可能追求高等级的范式。

但在产品应用时,客户往往需要更直观的表示,如学生姓名、手机号、宿舍房号、班主任姓名等数据放在一张表中展示。

但在数据库中,会设立学生表、宿舍分配表、班级档案表等多张数据表。

为了解决此类问题,sqlite 提供了视图,用于生成各类报表,接下来对视图进行讲解。

  • 视图是通过相关的名称存储在数据库中的一个 SQLite 语句。

  • 视图是一个以预定义的 SQLite 查询形式存在的表的组合。

  • 视图可以包含一个表的所有行或从一个或多个表选定行。

  • 视图可以从一个或多个表创建,这取决于要创建视图的 SQLite 查询。

  • 视图是一种虚表,没有物理存储空间。

3.1 创建视图

SQLite 视图可以从一个单一的表、多个表或其他视图创建,基本语法如下。

CREATE [TEMP | TEMPORARY] VIEW 视图名称 AS
SELECT 视图列1, 视图列2.....
FROM 表名
WHERE [条件];

比如需要对高于 60 60 60 分的学生数据进行分析,包括学号、姓名、考试名称和成绩,创建一个数据展示视图,命令如下。

CREATE VIEW my_view AS
SELECT s.code, s.name, a.examination,a.grade
FROM student s,achievement a
WHERE s.code = a.code and a.grade >= 60;

在这里插入图片描述

提示:请逐行复制执行命令。

3.2 查询视图

视图也是一张虚拟的表,同学们可以使用 SELECT 子句完成对视图的查询,命令如下。

SELECT * FROM my_view;

查询结果如下图所示。

在这里插入图片描述

3.3 删除视图

视图是一张临时的虚拟表,在视图使用完成后,同学们应及时的删除视图,避免资源的浪费。

删除视图的基本语法如下。

DROP VIEW 视图名;

比如要删除创建的 my_view 视图,命令如下。

DROP VIEW my_view;

执行后,视图将被删除。

在这里插入图片描述


4 索引

索引是一种特殊的查找表,数据库搜索引擎用来加快数据检索。

简单地说,索引是一个指向表中数据的指针。

一个数据库中的索引与一本书后边的索引是非常相似的。

索引有助于加快 SELECT 查询和 WHERE 子句,但它会减慢使用 UPDATE 和 INSERT 语句时的数据输入,在实战开发中应根据情况使用。

索引可以创建或删除,且不会对现有数据产生影响。

sqlite 中,索引可以分为以下 4 4 4 种:

  • 单列索引:是一个只基于表的一个列上创建的索引。
  • 唯一索引:不允许任何重复的值插入到表中,性能较高,保证了数据的完整性。
  • 组合索引:是基于一个表的两个或多个列上创建的索引。
  • 隐式索引:数据库服务器自动创建的索引,如主键、外键、唯一键等。

4.1 创建索引

创建单列索引的基本语法如下。

CREATE INDEX 索引名
ON 表名 (索引列名);

创建唯一索引的基本语法如下。

CREATE UNIQUE INDEX 索引名
ON 表名 (索引列名);

创建组合索引的基本语法如下。

CREATE INDEX 索引名
ON 表名 (索引列名1, 索引列名2, ..., 索引列名N);

索引列名尽量为经常使用 WHERE 子句条件筛选的列,否则在性能上会得不偿失。

例题2:在学生表中,需要经常查询学生的手机号,则对学生表的 m o b i l e mobile mobile(手机号)字段添加单列索引,命令如下。

CREATE INDEX student_mobile_index
ON student (mobile);

提示:请逐行复制执行。

4.2 查询索引

索引创建完成后,可以用下面的命令,根据数据表来查询关联的索引。

.indices 数据表名

比如要查询学生表( s t u d e n t student student)上的所有索引,命令如下。

.indices student

查询结果如下图所示。

在这里插入图片描述

其中 sqlite_autoindex_student_1 是创建表时创建的隐式索引

同学们也可以查询所有数据表的索引列表,命令如下。

SELECT * FROM sqlite_master WHERE type = 'index';

在这里插入图片描述

4.3 Indexed By 子句

Indexed By 子句是对索引功能的应用,基本语法如下。

SELECT|DELETE|UPDATE 列名1, 列名2...
INDEXED BY (索引列名)
表名
WHERE (条件);

例题3:需要查询学生表中,手机号以 6 6 6 结尾的学生数据,命令如下。

SELECT * FROM student INDEXED BY student_mobile_index WHERE mobile GLOB '*6';

在这里插入图片描述

4.4 删除索引

如果发现索引作用不大,则可以删除索引,删除索引的基本语法如下。

DROP INDEX 索引名;

比如删除之前创建的 student_mobile_index 索引,命令如下。

DROP INDEX student_mobile_index;

在这里插入图片描述

4.5 索引技巧

同学们在使用索引时,需要注意以下几点:

  • 索引不应该使用在较小的表上。
  • 索引不应该使用在有频繁的大批量的更新或插入操作的表上。
  • 索引不应该使用在含有大量的 NULL 值的列上。
  • 索引不应该使用在频繁操作的列上。

提示:索引的目的是提高数据库性能,但错误运用索引反而会导致性能低下。


5 子查询

子查询通常出现在 WHERE 子句中,用来实现较为复杂的条件查询

子查询可以与 SELECT、INSERT、UPDATE 、DELETE 语句和运算符一起使用。

子查询的基本语法如下。

SELECT 列名1, 列名2, ..., 列名N
FROM1, [2 ]
WHERE  条件列名 OPERATOR
      (SELECT 子列名1 [, 子列名2 ]
      FROM 子表1 [, 子表2 ]
      [WHERE])

例题4:需要查询有高等数学成绩的学生数据,查询的命令如下。

SELECT * FROM student WHERE code in (
   SELECT code FROM achievement WHERE examination GLOB '*高等数学*'
);

查询结果如下图所示。

在这里插入图片描述

提示:请同学们逐行复制执行。


6 总结

通过本次博客学习,同学们需要独立编写 sqlite 触发器、视图、索引和子查询的命令,理解索引的概念和应用场景。

在下一篇博客中,将讲解 SQLite 中 SQL 函数和日期存储问题。

猜你喜欢

转载自blog.csdn.net/qq_41464123/article/details/130463297
今日推荐