SELECT INTO 语句
SELECT INTO语句生成的结果表最多包含一行。 该语句将该行中的值赋给变量。 如果表为空,则语句不会为主变量或全局变量赋值。
调用 SELECT INTO
此语句只能嵌入在应用程序中。 这是一个无法动态准备的可执行语句。
授权 SELECT INTO
- 语句中确定的每个表和视图的 SELECT 权限
- 声明中确定的每张桌子和每处景观的所有权
- 读取语句中标识的任何全局变量的权限
- 对声明中确定的任何全局变量的所有权
- DBADM 数据库权限(仅限表格)
- DATAACCESS 权限
- SYSADM 权限
- SYSCTRL权限(仅限目录表)
如果SELECT INTO语句包含SQL数据更改语句,则权限集还必须至少包含与该SQL数据更改语句在表或视图中关联的权限(INSERT、UPDATE或DELETE)。
对于赋值给全局变量或数组元素的全局变量,权限集必须至少包含以下内容之一:

- 可变WRITE权限
- 可变的所有权
- DATAACCESS 权限
- SYSADM 权限

对于过渡变量的赋值,权限集必须至少包含以下内容之一:

- 定义了包含赋值语句的触发器的表或视图的UPDATE权限
- 更新列中与待赋值的过渡变量相对应的列的权限
- 包含赋值语句的触发器所在的表格或视图的所有权
- DBADM 数据库权限,其中包含定义了包含赋值语句的触发器的表
- DATAACCESS 权限
- SYSADM 权限

权限设置:
如果语句嵌入到应用程序中,权限集就是软件包所有者所拥有的权限。 如果语句是动态编写的,则权限集由生效的动态规则行为(运行、绑定、定义或调用)决定,并在动态规则行为和授权检查中进行总结。 有关这些行为的更多信息,包括决定这些行为的 DYNAMICRULES 绑定选项值列表,请参阅授权 ID 和动态 SQL。
语法 SELECT INTO
描述 SELECT INTO
FL 500 结果表是通过按以下顺序逻辑评估 isolation-clause、 from-clause、 where-clause、 group-by-clause、 having-clause、 order-by-clause、 offset-clause、 fetch-clause 和 select-clause 而得出的。 根据 Db2 子系统选择的计划,实际顺序可能略有不同。 有关这些条款的说明,请参阅查询下的主题。
语句中确定的表或视图可以存在于当前服务器上,也可以存在于当前服务器可以与之建立连接的任何 Db2 子系统中。
- WITH common-table-expression
- 有关指定公共表表达式的信息,请参阅公共表表达式。
- INTO 目标变量或数组变量 [数组索引 ]
- 确定一个或多个输出值的目标。 INTO子句中的目标数量必须与要分配的值数量相等。 结果行中的第一个值分配给列表中的第一个目标,第二个值分配给第二个目标,以此类推。 在INTO子句中,目标变量不能被指定多次。 根据 “任务和比较” 中描述的规则,按照列表中的顺序为每个目标分配任务。
如果目标数量少于结果列的值数量,则将值“W”分配给SQLCA的 SQLWARN3 字段。
如果任何赋值操作出错,则不会将值赋给目标,也不会再向指定目标赋值。 任何已分配的值将保持不变。
- global-variable-name
- 标识作为赋值目标的全球变量。
- 主机变量名
- 标识作为赋值目标的主变量。 对于LOB输出值,目标可以是常规的主变量(如果足够大)、LOB定位变量或LOB文件引用变量。
- SQL参数名称
- 标识作为赋值目标的参数。
- SQL变量名
- 标识作为赋值目标的SQL变量。 SQL变量在使用前必须声明。
过渡变量名
标识过渡表中要更新的列。 过渡变量名必须标识触发器主题表中的一列,可选择使用相关名称来限定,以标识新值。
- 数组变量 [数组索引]
- 指定作为赋值目标的数组元素。
如果语句中也指定了公共表表达式 ,则不能将数组元素指定为赋值的目标。
- 数组变量
- 指定一个数组变量。
- [数组索引 ]
- 用于指定数组中哪个元素是赋值目标。
对于普通数组,数组索引表达式必须可转换为整数,且不能为空值。 索引值必须在1和数组定义的最大基数之间。
对于关联数组,数组索引表达式必须可转换为关联数组的索引数据类型,且不能为空值。
数组索引不能为:
- 引用当前日期、当前时间或当前时间戳特殊寄存器的表达式
- 非确定性函数
- 由外部动作定义的功能
- 用MODIFIES SQL DATA定义的功能
- 序列表达式
- 不在标量全选中的列。
变量的数据类型必须与赋给它的值相匹配。 如果数值是数字,则变量必须能够表示该数值的一个整数部分。 对于日期或时间值,变量必须是一个字符串变量,其最小长度如赋值和比较中定义。
根据赋值和比较中描述的规则,对变量进行赋值。 任务按列表顺序分配。
如果SELECT INTO语句的SELECT列表中的算术表达式出现错误(除数为零或溢出)或数值转换错误,则结果为空值。 与任何其他无效值的情况一样,必须提供一个指示变量,且主变量保持不变。 然而,在这种情况下,指示变量被设置为 -2。 继续处理语句,就像错误没有发生一样。 (然而,此错误会导致SQLCODE为正。) 如果您不提供指示变量,SQLCA的SQLCODE字段将返回负值。 当遇到错误时,语句处理将终止。
如果发生错误,则不会为变量或后续变量赋值,但已赋值的变量仍保持赋值状态。
如果结果表有多行,则可能会发生错误,导致变量被赋值。 如果为变量赋值,则作为值来源的行将无法定义且不可预测。
- 跳过已锁定的数据
- 当其他事务对行持有不兼容的锁时,指定跳过该行。 这些行可以属于语句中指定的任何已访问表。 仅当隔离CS或RS生效时,才能使用跳过锁定数据,且仅适用于行级或页级锁定。
如果指定的隔离级别为可重复读取(WITH RR)或未承诺读取(WITH UR),则跳过锁定数据(SKIP LOCKED DATA)将被忽略。
- QUERYNO 整数
- 指定在EXPLAIN输出和跟踪记录中用于此SQL语句的编号。 该数字用于计划表中 QUERYNO 列,其中包含有关此 SQL 语句的信息。 这个数字也用于 SYSIBM.SYSSTMT 和 SYSIBM.SYSPACKSTMT 目录表的QUERYNO列。
如果省略该子句,则与SQL语句关联的数字就是预编译期间分配的语句编号。 因此,如果应用程序被修改并预编译,那么语句编号可能会改变。
使用QUERYNO子句为程序中的SQL语句分配唯一编号很有帮助:
- 为了简化访问路径选择优化提示的使用
- 用于将SQL语句文本与计划表中的EXPLAIN输出相关联
有关启用和使用优化提示的更多信息,请参阅影响访问路径选择。
备注 SELECT INTO
- 目标分配
- INTO子句中标识的或SQLDA中描述的第n个目标对应于游标结果表的第n列。 目标的数据类型必须与其对应的值相匹配。 如果数值,目标必须能够表示整个数值部分。 对于日期时间值,目标必须是字符串变量,且长度至少满足日期时间值的字符串表示形式中定义的要求。 当目标是一个宿主变量时,如果值为空,则必须指定一个指示变量。
任务按列表顺序分配。 根据 SQL语言元素中描述的规则,为每个目标分配任务。 如果目标数量少于该行中的值数量,则SQLCA的 SQLWARN3 字段设置为“W”。 如果目标数量超过结果列的数量,则不会发出警告。 如果目标是一个宿主变量,且值为空,则必须提供一个指示变量。 如果发生赋值错误,则不会将值赋给目标,也不会再向目标赋值。 任何已分配给目标的值仍保持分配状态。
如果同一赋值语句中包含多个赋值,则所有表达式将在执行赋值之前进行求值。 例如,在表达式中引用变量时,总是使用赋值语句中任何赋值之前的变量值。
通常情况下,您使用LOB定位器来分配和检索LOB列中的数据。 然而,由于兼容性规则,您也可以使用LOB定位器将数据分配给具有其他数据类型的目标。 有关定位器的更多信息,请参阅 《使用LOB定位器操作LOB时节省存储空间 》。
不能将没有时区值的时间戳分配给带有时区目标的时间戳。
- 默认编码方案
- 数据的默认编码方案是绑定选项ENCODING中的值,该选项用于应用程序编码。 如果此语句与 LENGTH 或 SUBSTRING 等函数一起使用,且这些函数正在对 LOB 定位器进行操作,而定位器指定的 LOB 数据所采用的编码方案与 ENCODING 绑定选项不同,则会发生 LOB 物化和字符转换。 为避免LOB实体化和字符转换,请从 SYSIBM.SYSDUMMYA、 SYSIBM.SYSDUMMYE 或 SYSIBM.SYSDUMMYU 示例表中选取LOB数据。
- 如果结果表为空
- 如果表为空,则语句将+100赋给SQLCODE,将'02000'赋给SQLSTATE,并且不向宿主变量或全局变量赋值。
- 插入的行数
- 如果游标的 SELECT INTO 语句包含 SQL 数据更改语句,则 SELECT INTO 操作会将 SQLERRD(3) 设置为插入的行数。
对抵消条款的考虑

- 当查询可能产生多行结果时, 偏移子句可用于 SELECT INTO 语句。
- 要影响返回的行,可以使用 order-by子句。 当您指定了按……排序子句时,结果中的行会被排序,指定的行数会被跳过,并返回第一行。 如果未指定 fetch子句 ,且结果表包含多行,则会发生错误。

取词条款考虑因素
FL 500- 当查询可能产生多行结果时, 取语句可用于 SELECT INTO 语句。 指定FETCH FIRST 1 ROW ONLY表示最多只能检索一行,而不管结果表中包含多少行。
- 使用 fetch子句将结果表明确限制为单行,为SELECT INTO语句提供了与可能返回多行的查询一起使用的方法。 当您知道只想检索一行时,使用该子句有助于避免使用光标。 要影响返回的行,可以使用 order-by子句。 当您指定了排序子句时,结果中的行会按顺序排列,然后返回第一行。 如果未指定 fetch子句 ,且结果表包含多行,则会发生错误。

例子 SELECT INTO
- 示例 1
- 将 DSN8C10.EMP 中的最高工资存入主变量 MAXSALRY。
EXEC SQL SELECT MAX(SALARY) INTO :MAXSALRY FROM DSN8C10.EMP; - 示例 2
- 将 DSN8C10.EMP中 528671号员工的行放入EMPREC主机结构中。
EXEC SQL SELECT * INTO :EMPREC FROM DSN8C10.EMP WHERE EMPNO = '528671' END-EXEC. - 示例 3
- 将 DSN8C10.EMP中 528671号员工的行放入EMPREC主机结构中。 假设此行稍后会更新,因此在查询执行时应该锁定。
EXEC SQL SELECT * INTO :EMPREC FROM DSN8C10.EMP WHERE EMPNO = '528671' WITH RS USE AND KEEP EXCLUSIVE LOCKS END-EXEC. - 示例 4
- 使用 SELECT INTO 语句,将表 T1 中的值 INTCOL1 检索到数组 MYINTARRAY1 中的元素,该元素由表达式 INTCOL2+MYINTVAR+1 的值索引。
SELECT INTCOL1 INTO MYINTARRAY1[INTCOL2+MYINTVAR+1] FROM T1 WHERE INTCOL1 = MYINTARRAY1[INTCOL2] ;
