SQLite 视图、索引和触发器示例

⚡ 智能摘要

SQLite 视图、索引和触发器是管理工具,使数据库更容易查询和维护:视图可以重用复杂的查询,索引可以加速搜索,触发器可以在数据更改时自动运行预定义的操作。

  • 👁️ 浏览次数: 视图是由 SELECT 语句构建的逻辑表,使您可以重用复杂的查询而无需重新编写它们。
  • 临时视图: 临时视图仅存在于当前连接中,连接关闭后会自动删除。
  • 指标: 索引的作用类似于书籍索引,它允许…… SQLite 快速查找匹配行,而不是扫描表格的每一行。
  • 🎯 索引类型: SQLite 支持表达式索引、部分索引和唯一索引,以便针对特定查询模式微调性能。
  • 🔔 触发器: 触发器会在对表执行 INSERT、UPDATE 或 DELETE 语句之前或之后自动运行预定义的操作。
  • 🤖 人工智能协助: AI文本转SQL工具和GitHub Copilot生成 SQLite 从纯英语提示中获​​取视图、索引和触发器。

SQLite 触发器、视图和索引

在日常使用中 SQLite,您将需要一些数据库管理工具。您还可以使用它们通过创建索引来提高数据库查询效率,或通过创建视图来提高数据库的可重用性。

SQLite 查看

视图与表非常相似。但视图是逻辑表;它们不像表那样物理存储。视图由 select 语句组成。

您可以为复杂的查询定义一个视图,并且可以通过直接调用视图来随时重用这些查询,而不必再次重写查询。

CREATE VIEW 语句

要在数据库上创建视图,您可以使用 CREATE VIEW 语句,后跟视图名称,然后在其后放置所需的查询。

计费示例: 在以下示例中,我们将在示例数据库“TutorialsSampleDB.db”中创建一个名为“AllStudentsView”的视图,如下所示:

步骤1) 打开“我的电脑”,导航到以下目录“C:\sqlite”,然后打开“sqlite3.exe”:

SQLite 查看

步骤2) 使用以下命令打开数据库“TutorialsSampleDB.db”:

SQLite 查看

步骤3) 以下是创建视图的 sqlite3 命令的基本语法

CREATE VIEW AllStudentsView
AS
  SELECT 
    s.StudentId,
    s.StudentName,
    s.DateOfBirth,
    d.DepartmentName
FROM Students AS s
INNER JOIN Departments AS d ON s.DepartmentId = d.DepartmentId;

该命令不应该有如下输出:

SQLite 查看

步骤4) 为了确保视图已创建,您可以通过运行以下命令来选择数据库中的视图列表:

SELECT name FROM sqlite_master WHERE type = 'view';

你应该会看到返回的视图是“AllStudentsView”:

SQLite 查看

步骤5) 现在我们的视图已创建,您可以将其用作普通表,如下所示:

SELECT * FROM AllStudentsView;

此命令将查询视图“AllStudents”并从中选择所有行,如下面的屏幕截图所示:

SQLite 查看

临时视图

临时视图对于用于创建它的当前数据库连接来说是临时的。然后,如果您关闭数据库连接,所有临时视图将被自动删除。使用以下命令之一创建临时视图:

  • 创建临时视图,或
  • 创建临时视图。

如果您想要暂时执行某些操作而不需要将其作为永久视图,则临时视图非常有用。因此,您只需创建一个临时视图,然后使用该视图进行处理。 Later 当你关闭与数据库的连接时,它将被自动删除。

计费示例:

在下面的例子中,我们将打开一个数据库连接,然后创建一个临时视图。

之后,我们将关闭该连接,并检查临时视图是否仍然存在。

步骤1) 如前所述,从“C:\sqlite”目录打开sqlite3.exe。

步骤2) 运行以下命令打开与数据库“TutorialsSampleDB.db”的连接:

.open TutorialsSampleDB.db

步骤3) 编写以下命令,创建临时视图“AllStudentsTempView”:

CREATE TEMP VIEW AllStudentsTempView
AS
  SELECT 
    s.StudentId,
    s.StudentName,
    s.DateOfBirth,
    d.DepartmentName
FROM Students AS s
INNER JOIN Departments AS d ON s.DepartmentId = d.DepartmentId;

SQLite 查看

步骤4) 请运行以下命令,确保创建临时视图“AllStudentsTempView”:

SELECT name FROM sqlite_temp_master WHERE type = 'view';

