DELETE 语句
DELETE语句用于从表或视图中删除行。 如果未为视图定义“代替删除”触发器,则从视图中删除一行会从该视图所基于的表中删除该行。 如果定义了这样的触发器,则启用触发器。
表格或视图可以位于当前服务器上,也可以位于当前服务器可以与之建立连接的任何 Db2 子系统上。
这种说法有两种形式:
- 搜索到的 “删除”表单用于删除一行或多行,具体取决于搜索条件。
- 定位的 “删除”表单指定删除与当前光标位置对应的一行或多行。
调用 DELETE
此语句可嵌入应用程序中或者以交互方式发出。 应用程序中嵌入了定位删除功能。 嵌入式和交互式形式都是可执行语句,可以动态编写。
授权 DELETE
权限要求取决于语句中标识的对象是用户定义的表、目录表还是视图,以及语句是否为已搜索的DELETE,且SQL标准规则是否有效:
当识别出目录表以外的表格时 :权限集必须至少包含以下一项:
- 桌上的删除权限
- 对表的所有权
- DBADM 数据库中包含表格的权限
- SYSADM 权限
如果数据库是隐式创建的,则数据库权限必须位于隐式数据库或 DSNDB04 上。
当识别出目录表时 :权限集必须至少包含以下一项:
- DBADM 目录数据库权限
- SYSCTRL 权限
- SYSADM 权限
当确定一个景观时 :特权集必须至少包含以下内容之一:
- 视图的删除权限
- SYSADM 权限
- 表或视图的 SELECT 权限
- 表格或视图的所有权
- 如果目标是一个表,且该表不是目录表,则DBADM是包含该表的数据库的权限
- DATAACCESS
- SYSADM 权限
如果被搜索的 DELETE 中的搜索条件包含子查询,或者赋值子句包含标量全选或行全选 ,请参阅查询授权 ,了解所需授权的说明。
视图的所有者与表格的所有者不同,可能没有删除视图的权限(或者可能拥有删除权限,但不能授予他人)。 鉴于图片本身的性质,无法将其用于删除操作。 更多信息,请参阅 CREATE VIEW语句中的权限说明。
如果语句嵌入在应用程序中,则权限集是指计划或包的所有者所拥有的权限。 如果语句是动态准备的,则权限集由有效的DYNAMICRULES行为(运行、绑定、定义或调用)确定,并在表1 中进行了汇总。 (如需了解这些行为的更多信息,包括确定这些行为的DYNAMICRULES绑定选项值列表,请参阅授权ID和动态SQL。)
FL 509 如果语句试图删除 SYSIBM.SYSAUDITPOLICIES 目录表中受防篡改审计策略约束的行,则需要额外的 RACF® 授权。 在语句执行期间,必须授权主授权ID或与主授权ID关联的某个组访问 RACF 中的防篡改审计策略配置文件。 如需了解授权规则的更多信息,请参阅 Db2 审核政策。
搜索 删除:
定位删除:
period-clause:
包括列:
数据类型:
内置类型:
任务条款:
隔离条款:
描述 DELETE
- FROM 表名或 视图名
- 标识要从中删除行的表格或视图。 名称必须标识 Db2 子系统中存在的表或视图,该名称由隐式或显式指定的位置名称标识。 该名称不得用于:
- 辅助表格
- 不允许删除的目录表
- 目录表的视图
目录表
- 只读视图(参见 CREATE VIEW语句 )
如果指定了获取子句,则用定义视图的代替触发器。
如果指定了fetch子句,则创建一个临时表。
如果指定了获取子句,则为只包含加速器的表。
- 系统维护的实体化查询表
- 为XML列隐式创建的表
- 如果 SYSIBMADM.GET_ARCHIVE 全局变量设置为Y,ARCHIVESENSITIVE绑定选项设置为YES,且操作为定位删除,则启用存档的表格
- 句中句
- 指定一个句点子句应用于删除操作的目标。 同一时期的名字不能重复出现。 如果删除操作的目标是视图:
- 视图定义的外部全选中的 FROM 子句必须直接或间接引用应用程序期间的时间表。
- 该视图不能定义“代替”触发器。
- FOR PORTION OF BUSINESS_TIME
- 指定删除仅适用于由期间子句指定的行中BUSINESS_TIME期间部分的行值。 BUSINESS_TIME 必须是在表格中定义的时段。
如果当 BUSTIMESENSITIVE 绑定选项设置为 YES 时,CURRENT TEMPORAL BUSINESS_TIME 特殊寄存器的值不为 NULL,则不能指定部分业务时间。
- FROM value1 TO value2
- 指定删除操作适用于从 value1 至 value2。 如果 value1 大于或等于 value2 ,或者 value1 或 value2 为空值。
此条款不得用于包含-包含期间。 
对于以 FROM value1 TO value2 ,删除操作的目标表一行中由period-name 指定的期间:
- 如果开始列的值小于 value1 而结束列的值大于 value1。
- 如果结束列的值大于或等于 value2 且开始列的值小于 value2。
- 如果行中期间名称的起始列的值大于或等于 value1 且该行对应结束列的值小于或等于 value2。
- 如果行与指定时段的开始或结束重叠,则部分包含在指定时段内。
- 如果行中的时间与指定时间段的开始和结束时间完全重合,则完全重合。
- 如果时期名称的两列均小于或等于 value1 或大于 value2。
如果指定时间段内没有包含某行的时期名称 ,则该行不会被删除。 否则,删除操作将根据“PORTION OF”子句的说明以及期间名称列中的值与指定期间的重叠情况执行,具体如下:
- 如果一行中的时期名称完全包含在指定的时期内,则该行将被删除。
- 如果行中的时期名称部分包含在指定的时期内,并且与指定时期的开始部分重叠:
- 该行已删除。
- 插入的行使用该行的原始值,但最后一列设置为 value1 ,其他生成的列使用新的值。
- 如果行中的时期名称部分包含在指定的时期内,并且与指定时期的结尾重叠:
- 该行已删除。
- 插入的行使用该行的原始值,但开始列设置为 value2 ,其他生成的列使用新的值。
- 如果行中的时期名称与指定的时期完全重合:
- 该行已删除。
- 插入的行使用该行的原始值,但最后一列设置为 value1 ,定义为数据更改操作的列被设置为“I”,其他生成的列使用新值。
- 使用该行的原始值插入另一行,但开始列设置为 value2 ,定义为数据更改操作的列被设置为“I”,其他生成的列使用新值。
任何现有的删除触发器都会对被删除的行激活,任何现有的插入触发器都会对隐式插入的行激活。
BETWEEN value1 AND value2
FL 500 指定删除操作适用于从 value1 至并包括 value2。 如果 value1 大于 value2 ,或者 value1 或 value2 为空值。 此条款不得用于包含-排除期间。对于用BETWEEN value1 和 value2 ,删除目标中连续的句号、句号名称涵盖以下范围之一:
- 如果开始列的值小于 value1 且结束列的值大于或等于 value1。
- 如果结束列的值大于 value2 且开始列的值小于或等于 value2。
- 如果行中期间名称的起始列的值大于或等于 value1 且该行对应结束列的值小于或等于 value2。
- 如果行与指定时段的开始或结束部分重叠,则部分包含在指定时段内,但不会同时包含在指定时段的开始和结束部分。
- 如果行中的时间与指定时间段的开始和结束时间完全重合,则完全重合。
- 如果时期名称的两列均小于或 value1 或大于 value2。
如果指定时间段内没有包含某行的时期名称 ,则该行不会被删除。 否则,删除操作将基于以下项目:
- “部分”条款的详细说明。
- 时期名称列中的值如何与指定时期重叠。
- spu (最小周期单位),取决于周期列的数据类型,如下所示:
- 对于包含日期列的期间,spu为1天。
- 在包含 TIMESTAMP(6) 列的时段内,spu 为 1 微秒。
根据这些项目,删除操作如下:
- 如果一行中的时期名称完全包含在指定的时期内,则该行将被删除。
- 如果行中的时期名称部分包含在指定的时期内,并且与指定时期的开始部分重叠:
- 该行已删除。
- 插入的行使用该行的原始值,但最后一列设置为 value1 - spu,其他生成的列使用新的值。
- 如果行中的时期名称部分包含在指定的时期内,并且与指定时期的结尾重叠:
- 该行已删除。
- 插入的行使用该行的原始值,但开始列设置为 value2 + spu,其他生成的列使用新的值。
- 如果行中的时期名称与指定的时期完全重合:
- 该行已删除。
- 插入的行使用该行的原始值,但最后一列设置为 value1 - spu,其他生成的列使用新的值。
- 使用该行的原始值插入另一行,但将开始列设置为 value2 + spu,其他生成的列使用新的值。

