EXECUTE 语句

EXECUTE语句用于执行已准备好的SQL语句。

调用 EXECUTE

此语句只能嵌入在应用程序中。 这是一个无法动态准备的可执行语句。 Java™中不能指定。

授权 EXECUTE

请参阅 PREPARE语句 ,了解创建预置语句所需的授权。

语法 EXECUTE

阅读语法图跳过可视化语法图 EXECUTE 声明-名称 USING,变量1数组变量[ 数组索引]2USING DESCRIPTOR描述符名称源行数据3
注意:
  • 1 只能在SQL PL上下文中指定全局变量。
  • 2 只能在SQL PL上下文中指定数组元素。
  • 3 仅当语句名称引用动态插入或合并语句时,才能指定此选项。该语句使用 FOR MULTIPLE ROWS 进行准备,并作为 PREPARE 语句中 ATTRIBUTES 子句的一部分进行指定。

源行数据:

阅读语法图跳过可视化语法图USING,主机变量数组宿主变量USING DESCRIPTOR描述符名称FOR宿主变量常数ROWS1
注意:
  • 1 如果未将FOR n ROWS子句指定为MERGE语句的一部分,且指定了主机变量数组,则必须在EXECUTE语句中指定FOR n ROWS子句。 如果MERGE与多行源数据一起使用,则还需要FOR n ROWS子句。 对于INSERT语句,FOR n ROWS子句只能用于只包含单个多行INSERT语句的动态语句。

描述 EXECUTE

statement-name
标识要执行的已准备好的语句。 语句名必须标识之前在工作单元中准备好的语句,且该语句不能是选择语句
USING
更改开始FL 500 引入变量列表或数组元素说明,其值将替换为准备语句中的参数标记(问号)。 (参数标记的解释见 PREPARE语句。) 如果准备好的语句包含参数标记,则必须在 EXECUTE 语句中包含 USING。 如果没有参数标记,则忽略“USING”。

第n个值对应于准备好的语句中的第n个参数标记。 在适当的情况下,可以提供定位器变量和文件引用变量作为参数标记值的来源。

有关参数标记值的替换,请参阅参数标记替换
可变,...
标识应用程序中根据变量和宿主结构声明规则声明的变量或宿主结构。 当语句被执行时,对结构的引用会被替换为对每个变量的引用。 变量的数量必须与已准备语句中参数标记的数量相同。 第 n 个变量对应于已准备的语句中的第 n 个参数标记。 在适当的情况下,可以提供定位器变量和文件引用变量作为参数标记值的来源。 不能指定全局变量。

只有在SQL PL中发出EXECUTE语句时,才需要指定数组全局变量。

数组变量 [ 数组索引 ]
标识数组元素。 只有在SQL PL中发出EXECUTE语句时,才需要指定数组元素。
数组变量
指定一个数组变量。
[数组索引 ]
用于指定数组中要使用的元素的表达式。

对于普通数组,数组索引表达式必须可转换为整数,且不能为空值。 索引值必须在1和数组定义的最大基数之间。

对于关联数组,数组索引表达式必须可转换为关联数组的索引数据类型,且不能为空值。

数组索引不能为:

  • 引用当前日期、当前时间或当前时间戳特殊寄存器的表达式
  • 非确定性函数
  • 由外部动作定义的功能
  • 用MODIFIES SQL DATA定义的功能
  • 序列表达式
数组变量
指定一个数组变量。
更改结束
USING DESCRIPTOR 描述符名称
标识包含输入主机变量有效描述的 SQLDA。

在调用EXECUTE语句之前,必须在SQLDA中设置以下字段:

  • SQLN 表示 SQLDA 中提供的 SQLVAR 出现的次数
  • SQLABC用于指示为SQLDA分配的存储字节数
  • SQLD 用于指示处理语句时 SQLDA 中使用的变量数量
  • SQLVAR条目,用于指示变量的属性

SQLDA必须具有足够的存储空间来容纳所有SQLVAR条目。 如果SQLVAR条目包含LOB值或基于LOB的不同类型,则每个参数必须有额外的SQLVAR条目。 如需了解SQLDA的更多信息,包括SQLVAR的描述以及如何确定SQLVAR条目数量的说明,请参阅 SQL描述符区域(SQLDA )。

SQLD的值必须大于或等于零且小于或等于SQLN。 它必须与准备好的语句中的参数标记数量相同。 SQLDA描述的第n个变量对应于预编译语句中的第n个参数标记。

REXX SQLDA不包含SQLN字段。

请参阅 《识别C或C++中的SQLDA 》,了解如何在C中表示描述符名称

源行数据
准备好的语句必须是INSERT或MERGE语句,其中FOR MULTIPLE ROWS子句被指定为PREPARE语句中ATTRIBUTES子句的一部分。
使用主机变量数组主机变量
引入一个宿主变量或宿主变量数组列表,其值将替换准备好的INSERT或MERGE语句中的参数标记(问号)。 INSERT或MERGE语句中指定的列数必须小于或等于指定的主变量或主变量数组的总数。
主机变量数组
标识一个必须在应用程序中根据声明宿主变量数组的规则定义的宿主变量数组。 对结构的引用被替换为对每个变量的引用。 变量的数量必须与已准备语句中参数标记的数量相同。 第n个变量为准备好的语句中的第n个参数标记提供值。

C/C++、COBOL和PL/I支持 host-variable-array。 更多信息,请参阅 PL/I、C、C++和COBOL中的宿主变量数组

主机变量
标识应用程序中必须根据声明宿主变量的规则描述的变量。
使用描述符描述符名称
标识一个SQLDA,其中必须包含对包含要插入的值的主变量数组或主变量的有效描述。

在执行动态插入或合并语句的EXECUTE语句之前,必须在SQLDA中设置以下字段:

  • SQLN用于指示SQLDA中提供的SQLVAR条目数。
  • SQLABC用于指示为SQLDA分配的存储字节数。
  • SQLD表示变量数量,加上一个,用于为INSERT或MERGE语句的列提供值的SQLDA中。 SQLD的值必须大于或等于零且小于或等于SQLN。
  • SQLVAR条目,用于指示主变量数组中元素的属性,这些属性对应于INSERT或MERGE语句源列提供的值。 在每个SQLVAR中,设置了以下字段:
    • SQLTYPE 表示主机变量数组元素的数据类型。
    • SQLDATA指向相应的宿主变量数组。
    • SQLLEN和SQLLONGLEN表示数组中单个元素的长度。
  • SQLNAME,第五和第六字节必须包含一个标志字段,第七和第八字节必须包含一个二进制小整数(半字节),其中包含宿主变量数组的维度,以及(如果指定)相应的指示数组。

SQLDA必须有足够的存储空间,以容纳每个目标列的SQLVAR条目(列中包含的值)以及一个额外的SQLVAR条目(行数)。 Db2 系统会生成代码,用于输入此额外SQLVAR条目的所需信息。 每个SQLVAR条目描述一个包含源表列值的宿主变量、宿主变量数组或缓冲区。 最后一个SQLVAR条目包含数据行数。 例如,如果INSERT或MERGE语句为目标表的五个列提供值,则必须提供六个SQLVAR条目。 如果任何值是LOB值,则必须提供两倍的SQLVAR条目,并且SQLN必须设置为SQLVAR条目的数量。 因此,如果INSERT或MERGE语句为源表的5列提供值,并且要插入的某些值是LOB值,则必须提供12个SQLVAR条目。

SQLVAR中用于记录行数的条目还必须包含一个标志值。 请参阅基本 SQLVAR 出现的字段描述 ,了解更多信息。

将SQLDATA和SQLIND指针设置为相应数组的开头。

n行

指定源数据的行数,其中 n主机变量整数常量。 插入或合并操作的值在 USING 子句中指定。

host-variableinteger-constant 被赋值给一个整数 k。 如果指定了宿主变量 ,则该变量必须为精确数值类型,且其范围必须为零,且不得包含指示变量。 k的取值范围必须为0到32767。

如果正在处理的语句是包含 FOR n ROWS 子句的动态 INSERT 或 MERGE 语句,则不能在 EXECUTE 语句中指定 FOR n ROWS。

备注 EXECUTE

处理器时间过长:
Db2 如果准备好的SQL语句需要花费太多处理器时间才能完成,则可以停止执行该语句。 当这种情况发生时,就会产生错误。 发出语句的应用程序并未终止,它还可以发出另一个SQL语句。
参数标记替换:
在执行准备好的语句之前,语句中的每个参数标记实际上都会被替换为相应的宿主变量。 替换是一个赋值操作,其中源是宿主变量的值,目标是 Db2 中的变量。 分配规则与分配和比较中描述的分配到列的规则相同。 对于类型化参数标记,目标变量的属性是 CAST 规范指定的属性。 对于非类型化参数标记,将根据参数标记的上下文来确定目标变量的属性。 有关影响参数标记的规则,请参阅参数标记

由 V 表示对应于参数标记 P 的主机变量。 根据为列赋值的规则,V的值被赋给P的目标变量:

  • V 必须与目标兼容。
  • 如果V是一个字符串,则其长度不能大于目标字符串的长度属性。
  • 如果 V 是一个数字,那么其整数部分的绝对值不能大于目标的整数部分的最大绝对值。
  • 如果 V 的属性与目标的属性不相同,那么会将该值转换为符合目标的属性。
  • 如果目标不能包含空值,则V不能为空。

当执行准备好的语句时,用于代替P的值是P的目标变量的值。 例如,如果 V 是 CHAR(6),目标字符串是 CHAR(8),则用 V 的值代替 P,并在右侧用两个空格填充。