SQLite 查看

步骤5) 关闭sqlite3.exe并重新打开。

步骤6) 使用以下命令打开与数据库“TutorialsSampleDB.db”的连接:

.open TutorialsSampleDB.db

步骤7) 运行以下命令获取在数据库上创建的临时视图列表:

SELECT name FROM sqlite_temp_master WHERE type = 'view';

您不应该看到任何输出,因为我们在上一步关闭数据库连接时创建的临时视图已被删除。否则,只要您保持数据库打开的连接,您就可以看到包含数据的临时视图。

SQLite 查看

备注:

  • 您不能对视图使用语句 INSERT、DELETE 或 UPDATE,只能使用“从视图中选择”命令,如 CREATE View 示例中的步骤 5 所示。
  • 要删除视图,可以使用“DROP VIEW”语句:
DROP VIEW AllStudentsView;

为了确保删除视图,您可以运行以下命令,该命令会为您提供数据库中的视图列表:

SELECT name FROM sqlite_master WHERE type = 'view';

您将发现由于视图已被删除,因此没有返回任何视图,如下所示:

SQLite 查看

除了重用带有视图的复杂查询之外, SQLite 此外,通过索引还可以更快地检索匹配的行。

SQLite 索引

如果你有一本书,你想搜索这本书的关键词。你会在书的索引中搜索这个关键词。然后你将导航到该关键词的页码以阅读有关该关键词的更多信息。

但是,如果这本书没有索引,也没有页码,你就得从头到尾浏览整本书,直到找到你要搜索的关键词。这非常困难,尤其是当你有索引并且搜索关键词的过程非常缓慢的时候。

索引 SQLite (同样的概念也适用于其他 数据库管理系统 其工作方式与书后的索引相同。

当您搜索 SQLite 带有搜索条件的表格, SQLite 会搜索表的所有行,直到找到符合搜索条件的行。当表较大时,该过程会变得非常缓慢。

索引将加快数据搜索查询速度,并有助于从表中检索数据。索引是在表列上定义的。

使用索引提高性能:

索引可以提高在表中搜索数据的性能。在列上创建索引时, SQLite 将为该索引创建一个数据结构,其中每个字段值都有一个指向该值所属的整行的指针。

然后,如果您对索引中的列运行带有搜索条件的查询, SQLite 将首先在索引中查找值。 SQLite 不会扫描整个表格。然后它将读取表格行的值指向的位置。 SQLite 将定位该位置上的行并检索它。

但是,如果您要搜索的列不是索引的一部分, SQLite 将对列值进行扫描以查找所需的数据。如果没有索引,这个过程通常会比较慢。

想象一下,有一本书没有索引,而你需要搜索一个特定的单词。你会从第一页到最后一页扫描整本书来寻找那个单词。但是,如果这本书有索引,你会先在书上查找这个单词。获取它所在的页码,然后导航到它。这比从封面到封底扫描整本书要快得多。

SQLite 创建指数

要在列上创建索引,应使用命令 CREATE INDEX。并且应按如下方式定义它:

  • 您必须在 CREATE INDEX 命令后指定索引的名称。
  • 在索引名称后面,必须放置关键字“ON”,后跟将创建索引的表名。
  • 然后是用于索引的列名列表。
  • 您可以在任何列名后使用以下关键字“ASC”或“DESC”之一来指定用于对索引数据进行排序的排序顺序。

计费示例:

在以下示例中,我们将在“Students”数据库的 students 表上创建索引“StudentNameIndex”,如下所示:

步骤1) 如前所述,导航至“C:\sqlite”文件夹。

步骤2) 打开 sqlite3.exe。

步骤3) 使用以下命令打开数据库“TutorialsSampleDB.db”:

.open TutorialsSampleDB.db

步骤4) 使用以下命令创建新索引“StudentNameIndex”:

CREATE INDEX StudentNameIndex ON Students(StudentName);

您应该看不到任何输出:

SQLite 索引

步骤5) 为了确保索引已创建,您可以运行以下查询,该查询为您提供在表 Students 中创建的索引列表:

PRAGMA index_list(Students);

您应该看到我们刚刚创建的索引返回:

SQLite 索引

备注:

  • 索引不仅可以根据列创建,还可以基于表达式创建。如下所示:
CREATE INDEX OrderTotalIndex ON OrderItems(OrderId, Quantity*Price);

