INSERT 语句
INSERT语句用于向表或视图中插入行。 如果未为视图定义“代替插入”触发器,则向视图中插入一行数据会将该行插入到视图所基于的表中。 如果定义了这样的触发器,则启用触发器。
表格或视图可以位于当前服务器上,也可以位于当前服务器可以与之建立连接的任何 Db2 子系统上。
- 价值观 形式
INSERT语句的VALUES形式用于使用提供的或引用的值向表或视图中插入单行。
- 完整选择表单
INSERT语句的fullselect形式使用来自其他表或视图的值,或同时使用来自其他表和视图的值,向表或视图中插入一行或多行。
- FOR n ROWS form
INSERT语句的FOR n ROWS形式使用提供的或引用的值向表或视图中插入多行。 虽然不是必需的,但数值可以来自宿主变量数组。
SQL过程应用程序支持这种形式的插入。 然而,由于SQL程序不支持宿主变量数组,因此只支持插入标量值。
调用 INSERT
此语句可嵌入应用程序中或者以交互方式发出。 它是可动态准备的可执行语句。
授权 INSERT
权限要求取决于语句中标识的对象是用户定义的表、允许插入的目录表还是视图:
当识别出用户定义的表时 :权限集必须至少包含以下一项:
- 插入权限在表格中
- 对表的所有权
- DBADM 数据库中包含表格的权限
- SYSADM 权限
- DATAACCESS 权限
如果数据库是隐式创建的,则数据库权限必须位于隐式数据库或 DSNDB04 上。
当识别出目录表时 :权限集必须至少包含以下一项:
- ACCESSCTRL 权限
- DATAACCESS 权限
- DBADM 目录数据库权限
安装 SYSOPR 权限
- SQLADM 权限
- SYSCTRL 权限
- SYSADM 权限
- 系统 DBADM 权限
当确定一个景观时 :特权集必须至少包含以下内容之一:
- DATAACCESS 权限
- 视图的插入权限
- SYSADM 权限
视图的所有者与表的所有者不同,可能没有视图的插入权限(或者有插入权限但不能授予他人)。 由于景观本身的性质,无法将其用于插入。 更多信息,请参阅 CREATE VIEW语句中的权限讨论。
如果INSERT语句嵌入在SELECT语句中,则权限集必须包含对表或视图的SELECT权限。
如果指定了全选,则权限集必须包含执行全选的权限。 如需了解授权规则的更多信息,请查看授权查询。
如果语句嵌入在应用程序中,则权限集是指计划或包的所有者所拥有的权限。 如果语句是动态准备的,则权限集由有效的DYNAMICRULES行为(运行、绑定、定义或调用)确定,并在表1 中进行了汇总。 (如需了解这些行为的更多信息,包括确定这些行为的DYNAMICRULES绑定选项值列表,请参阅授权ID和动态SQL。)
语法 INSERT
包括列:
数据类型:
内置类型:
隔离条款:
for-n-rows-insert:
描述 INSERT
- INTO 表名或视图名
- 标识INSERT语句的对象。 名称必须标识当前服务器上存在的表或视图。 该名称不得用于:
- 辅助表格
- 目录表
目录表
- 除非为视图上的插入操作定义了而不是触发器,否则只能以只读方式查看。 (有关只读视图的描述,请参阅 CREATE VIEW语句。)
- 由常数、表达式或标量函数导出的视图列
- 视图列是从基本表列派生而来的,就像视图中的其他列一样
- 一个实体化的查询表
- 为XML列隐式创建的表
在 IMS 或 CICS® 应用程序中,包含已识别表或视图的 Db2 子系统必须是一个支持两阶段提交(two-phase commit)的远程服务器。
- 列名,...
- 指定插入值的列。 每个名称都必须标识表或视图的列。 这些列可以以任何顺序识别,但同一列不能被识别多次。
如果扩展指标未启用,则不能识别不接受插入值的视图列。 如果扩展指示符未启用,且INSERT语句的对象是列不能接受插入值的视图,则必须指定列名列表,且该列表不能识别这些列。
如果指定了限定符,则该限定符必须有效(即表名必须是INTO关键字后指定的表或视图名称,如果为表名指定了限定符,则该限定符必须与默认限定符匹配)。省略列列表是对列表的隐式说明,其中表格(未定义为隐式隐藏)或视图的每一列均从左到右依次标识。 此列表是在报表编制时创建的,因此不包括报表编制后添加的列。
对不包含列列表的INSERT语句进行重新绑定,其效果是重新建立隐式名称列表。 因此,INSERT语句必须指定的列值数量可能会发生变化,从而导致语句重新编译时出错。 因此,最好在INSERT语句中始终指定列名。
- 包括列
- 指定当 INSERT 语句嵌套在子选择、SELECT 语句或 SELECT INTO 语句中使用的外部全查询的 FROM 子句中时,与 table-name 或 view-name 的列一起包含在 INSERT 语句的结果表中的一组列。 包含的列将附加到以表名或视图名标识的列列表的末尾。
- INCLUDE
- 介绍插入语句结果表中包含的列列表。 仅当INSERT语句嵌套在SELECT语句或SELECT INTO语句的FROM子句中时,才可使用包含的列。
- 列名
- 指定INSERT语句结果表中某列的名称,该列的名称不能与表或视图中其他列的名称相同,也不能与表名或视图名中指定的列相同。
- 数据类型
- 指定包含列的数据类型。 包含的列可以为空。
- built-in-type
- 指定内置数据类型。 有关每种内置类型的描述,请参阅 CREATE TABLE语句。
INCLUDE列中不能指定CCSID 1208和CCSID 1200子句。
- 独特类型
- 指定一种不同的类型。 列的任何长度、精度或比例属性都是通过使用CREATE TYPE语句指定的不同类型的源类型的属性。
- 超越用户价值
- 指定忽略在 VALUES 子句中指定的值,或忽略由 fullselect 为定义为 GENERATED ALWAYS 或 GENERATED BY DEFAULT 的列生成的值。 取而代之的是,系统生成的数值将覆盖用户指定的数值。
如果指定了“覆盖用户值”,则隐式或显式列列表必须包含一个定义为“始终生成”或“默认生成”的列。 例如,ROWID列、标识列或行变更时间戳列。
- VALUES 表格描述
- 以下描述适用于插入的值表单。
- VALUES
- 以数值列表的形式指定一行新内容。 VALUES子句中的值个数必须与列列表和INCLUDE子句中标识的列中的名称个数相等。 第一个值插入到列表中的第一列中,第二个值插入到第二列中,以此类推。 如果指定了多个值,则必须用括号括起。
只有在INSERT语句嵌套在SELECT语句或SELECT INTO语句的FROM子句中时,才会处理包含列的分配。
- 表达式
- 任何表达方式,如表达式中描述的那样。 表达式中不能包含列名。 如果表达式是一个宿主变量,则宿主变量可以标识一个结构。 任何指定的宿主变量或结构都必须根据宿主结构和变量的声明规则在应用程序中进行描述。
如果表达式是一个宿主变量,它可以包含一个指示变量或指示数组(在宿主结构的情况下)。
如果扩展指示器已启用,且表达式不是单个变量,则 DEFAULT (-5) 和 UNASSIGNED (-7) 的扩展指示器值不得用于该表达式。
另外:- 如果满足以下任一条件,则可以使用CAST规范:
- 目标列定义为可空。
- 目标列定义为非空且默认值为非空,CAST规范的源是一个单一的主机变量,且主机变量的数据属性(数据类型、长度、精度和比例)与CAST规范的结果相同。
- 如果全选列表中的每个表达式满足以下条件之一,则可以使用标量全选:
- 与表达式相对应的目标列被定义为可空。
- 表达式并不比引用单个宿主变量更复杂,该宿主变量的指示器设置为扩展指示器值 DEFAULT (-5) 或 UNASSIGNED (-7) ,或者表达式是一个 CAST 规范,该规范作为独立表达式是有效的。
- 如果满足以下任一条件,则可以使用CAST规范:
- 缺省值
- 指定列的默认值。 如果列是生成列,则 Db2 将为列生成一个值。
有关数据类型的默认值的信息,请参阅 CREATE TABLE语句中DEFAULT子句的描述。
- NULL
- 指定空值作为列值。 仅对可空列指定 NULL。
如果隐式或显式列列表中包含定义为“始终生成”的 ROWID、标识列或行更改时间戳列,则必须指定 DEFAULT,除非指定 OVERRIDING USER VALUE 子句,以指示将忽略任何用户指定的值,并插入系统生成的唯一值。
对于定义为“默认生成”的ROWID或标识列,您可以指定一个值。 然而,只有在ROWID列上定义了单列唯一索引,且指定的值是之前由 Db2 生成的有效行ID值时,才能将值插入到默认定义的ROWID列中。 当值被插入到默认定义的身份列中时, Db2 不会验证指定的值是否是该列的唯一值,除非该身份列具有单列唯一索引。
虽然隐式隐藏的XML值DOCID列被定义为 GENERATED ALWAYS,但您可以在显式列列表中包含DOCID列并为其指定值。 但是, Db2 将忽略该值。
- 完整选择表单说明
以下描述适用于INSERT 的全选表单。
- WITH common-table-expression
- 指定一个公共表表达式。 关于常见表表达式的解释,请参阅常见表表达式。
- 全部选择
- 以全选查询结果表的形式指定一组新行。 如果结果表为空,则SQLCODE设置为+100,SQLSTATE设置为'02000'。
INSERT语句的基本对象和fullselect或fullselect的任何子查询的基本对象可以是同一个表。 在这种情况下,在插入任何行之前,将完全评估全选。
有关“全选”的解释,请参阅 “全选 ”。
结果表中的列数必须与列列表和INCLUDE子句中指定的列数相等。 结果第一列的值插入列表的第一列,第二列的值插入第二列,以此类推。 为生成的列生成的任何值都必须符合在 VALUES 子句下为这些列描述的规则。 只有在INSERT语句嵌套在SELECT语句或SELECT INTO语句的FROM子句中时,才会处理包含列的分配。
如果指定结果列值的表达式是一个变量,则宿主变量可以包含一个指示变量。 当扩展指示变量启用时,与fullselect选择列表中的表达式相对应的目标列,如果包含扩展指示变量,且该变量的值为DEFAULT (-5) 或UNASSIGNED (-7) ,则必须定义为可空,且为以下表达式之一:- 表达式不能比引用单个宿主变量更复杂。
- 表达式必须为CAST规范,并具有以下特征:
- CAST规范的源必须是一个单一的主机变量。
- 宿主变量的数据属性(数据类型、长度、精度和范围)与转换规格的结果相同。
如果对象表是自引用表,则全选查询返回的行数不能超过一行。
- 隔离条款
- 指定执行全选时使用的隔离级别。
- WITH
- 介绍隔离级别,可以是以下值之一:
- RR
- 可重复读取
- RS
- 读取稳定性
- CS
- 光标稳定性
语句的默认隔离级别是语句所属包或计划的隔离级别,其中包隔离级别优先于计划隔离级别。 如果没有指定包隔离,则默认使用计划隔离。
- QUERYNO 整数
- 指定在EXPLAIN输出和跟踪记录中用于此SQL语句的编号。 该数字用于计划表中 QUERYNO 列,其中包含有关此 SQL 语句的信息。 这个数字也用于 SYSIBM.SYSSTMT 和 SYSIBM.SYSPACKSTMT 目录表的QUERYNO列。
如果省略该子句,则与SQL语句关联的数字就是预编译期间分配的语句编号。 因此,如果应用程序被修改并预编译,那么语句编号可能会改变。
使用QUERYNO子句为程序中的SQL语句分配唯一编号很有帮助:
- 为了简化优化提示的使用,以便选择访问路径
- 用于将计划表中的SQL语句文本与EXPLAIN输出相关联
有关启用和使用优化提示的更多信息,请参阅影响访问路径选择
有关访问计划表的信息,请参阅 《使用EXPLAIN调查SQL性能 》。
- FOR n ROWS form descriptions
以下描述适用于插入的 发送给 n 行 表单。
- 值
- 指定要插入的行的项目。 VALUES子句中的项目数量必须与隐式或显式列列表中的名称数量相等。 列表中的第一项为列表第一列提供(或多个)值。 列表中的第二项为第二列提供数值(或多个数值),以此类推。
- 表达式
- 任何表达方式,如表达式中描述的那样。 表达式中不能包含列名。 对于插入的每一行,都会为对应的列赋值表达式的值。
- 主机变量数组
- 每个宿主变量数组必须在应用程序中根据数组声明规则进行定义。 宿主变量数组包含作为插入操作目标的表列数据。 要插入的行数必须小于或等于每个宿主变量数组的维度。
可以为每个主变量数组指定可选的指示器数组。 如果任何SQLVAR的SQLTYPE表明SQLVAR可以为空,则应予以说明。 指标必须是小整数。 指示器阵列必须足够大,以便为每行输入数据提供一个指示器。
如果启用扩展指示变量,则可以在指示数组中使用 DEFAULT 或 UNASSIGNED 的扩展指示变量值。
C/C++、COBOL 和 PL/I 支持 host-variable-array。 更多信息,请参阅主机变量数组。
- 缺省值
- 指定列的默认值。 如果列是生成列,则 Db2 将为列生成一个值。
有关数据类型的默认值的信息,请参阅 CREATE TABLE语句中DEFAULT子句的描述。
- NULL
- 将空值指定为插入的每一行中列的值。 对于插入的每一行,其对应的列被赋值为空值。 仅对可空列指定 NULL。
- n行
指定要插入的行数,其中 n 是 主机变量或整数常量。 对于动态INSERT语句,可以在EXECUTE语句中指定此子句。 更多信息,请参阅 EXECUTE语句。 然而,当动态 SELECT 语句包含多个多行 INSERT 语句时,必须使用此子句。
host-variable 或 integer-constant 被赋值给一个整数 k。 如果指定了宿主变量 ,则该变量必须为精确数值类型且比例系数为零,且不得包含指示变量。 此外 ,k 必须在范围内, 0<k<=32767。k 行从指定的源数据插入到目标表中。
如果语句在加速器上运行,则仅在VALUES子句使用主机变量数组时,才支持FOR integer-constant ROWS。
如果在此子句中指定了参数标记,则必须通过关联的 EXECUTE 或 OPEN 语句的 USING 子句提供值。
- 是否为原子型继续 SQLEXCEPTION
- 指定是否应将所有行作为原子操作插入。
- ATOMIC
- 指定如果任何一行插入失败,则所有插入对数据库所做的更改(包括成功插入所做的更改)都将撤销。 这是缺省值。
- 非原子继续SQLEXCEPTION
- 指定无论该行中的任何特定插入是否失败,INSERT语句都不会撤消其他行成功插入对数据库所做的任何更改,并且会尝试插入后续行。 然而,最小原子性至少是单个插入(即部分插入无法完成),包括因INSERT语句而执行的任何触发器。
此条款仅适用于静态INSERT语句。 如果INSERT语句包含在SELECT语句中,则也不必指定此条款。 对于动态插入语句,请在准备语句中指定子句。 更多信息,请参阅 PREPARE声明。
备注 INSERT
- 插入规则:
- 插入的值必须符合以下规则。 如果执行INSERT语句时没有发生错误,或者发生了其他错误,则不会插入任何行,光标的位置也不会改变。
- 默认值。 任何列列表中未列出的列的默认值为该列的插入值。 没有默认值的列必须包含在列列表中。 同样,如果将默认值插入到视图中的任何列中,则该列将不会包含在视图中。 因此,基础表中不在视图中的所有列都必须有默认值。
- 长度。 如果列的插入值为数字,则该列必须为数字列,能够表示数字的整数部分。 如果列的插入值为字符串,则该列必须为长度属性至少与字符串长度相同的字符串列,或者如果字符串表示日期、时间或时间戳,则为日期时间列。
- 任务。 根据SQL语言元素中描述的赋值规则,将值插入到列中。
- 独特性限制。 如果已识别表或已识别视图的基表有一个或多个唯一索引,则插入到该表中的每一行都必须符合这些索引所施加的限制。
- 参考约束。 外键的每个非空插入值必须等于关系中父表父键的某个值。
- 检查约束条件。 已识别的表或已识别的视图的基表可能有一个或多个检查约束。 每行插入的内容必须符合这些约束条件。 因此,每个检查条件必须为真或未知。
- 现场和验证程序。 如果已识别的表或已识别的视图的基表具有字段或验证程序,则插入的每一行都必须符合该程序所施加的限制。
- 包含VARBINARY列的索引。 如果已识别表中的 VARBINARY 列或基于 VARBINARY 数据类型的不同类型列具有索引,则该索引列不能指定 DESC 属性。 要在已识别表格上使用SQL数据更改操作,要么删除索引,要么将列的数据类型改为二进制,然后重建索引。
- 查看和带有检查选项。 对于使用“带检查选项”定义的视图,您插入到视图中的每一行都必须符合视图的定义。 如果您命名的视图依赖于其他视图,而这些视图的定义包含“带检查选项”,则插入的行也必须符合这些视图的定义。 有关这种情况的规则说明,请参阅 CREATE VIEW语句。
对于未定义为“带检查选项”的视图,您可以插入不符合视图定义的行。 这些行不会显示在视图中,而是插入到视图的基表中。
- 省略列列表。 当省略列列表时,必须为绑定INSERT语句或(动态执行时)准备INSERT语句时表中存在的每一列指定一个值。
- 触发器。 INSERT语句可能会激活触发器。 触发器可能会根据插入的值导致其他语句被执行或引发错误条件。 如果视图的INSERT语句激活了INSTEAD OF触发器,则有效性、参照完整性以及检查约束将根据触发器中执行的数据更改进行检查,而不是根据激活触发器的视图的定义或基础表或视图的定义进行检查。当处理插入多条记录的INSERT语句的触发器时,取决于INSERT语句中有效的原子性选项:
- 原子。 插入语句作为单个语句处理。 任何语句级别的触发器都会为语句激活一次,转换表将包含所有插入的行。
- 非原子继续SQLEXCEPTION。 这些嵌件是单独加工的。 对于插入的每一行,都会处理任何语句级别的触发器,并且转换表包含插入的单独行。 当启用此选项时,如果出现错误,处理将继续,但指定的某些行将不会被插入。 在这种情况下,如果在基础表上定义了插入触发器,则语句级触发器将仅针对成功插入的行激活。
无论哪个源行出现故障,INSERT语句都不会撤销该语句对数据库所做的任何更改。 将尝试为失败行之后的行插入。 然而,原子性的最低水平至少是单个源行的原子性(也就是说,部分插入操作无法完成),包括因INSERT语句而激活的任何触发器。
- 插入XML文档:
- 当XML文档插入到包含XML索引的表中时,插入到索引中的XML值将转换为CREATE INDEX语句中指定的数据类型。 如果XML值无法转换为指定的数据类型,则XML索引将忽略该XML值,但文档仍会插入到表中。 如果为转换指定的数据类型为 DECFLOAT,则值在插入索引时会被舍入。 如果索引是唯一的,那么铸造过程中出现的舍入可能会导致重复值。
- 已插入的行数:
- 通常,INSERT语句执行完毕后,SQLCA中的SQLERRD(3)的值就是插入的行数。 SQLERRD(3)中的值不包括作为触发器结果插入的行数。
如需了解SQLCA的完整描述,包括上述声明的例外情况,请参阅 SQL通信区(SQLCA )。
- 嵌套用户定义函数或存储过程:
- INSERT语句可以隐式或显式地引用用户定义的函数或存储过程。 这被称为SQL语句嵌套。 插入语句中嵌套的用户定义函数或存储过程不得访问您要向其插入值的表。
- 锁定:
- 除非已经存在合适的锁,否则在成功插入操作后,将获取一个或多个专用锁。 在提交或回滚操作释放锁之前,只有执行插入操作的应用程序进程可以访问插入的行。 如果未将 LOB 插入该行,则使用未提交读取运行的应用程序进程也可以访问已插入的行。 锁还可以防止其他应用程序在桌面上执行操作。 然而,未提交读取的应用程序进程可以访问锁定的页面和行。
锁不会在已声明的临时表上获取。
- 在具有多层安全性的表格中插入行 :
- 当您向具有多层安全性的表格中插入行时, Db2 会根据以下规则确定该行安全标签列的值:
- 如果用户(主授权ID)具有写权限或写控制未启用,则用户可以为该行设置任何有效的安全标签。 指定的值必须分配给定义为 CHAR(8) FOR SBCS DATA NOT NULL 的列。 如果用户未指定安全标签的值或指定了 DEFAULT,则该行的安全标签将变为与用户的安全标签相同。
- 如果用户没有写权限,且写权限被启用,则该行的安全标签与用户的安全标签相同。
- 在执行行或列访问控制的表格中插入行:
- 当对一个表发出插入语句,且该表已启用行或列访问控制时,启用行权限或列掩码中指定的规则将决定是否可以插入该行。 通常情况下,这些规则基于授权ID或流程角色。 以下规则描述了在插入期间启用行权限和列掩码的使用方法:
- 插入的行不能受启用的列掩码影响,在获取行的源值时,列掩码的列会被引用。
当在计算新行的值时引用列时,如果该列具有启用的列掩码,则使用掩码值来计算新值。 如果对象表还启用了列访问控制,则用于推导新值的列掩码必须确保列掩码中定义的访问控制规则的评估将列解析为自身,而不是常量或表达式。 如果列掩码没有将列掩码设置为自身,则新值不能用于插入,并且在运行时返回错误。
如果指定了“用户优先”子句,则忽略新行中的相应值,并且上述列掩码规则不适用于这些值。
- 如果该行可以插入,并且该表有“插入前”触发器,则触发器被激活。
在触发操作中,插入的新值可以在过渡变量中修改。 当触发器返回值时,新值的最终值就是插入值。
- 插入的行必须符合启用的行权限。
当为表定义了多个启用行权限时,通过在每个启用行权限的搜索条件中应用逻辑或运算符,可以得出行访问控制搜索条件。 符合启用行权限的行是指,如果插入该行,则可以使用行访问控制搜索条件将其检索回来。
在此过程中,柱面罩不适用。
- 如果可以插入行,并且表中有“插入后”触发器,则触发器将被激活。
前面的规则不适用于包含列。 包含列受选择列表规则的约束,因为它们不是INSERT语句对象表的列。
- 插入的行不能受启用的列掩码影响,在获取行的源值时,列掩码的列会被引用。
扩展指标的使用:
启用扩展指示器时,指示器值不能为正值和0到 -7 之间的数值。 在不支持的情况下,DEFAULT和UNASSIGNED扩展指示器值不得出现。
扩展指标:
在INSERT语句中,UNASSIGNED的扩展指示器值具有将列设置为默认值的作用。 如果目标列不可更新,则只能为其分配扩展指示符值“未分配”,除非该列是定义为“始终生成”的身份列。 如果目标列是定义为“始终生成”的身份列,则必须为其指定DEFAULT关键字,或者DEFAULT或UNASSIGNED的扩展指示器值。
扩展指示器和插入触发器:
插入式触发器的激活不受扩展指示器使用的影响。 如果隐式或显式列列表中的所有列都分配了未分配或默认的扩展指示符值,则尝试插入所有列都有各自默认值的插入。 如果插入成功,则插入触发器被激活。
扩展指示器和延迟错误检查:
启用扩展指示符后,通常在报表准备期间进行的确认插入不可更新列的操作将推迟到报表执行时进行。
- 插入操作期间表空间数据压缩:
- 如果表空间定义为压缩,且数据插入到表空间中的表中,则第一行数据将以未压缩的形式存储。 当 Db2 确定的数据量被插入到表中时,压缩字典将被创建并存储在表空间中。 在创建词典后插入到表格中的行使用压缩词典进行压缩存储。
- 生成的列:
- 除非VALUES列表中的相应条目为DEFAULT或扩展指示符指定要分配的默认值,否则不应在列列表中指定定义为GENERATED ALWAYS的生成列。 指定 OVERRIDING USER VALUE 子句,以指示插入行时忽略任何用户指定的值,并使用 Db2 指定默认值。
- 将行插入系统周期时间表:
- 当一行插入到系统周期时间表中时, Db2 会为以下列分配值,如下所示:
行首列被分配一个列数据类型的值。 如果在插入时 SYSIBM.TEMPORAL_LOGICAL_TRANSACTION_TIME 内置全局变量的值为空,则使用在执行第一个数据更改语句期间读取的时钟时间来生成该值,该语句以工作单元为单位,要求将值分配给表中的行开始列或事务开始ID列,或者删除系统周期时间表中的行。 否则,在插入时,行首列的值将设为 SYSIBM.TEMPORAL_LOGICAL_TRANSACTION_TIME 内置全局变量的值。
- 行尾列被分配一个列的数据类型值。
- 交易开始ID列被分配一个单位工作量的唯一值或空值。 如果该列可以为空,则将空值分配给事务起始 ID 列。 否则,在执行第一个数据更改语句时,需要将值分配给表中的行开始列或事务开始ID列 ,此时通过读取时间戳来生成值。 当系统周期时间表中某一行被删除时,也会发生这种情况。 如果在一个SQL事务中插入多行,则事务开始ID列的值对所有行都是相同的,并且与另一个工作单元为该列生成的值不同。
如果CURRENT TEMPORAL SYSTEM_TIME特殊寄存器被设置为非空值,则INSERT语句的底层目标不能是系统周期时间表。 无论系统周期时间表是直接引用还是间接引用,此限制均适用。
- 将行插入到应用程序期间的时间表中:
- 当一行插入到应用期间的时间表中时,如果应用期间的开始列和结束列定义的期间与表中另一行的应用期间的开始列和结束列定义的期间重叠,则返回错误。
- 在启用存档的表格中插入行:
- 如果 SYSIBMADM.MOVE_TO_ARCHIVE 全局变量的值为“Y”,则指定启用归档的表作为目标的INSERT语句将返回错误。 否则,如果此全局变量未设置为“Y”,则可以将启用了归档的表指定为INSERT语句的目标。 在这种情况下,关联的归档表的内容不会受到影响。
当系统周期临时表或应用程序周期临时表也被引用时,数据更改语句不得引用启用存档的表。
- 插入无列列表:
- 没有列列表的插入语句不包括隐式隐藏的列,因此定义为隐式隐藏的列必须具有定义的默认值。
- 在目录表中插入一行 SYSIBM.SYSSTRINGS:
- 如果对象表为 SYSIBM.SYSSTRINGS ,则只能指定某些值,如指定转换程序中所述。
- 使用日期时间寄存器时的日期时间表示:
- 正如日期时间特殊寄存器中所述,当在单个 SQL 语句中隐式或显式指定两个或多个日期时间寄存器时,它们表示同一时间点。 插入多行时也是如此。 当原子(ATOMIC)对插入(INSERT)语句生效时,特殊寄存器会进行一次评估,以处理该语句。 如果NOT ATOMIC生效,则会在处理每行源数据时评估特殊寄存器。
- INSERT语句的非原子处理:
- 当指定NOT ATOMIC时,源数据行将单独处理。 在处理每行源数据时,INSERT语句中任何对特殊寄存器、序列表达式和函数的引用都会被计算。在处理每行源数据时,语句级触发器会被激活。
如果在插入一行时发生一个或多个错误,处理将继续进行。 错误发生时插入的行没有插入。 执行继续进行,插入下一行,在执行多行插入语句期间所做的任何其他更改都不会被撤销。 然而,插入单独一行是一个原子操作。
- 多行插入语句的诊断信息:
- 一个多行的INSERT语句可能会遇到多个条件。 这些条件可能是错误或警告。 使用GET DIAGNOSTICS语句获取INSERT语句中遇到的所有条件的信息。 更多信息请参阅 “获取诊断”声明。
如果在插入行时出现警告,处理将继续。
当非原子INSERT语句出现多个错误或警告时,可使用GET DIAGNOSTICS语句获取每行的诊断信息。 SQLSTATE和SQLCODE反映了INSERT语句执行期间发生的情况:
- SQLSTATE 01659,SQLCODE +252。 所有行都已插入,但出现了一个或多个警告。
- SQLSTATE 22529,SQLCODE -253。 至少成功插入了一行,但出现了一个或多个错误。 可能还出现过一些警告。
- SQLSTATE 22530,SQLCODE -254。 没有插入任何行。 尝试插入多行数据时发生了一个或多个错误。
- SQLSTATE 429BI ,SQLCODE -20252。 Db2 能够记录的错误数已超出上限。 语句处理结束。
当ATOMIC生效时,如果插入值违反了任何约束,或者在插入一行时发生任何其他错误,则执行多行INSERT语句期间所做的所有更改都会撤销。 SQLCA会显示最后一次遇到的警告。
在插入多行数据(包括原子和非原子数据)的INSERT语句执行后,信息将通过SQLCA返回给程序。 SQLCA的设置如下:
- SQLCODE包含SQLCODE。
- SQLSTATE包含SQLSTATE。
- SQLERRD3 包含实际插入的行数。 SQLERRD3 是插入的行数,如果少于请求的行数,则表明发生了错误。
- 如果在任何一次插入操作中设置了SQLWARN标志,则该标志会被设置。
SQLCA用于返回在多行插入期间发现的错误和警告信息。 如果提供了指示器数组,则指示器变量值用于确定是否使用主机变量数组中的值或NULL。 SQLSTATE包含上次数据映射错误的警告。
- 指定动态多行插入语句的行数:
- 在使用主机变量数组动态多行插入语句指定要插入的行数时,请注意以下几点:
- FOR n ROWS子句可以作为INSERT语句的一部分或EXECUTE语句的一部分,但不能同时作为两部分
- 在INSERT语句中,您可以在FOR n ROWS子句中指定一个数字常量,以指示要插入的行数,或者指定一个参数标记,以指示将通过关联的EXECUTE或OPEN语句指定行数。 SELECT语句中包含的多行INSERT语句必须包含FOR n ROWS子句。
- 在执行语句中,当SELECT语句中不包含动态INSERT语句时,可以使用EXECUTE语句的FOR n ROWS子句或USING子句指定行数:
- 如果INSERT语句不包含FOR n ROWS子句,则可以在EXECUTE语句的FOR n ROWS子句中用常数或主机变量指定要插入的行数。
- 如果参数标记被指定为INSERT语句中FOR n ROWS子句的一部分,则必须使用EXECUTE语句的USING子句指定行数的值。
- 在OPEN语句中,当一个动态SELECT语句包含一个或多个带有参数标记的FOR n ROWS子句的INSERT语句时,必须使用OPEN语句的USING子句来指定要插入的行数(即参数标记的值)。
- DRDA对多行INSERT语句的考虑:
- Db2 for z/OS 使用主机变量数组执行单个多行插入语句时,将用户数据和控制信息的大小限制为 (LOB除外,LOB在不同的数据流中处理)。 10M
当 Db2 for z/OS 请求者执行多行INSERT语句时,在某些情况下,请求者插入的行数可能未知。 这些情况包括:
- 对于静态或动态INSERT语句,FOR n ROWS 子句包含常量n的值。
- 在动态插入语句的EXECUTE语句的USING子句中指定宿主变量。
无论哪种情况,如果插入的行数未知,请求者可能会向服务器发送超出所需的数据量。 实际插入的行数是正确的,因为服务器知道要插入的正确行数。 然而,性能可能会受到不利影响。 请考虑以下方案:
在请求者处,当执行此语句时,插入的行数(5)未知。 因此,请求者将向服务器发送10个serial_num值和10个name值(因为可以无错误插入的最大行数为10,这是最小主机变量数组的大小)。... long serial_num [10]; struct { short len; char data [18]; }name [20] ... EXEC SQL INSERT INTO T1 VALUES (:serial_num, :name) FOR 5 ROWS请使用以下编程技巧来避免或减少问题:
- 在INSERT语句的FOR n ROWS子句中,避免对n 使用常量。 对于静态INSERT语句,此技术可确保请求者知道 n的值。
- 对于动态INSERT语句,请在EXECUTE语句中使用USING DESCRIPTOR子句,而不是 USING host-variables 子句。 如果在EXECUTE语句中使用USING DESCRIPTOR子句,则必须在DESCRIPTOR中指定“n”的值。
- 如果上述方法均不可行:
- 声明您的宿主变量数组尽可能小,或者在描述符中注明宿主变量数组的大小为“n”。 这样可避免将大量不会用到的服务器变量数组条目发送到服务器。
- 确保将不同长度的字符串数组初始化为0(零)。 这样可减少发送到服务器的数据量。
- 确保十进制主机变量数组被初始化为有效值。 这样,如果请求者遇到无效的小数数据,就不会返回负面的SQLCODE。
- 同一工作单元中的其他SQL语句:
- 在同一工作单元中,以下语句不能紧跟在INSERT语句之后:
- ALTER TABLE语句,用于更改列的数据类型(ALTER COLUMN SET DATA TYPE)
- ALTER INDEX语句,用于更改具有不同长度列的索引的填充属性(从PADDED更改为NOT PADDED,反之亦然)
- CREATE TABLE语句用于创建仅包含加速器的表。
- INSERT、UPDATE或DELETE语句,用于从其他加速器更新仅加速器表。
INSERT语句示例
- 假设您想在NEWDEPT表中添加新的一行。 您可以使用以下INSERT语句。
INSERT INTO NEWDEPT (DEPTNO, DEPTNAME, MGRNO, ADMRDEPT) VALUES ('E31', 'PUBLISHING', '000020', 'D11');将新部门行插入NEWDEPT表后,您可以使用以下SELECT语句查看修改后的表。
SELECT * FROM NEWDEPT WHERE DEPTNO LIKE 'E%' ORDER BY DEPTNO;结果表为您显示了为部门 E31 插入的新部门行,以及任何以字母 E 开头的现有部门。
DEPTNO DEPTNAME MGRNO ADMRDEPT ====== ================ ====== ======== E21 SOFTWARE SUPPORT ------ D11 E31 PUBLISHING 000020 D11 - 以下语句将值插入到 DSN8C10.EMP 示例表的单行中。
INSERT INTO DSN8C10.EMP VALUES ('000205','MARY','T','SMITH','D11','2866', '1981-08-10','ANALYST',16,'F','1956-05-22', 16345,500,2300); 假设 SMITH.TEMPEMPL 是一个已创建的临时表。 下面的语句将示例表 DSN8C10.EMP 中的数据填充到表中。
INSERT INTO SMITH.TEMPEMPL SELECT * FROM DSN8C10.EMP;假设 SESSION.TEMPEMPL 是一个已声明的临时表。 以下语句将部门 D11 的数据填充到示例表 DSN8C10.EMP 中。
INSERT INTO SESSION.TEMPEMPL SELECT * FROM DSN8C10.EMP WHERE WORKDEPT='D11';以下语句在示例表 DSN8C10.EMP_PHOTO_RESUME 中插入一行。 将列 EMPNO 的值设置为主机变量 HV_ENUM 中的值。 让列 EMP_ROWID 的值生成,因为它是用行 ID 数据类型和子句 GENERATED ALWAYS 定义的。
INSERT INTO DSN8C10.EMP_PHOTO_RESUME(EMPNO, EMP_ROWID) VALUES (:HV_ENUM, DEFAULT);您只能将用户指定的值插入到定义为“默认生成”而非“始终生成”的 ROWID 列中。 因此,在上面的示例中,如果您尝试将值插入到 EMP_ROWID 中,而不是指定 DEFAULT,除非您同时指定 OVERRIDING USER VALUE,否则语句将失败。 对于定义为“始终生成”的列,OVERRIDING USER VALUE子句会导致 Db2 忽略任何用户指定的值,并生成一个值。
例如,假设您要将 DSN8C10.EMP_PHOTO_RESUME 中的行复制到另一个定义类似的表(两个表都有一个定义为 GENERATED ALWAYS 的 ROWID 列)。 对于以下INSERT语句,OVERRIDING USER VALUE子句导致 Db2 忽略 DSN8C10.EMP_PHOTO_RESUME中的 EMP_ROWID列值,并为 B.EMP_PHOTO_RESUME 中的相应ROWID列生成值。
INSERT INTO B.EMP_PHOTO_RESUME OVERRIDING USER VALUE SELECT * FROM DSN8C10.EMP_PHOTO_RESUME;假设 T1 表格有一列。 以下语句在 T1 表中插入变量(
:hv)数量的数据行。 要插入的值以主机变量数组(:hva)的形式提供。在本例中,:hva表示主机变量数组,:hvind表示指示变量数组。EXEC SQL INSERT INTO T1 VALUES (:hva:hvind) FOR :hv ROWS ATOMIC;- 假设 T2 表有2列, C1 是SMALL INTEGER列, C2 是INTEGER列。 以下语句在 T2 表中插入10行数据。 待插入的值在主机变量数组 :hva1 (整数数组)和 :hva2 (小数(15,0)数组)中提供。 :hva1 和 :hva2 的数据值如下表所示:
表 1. :hva1 的数据值和 :hva2 数组条目 :hva1 :hva2 1 1 32768 2 -12 90000 3 79 2 4 32768 19 5 8 36 6 5 24 7 400 36 8 73 4000000000 9 -200 2000000000 10 35 88 EXEC SQL INSERT INTO T2 (C1, C2) VALUES (:hva1:hvind1, :hva2:hvind2) FOR 10 ROWS NOT ATOMIC CONTINUE ON SQLEXCEPTION;执行INSERT语句后,SQLCA中会出现以下信息:
SQLCODE = -253 SQLSTATE = 22529 SQLERRD3 = 8虽然尝试插入10行,但只插入8行数据。 由于指定了NOT ATOMIC CONTINUE ON SQLEXCEPTION,在第一次插入失败后继续处理。 例如,您可以使用GET DIAGNOSTICS语句来获取更多信息。
该语句的结果是num_rows = 8和num_cond = 2(2个条件)。
GET DIAGNOSTICS :num_rows = ROW_COUNT, :num_cond = NUMBER;该语句的结果为:sqlstate = 22003,sqlcode = -302,row_num = 4。
GET DIAGNOSTICS CONDITION 2 :sqlstate = RETURNED_SQLSTATE, :sqlcode = DB2_RETURNED_SQLCODE, :row_num = DB2_ROW_NUMBER;该语句的结果为:sqlstate = 22003,sqlcode = -302,row_num = 8。
GET DIAGNOSTICS CONDITION 1 :sqlstate = RETURNED_SQLSTATE, :sqlcode = DB2_RETURNED_SQLCODE, :row_num = DB2_ROW_NUMBER; 假设上表 T2 有两列。 C1 是SMALL INTEGER列,而 是INTEGER列。 C2 以下语句向 T2 表中插入8行数据。 待插入的值在主机变量数组 :hva1 (整数数组)和 :hva2 (小数(15,0)数组)中提供 :hva1 和 :hva2 的数据值如表1 所示。
EXEC SQL INSERT INTO T2 (C1, C2) VALUES (:hva1:hvind1, :hva2:hvind2) FOR 8 ROWS NOT ATOMIC CONTINUE ON SQLEXCEPTION;执行INSERT语句后,SQLCA中会出现以下信息:
SQLCODE = -253 SQLSTATE = 22529 SQLERRD3 = 6虽然尝试插入8行,但只插入6行数据。 由于指定了NOT ATOMIC CONTINUE ON SQLEXCEPTION,在第一次插入失败后继续处理。 您可以使用GET DIAGNOSTICS语句来获取更多信息。 例如,以下语句的结果为num_rows = 68和num_cond = 2(2个条件)。
GET DIAGNOSTICS :num_rows = ROW_COUNT, :num_cond = NUMBER;以下语句的结果是:sqlstate = 22003,sqlcode = -302,row_num = 4。
GET DIAGNOSTICS CONDITION 2 :sqlstate = RETURNED_SQLSTATE, :sqlcode = DB2_RETURNED_SQLCODE, :row_num = DB2_ROW_NUMBER;以下语句的结果为:sqlstate = 22003,sqlcode = -302,row_num = 8。
GET DIAGNOSTICS CONDITION 1 :sqlstate = RETURNED_SQLSTATE, :sqlcode = DB2_RETURNED_SQLCODE, :row_num = DB2_ROW_NUMBER;假设表 T1 有两列。 在 T1 中插入一个可变数字(
:hvn)或行。 要插入的值位于主机变量数组:hva和:hvb中。 在这个示例中,INSERT语句包含在游标 CS1 的SELECT语句中。 SELECT语句在WHERE子句中使用了另外两个输入主机变量(:hv1和:hv2)。 可以使用静态或动态INSERT语句。-- Static INSERT statement: DECLARE CS1 CURSOR WITH ROWSET POSITIONING FOR SELECT * FROM FINAL TABLE (INSERT INTO T1 VALUES (:hva, :hvb) FOR :hvn ROWS) WHERE C1 > :hv1 AND C2 < :hv2; OPEN CS1; -- Dynamic INSERT statement: PREPARE INSSTMT FROM 'SELECT * FROM FINAL TABLE (INSERT INTO T1 VALUES ( ? , ? ) FOR ? ROWS) WHERE C1 > ? AND C2 < ?'; DECLARE CS1 CURSOR WITH ROWSET POSITIONING FOR :INSSTMT; OPEN CS1 USING :hva, :hvb, :hvn, :hv1, :hv2; (or OPEN CS1 USING DESCRIPTOR ...)如果使用描述符指定多行INSERT语句的主变量数组,则该描述符(SQLDA)必须描述语句中的所有输入主变量,并且SQLDA中的条目顺序应与语句中FOR n ROWS子句的主变量、主变量数组和值的顺序相同。 例如,根据上述语句,描述符中的SQLVAR条目必须按以下顺序分配:
:hvn, :hva, :hvb, :hv1, hv2。 此外,主机变量数组的 SQLVAR 条目必须在 SQLDA 中标记为列数组(通过在主机变量的 SQLNAME 字段中指定一个特殊值),行数的 SQLVAR 条目必须在 SQLDA 中标记(通过在主机变量的 SQLNAME 字段中指定另一个特殊值)。- 在表格 T1 中插入一行。 该行包含列 COL1 的值“xyz”,以及列 COL2 的数组INTA的基数。

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 ('xyz', CARDINALITY(INTA));
将数组CHARA和INTA中的值插入表 T1。 对于 T1 行,CHARA数组的值用于 COL1 列,INTA数组的值与相同的数组索引用于 COL2 列。