执行时出错:
在本地和远程处理中,DEFER(PREPARE)和REOPT(ALWAYS)/REOPT(ONCE)绑定选项可能会导致一些错误,这些错误通常在PREPARE处理期间发出,但在EXECUTE期间发出。
执行以原生 SQL 语言编写的数据定义语句时需考虑以下事项:
用原生SQL语言编写的数据定义语句只能执行一次。 要多次执行数据定义语句,请在每次使用数据定义语句的 EXECUTE 语句之前发出 PREPARE 语句。

例子 EXECUTE

示例 1
在这个示例中,准备并执行了带有参数标记的INSERT语句。 S1 是与 DSN8C10. DEPT 格式对应的结构。
   EXEC SQL PREPARE DEPT_INSERT FROM
     'INSERT INTO DSN8C10.DEPT VALUES(?,?,?,?)';
   -- Check for successful execution and read values into S1
   EXEC SQL EXECUTE DEPT_INSERT USING :S1;
示例 2
假设 IWH.PROGPARM 表格有9列。 编写并执行动态INSERT语句,向 IWH.PROGPARM 表中插入5行数据。 要插入的值以数组形式提供,其中一列的所有值都以主机变量数组的形式与EXECUTE语句一起提供。
STMT = 'INSERT INTO IWH.PROGPARM  (IWHID, UPDATE_BY,UPDATE_TS,NAME,
                                   SHORT_DESCRIPTION, ORDERNO, PARMDATA, 
                                   PARMDATALONG, VWPROGKEY)  
VALUES ( ? , ? , ? , ? , ? , ? , ? , ? , ? )';  
ATTRVAR = 'FOR MULTIPLE ROWS';
EXEC SQL PREPARE INS_STMT ATTRIBUTES :ATTRVAR FROM :STMT;
NROWS = 5;
EXEC SQL EXECUTE INS_STMT FOR :NROWS ROWS 
           USING :V1, :V2, :V3, :V4, :V5, :V6, :V7, :V8, :V9; 

在这个示例中,USING子句中的每个宿主变量都代表INSERT语句目标中对应列的值数组。

示例 3
使用动态提供的员工行值,如果数据是现有员工的,则更新主表EMPLOYEE;如果数据是新员工的,则插入新行。
hv_stmt = 
  "MERGE INTO EMPLOYEE AS T
    USING (VALUES (CAST (? AS CHAR(6)), CAST (? AS VARCHAR(12)),
                  CAST (? AS CHAR(1)), CAST (? AS VARCHAR(15)),
                  CAST (? AS INTEGER)))
    AS S (EMPNO, FIRSTNAME, MI, LASTNAME, SALARY)
    ON T.EMPNO = S.EMPNO
    WHEN MATCHED THEN UPDATE
        SET SALARY = S.SALARY
    WHEN NOT MATCHED THEN INSERT (EMPNO, FIRSTNAME, MI, LASTNAME, SALARY)
        VALUES (S.EMPNO, S.FIRSTNAME, S.MI, S.LASTNAME, S.SALARY)
    NOT ATOMIC CONTINUE ON SQLEXCEPTION";
hv_attr = 'FOR MULTIPLE ROWS';
EXEC SQL 
    PREPARE merge_stmt 
     ATTRIBUTES :hv_attr FROM :hv_stmt;
hv_nrows = 5;
/* Initialize the hostvar array of hv_empno, hv_firstname... */
EXEC SQL 
   EXECUTE merge_stmt 
   USING :hv_empno, :hv_firstname, :hv_mi, 
         :hv_lastname, :hv_salary
      FOR :hv_nrows ROWS;
示例 4

假设已定义了以下数组类型、数组变量和表。

CREATE TYPE INTARRAY AS INTEGER ARRAY[100];
CREATE TYPE STRINGARRAY AS VARCHAR(10) ARRAY[100];
CREATE TABLE T1 (COL1 CHAR(10), COL2 INT);

在 EXECUTE 语句中作为表达式的输入值用作数组变量。

CREATE PROCEDURE PROCESSPERSONS (OUT WITHO STRINGARRAY, INOUT INT0 INT)
BEGIN
 DECLARE INTA INTARRAY;
 DECLARE STMT CHAR(100);
-- Initialize the array
 SET INTA = ARRAY[1,INTEGER(2),3+0,4,5,6] ;
-- Use dynamic sql with an array parameter marker to
--  provide a value for a dynamic INSERT statement
 SET STMT = 'INSERT INTO T1 VALUES('XYZ', CARDINALITY(CAST(? AS INTARRAY)))';
 PREPARE INS_STMT FROM STMT;
 EXECUTE INS_STMT USING INTA; 
-- INTA is an array variable used as input for the 
-- INSERT statement
…
END