“OrderTotalIndex” 将基于 OrderId 列以及 Quantity 列值和 Price 列值的乘积。因此,任何针对“OrderId”和“Quantity*Price”的查询都将是高效的,因为查询将使用索引。

  • 如果您在 CREATE INDEX 语句中指定了 WHERE 子句,则索引将是部分索引。在这种情况下,索引中将只有符合 WHERE 子句中条件的行才会有条目。例如,在以下索引中:
    CREATE INDEX OrderTotalIndexForLargeQuantities ON OrderItems(OrderId, Quantity*Price)
    WHERE Quantity > 10000;

    (在上面的例子中,由于指定了 WHERE 子句,因此索引将是部分索引。在这种情况下,索引将仅适用于数量值大于 10000 的订单。请注意,此索引被称为部分索引是因为 WHERE 子句,而不是因为它上使用的表达式。但是,您可以将表达式与普通索引一起使用。)

  • 您可以使用 CREATE UNIQUE INDEX 语句而不是 CREATE INDEX 来防止列的重复条目,因此索引列的所有值都将是唯一的。
  • 要删除索引,请使用 DROP INDEX 命令,后跟要删除的索引名称。

索引可以加快读取速度,而触发器则允许 SQLite 数据发生变化时自动响应。

SQLite 触发端口

简介 SQLite 触发端口

触发器是数据库表上发生特定操作时自动执行的预定义操作。可以定义触发器,使其在表上发生以下操作之一时触发:

  • 插入到表中。
  • 从表中删除行。
  • 更新其中一个表列。

SQLite 支持FOR EACH ROW触发器,这样,触发器中预定义的操作将对表上发生的操作(无论是插入、删除还是更新)所涉及的所有行执行。

SQLite 创建触发器

要创建一个新的 TRIGGER,可以使用以下 CREATE TRIGGER 语句:

  • 在 CREATE TRIGGER 之后,您应该指定一个触发器名称。
  • 在触发器名称之后,您必须指定触发器名称的执行时间。您有三个选项:
    • BEFORE – 触发器将在指定的 INSERT、UPDATE 或 delete 语句之前执行。
    • After – 触发器将在指定的 INSERT、UPDATE 或 delete 语句之后执行。
    • INSTEAD OF – 它将用 TRIGGER 中指定的语句替换触发触发器的操作。INSTEAD OF 触发器不适用于表,仅适用于视图。
  • 然后,您必须指定操作的类型,触发器将在操作发生时触发。DELETE、INSERT 或 UPDATE。
  • 您可以选择一个可选的列名,这样除非操作发生在该列上,否则触发器就不会触发。
  • 然后您必须指定将创建触发器的表名。
  • 在触发器的主体内,您应该指定在触发触发器时应对每一行执行的语句。

触发器将仅根据创建触发器命令中指定的语句类型来激活(触发)。例如:

  • BEFORE INSERT 触发器将在任何插入语句之前被激活(触发)。
  • AFTER UPDATE 触发器将在任何更新语句之后被激活(触发),...等等。

在触发器内部,可以使用“new”关键字引用新插入的值。此外,还可以使用 old 关键字引用已删除或更新的值。如下所示:

  • 在 INSERT 触发器中 – 可以使用新关键字。
  • 在 UPDATE 触发器内部 – 可以使用 new 和 old 关键字。
  • 在 DELETE 触发器中 – 可以使用 old 关键字。

例如:

接下来,我们将创建一个触发器,该触发器将在向“学生”表中插入新学生之前触发。

它会将新插入的学生信息记录到“StudentsLog”表中,并自动添加插入语句执行时的当前时间戳。如下所示:

步骤1) 导航到“C:\sqlite”目录并运行sqlite3.exe。

步骤2) 运行以下命令打开数据库“TutorialsSampleDB.db”:

.open TutorialsSampleDB.db

步骤3) 创建触发器“InsertIntoStudentTrigger”,运行以下命令:

CREATE TRIGGER InsertIntoStudentTrigger 
       BEFORE INSERT ON Students
BEGIN
  INSERT INTO StudentsLog VALUES(new.StudentId, datetime(), 'Insert');
END;

“datetime()”函数会返回插入语句执行时的当前日期时间戳。这样我们就可以记录插入事务,并自动为每个事务添加时间戳。

该命令应该成功运行,并且您没有得到任何输出:

SQLite 触发端口