CREATE TYPE INTARRAY AS INTEGER ARRAY[10]; CREATE TYPE CHARARRAY AS CHAR(7) ARRAY[10]; CREATE VARIABLE INTA AS INTARRAY; CREATE VARIABLE CHARA AS CHARARRAY; SET INTA = ARRAY[1, 2, 3, 4, 5]; SET CHARA = ARRAY['a', 'b', 'c', 'd']; CREATE TABLE T1 (COL1 CHAR(7), COL2 INT); INSERT INTO T1 SELECT * FROM UNNEST(CHARA, INTA) AS (COL1, COL2);
- 在表格 T1 中插入三行数据。 对于每插入的一行,将INTA数组变量中第十个元素的值赋给 COL1 列。

CREATE TYPE INTARRAY AS INTEGER ARRAY[10]; CREATE VARIABLE INTA AS INTARRAY; CREATE VARIABLE VAR1 AS INTEGER; CREATE VARIABLE VAR2 AS INTEGER; SET INTA = ARRAY[10, 20, 30, 40, 50, 60, 70, 80, 90, 100]; CREATE TABLE T1 (COL1 INT, COL2 CHAR(10)); SET VAR1 = 10; SET VAR2 = 3; -- Perform a multiple row insert (specifying a FOR n ROWS clause). -- The value to be inserted is specified by a reference to an array element. INSERT INTO T1 (COL1) VALUES(INTA[VAR1]) FOR VAR2 ROWS;
这些操作的结果是,在 COL1 列中为三行分配了100的值。
