INSERT 语句
INSERT 语句将行插入到表,昵称或视图中,或者插入到指定全查询的底层表,昵称或视图中。
将行插入昵称会将该行插入昵称所引用的数据源对象中。 如果没有为此视图上的插入操作定义 INSTEAD OF 触发器,那么将行插入到视图中还会将该行插入到视图所基于的表中。 如果定义了此类触发器,那么将改为执行该触发器。
调用
此语句可以嵌入在应用程序中,也可通过动态 SQL 语句来发出。 它是可动态准备的可执行语句。
权限
- 对目标表,视图或昵称的 INSERT 特权
- 对目标表,视图或昵称的 CONTROL 特权
- 对包含目标表,视图或昵称的模式的 INSERTIN 特权
- 对包含目标表,视图或昵称的模式的模式 DATAACCESS 权限
- DATAACCESS 权限
- SELECT 特权
- CONTROL 特权
- 对包含表,视图或昵称的模式的 SELECTIN 特权
- 对包含表,视图或昵称的模式的模式 DATAACCESS 权限
- DATAACCESS 权限
不会针对静态 INSERT 语句检查 GROUP 特权。
如果插入操作的目标是昵称,那么在数据源上执行语句之前,不会考虑对该对象的特权。 此时,用于连接到数据源的授权标识必须具有对数据源上的对象执行的操作所需的特权。 可以将语句的授权标识映射到数据源上的其他授权标识。
语法
描述
- INTO table-name, view-name, nickname或 (全查询)
- 标识插入操作的对象。 该名称必须标识下列其中一个对象:
- 应用程序服务器上存在的表,视图或昵称
- 使用 remote-object-name 指定的远程服务器上的表或视图
如果插入操作的对象是全查询,那么该全查询必须可插入,如 CREATE VIEW 语句的描述中的
可插入视图
注释项中所定义。如果插入操作的对象是昵称,那么不得使用 DEFAULT 和 UNASSIGNED 的扩展指示符变量值 (SQLSTATE 22539)。
如果此视图上的插入操作不存在 INSTEAD OF 触发器,那么无法将值插入到派生自以下元素的视图列中:- 常量、表达式或标量函数
- 基本表列与视图的某个其他列相同
如果插入操作的对象是具有此类列的视图,那么必须指定列名的列表,并且该列表不得标识这些列。
可以将行插入到使用 UNION ALL 定义的视图 或全查询 中,前提是该行正好满足其中一个底层基本表的检查约束。 如果某行满足多个表的检查约束,或者根本没有表,那么将返回错误 (SQLSTATE 23513)。
如果视图的任何基本表包含前触发器,前触发器包含 UPDATE , DELETE 或 INSERT 操作,或者调用任何包含此类操作的例程 (SQLSTATE 42987) ,那么不能将行插入到使用 UNION ALL 定义的视图或全查询中。
- (column-name,...)
- 指定为其提供插入值的列。 每个名称都必须标识指定表,视图或昵称的列,或全查询中的列。 同一列不能被标识多次。 如果未启用扩展指示符变量,那么不能识别无法接受插入值的列 (例如,基于表达式的列)。
省略列列表是列表的隐式规范,其中表 (未隐式隐藏) 或视图的每个列或全查询的选择列表中的每个项按从左到右顺序标识。 此列表是在准备语句时建立的,因此不包括在准备语句后添加到表中的列。
- include-columns
- 指定 INSERT 语句的中间结果表中包含的一组列以及 table-name 或 view-name的列 (当它嵌套在全查询的 FROM 子句中时)。 include-columns 附加在为 table-name 或 view-name指定的列列表的末尾。
- INCLUDE
- 指定要包含在 INSERT 语句的中间结果表中的列的列表。 仅当 INSERT 语句嵌套在全查询的 FROM 子句中时,才能指定此子句。
- 列名称
- 指定 INSERT 语句的中间结果表的列。 该名称不能与另一个包含列的名称相同,也不能与 table-name 或 view-name 中的列的名称相同 (SQLSTATE 42711)。
- data-type
- 指定包含列的数据类型。 数据类型必须是 CREATE TABLE 语句支持的数据类型。
- 值
- 引入要插入的一个或多个值行。
VALUES 子句中指定的每一行都必须可分配给 隐式或显式列列表以及 INCLUDE 子句中标识的列,除非使用了 行变量。 当指定了 括号中的行值列表时, 第一个值将插入到列表中的第一列中,第二个值将插入到第二列中,依此类推。 当指定 行 表达式 时,行类型中的字段数必须与隐式或显式列列表中的名称数匹配。
- expression
- 表达式 可以是
表达式
主题中定义的任何表达式。 如果 expression 是行类型,那么它不得出现在括号中。 如果 expression 是变量,那么主变量可以包含指示符变量,对于主结构,可以包含为扩展指示符变量启用的指示符数组。 如果启用了扩展指示符变量,那么当下列任一语句为 true 时,不得使用缺省 (-5) 或未分配 (-7) 的扩展指示符变量值 (SQLSTATE 22539):- 此表达式比具有显式强制转型的单个主变量更复杂
- 目标列的数据类型为结构化类型
- NULL
- 指定空值,并且只应为可空列指定。
- 缺省值
- 指定将使用缺省值。 指定 DEFAULT 的结果取决于定义列的方式,如下所示:
- 如果根据表达式将列定义为生成的列,那么系统将根据该表达式生成列值。
- 如果使用 IDENTITY 子句,那么值由数据库管理器生成。
- 如果使用 ROW CHANGE TIMESTAMP 子句,那么数据库管理器将生成每个插入行的值作为数据库分区中表分区唯一的时间戳记。
- 如果使用 WITH DEFAULT 子句,那么插入的值是针对列定义的 (请参阅
CREATE TABLE
中的 default-clause )。 - 如果使用 NOT NULL 子句,并且未使用 GENERATED 子句,或者未使用 WITH DEFAULT 子句或使用 DEFAULT NULL ,那么不能对该列指定 DEFAULT 关键字 (SQLSTATE 23502)。
- 插入昵称时,仅当数据源在其查询语言语法中支持 DEFAULT 关键字时,才会将 DEFAULT 关键字通过 INSERT 语句传递到数据源。
- row-expression
- 指定不包含列名的 "行表达式" 中描述的类型的任何行表达式。 行中的字段数必须与插入的目标相匹配,并且每个字段必须可分配给相应的列。
- WITH common-table-expression
- 定义一个公共表表达式,以便与下面的全查询配合使用。
- fullselect
- 以全查询结果表的形式指定一组新行。 可能有一个,多个或无。 如果结果表为空,那么 SQLCODE 设置为 +100 , SQLSTATE 设置为 "02000"。
当 INSERT 的基本对象与全查询或全查询的任何子查询的基本对象是同一个表时,将在插入任何行之前对全查询进行完全求值。
结果表中的列数必须等于列列表中的名称数。 结果的第一列的值插入列表中的第一列,第二列中的第二个值,依此类推。
如果指定结果列值的表达式是变量,那么主变量可以包含为扩展指示符变量启用的指示符变量。 如果已启用扩展指示符变量,并且表达式超过单个主变量或正在显式强制类型转换的主变量,那么不得使用缺省或未分配的扩展指示符变量值 (SQLSTATE 22539)。 缺省值或未分配值的影响将应用于 全查询的相应目标列。
- WITH
- 指定执行语句的隔离级别。
- RR
- 可重复读取
- RS
- 读稳定性
- CS
- 游标稳定性
- UR
- 未落实的读
规则
- 触发器: INSERT 语句可能导致执行触发器。 触发器可能导致执行其他语句,或者可能根据插入的值提出错误条件。 如果对视图的插入操作导致 INSTEAD OF 触发器触发,那么将根据触发器中执行的更新而不是导致触发器触发的视图或其底层表来检查有效性,引用完整性和约束。
- 缺省值: 在列列表中未包含的任何列中插入的值都是该列的缺省值或空值。 不允许空值且未使用 NOT NULL WITH DEFAULT 定义的列必须包含在列列表中。 同样,如果插入到视图中,那么插入到不在视图中的基本表的任何列中的值都是该列的缺省值或空值。 因此,不在视图中的基本表的所有列都必须具有缺省值或允许空值。 可以插入到使用 GENERATED ALWAYS 子句定义的生成列中的唯一值是 DEFAULT (SQLSTATE 428C9)。
- 长度: 如果列的插入值是数字,那么该列必须是具有表示该数字的整数部分的容量的数字列。 如果列的插入值是字符串,那么该列必须是长度属性至少与字符串长度一样大的字符串列,如果该字符串表示日期,时间或时间戳记,那么该列必须是日期时间列。
- 分配: 将根据特定分配规则向列分配 "插入" 值。
- 有效性: 如果指定的表或指定的视图的基本表具有一个或多个唯一索引,那么插入到表中的每一行都必须符合这些索引施加的约束。 如果指定了其定义包含 WITH CHECK OPTION 的视图,那么插入到该视图中的每一行都必须符合该视图的定义。 有关管理此情境的规则的说明,请参阅
CREATE VIEW
。 - 引用完整性: 对于在表上定义的每个约束,外键的每个非空插入值必须等于父表的主键值。
- 检查约束: 插入值必须满足对表定义的检查约束的检查条件。 对定义了检查约束的表执行 INSERT 时,将针对插入的每行对约束条件求值一次。
- XML 值: 插入到 XML 列中的值必须是格式正确的 XML 文档 (SQLSTATE 2200M)。
- 安全策略: 如果标识的表或标识的视图的基本表受安全策略保护,那么会话授权标识必须具有基于标签的访问控制 (LBAC) 凭证,这些凭证允许:
- 对显式提供其数据值的所有受保护列的写访问权 (SQLSTATE 42512)
- 对带 RESTRICT NOT AUTHORIZED WRITE SECURITY LABEL 选项创建的安全策略的 DB2SECURITYLABEL 列提供的任何显式值的写访问权 (SQLSTATE 23523)
如果对 DB2SECURITYLABEL 列使用隐式值,则会话授权标识还必须被授予安全标签以获取安全策略的写访问权,(SQLSTATE 23523),这可能在以下情况下发生:
- 未显式提供 DB2SECURITYLABEL 列的值
- 已明确提供 DB2SECURITYLABEL 列的值,但会话授权标识没有对该值的写访问权,并且安全策略是带 OVERRIDE NOT AUTHORIZED WRITE SECURITY LABEL 选项创建的
- 使用扩展指示符变量:如果启用,那么不能输入 -1 到 -7 范围内的负指示符变量值 (SQLSTATE 22010)。 此外,如果已启用,那么扩展指示符变量值 default 和 unassigned 不能出现在不受支持的上下文中 (SQLSTATE 22539)。
- 扩展指示符变量: 在 INSERT 语句中,值 unassigned 具有将列设置为其缺省值的效果。
如果目标列是定义为 GENERATED ALWAYS 的列,则它必须被分配 DEFAULT 关键字,或基于扩展指示符变量的值 default 或 unassigned (SQLSTATE 428C9)。
注意
- 执行 INSERT 语句后, SQLCA 的 SQLERRD (3) 部分的第三个变量的值指示传递给插入操作的行数。 在 SQL 过程语句的上下文中,可以使用 GET DIAGNOSTICS 语句的 ROW_COUNT 变量来检索该值。 SQLERRD (5) 包含所有触发的插入,更新和删除操作的计数。
- 除非已存在相应的锁定,否则将在成功执行 INSERT 语句时获取一个或多个互斥锁定。 在释放锁定之前,只能通过以下方式访问插入的行:
- 执行插入的应用程序进程。
- 另一个通过只读游标, SELECT INTO 语句或子查询中使用的子查询使用隔离级别 UR 的应用程序进程。
- 有关锁定的更多信息,请参阅 COMMIT , ROLLBACK 和 LOCK TABLE 语句的描述。
- 如果应用程序正在对分区数据库运行,并且它与选项 INSERT BUF 绑定,那么可以缓冲带有未使用 EXECUTE IMMEDIATE 处理的 VALUES 语句的 INSERT。 假定正在应用程序逻辑中的循环内处理此类 INSERT 语句。 它尝试在一个或多个缓冲区中缓冲新行值,而不是执行语句以完成。 因此,稍后会执行将行实际插入到表中的操作,这与应用程序的 INSERT 逻辑是异步的。 请注意,此异步插入可能会导致在应用程序中 INSERT 之后的其他一些 SQL 语句上返回与 INSERT 相关的错误。
这有可能显着提高 INSERT 性能,但由于错误处理的异步性质,最好与干净数据配合使用。
- 将行插入到具有标识列的表中时,将为该标识列生成值。
- 对于 GENERATED ALWAYS 标识列,将始终生成值。
- 对于 GENERATED BY DEFAULT 列,如果未显式指定值 (使用 VALUES 子句或子查询) ,那么将生成值。
- 为用户定义的单值类型标识列插入值时,将在源类型中完成整个计算,并将结果强制转换为单值类型,然后再将该值实际分配给该列。 (在计算之前,不会将先前值强制转换为源类型。)
- 插入到 GENERATED ALWAYS 标识列时,将始终为该列生成值,并且用户在插入时不得指定值。 如果 GENERATED ALWAYS 标识列列示在 INSERT 语句的列列表中,并且 VALUES 子句中包含非 DEFAULT 值,那么将发生错误 (SQLSTATE 428C9)。例如,假定 EMPID 定义为 GENERATED ALWAYS 标识列,那么命令:
将导致错误。INSERT INTO T2 (EMPID, EMPNAME, EMPADDR) VALUES (:hv_valid_emp_id, :hv_name, :hv_addr) - 插入到 GENERATED ALWAYS ROW CHANGE TIMESTAMP 列时,将始终为该列生成值,并且用户在插入时不得指定值 (SQLSTATE 428C9)。 对于在数据库分区上插入的每一行,生成的值都是唯一的。
- 当插入到 GENERATED BY DEFAULT 列时,可以在 VALUES 子句中或从子查询中指定该列的实际值。 但是,在 VALUES 子句中指定值时,数据库管理器不会对该值执行任何验证。 要保证 IDENTITY 列 值的唯一性,必须在标识列上创建唯一索引。当插入到具有 GENERATED BY DEFAULT 标识列的表中,而不指定列列表时, VALUES 子句可以指定 DEFAULT 关键字来表示标识列的值。 在这种情况下,将生成标识列的值。
在此示例中, EMPID 定义为标识列,因此插入到此列中的值由数据库管理器生成。INSERT INTO T2 (EMPID, EMPNAME, EMPADDR) VALUES (DEFAULT, :hv_name, :hv_addr) - 使用子查询插入标识列的规则与使用 VALUES 子句插入的规则类似。 仅当标识列定义为 GENERATED BY DEFAULT 时,才能指定标识列的值。例如,假定 T1 和 T2 是具有相同定义的表,这两个表都包含列 intcol1 和 identcol2 (这两个列都是类型 INTEGER ,第二列具有 identity 属性)。 请考虑以下插入:
此示例在逻辑上等效于:INSERT INTO T2 SELECT * FROM T1
在这两种情况下, INSERT 语句都在为 T2的标识列提供显式值。 可以为标识列提供此显式规范的值,但 T2 中的标识列必须定义为 GENERATED BY DEFAULT。 否则,将产生错误 (SQLSTATE 428C9)。INSERT INTO T2 (intcol1,identcol2) SELECT intcol1, identcol2 FROM T1如果存在具有定义为 GENERATED ALWAYS 标识的列的表,那么仍可以从具有相同定义的表中传播所有其他列。 例如,给定先前描述的示例表 T1 和 T2 ,可以使用以下 SQL 将 intcol1 值从 T1 传播到 T2 :
请注意,由于未在列表中指定 identcol2 ,因此将使用其缺省 (生成) 值进行填充。INSERT INTO T2 (intcol1) SELECT intcol1 FROM T1 - 当将行插入到单列表中,其中该列定义为 GENERATED ALWAYS 标识列或 ROW CHANGE TIMESTAMP 列时,可以使用 DEFAULT 关键字指定 VALUES 子句。 在这种情况下,应用程序不会为表提供任何值,并且数据库管理器会为标识或 ROW CHANGE TIMESTAMP 列生成值。
假定该列具有 identity 属性的同一单列表,要使用单个 INSERT 语句插入多行,可以使用以下 INSERT 语句:INSERT INTO IDTABLE VALUES(DEFAULT)INSERT INTO IDTABLE VALUES (DEFAULT), (DEFAULT), (DEFAULT), (DEFAULT) - 生成标识列的值时,将使用生成的值; 下次需要值时,将生成新值。 即使涉及标识列的 INSERT 语句失败或已回滚,也是如此。
例如,假定已在标识列上创建唯一索引。 如果在生成标识列的值时检测到重复键违例,那么会发生错误 (SQLSTATE 23505) ,并且会将为该标识列生成的值视为已使用。 当标识列定义为 GENERATED BY DEFAULT 并且系统尝试生成新值,但用户在先前的 INSERT 语句中显式指定了标识列的值时,可能会发生此情况。 在这种情况下,重新发出相同的 INSERT 语句可能会导致成功。 将生成标识列的下一个值,并且此下一个值可能是唯一的,并且此 INSERT 语句将成功。
- 如果在生成标识列的值时超过了标识列的最大值 (或降序的最小值) ,那么会发生错误 (SQLSTATE 23522)。 在此情况下,用户必须使用具有较大范围的标识列 (即,更改列的数据类型或增量值以允许更大范围的值) 的 DROP 和 CREATE 新表。
例如,可能已使用 SMALLINT 数据类型定义了标识列,并且该列最终耗尽了可分配的值。 要将标识列重新定义为 INTEGER ,将需要卸载数据,必须删除该表并使用该列的新定义重新创建该表,然后将重新装入数据。 当重新定义表时,它需要为标识列指定 START WITH 值,以便生成的下一个值将是原始序列中的下一个值。 要确定结束值,请在卸载数据之前使用标识列的 MAX (对于升序) 或标识列的 MIN (对于降序) 发出查询。
- 扩展指示符变量和插入触发器: 使用扩展指示符变量不会导致激活插入触发器的任何更改。 如果隐式或显式列列表中的所有列都已分配到基于扩展指示符变量的值 unassigned 或 default ,那么将尝试插入,其中所有列都具有各自的缺省值,如果成功,将激活插入触发器。
- 扩展指示符变量和延迟错误检查: 当启用扩展指示符变量时,将延迟到语句执行时进行验证,否则将在语句准备过程中执行验证,以识别不可更新的列中的插入。 只能在执行期间确定是否应该报告错误。
- 插入到具有行开始列,行结束列或事务开始标识列的表中: 将行插入到具有这些生成列 (例如,系统周期时态表) 的表中时,数据库管理器会将值分配给以下列:
- 为行开始列分配一个值,该值是在执行事务中的第一个数据更改语句期间使用时间时钟读数生成的,该更改语句要求将值分配给表中的行开始列或事务开始标识列,或者删除系统时间段时态表中的行。 数据库管理器确保跨事务的行开始列的所生成值的唯一性。 如果在单个 SQL 事务中插入多行,那么行开始列的值对于所有行都是相同的,并且与为另一个事务的列生成的值是唯一的。
- 将为行结束列分配该列的数据类型的最大值 (9999-12-30-00.00.00.000000000000)。
- 为事务开始标识列分配了每个事务的唯一时间戳记值或空值。 如果该列可空,那么会将空值分配给事务开始标识列。 否则,将在执行事务中的第一个数据更改语句期间使用时间时钟来生成该值,该语句要求将值分配给表中的 "行开始" 或 "事务开始标识" 列,或者删除系统时间段时态表中的行。 如果在单个 SQL 事务中插入多行,那么事务开始标识列的值对于所有行都是相同的,并且与为另一个事务的列生成的值是唯一的。
- 插入到系统时间段时态表中: 将行插入到系统时间段时态表中时,数据库管理器会将值分配给具有行开始,行结束或事务开始标识列的表所指示的列。 此外,插入行时,不会将任何行添加到与系统时间段时态表相关联的历史记录表中。
- 插入到应用程序周期时态表中: 将行插入到应用程序周期时态表中并且满足以下条件时,将返回错误:
- 应用程序时间段时态表具有定义了 BUSINESS_TIME WITHOUT 交叠子句的主键或唯一约束,或者定义了 BUSINESS_TIME WITHOUT 交叠子句的唯一索引。
- BUSINESS_TIME 时间段的开始列和结束列所定义的时间段与 BUSINESS_TIME 时间段的开始列和结束列所定义的时间段重叠,而另一行与同一唯一约束或唯一索引的其他列相匹配。
- 不带列列表的 INSERT 的注意事项: 不带列列表的 INSERT 语句不包含隐式隐藏列。 定义为隐式隐藏且非空的列必须具有已定义的缺省值。
示例
- 示例 1: 将具有以下规范的新部门插入到 DEPARTMENT 表中:
- 部门号 (DEPTNO) 为 "E31"
- 部门名称 (DEPTNAME) 为 "ARCHITECTURE"
- 由 (MGRNO) 编号为 "00390" 的人员管理
- 向 (ADMRDEPT) 部门 "E01" 报告。
INSERT INTO DEPARTMENT VALUES ('E31', 'ARCHITECTURE', '00390', 'E01') - 示例 2: 将新部门插入到 DEPARTMENT 表中,如示例 1 中所示,但不将经理分配给新部门。
INSERT INTO DEPARTMENT (DEPTNO, DEPTNAME, ADMRDEPT ) VALUES ('E31', 'ARCHITECTURE', 'E01') - 示例 3: 使用一个语句将两个新部门插入到 DEPARTMENT 表中,例如 2 ,但不将经理分配给新部门。
INSERT INTO DEPARTMENT (DEPTNO, DEPTNAME, ADMRDEPT) VALUES ('B11', 'PURCHASING', 'B01'), ('E41', 'DATABASE ADMINISTRATION', 'E01') - 示例 4: 创建与 EMP_ACT 表具有相同列的临时表 MA_EMP_ACT。 使用 EMP_ACT 表中的行装入 MA_EMP_ACT ,项目编号 (PROJNO) 以字母 "MA" 开头。
CREATE TABLE MA_EMP_ACT ( EMPNO CHAR(6) NOT NULL, PROJNO CHAR(6) NOT NULL, ACTNO SMALLINT NOT NULL, EMPTIME DEC(5,2), EMSTDATE DATE, EMENDATE DATE ) INSERT INTO MA_EMP_ACT SELECT * FROM EMP_ACT WHERE SUBSTR(PROJNO, 1, 2) = 'MA' - 示例 5: 使用 C 程序语句将框架项目添加到 PROJECT 表。 从主变量获取项目编号 (PROJNO) ,项目名称 (PROJNAME) ,部门编号 (DEPTNO) 和负责员工 (RESPEMP)。 使用当前日期作为项目开始日期 (PRSTDATE)。 将空值分配给表中的其余列。
EXEC SQL INSERT INTO PROJECT (PROJNO, PROJNAME, DEPTNO, RESPEMP, PRSTDATE) VALUES (:PRJNO, :PRJNM, :DPTNO, :REMP, CURRENT DATE); - 示例 6: 在 SELECT 语句中指定 INSERT 语句作为 data-change-table-reference 。 定义一个额外的包含列,该列的值在 VALUES 子句中指定,然后用作插入行的排序列。
SELECT INORDER.ORDERNUM FROM NEW TABLE (INSERT INTO ORDERS(CUSTNO)INCLUDE (INSERTNUM INTEGER) VALUES(:CNUM1, 1), (:CNUM2, 2)) InsertedOrders ORDER BY INSERTNUM; - 示例 7: 使用 C 程序语句向 DOCUMENTS 表添加文档。 从绑定到 SQL TYPE IS XML AS BLOB_FILE 的主变量获取文档标识 (DOCID) 列和文档数据 (XMLDOC) 列的值。
EXEC SQL INSERT INTO DOCUMENTS (DOCID, XMLDOC) VALUES (:docid, :xmldoc) - 示例 8: 对于以下 INSERT 语句,假定表 SALARY_INFO 由三列定义,并且最后一列是隐式隐藏的 ROW CHANGE TIMESTAMP 列。 在以下语句中,在列列表中显式引用隐式隐藏列,并在 VALUES 子句中为其提供值。
以下 INSERT 语句使用隐式列列表。 隐式列列表不包含隐式隐藏列,因此 VALUES 子句仅包含其他两列的值。INSERT INTO SALARY_INFO (LEVEL, SALARY, UPDATE_TIME) VALUES (2, 30000, CURRENT TIMESTAMP)
在这种情况下,必须将 UPDATE_TIME 列定义为具有缺省值,并且该缺省值将用于插入的行。INSERT INTO SALARY_INFO VALUES (2, 30000)
