RETURNING 子句本身不是一个语句,而是一个子句,可以可选地出现在顶级 DELETE、INSERT 和 UPDATE 语句的结尾附近。RETURNING 子句的效果是使语句为删除、插入或更新的每个数据库行返回一行结果。RETURNING 不是标准 SQL。它是一个扩展。SQLite 的 RETURNING 语法仿照 PostgreSQL。
RETURNING 语法从 SQLite 3.35.0(2021-03-12)版本开始支持。
RETURNING 子句旨在为应用程序提供 SQLite 自动填充的列的值。例如
CREATE TABLE t0( a INTEGER PRIMARY KEY, b DATE DEFAULT CURRENT_TIMESTAMP, c INTEGER ); INSERT INTO t0(c) VALUES(random()) RETURNING *;
在上面的 INSERT 语句中,SQLite 计算所有三个列的值。RETURNING 子句导致 SQLite 将选定的值报告回应用程序。这样可以避免应用程序发出单独的查询来找出到底插入了哪些值。
RETURNING 子句后跟一个用逗号分隔的表达式列表。这些表达式类似于 SELECT 语句 中 SELECT 关键字后的表达式,因为它们定义结果集中列的值。每个表达式定义单个列的值。每个表达式后可以可选地跟一个 AS 子句,该子句确定结果列的名称。特殊表达式 "*" 将扩展为要删除、插入或更新的表的 非隐藏 列的列表。
对于 INSERT 和 UPDATE 语句,对要修改的表中列的引用指的是该列在应用更改后的值。对于 DELETE 语句,对列的引用是指删除发生之前的列的值。
RETURNING 子句仅返回直接由 DELETE、INSERT 或 UPDATE 语句修改的行。RETURNING 子句不会报告由 外键约束 或 触发器 引起的任何其他数据库更改。
针对 UPSERT 的 RETURNING 子句将报告插入和更新的行。
当运行具有 RETURNING 子句的 DELETE、INSERT 或 UPDATE 语句时,所有数据库更改都发生在 sqlite3_step() 的第一次调用期间。RETURNING 子句输出在内存中累积。第一次 sqlite3_step() 调用返回 RETURNING 输出的一行,随后的 RETURNING 输出行由对 sqlite3_step() 的后续调用返回。换句话说,所有 RETURNING 子句输出在所有数据库修改操作完成后才会释放。
这意味着,如果语句具有生成大量输出的 RETURNING 子句,无论是许多行还是大型字符串或 BLOB 值,那么该语句在运行时可能会使用大量临时内存来保存这些值。
虽然 SQLite 保证所有数据库更改将在任何 RETURNING 输出发出之前发生,但它不保证单个 RETURNING 行的顺序将与这些行在数据库中更改的顺序匹配。RETURNING 行的输出顺序是任意的,不一定与行在内部处理的顺序相关。
SQLite 保证所有数据库更改将在任何 RETURNING 输出发出之前发生,但 SQLite 不会对数据库更改发生的顺序或 RETURNING 输出何时相对于这些数据库更改计算做出任何保证。RETURNING 子句输出在第一次调用 sqlite3_step() 期间全部计算并放置在临时存储中,但这些输出计算的特定顺序以及数据库更改发生的顺序是未指定的。顺序可能在一次查询到下一次查询之间发生变化。
因此,如果 RETURNING 输出的列包含引用要修改表的子查询,那么该子查询的结果可能取决于未指定的行为,因此可能会在一次查询调用到下一次查询调用之间发生变化。
当上一节“处理顺序”说“数据库更改发生在 sqlite3_step() 的第一次调用期间”时,这意味着更改存储在运行该语句的数据库连接的私有页面缓存中。这不意味着更改实际已提交。提交在语句完成之前不会发生,如果语句是更大事务的一部分,甚至可能不会发生。对数据库的更改仍然是原子性的、一致的、隔离的和持久的(ACID)。当上一节说“更改发生”时,这意味着内部数据结构已根据事务提交进行调整。这些更改中的一部分可能会或可能不会溢出到 预写日志,这取决于页面缓存的压力有多大。如果页面缓存没有承受内存压力,那么在事务完成之前可能什么都不会写入磁盘,这发生在 sqlite3_step() 返回 SQLITE_DONE 之后。
换句话说,当上一节说“数据库更改发生”时,这意味着更改发生在运行该语句的特定数据库连接的内存中,而不是更改写入磁盘。
RETURNING 子句在针对 虚拟表 的 DELETE 和 UPDATE 语句中不可用。此限制可能会在将来的 SQLite 版本中删除。
RETURNING 子句仅在顶级 DELETE、INSERT 和 UPDATE 语句中可用。RETURNING 子句不能由触发器内的语句使用。
即使带有 RETURNING 子句的 DML 语句返回表内容,也不能用作子查询。RETURNING 子句只能将数据返回给应用程序。目前无法将 RETURNING 输出转移到另一个表或查询中。PostgreSQL 能够像在 公共表表达式 中使用视图一样使用带有 RETURNING 子句的 DML 语句。SQLite 目前没有这种功能,不过这可能是将来版本中会添加的功能。
RETURNING 子句发出的行以任意顺序出现。该顺序可能会根据数据库模式、使用的 SQLite 的特定版本,甚至从同一个语句的执行到下一次执行而发生变化。无法使输出行以特定顺序出现。即使 SQLite 使用 SQLITE_ENABLE_UPDATE_DELETE_LIMIT 选项编译,以便在 DELETE 和 UPDATE 语句中允许 ORDER BY 子句,这些 ORDER BY 子句也不会限制 RETURNING 的输出顺序。
RETURNING 子句发出的值是顶级 DELETE、INSERT 或 UPDATE 语句看到的的值,不反映由 触发器 进行的任何后续值更改。因此,如果数据库包含在每个插入或更新的行中修改某些值的 AFTER 触发器,则 RETURNING 子句会发出在这些触发器运行之前计算的原始值。
RETURNING 子句可能不包含顶级 聚合函数 或 窗口函数。如果 RETURNING 子句中有子查询,那么这些子查询可以包含聚合和窗口函数,但聚合不能出现在顶级。
RETURNING 子句只能引用要修改的表。在 UPDATE FROM 语句中,FROM 子句中命名的辅助表不能参与 RETURNING 子句。