- value1, value2
- 指定返回内置数据类型值的表达式。 每个表达式的结果必须与指定期间列的数据类型相匹配。 参见 “分配和比较” 中描述的比较规则。 每个表达式可以包含以下任何支持的运算符:
- 常量
- 专用寄存器
- 变量
- 数组元素说明
- 一个内置标量函数,其参数为支持的操作数
- CAST 规范,其中 CAST 操作数是受支持的运算数
- 使用算术运算符和操作数的表达式
每个表达式的精度不能高于该期间列的精度。
如果将期间的开始和结束列定义为不带时区的TIMESTAMP,则每个表达式不得返回带有时区的TIMESTAMP值。
视图的期间子句不能包含未定义的参数标记。
- 相关名称
- 指定可在搜索条件中使用的替代名称,用于指定表或视图。 (关于相关名称的解释,请参阅相关名称。)
- 包括列
- 当DELETE语句嵌套在子查询、SELECT语句或SELECT INTO语句的外层全选查询的FROM子句中时,指定包含在结果表中的列集,以及表名或视图名的列。 包含的列附加到以表名或视图名标识的列列表的末尾。 如果对include-column指定的列未赋值,则该列返回NULL值。
- INCLUDE
- 介绍DELETE语句结果表中包含的列列表。 仅当DELETE语句嵌套在SELECT语句或SELECT INTO语句的FROM子句中时,才可使用包含的列。
- 列名
- 指定 DELETE 语句结果表中某列的名称,该列的名称不能与表或视图中 table-name 或 view-name 中指定的其他列或列名相同。
- 数据类型
- 指定包含列的数据类型。 包含的列可以为空。
- built-in-type
- 指定内置数据类型。 有关每种内置类型的描述,请参阅 CREATE TABLE语句。
INCLUDE列中不能指定CCSID 1208和CCSID 1200子句。
- 独特类型
- 指定一种不同的类型。 列的任何长度、精度或比例属性都是通过使用CREATE TYPE语句指定的不同类型的源类型的属性。
- SET
- 介绍如何为列赋值。
- assignment-clause
- 赋值子句引入一个或多个列名列表以及要赋给这些列的值。 列名是唯一可以使用赋值子句设置的列。
- 列名
- 标识一个包含列。
只有在DELETE语句嵌套在SELECT语句或SELECT INTO语句的FROM子句中时,才会处理包含列的分配。 在INCLUDE子句中命名的列是唯一可以使用SET子句设置的列。 对于未使用明确的SET子句设置的包含列,将返回空值。
- 表达式
- 指示列的新值。 表达式是指表达式中描述的任何类型的表达式。 它不能包含聚合函数。
表达式中的列名必须标识表或视图的列。 对于每行删除,表达式中列的值是删除前一行中列的值。
- NULL
- 指定空值作为列的新值。 仅对可空列指定 NULL。
- row-fullselect
- 指定返回单行的全查询。 列值被分配给每个对应的列名。 如果fullselect没有返回任何行,则将为每个列分配空值;如果任何要删除的列不是空值,则会发生错误。 如果结果中存在多个行,那么也会发生错误。
如果全选指的是要删除的列,则全选中的该列的值是删除行之前该行中该列的值。
- WHERE
- 指定要删除的行。 您可以省略该子句,给出搜索条件,或指定光标。 对于创建的临时表或创建的临时表的视图,必须省略该子句。 当省略该子句时,表或视图的所有行都会被删除。
- search-condition
- 是否满足SQL语言元素中描述的任何搜索条件。 除了子查询之外,搜索条件中的每个列名都必须标识表或视图的列。
搜索条件应用于表格或视图的每一行,删除的行是搜索条件结果为真的行。
如果搜索条件包含子查询,则每次将搜索条件应用于一行时,都会执行子查询,并将结果用于应用搜索条件。 实际上,没有关联引用的子查询只执行一次,而具有关联引用的子查询则必须针对每一行执行一次。
令 T2 表示DELETE语句的对象表,令 T1 表示该语句子查询的FROM子句中引用的表。 T1 不能是 上的DELETE可以删除的表格。 T2 因此,以下规则适用:
- T1 不得是 的从属关系,且与CASCADE或SET NULL的删除规则相关,除非在执行DELETE操作之前子查询的结果已经实现。 T2
- T1 不得是 的从属关系,且如果删除 会连带删除 ,则删除规则为CASCADE或SET NULL。 T3 T2 T3
取语句
FL 500 将删除的效果限制在符合条件的行的子集内。 详情请参阅取语句。
- 当前光标名称
- 确定用于删除操作的指针。 cursor-name 必须按照 DECLARE CURSOR 语句中的说明,将声明的游标标识为 DECLARE CURSOR 语句。 如果DELETE语句嵌入在程序中,则DECLARE CURSOR语句必须包含 select语句 ,而不是语句名称。
命名的表或视图还必须在游标的 SELECT 语句的 FROM 子句中命名,并且游标的结果表必须能够被删除。 有关只读结果表的说明,请参阅只读游标。 请注意,DELETE语句的对象不能在游标的SELECT语句的WHERE子句中作为子查询的对象。
如果光标不明确,且计划或套餐与 CURRENTDATA(NO) 绑定,则当尝试对以下任何一项应用 DELETE WHERE CURRENT OF 时, Db2 可能会向应用程序返回错误:
- 使用块访存的游标
- 使用并行性查询的游标
- 光标位于已被此应用程序或其他应用程序修改的行上
执行 DELETE 语句时,光标必须打开并定位在结果表的某一行或某一行集上。
- 如果光标位于单行上,则该行将被删除,删除后光标将位于结果表下一行的前面。 如果没有下一行,光标将定位在最后一行之后。
- 如果光标位于行集上,则与当前行集的行相对应的所有行都会被删除,删除后,光标会位于结果表的下一个行集之前。 如果没有下一行,光标将定位在最后一行之后。
对于引用了定义了而不是删除触发器的视图的光标,即使该视图是可更新视图,也不得指定已定位的DELETE。
- 行 n 的行集
- 指定要删除当前行集的哪一行。 行集的相应行被删除,光标仍停留在当前行集上。 如果行集由单个行组成,或者行集中的所有其他行已被删除,则光标位于结果表的下一行集之前。 如果没有下一行,光标将位于最后一行之后。
host-variable 或 integer-constant 被赋值给一个整数 k。 如果指定了宿主变量 ,则该变量必须为精确数值类型且比例系数为零,不得包含指示变量,且 k 必须在 1-32767 范围内。 光标必须位于行集上,且指定值必须是光标最近检索的行集的有效值。
如果指定的行无法删除,则返回错误。 指定的行可能位于最近请求的行集范围内,但当前行集包含的行数少于建立该行集时隐式或显式请求的行数。
如果通过定位删除操作删除当前行集中特定行的敏感静态光标,并且该行已被标识为删除孔(即结果表中某一行,其对应行已从基础表中删除),则将返回错误。
如果通过定位删除指定当前行集特定行的敏感静态光标,并且该行已被识别为更新漏洞(即结果表中某行已更新,使其不再满足 SELECT 语句的谓词),则返回错误。
另一个应用程序可能会删除SELECT语句的基表中的某一行,使得游标的指定行在基表中不再有对应的行。 尝试删除此类行会导致错误。
如果未指定 FOR ROW n OF ROWSET 子句,则光标当前位置将决定受语句影响的行:
- 如果光标位于单行上,则该行将被删除。 删除行后,光标将定位到结果表的下一行之前。 如果没有下一行,光标将定位在最后一行之后。
- 如果光标位于行集上,则与当前行集的行相对应的所有行都会被删除。 删除行后,光标将定位在结果表的下一行组之前。 如果没有下一行,光标将定位在最后一行之后。
- 隔离条款
- 指定在通过语句定位要删除的行时使用的隔离级别。
- WITH
- 介绍隔离级别,可能为以下之一:
- RR
- 可重复读取
- RS
- 读取稳定性
- CS
- 光标稳定性
语句的默认隔离级别是语句所属包或计划的隔离级别,包隔离级别优先于计划隔离级别。 如果没有指定包隔离,则默认使用计划隔离。
- 跳过已锁定的数据
- SKIP LOCKED DATA子句规定,当其他事务对某行持有不兼容的锁时,将跳过该行。 这些行可以属于语句中指定的任何已访问表。 仅当隔离CS或RS生效时,才能使用跳过锁定数据,且仅适用于行级或页级锁定。
对于DELETE语句,SKIP LOCKED DATA只能以DELETE语句的搜索形式指定。 如果指定的隔离级别为可重复读取(WITH RR)或未承诺读取(WITH UR),则跳过锁定数据(SKIP LOCKED DATA)将被忽略。 语句的默认隔离级别取决于绑定语句的程序包或计划的隔离级别,其中程序包隔离级别优先于计划隔离级别。 如果没有指定包隔离,则默认使用计划隔离。
- QUERYNO 整数
- 指定在EXPLAIN输出和跟踪记录中用于此SQL语句的编号。 该数字用于计划表中 QUERYNO 列,其中包含有关此 SQL 语句的信息。 这个数字也用于 SYSIBM.SYSSTMT 和 SYSIBM.SYSPACKSTMT 目录表的QUERYNO列。
如果省略该子句,则与SQL语句关联的数字就是预编译期间分配的语句编号。 因此,如果应用程序被修改并预编译,那么语句编号可能会改变。
使用QUERYNO子句为程序中的SQL语句分配唯一编号很有帮助:
- 为了简化优化提示的使用,以便选择访问路径
- 用于将计划表中的SQL语句文本与EXPLAIN输出相关联
有关启用和使用优化提示的更多信息,请参阅影响访问路径选择
有关访问计划表的信息,请参阅 《使用EXPLAIN调查SQL性能 》。
备注 DELETE
- 删除操作错误:
- 如果在执行任何删除操作时发生错误,则不会进行任何更改。 如果在执行定位删除时发生错误,光标的位置将保持不变。 然而,错误可能会导致光标位置无效,在这种情况下,光标将关闭。 删除操作也有可能造成回滚,在这种情况下,光标将关闭。
- 光标位置:
- 如果应用程序删除一行,而光标位于该行,则光标将移至结果表下一行之前。 假设C是一个光标,位于R行之前(可能是通过C执行的OPEN、DELETE,或通过其他光标执行的DELETE,或搜索到的DELETE)。 在SQL数据变更语句影响R所基于的表时,下一个引用C的FETCH操作不一定将C定位在R上。 例如,操作可以将C定位在R'上,其中R'是结果表的下一行。
- 锁定:
- 除非已经存在适当的锁,否则在成功删除操作期间会获取一个或多个专用锁。 在提交或回滚操作释放锁之前,只有执行删除操作的应用程序进程才能感知到删除操作的效果,而锁可以阻止其他应用程序进程对表执行操作。 从已声明的临时表中删除行时,除非删除所有行(DELETE FROM T),否则不会获取锁。 当从已声明的临时表中删除所有行时,将在表的页面上获取分段表锁,而表空间中的其他表不会受到影响。
- 触发器:
- 删除操作可能会激活触发器。 触发器可能会导致其他语句被执行,或者可能会引发基于已删除行的错误条件。 如果视图中的 DELETE 语句导致 INSTEAD OF 触发器被激活,则参照完整性检查将针对触发器中执行的更新,而不是针对导致触发器被激活的视图的基础表。
- 在表格中定义触发器,并对其行或列访问控制进行强制:
- 行权限和列掩码不适用于转换变量和转换表的初始值。 触发表所强制执行的行和列访问控制,对于触发器主体中引用的任何转换变量或转换表,或者作为参数传递给触发器主体中调用的用户定义函数,也是可以忽略的。 为了确保触发器操作中的SQL语句不存在任何安全问题(例如,访问过渡变量和过渡表中的敏感数据),触发器必须安全。 有关触发器安全性的信息,请参阅 CREATE TRIGGER语句(基本触发器 )和 ALTER TRIGGER语句(基本触发器 )。
- 引用完整性:
- 如果已识别表或已识别视图的基表是父级,则所选行不得与删除规则为“限制”或“无操作”的任何从属关系相关联。 此外,删除操作不得级联到与RESTRICT或NO ACTION删除规则存在关系依赖的后继行。
如果删除操作未受到RESTRICT或NO ACTION删除规则的阻止,则所选行将被删除,而与所选行相关的任何行也将被删除。
- 在受SET NULL删除规则约束的关系中,任何行中作为从属关系的可空列的外键都设置为空值。
- 任何受CASCADE删除规则约束的关系中的从属行也会被删除,这些规则反过来也适用于这些行。
NO ACTION和RESTRICT之间的唯一区别在于引用约束是否被强制执行。 RESTRICT( IBM SQL规则)立即执行规则,NO ACTION(SQL标准规则)在语句末尾执行规则。 只有在搜索DELETE涉及自引用约束,且删除多行时,这种差异才重要。 在RESTRICT(如果允许的话)阻止删除的情况下,任何操作都不可能使删除成功。
- 检查约束:
- 当关系中存在依赖项,且删除规则为SET NULL时,检查约束可以防止删除父表中的行。 如果删除父表中的某一行会导致从属表中的某列被设置为空,而存在一个检查约束指定该列不能为空,则该行不会被删除。
- 在执行行或列访问控制的表上定义的参照约束:
- 行和列访问控制不影响参照约束。
- 嵌套用户定义函数或存储过程:
- DELETE语句可以隐式或显式地引用用户定义的函数或存储过程。 这被称为SQL语句嵌套。 在DELETE中嵌套的用户定义函数或存储过程不得访问您要从中删除行的表。
- 包含VARBINARY列的索引:
- 如果已识别表中的 VARBINARY 列或基于 VARBINARY 数据类型的独特类型列具有索引,则该索引列不能指定 DESC 属性。 要在已识别表格上使用SQL数据更改操作,要么删除索引,要么将列的数据类型改为二进制,然后重建索引。
- 删除的行数:
- 除以下说明外,删除操作会将SQLCA中的SQLERRD(3)设置为已删除行的数量。 此数字不包括因级联删除规则或触发器而删除的任何行。
不带WHERE子句的DELETE FROM T将删除T的所有行。 如果表 T 包含在分段表空间中且不是父表,则执行此删除操作时无需访问 T。SQLERRD(3) 字段设置为 -1。 (如需了解SQLCA的完整描述,包括上述例外情况,请参阅 SQL通信区(SQLCA )。
- 使用敏感静态滚动光标定位删除的规则:
- 当敏感静态可滚动光标被启用时,以下规则适用:
- 删除尝试删除孔或更新孔。 如果使用定位删除功能删除敏感静态可滚动光标,并试图删除已被标记为删除孔的行(即结果表中某一行,其对应行已从基础表中删除),则会发生错误。
如果尝试删除已被识别为更新漏洞的行(即结果表中对应行已被更新,不再满足SELECT语句谓词的行),则会发生错误。
- 删除操作。 使用敏感静态可滚动光标定位删除操作,具体操作如下:
- 游标基础表目标行中的 SELECT 列表项与结果表对应行中的值进行比较(也就是说,结果表必须与基础表保持一致)。 如果数值不匹配,删除操作将被拒绝并出现错误。 当目标行成功执行FETCH SENSITIVE后,可以再次尝试执行该操作。
- SELECT语句的WHERE子句被重新评估,以确定基础表中的当前值是否仍然满足搜索条件。 将“选择”列表中的值进行比较,以确定这些值没有发生变化。 如果WHERE子句的计算结果为真,且SELECT列表中的值没有改变,则允许继续执行删除操作。 否则,就会发生错误,删除操作被拒绝,光标中出现更新漏洞。
- 成功删除基本表行后,临时结果表将更新,该行将被标记为删除孔。
- 删除孔的回滚。 删除的孔通常是永久性的。 删除孔一旦被识别,就会一直保持删除孔的状态,直到光标被关闭。 但是,如果使用此光标定位删除操作确实导致孔洞的产生(即使用此光标进行更改导致孔洞的产生),而随后又回滚了删除操作,则该行不再被视为删除孔洞。
- 结果表。 如果使用可滚动光标尝试定位更新或定位删除,则对定义了敏感静态可滚动光标的基表行进行的任何删除(无论定位还是搜索)都会反映在结果表中。 当尝试FETCH SENSITIVE时,一个敏感的静态可滚动光标会看到这些删除。
如果未指定 FOR ROW n OF ROWSET 子句 ,则删除由最近的 FETCH 语句获取的指定游标的整个行集。
- 删除尝试删除孔或更新孔。 如果使用定位删除功能删除敏感静态可滚动光标,并试图删除已被标记为删除孔的行(即结果表中某一行,其对应行已从基础表中删除),则会发生错误。
参考更新后的列:
如果游标使用FETCH语句来检索稍后要更新的列,请在选择列时指定FOR UPDATE OF。 然后在后续的UPDATE或DELETE语句中指定WHERE CURRENT OF。 这些条款阻止了 Db2 通过更新列的索引进行访问,否则可能导致 Db2 多次读取同一行。更多信息,请参阅更新之前检索的数据。

- 从具有多层安全性的表中删除行:
- 当您从具有多层安全性的表中删除行时, Db2 会将用户的安全标签(主要授权ID)与行的安全标签进行比较。 删除操作遵循以下规则:
- 如果用户的安全标签与行中的安全标签相同,则该行将被删除。
- 如果用户的安全标签优先于行的安全标签,则用户的写权限将决定DELETE语句的结果:
- 如果用户具有写权限或写权限未启用,则该行将被删除。
- 如果用户没有写权限,且写权限控制已启用,则该行不会被删除。
- 如果该行安全标签优先于用户安全标签,则该行不会被删除。
- 从执行行和列访问控制的表中删除行:
- 当对一个已实施行访问控制的表发出DELETE语句时,行权限中指定的规则会影响行是否可以被删除。 通常情况下,这些规则基于授权ID或流程角色。
对行访问控制进行了强制设置的表至少具有一个行权限,即默认行权限,该权限阻止对表的任何访问。 当为表定义并启用多行权限时,行访问控制搜索条件是通过在每个已启用权限的搜索条件中使用逻辑或运算符得出的。 此行访问控制搜索条件应用于表,以确定DELETE语句的授权ID或角色可以访问哪些行。 如果在DELETE语句中指定WHERE子句,则用户指定的谓词将应用于可访问的行,以确定要删除的行。 如果没有WHERE子句,则可访问的行就是要删除的行。
如果需要删除行,并且存在表的DELETE触发器,则触发器将被激活。
当对已实施列访问控制的表发出 DELETE 语句时,列掩码不会影响 DELETE 语句。
以上规则不适用于包含列。 include-columns 受选择列表规则的约束,因为它们不是 DELETE 语句对象表的列。
- 同一工作单元中的其他SQL语句:
- 在同一工作单元中,以下语句不能紧跟在DELETE语句之后:
- ALTER TABLE语句,用于更改列的数据类型(ALTER COLUMN SET DATA TYPE)
- ALTER INDEX语句,用于更改具有不同长度列的索引的填充属性(从PADDED更改为NOT PADDED,反之亦然)
- CREATE TABLE语句用于创建仅包含加速器的表。
- INSERT、UPDATE或DELETE语句,用于从其他加速器更新仅加速器表
- 系统周期时间表的注意事项:
- 如果 DELETE 语句的搜索条件包含引用历史表的关联子查询(显式引用历史表名称或隐式引用 FROM 子句中的句点),则作为历史行存储的被删除行可能会对随后处理的语句的行删除操作可见。
如果表被定义为系统周期临时表,则不包含搜索条件的DELETE语句不使用批量删除操作。
如果将 CURRENT TEMPORAL SYSTEM_TIME 特殊寄存器设置为非空值,则 DELETE 语句的底层目标不能是系统周期临时表。 无论系统周期时间表是直接引用还是间接引用,此限制均适用。
- 历史表格注意事项:
- 当删除系统周期时间表中的一行时,该行的历史副本将插入到相应的历史表中,并且历史行的结束时间戳将以系统确定的值的形式捕获,该值对应于数据更改操作的时间。
如果在数据更改操作时, SYSIBM.TEMPORAL_LOGICAL_TRANSACTION_TIME 内置全局变量的值为空,则使用在执行第一个数据更改语句期间读取的时钟时间来生成该值,该语句以工作单元为单位,要求将值分配给表中的行开始列或事务开始ID列,或者删除系统周期时间表中的行。 否则,在数据更改操作时,该值将从 SYSIBM.TEMPORAL_LOGICAL_TRANSACTION_TIME 内置全局变量中分配。
如果一个冲突事务正在更新系统时间表的同一行,并且要插入关联历史表的行的结束列的值大于对应开始列的值,则将返回错误。 - 申请期间临时时间表注意事项:
- 包含“FOR PORTION OF BUSINESS_TIME”子句的DELETE语句用于指定删除操作在两个时间点之间生效。
假设指定了 FOR PORTION OF BUSINESS_TIME,并且某行的期间值仅部分包含在指定的期间内,即从 value1 至 value2 或介于 value1 和 value2。 (行的时间值由开始列和结束列的值指定。) 在这种情况下,该行将被删除,并自动插入一行或两行,以表示该行未被删除的部分。 对于因对表进行删除操作而自动插入的每一行,应用程序期间临时表中每生成一列都会生成新的值。 如果生成的列被定义为唯一或主键、参照约束中的父键或唯一索引的一部分,则自动插入可能会违反约束或索引。 在这种情况下,将返回一个错误。
当DELETE语句的目标是应用程序时段表,且当前临时性业务时间特殊寄存器的有效值不是空值时, Db2 会在语句中添加以下附加谓词:

- 包容性-排他性时期:
bt_begin <= CURRENT TEMPORAL BUSINESS_TIME AND bt_end > CURRENT TEMPORAL BUSINESS_TIME - 包容性-包容期:
bt_begin <= CURRENT TEMPORAL BUSINESS_TIME AND bt_end >= CURRENT TEMPORAL BUSINESS_TIME

在之前的代码中,bt_begin和bt_end分别是DELETE语句目标表BUSINESS_TIME期间的开始和结束列。
- 包容性-排他性时期:
- 从启用存档的表中删除行:
- 如果DELETE语句的目标是启用了归档的表,则关联的归档表中的现有行不会受到影响。
当删除启用存档功能的一列时,对关联的存档表的影响取决于 SYSIBMADM.MOVE_TO_ARCHIVE 全局变量的设置。 如果全局变量设置为Y,则会将已删除行的副本插入关联的归档表中。 否则,删除的行副本不会插入到关联的归档表中。
当系统周期临时表或应用程序周期临时表也被引用时,数据更改语句不能引用启用存档的表。
- 语法替代方案:
- 为了与其他SQL实现兼容,可以省略紧跟在DELETE关键字之后的FROM关键字。
示例 DELETE 语句
以下语句将删除NEWEMP表中员工编号为000060的每一行。
DELETE FROM NEWEMP
WHERE EMPNO = '000060';
假设以下示例中的语句嵌入了 PL/I 程序。
- 从表 DSN8C10.EMP 中删除光标 C1 当前所在的行。
EXEC SQL DELETE FROM DSN8C10.EMP WHERE CURRENT OF C1; - 从表 DSN8C10.EMP 中删除部门 E11 和 D21 的所有行。
EXEC SQL DELETE FROM DSN8C10.EMP WHERE WORKDEPT = 'E11' OR WORKDEPT = 'D21'; - 从员工表X中删除缺勤最多的员工。
EXEC SQL DELETE FROM EMP X WHERE ABSENT = (SELECT MAX(ABSENT) FROM EMP Y WHERE X.WORKDEPT = Y.WORKDEPT); - 假设光标 CS1 位于由 10 行组成的行集上,行集由表 T1 组成,则删除行集中的所有 10 行。
EXEC SQL DELETE FROM T1 WHERE CURRENT OF CS1; - 假设光标 CS1 位于由 10 行组成的行集 T1 中,请删除行集中的第四行。
EXEC SQL DELETE FROM T1 WHERE CURRENT OF CS1 FOR ROW 4 OF ROWSET; - 如果列 COL2 的值与数组INTA的基数匹配,则删除表 T1 中的行。 在DELETE语句中,INTA数组被指定为CARDINALITY函数的参数。
CREATE TYPE INTARRAY AS INTEGER ARRAY[6]; CREATE VARIABLE INTA AS INTARRAY; SET INTA = ARRAY[1, 2, 3, 4, 5]; CREATE TABLE T1 (COL1 CHAR(7), COL2 INT); INSERT INTO T1 VALUES('abc', 10); DELETE FROM T1 WHERE COL2 = CARDINALITY(INTA); - 从表 T1 中删除仅3行,其中列 C2 的值大于10。
DELETE FROM T1 WHERE C2 > 10 FETCH FIRST 3 ROWS ONLY;
