删除

、概述

删除-stmt:

WITH RECURSIVE common-table-expression , DELETE FROM qualified-table-name returning-clause expr WHERE

公用表表达式:

表达式:

限定表名:

返回子句:

DELETE 命令从qualified-table-name标识的表中删除记录

如果 WHERE 子句不存在,则删除表中的所有记录。如果提供了 WHERE 子句,则仅删除 WHERE 子句布尔表达式为真的那些行。保留表达式为 false 或 NULL 的行。

2. CREATE TRIGGER中DELETE语句的限制

以下限制适用于CREATE TRIGGER语句主体中出现的 DELETE语句:

  • 在触发器主体中指定为 DELETE 语句的一部分的名必须是非限定的。换句话说, 模式名称触发器中不允许表名前缀。如果触发器附加到的表不在临时数据库中,则触发器主体中的 DELETE 语句必须对与其相同的数据库中的表进行操作。如果触发器附加到的表在 TEMP 数据库中,则被删除表的非限定名称的解析方式与顶级语句的解析方式相同(通过首先搜索 TEMP 数据库,然后是主数据库)数据库,然后是按附加顺序排列的任何其他数据库)。

  • 触发器中的 DELETE 语句不允许使用 INDEXED BY 和 NOT INDEXED 子句。

  • 触发器中的 DELETE 语句不支持 LIMIT 和 ORDER BY 子句(如下所述)。

  • 触发器不支持 RETURNING 子句。

3.可选的 LIMIT 和 ORDER BY 子句

如果使用SQLITE_ENABLE_UPDATE_DELETE_LIMIT 编译时选项编译 SQLite,则通过添加可选的 ORDER BY 和 LIMIT 子句扩展 DELETE 语句的语法:

删除-stmt-限制:

WITH RECURSIVE common-table-expression , DELETE FROM qualified-table-name WHERE expr returning-clause ORDER BY ordering-term , LIMIT expr OFFSET expr , expr

如果 DELETE 语句有 LIMIT 子句,将被删除的最大行数是通过评估伴随的表达式并将其转换为整数值来找到的。如果评估 LIMIT 子句的结果不能无损地转换为整数值,则为错误。负的 LIMIT 值被解释为“无限制”。如果 DELETE 语句也有一个 OFFSET 子句,那么它会被类似地评估并转换为一个整数值。同样,如果该值不能无损地转换为整数,则会出错。如果没有 OFFSET 子句,或者计算出的整数值为负,则有效的 OFFSET 值为零。

如果 DELETE 语句有一个 ORDER BY 子句,那么在没有 LIMIT 子句的情况下将被删除的所有行都根据 ORDER BY 排序。M行(其中M是通过评估 OFFSET 子句表达式找到的值)将被跳过,而接下来的 N行(其中N是 LIMIT 表达式的值)将被删除。如果在考虑 OFFSET 子句后剩余的行 少于N ,或者如果 LIMIT 子句的计算结果为负值,则删除所有剩余的行。

如果 DELETE 语句没有 ORDER BY 子句,则在应用 LIMIT 和 OFFSET 子句以确定实际删除的子集之前,将以任意顺序组合在没有 LIMIT 子句的情况下将被删除的所有行。

DELETE 语句上的 ORDER BY 子句仅用于确定哪些行落在 LIMIT 范围内。删除行的顺序是任意的,不受 ORDER BY 子句的影响。这意味着如果有RETURNING 子句,语句返回的行可能不会按照 ORDER BY 子句指定的顺序排列。

4.截断优化

当 WHERE 子句和 RETURNING 子句都从 DELETE 语句中省略并且被删除的表没有触发器时,SQLite 使用优化来擦除整个表的内容,而不必单独访问表的每一行。这种“截断”优化使删除运行得更快。在 SQLite版本 3.6.5 (2008-11-12) 之前,截断优化还意味着sqlite3_changes()sqlite3_total_changes()接口以及count_changes 指示 实际上不会返回已删除的行数。从版本 3.6.5 (2008-11-12) 开始,该问题已得到修复。

通过使用SQLITE_OMIT_TRUNCATE_OPTIMIZATION编译时开关重新编译 SQLite,可以为所有查询永久禁用截断优化。

截断优化也可以在运行时使用sqlite3_set_authorizer()接口禁用。如果授权方回调SQLITE_DELETE操作代码返回SQLITE_IGNORE,则 DELETE 操作将继续,但截断优化将被绕过,行将被逐行删除。