RETURNING子句本身不是语句,而是可以选择性地出现在顶级DELETE,INSERT和UPDATE语句的末尾的子句 。RETURNING子句的作用是使语句为删除,插入或更新的每个数据库行返回一个结果行。返回不是标准的SQL。它是一个扩展。SQLite的RETURNING语法是在PostgreSQL之后建模的 。
从3.35.0(2021-03-12)版本开始,SQLite支持RETURNING语法。
RETURNING子句旨在为应用程序提供SQLite自动填充的列的值。例如:
创建表t0( 整数主键, b DATE DEFAULT CURRENT_TIMESTAMP, c整数 ); 插入t0(c)值(random())返回*;
在上面的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值),则该语句在运行时可能会使用大量的临时内存来保存这些值。
RETURNING子句的第一个原型返回生成的值。该方法使用较少的内存,但存在其他问题:
如果对交错的两个或多个DML语句调用sqlite3_step(),并且其中一个语句遇到约束故障并中止,将其更改还原,那么这可能会中断另一个DML语句的操作。这不会破坏数据库文件,但是会在数据库中产生令人惊讶且难以解释的结果。
如果应用程序无法重复调用sqlite3_step()直到收到SQLITE_DONE,则可能永远不会发生某些数据库更改。
操作顺序与诸如PostgreSQL之类的客户端/服务器数据库引擎不同,这可能会导致某些应用程序的可移植性问题。
由于这些原因,当前的实现已被修改,以便所有数据库更改都在发出任何RETURNING输出之前发生。
尽管SQLite保证所有数据库更改都会在发出任何RETURNING输出之前发生,但它不能保证单个RETURNING行的顺序将与数据库中这些行的更改顺序匹配。RETURNING行的输出顺序是任意的,并且不一定与内部处理行的顺序有关。
RETURNING子句在针对虚拟表的DELETE和UPDATE语句上不可用。在将来的SQLite版本中可能会删除此限制。
RETURNING子句仅在顶级DELETE,INSERT和UPDATE语句中可用。触发器内的语句不能使用RETURNING子句。
即使带有RETURNING子句的DML语句返回表内容,也不能将其用作子查询。RETURNING子句只能将数据返回到应用程序。当前无法将RETURNING输出转移到另一个表或查询中。PostgreSQL可以使用带有RETURNING子句的DML语句,例如公用表表达式中的视图 。SQLite当前不具备此功能,尽管将来的版本中可能会添加该功能。
RETURNING子句发出的行以任意顺序出现。该顺序可能会根据数据库模式,所使用的SQLite的特定版本甚至从同一条语句的执行到下一条执行而变化。无法使输出行以特定顺序出现。即使使用SQLITE_ENABLE_UPDATE_DELETE_LIMIT 选项编译SQLite ,从而允许在DELETE和UPDATE语句上使用ORDER BY子句,这些ORDER BY子句也不会限制RETURNING的输出顺序。
RETURNING子句发出的值是顶级DELETE,INSERT或UPDATE语句所看到的值,并且不反映触发器随后进行的任何值更改。因此,如果数据库包含AFTER触发器,该触发器修改插入或更新的每一行的某些值,则RETURNING子句将发出在这些触发器运行之前计算出的原始值。
RETURNING子句可能不包含顶级聚合函数或 窗口函数。如果RETURNING子句中有子查询,则这些子查询可能包含聚合和窗口函数,但聚合不能在顶层发生。
RETURNING子句只能引用正在修改的表。在UPDATE FROM语句中,在FROM子句中命名的辅助表可能不参与RETURNING子句。