每次在学生表中插入新学生时,触发器“InsertIntoStudentTrigger”都会被触发。“new”关键字指的是要插入的值。例如,“new.StudentId”将是要插入的学生ID。

现在,我们将测试插入新学生时触发器的行为。

步骤4) 编写以下命令,在学生表中插入一名新学生:

INSERT INTO Students VALUES(11, 'guru11', 1, '1999-10-12');

步骤5) 编写以下命令,选择“StudentsLog”表中的所有行:

SELECT * FROM StudentsLog;

您应该看到我们刚刚插入的新学生返回了一行新行:

SQLite 触发端口

此行是在插入 ID 为 11 的新学生之前由触发器插入的。

在这个例子中,我们使用了创建的触发器“InsertIntoStudentTrigger”,来自动记录“StudentsLog”表中的所有插入事务。同样,您也可以记录任何更新或删除语句。

使用触发器防止意外更新:

在表上使用 BEFORE UPDATE 触发器,您可以根据表达式阻止对列的更新语句。

例如:

在下面的例子中,我们将阻止任何更新语句更新 Students 表中的“studentname”列:

步骤1) 导航到“C:\sqlite”目录并运行sqlite3.exe。

步骤2) 运行以下命令打开数据库“TutorialsSampleDB.db”:

.open TutorialsSampleDB.db

步骤3) 通过运行以下命令,在“Students”表上创建一个新的触发器“preventUpdateStudentName”。

CREATE TRIGGER preventUpdateStudentName
BEFORE UPDATE OF StudentName ON Students
FOR EACH ROW
BEGIN
    SELECT RAISE(ABORT, 'You cannot update studentname');
END;

“RAISE”命令会引发错误,并显示错误消息“您无法更新学生姓名”,然后阻止更新语句的执行。

现在,我们将验证触发器是否运行良好,并且它可以阻止对 studentname 列的任何更新。

步骤4) 运行以下更新命令,将学生姓名“Jack”更新为“Jack1”。

UPDATE Students SET StudentName = 'Jack1' WHERE StudentName = 'Jack';

您应该会收到我们在触发器中指定的错误消息,提示“您无法更新学生姓名”,如下所示:

SQLite 触发端口

步骤5) 运行以下命令,它将从学生表中选择学生姓名列表。

SELECT StudentName FROM Students;

您应该看到学生姓名“Jack”仍然相同并且没有改变:

SQLite 触发端口

常见问题

表在物理上将数据存储在磁盘上,而视图是由已保存的 SELECT 语句定义的虚拟表。视图本身不存储任何数据;每次读取视图时,它都会运行该查询,并显示来自底层表的行。

SQLite 视图是只读的,因此无法直接对其执行 INSERT、UPDATE 和 DELETE 操作。要使视图可写,请附加一个 INSTEAD OF 触发器,该触发器会将操作转换为对底层基表的更改。

在 WHERE、JOIN 或 ORDER BY 子句中频繁使用的列上创建索引,尤其是那些基数高且重复值少的列。索引可以加快 SELECT 查询速度,但对很少查询或非常小的表添加索引几乎没有好处。

是的。每次行发生变化时,索引都必须更新,因此每个额外的索引都会增加写入开销和存储空间。对经常搜索的列建立索引,但要避免对经常接收大量 INSERT、UPDATE 或 DELETE 操作的表建立过度索引。

序号 SQLite 它没有 CREATE MATERIALIZED VIEW 命令,而且普通视图永远不会缓存其结果。要模拟物化视图,请创建一个真实的表,并使用源表上的 AFTER INSERT、UPDATE 和 DELETE 触发器来保持其同步。

sqlite_master 是内置的模式目录,其中列出了数据库中的每个表、视图、索引和触发器。例如,可以使用 SELECT name FROM sqlite_master WHERE type = 'view'; 查询该目录,以检查存在哪些对象。

是的。AI文本转SQL助手可以将纯英语请求转换为SQL语句。 SQLite 创建视图 (CREATE VIEW)、创建索引 (CREATE INDEX) 和创建触发器 (CREATE TRIGGER) 语句。提供真实的表名和列名可以提高准确性,并且每个生成的语句在应用于生产数据之前都应该经过审查和测试。

GitHub 副驾驶 提示 SQLite 在编辑器中内联视图、索引和触发器,例如 VS Code它会读取附近的模式和注释,因此代码补全会重用你真实的表名和列名,但你仍然应该在执行每个语句之前对其进行验证。

总结一下这篇文章: