CALL 语句
CALL语句调用一个存储过程。
调用 CALL
此语句可嵌入应用程序中。 该语句可通过 Db2 command line processor 进行交互式执行。 请参阅 Db2 命令行处理器CALL语句 ,了解如何使用 Db2 command line processor 和CALL语句。 此语句也可以动态编写,但仅限于支持动态CALL语句的 ODBC 或CLI驱动程序。 IBM® 的 ODBC 和CLI驱动程序提供了这一功能。
授权 CALL
调用存储过程需要以下权限:
- 存储过程
在 Db2 for z/OS® 版本6之前创建的存储过程不需要EXECUTE权限。
- 存储过程包和大多数在存储过程中运行的包需要额外的权限。
在存储过程下执行包的授权中详细解释了哪些包需要授权。
执行存储过程的授权
对存储过程具有执行权限的授权ID或角色取决于CALL语句的形式:
- 对于使用语法CALL 过程的静态SQL程序,包含CALL语句的计划或包的所有者必须具有以下权限之一:
- 存储过程上的EXECUTE权限
- 存储过程的所有权
- DATAACCESS 权限
- SYSADM 权限
- 对于使用语法 CALL variable 的静态SQL程序,包含CALL语句的计划或包的授权ID或角色必须具有以下之一:
- 存储过程上的EXECUTE权限
- 存储过程的所有权
- DATAACCESS 权限
- SYSADM 权限
包含CALL语句的计划或包的DYNAMICRULES行为决定授权ID或角色以及该授权ID或角色所拥有的权限集:- 运行行为
- 特权集是SQL授权ID和流程的每个授权ID或角色所拥有的一组特权的组合。
- 绑定行为
- 特权集是指套餐或计划所有者主授权ID所拥有的特权。
- 定义行为
- 特权集是指发出CALL语句的存储过程或用户定义函数的授权ID或所有者(定义者)角色所拥有的特权。
- 调用行为
- 特权集是指由存储过程或用户定义函数的调用者的授权ID或角色持有的特权,这些调用者发出了CALL语句。 但是,如果调用者是该进程的主要授权ID或当前SQLID值,则权限集是每个授权ID或角色所拥有权限集的并集。
授权执行存储过程(包括嵌套存储过程)中的包
运行存储过程包以及存储过程(包括嵌套存储过程)下使用的任何包所需的授权适用于任何形式的CALL语句,如下所示:
- 存储过程包 :在 “授权ID集” 中定义的授权ID或角色之一必须至少具有以下权限之一:
- EXECUTE权限
- 套餐所有权
- PACKADM 授权领取包裹
- SYSADM 权限
- 用户自定义函数包和触发器包 :如果存储过程或存储过程下的任何应用程序调用用户自定义函数,则 Db2 仅要求用户自定义函数包的所有者(定义者)拥有执行权限,而不要求调用者拥有执行权限。 但是,调用用户定义函数的SQL语句的授权ID或角色必须对该函数具有EXECUTE权限。
同样,如果在存储过程下使用触发器,则 Db2 不需要对触发器包具有EXECUTE权限;但是,激活触发器的SQL语句的授权ID或角色必须对触发器具有EXECUTE权限。
在存储过程下使用的任何用户定义的功能包或触发器包都不需要PKLIST条目。
- 除用户定义函数、触发器和存储过程包之外的包 : 在“授权ID集” 下定义的授权ID或角色之一,必须对除存储过程下使用的用户定义函数和触发器包之外的任何包具有以下至少一项权限或授权:
- EXECUTE权限
- 套餐所有权
- PACKADM 授权领取包裹
- SYSADM 权限
在存储过程下使用的任何这些包都需要PKLIST条目。
为了提高性能和简化操作,请考虑将存储过程包和存储过程下运行的任何包的“执行”权限授予存储过程的所有者。
授权ID集 : Db2 按列出的顺序检查以下授权ID,以获得执行存储过程包和存储过程下运行的任何包所需的授权,这些包包括前面描述的用户定义函数和触发器包。 在找到第一个对目标包具有 EXECUTE ON PACKAGE 权限的授权 ID 后,授权检查结束。
- 存储过程的拥有者(定义者)。
- 该计划的所有者包含调用存储过程的CALL语句,如果以下任一条件为真:
- 调用应用程序(直接绑定到计划的包或DBRM)是本地的。
- 呼叫应用程序已分发, Db2 子系统既是请求方也是服务器,且PRIVATE_PROTOCOL子系统参数未设置为NO。
- 如果调用应用程序是分布式应用程序,且满足以下任一条件,则包含调用存储过程的CALL语句的包的所有者:
- Db2 子系统是服务器,但不是请求者。
- Db2 子系统既是服务器又是请求者,PRIVATE_PROTOCOL子系统参数设置为NO。
- 该呼叫应用程序使用可恢复资源管理服务附件功能(RRSAF),且没有计划。
- 如果CALL语句采用 CALL variable 的形式,则授权ID由包含CALL语句的计划或套餐的DYNAMICRULES绑定选项的值确定。
- 如果调用应用程序与DYNAMICRULES(RUN)选项绑定,则 Db2 会在运行时检查进程的授权ID及其辅助授权ID,或者由其他DYNAMICRULES绑定选项值确定的单个授权ID。
- 如果调用应用程序绑定了一个非DYNAMICRULES(RUN)的值,则 Db2 仅检查单个授权ID,即使该ID未通过EXECUTE ON PACKAGE授权检查。
- 如果调用应用程序是一个包,并且与DYNAMICRULES(BIND)绑定,则 Db2 会检查包所有者的授权ID。 Db2 不检查计划所有者的授权ID。
授权在存储程序中执行远程语句包:在存储程序中远程执行的SQL语句遵循与在独立应用程序中远程执行的SQL语句相同的授权规则。 如果存储过程连接到远程 Db2 服务器并在该服务器上执行SQL语句,则服务器上PRIVATE_PROTOCOL子系统参数的设置将决定必须授予包含SQL语句的程序包的EXECUTE权限的ID。
如需了解更多信息,请访问DRDA,邮箱地址为 Db2 for z/OS。
CALL的语法
描述 CALL
- 过程名或变量
- 标识通过指定过程名称或变量中包含的过程名称进行调用的过程。 当前服务器上必须存在已识别的过程。
如果程序名称指定了三个特殊字符中的任何一个,即国家语言的字母扩展字符 $#@,则使用变量指定程序名称。
如果使用了变量:
- 它必须是一个长度属性不超过254的CHAR或VARCHAR变量。
- 其后不能跟指示变量。
- 该变量的值取决于服务器的规格。 无论使用何种服务器,规格必须:
- 在变量内保持左对齐
- 不包含嵌入的空格
- 如果右侧长度小于可变长度,则用空白填充
- 包含大小写字母。 小写字母不会自动转换为大写。
- 在由三个部分组成的程序名称的任何部分使用分隔符。
当执行CALL语句时,过程名称或说明必须标识服务器上存在的存储过程。
当包含CALL语句的包被绑定时,如果指定了VALIDATE(BIND),则必须创建调用的存储过程。 虽然如果指定了 VALIDATE(RUN),则无需在绑定时创建存储过程,但必须在执行 CALL 语句时创建。
- 表达, NULL ,或 TABLE 过渡表名
- 确定作为参数传递给存储过程的值列表。 第n个值对应于程序中的第n个参数。 使用CREATE PROCEDURE定义的每个参数,如果为OUT或INOUT,则必须指定为变量。
指定的参数数量必须与当前服务器上以指定过程名称定义的过程的参数数量相同。
如果指定了 USING DESCRIPTOR,则由已识别的 SQLDA 描述的每个变量都是参数,或者作为 CALL 语句参数的表达式的一部分。 如果CALL语句中没有指定宿主结构,则CALL语句的第n个参数对应于存储过程中的第n个参数 ,且两者中的数字必须相同。 否则,对宿主结构的每次引用都将替换为对宿主结构中包含的每个变量的引用,并且结果参数的数量必须与为存储过程定义的参数数量相同。
但是,如果参数未定义为字符型位数据,则不能将字符型位数据参数作为输入传递给该参数。 同样,不能将非“位数据”字符参数作为“位数据”字符参数的输入。
参数的属性由当前服务器决定。 除了数据类型和长度等属性外,每个参数的描述还说明了存储过程如何使用它:
- IN表示输入值
- OUT表示输出值
- INOUT既表示输入值,也代表输出值
所有非变量参数均视为输入参数(IN)。
- 表达式
- 参数是特定表达式的结果,在调用存储过程之前进行计算。
如果表达式是一个单一变量,则该过程的相应参数可以定义为IN、INOUT或OUT。 否则,必须将相应参数定义为IN。 一个表达式可以包含以下任意一项:
- 变量
- 常量
- 专用寄存器
- 会话全局变量 (session global variable)
- 带变量或常量参数的函数
变量可以识别结构。 任何指定的变量或结构都必须根据声明主机结构和变量的规则在应用程序中进行描述。 对宿主结构的引用被替换为对宿主结构中每个变量的引用。
如果表达式的结果可以为空值,则必须允许空参数,或者将存储过程的相应参数定义为OUT。
如果过程是远程的, 表达式不得将关联数组值作为函数的参数。
根据在CREATE PROCEDURE语句中为过程定义的相应参数,以下附加规则适用:
- IN表达式可以包含对多个变量的引用。 除了表达式中所述的规则之外, 表达式不能包含列名、标量子选择、文件引用变量、聚合函数或源自聚合函数的用户定义函数。
- INOUT或OUT 表达式只能有一个变量。 表达式不能包含文件引用变量或数组元素。
- NULL
- 参数为空值。 该过程的相应参数必须定义为IN,并且该过程的描述必须允许空参数。
- TABLE 过渡表名
- 该参数是一个转换表,作为表定位器传递给过程。 只有在触发器的触发动作定义中,才能将CALL语句与TABLE子句结合使用。 如果过程的相应参数是在CREATE PROCEDURE语句的TABLE LIKE子句中定义的,则必须在CALL语句中指定转换表的名称。 有关创建触发器的信息,请参阅 CREATE TRIGGER语句(基本触发器 )和创建触发器。
无论参数定义为IN、INOUT还是OUT,从程序返回时都不会影响转换表,因为转换表是只读的。
- USING DESCRIPTOR 描述符名称
- 标识一个SQLDA,其中包含将要作为参数传递给存储过程的变量的有效描述。 如果存储过程没有参数,SQLDA将被忽略。
在处理CALL语句之前,用户必须在SQLDA中设置以下字段:
- SQLN用于指示SQLDA中提供的SQLVAR出现的次数。 该数值不得小于SQLD。 该字段不属于REXX SQLDA的一部分,因此无需为REXX程序设置。
- SQLDABC表示为SQLDA分配的存储字节数。 这个数字不能小于 SQLN*44+16。 该字段不属于REXX SQLDA的一部分,因此无需为REXX程序设置。
- SQLD用于指示处理语句时SQLDA中使用的变量数量。 这个数字必须与存储过程的参数数量相同。
- SQLVAR的出现次数,以表明变量的属性。
当作为参数传递给存储过程的变量具有LOB数据类型或LOB定位器时,设置SQLDA字段时还有其他注意事项。 更多信息,请参阅 SQL描述符区(SQLDA )。
SQL CALL语句会忽略SQLDA中的不同类型信息。 仅使用基本SQL类型信息来处理SQLDA描述的输入和输出参数。
在REXX中,只支持变量 USING DESCRIPTOR。 由于SQLDA不支持全局变量,因此REXX也不支持全局变量。
请参阅 《在C或C++中识别SQLDA 》,了解如何在C中表示描述符名称。
备注 CALL
参数赋值 :执行CALL语句时,每个参数的值都会根据存储赋值规则分配给存储过程的相应IN或INOUT参数。 如果CALL语句的参数与存储过程参数的数据类型不匹配,则CALL语句中指定的每个参数在执行时都会转换为存储过程相应参数的数据类型。 转换的规则与分配列的规则相同。
根据宿主语言的调用约定,控制权将传递给存储过程。
当存储过程的执行完成时,存储过程每个参数的值(定义为OUT或INOUT)将分配给CALL语句的相应参数。 如果程序返回错误,则OUT参数未定义,INOUT参数保持不变。
不能将没有时区值的时间戳分配给带有时区目标的时间戳。
当数组参数的值被赋给相应的数组参数时,以下规则适用:
- 对于本地过程调用 :参数和参数必须定义为相同的数组类型。
- 对于远程过程调用 :数组参数中元素的数据类型必须与数组参数中元素的数据类型相同。 此外,对于IN或OUT参数,下表中某一行中的所有相关条件必须为真。 对于INOUT参数,下表第1行中的所有相关条件必须为真,或者第2行和第3行中的所有相关条件必须为真。 相关条件以Y表示。
参数与相关参数的关系 关系适用于IN参数 关系适用于OUT参数 关系适用于INOUT参数 参数是一个普通数组,参数也是一个普通数组,参数和参数的数组索引定义了相同的数据类型。 Y Y Y 参数是一个普通数组,参数是一个关联数组类型,参数是一个IN或INOUT参数,数组索引的数据类型是INTEGER。 关联数组参数被分配一个关联数组值,该值从普通数组参数值派生而来。 普通数组中数组元素的值将按其在普通数组参数中的顺序赋值给关联数组参数。 目标关联数组参数中的索引值从1开始,与普通数组参数值的基数相同。 Y Y 参数是一个普通的数组类型,参数是一个关联数组类型,参数是一个INOUT或OUT参数。 该参数被赋予一个普通数组值,该值来自关联数组参数值。 关联数组值中数组元素的值按 Db2 确定的顺序赋给目标普通数组。 目标普通数组参数中的索引值从1开始,与关联数组参数值的基数相同。 关联数组参数值的索引值将被忽略。 Y Y
有关参数分配规则的详细信息,请参阅分配和比较。
当CALL语句中指定的参数与存储过程相应参数的数据类型在精度、比例、长度、编码方案或CCSID方面存在差异时,会发生转换。 当存储过程的相应参数具有不同的编码方案或CCSID时,CALL语句中指定的字符串参数可能会发生转换。 例如,当CALL语句传递一个混合数据类型的参数时,如果该参数实际包含DBCS字符,并且被定义为FOR SBCS DATA的存储过程的参数,则会发生错误。 同样,当存储过程返回的数据中包含DBCS字符时,也会发生错误,因为CALL语句的参数被定义为FOR SBCS DATA。
程序签名 :程序由程序结构、程序名称和参数数量确定。 这被称为程序签名,在数据库中必须是唯一的。 Db2 for z/OS 不支持重载过程名称(具有相同架构和过程名称但参数数量不同的过程)。
SQL路径 :调用过程时,需要先指定一个限定名称(架构和过程名称),后跟括号内可选的参数列表。 调用过程时也可以不指定模式名称,这样就可以在具有相同过程名称和相同参数数量的多个模式中选择可能的过程。 在这种情况下,SQL路径用于协助过程解析。 SQL路径是一个模式列表,用于搜索与CALL语句中的过程具有相同名称和参数数量的过程。 对于明确指定过程名称的CALL语句,SQL路径是通过使用特定于平台的绑定选项来指定的。 对于CALL 变量语句,SQL路径是指在调用过程时CURRENT PATH特殊寄存器的值。
程序解析 :对于程序调用,数据库管理器必须决定调用同名的可能程序中的哪一个。
过程名是限定名或非标准名。 名称的每个部分都必须由SBCS字符组成:
- 一个完全合格的程序名称由三个部分组成。 第一部分是SQL标识符,包含存储过程所在的数据库管理系统(DBMS)的名称。 第二部分是SQL标识符,包含存储过程的架构名称。 最后一部分是SQL标识符,包含存储过程的名称。 必须用句点分隔各个部分。 任何或所有部分都可以是定界标识。
- 由两部分组成的程序名称有一个隐含限定符。 隐含限定符是当前服务器的位置名称。 这两个部分分别标识了架构名称和存储过程的名称。 两部分之间必须有一个间隔。
- 无限制的程序名称是一个部分名称,带有两个隐含限定符。 第一个隐含限定符是当前服务器的位置名称。 第二个隐含限定符取决于服务器。 如果服务器是 Db2 for z/OS ,则隐式限定符是架构名称。 Db2 使用 SQL路径来确定模式名称的值。
- 如果程序名称在CALL语句 (CALL procedure-name )中指定为字符串常量, 则SQL路径是与调用包或计划关联的PATH绑定选项的值。
- 如果在CALL语句中为过程名称指定了变量 (CALL variable ), 则SQL路径为CURRENT PATH特殊寄存器的值。
Db2 从左到右搜索 SQL路径中的模式名称,直到在 目录中找到具有指定模式名称的存储过程。 Db2 当找到匹配的 schema.procedure-name 匹配项时,只有在满足以下条件时搜索才会停止:- 用户有权调用存储过程。
- 存储过程定义中的参数数量与CALL语句中指定的参数数量一致。
解决该过程取决于如何指定过程名称。 对于使用变量指定过程名称的CALL语句,过程解析在运行时进行。 对于包含过程名称作为标识符的CALL语句,当CALL语句绑定时,会发生过程解析。
数据库管理员通过以下步骤解决程序问题:
- 在目录中查找满足以下所有条件的全部程序:
- 对于指定模式名称(限定引用)的调用,模式名称和过程名称与调用名称匹配。
对于未指定模式名称的调用(无限制引用),过程名称与调用名称匹配,且过程的模式名称与SQL路径中的某个模式匹配。
- 定义的参数数量与调用中指定的参数数量一致。
- 调用者对过程具有执行权限。
- 对于指定模式名称(限定引用)的调用,模式名称和过程名称与调用名称匹配。
- 在步骤1中留下的候选程序中,选择其结构在SQL路径中排在首位的程序。 如果步骤1后没有剩余的候选程序,则返回错误。
- 对于使用变量指定过程名称的CALL语句,CURRENT ROUTINE VERSION特殊寄存器会影响调用哪个版本的本机SQL过程。 如果设置了当前常规版本特殊寄存器,请检查是否存在具有该版本名称的程序版本。 如果没有,请选择当前正在使用的版本。
对于不使用变量指定过程名称的CALL语句,请选择当前激活的过程版本。
版本解析 :通常情况下,CALL语句将使用当前活动的本机SQL过程的版本。 但是,如果CALL语句是同一存储过程体内的递归调用,且原始CALL语句使用的版本与当前活动版本不同,则不会使用活动版本。 原始CALL语句中的版本将用于任何递归CALL语句,直到整个存储过程执行完毕。 这保留了原始CALL语句所使用的版本的语义。 这包括递归调用是间接调用的情况。 例如,假设过程 SP1 调用过程 SP2 ,后者递归调用 SP1。 第二次调用过程 SP1 时,将使用调用过程 SP1 的原始CALL语句时激活的过程版本。
由于当前激活的版本可以在下一个CALL语句中使用,因此同一过程的两个或多个版本可以同时运行。 给定线程加载的SQL过程可能有不同的版本。 例如,应用程序中的CALL SP1 语句将导致当前活动的版本 SP1_V1 加载并执行。 在CALL语句执行完毕后,ALTER PROCEDURE ALTER ACTIVE VERSION语句可以执行,并将存储过程 SP1 的当前版本更改为 SP1_V2。 同一线程中后续的CALL SP1 语句将加载当前活动的程序版本 SP1_V2 并执行它。
参数赋值 :当执行CALL语句时,每个参数的值都会根据存储分配规则分配给过程的相应参数。 根据宿主语言的调用约定,控制权将传递给该过程。 当执行过程完成后,该过程的每个参数值将根据存储分配规则分配给定义为 OUT 或 INOUT 的 CALL 语句的相应参数。 如果程序返回错误,则OUT参数未定义,INOUT参数保持不变。 有关分配规则的详细信息,请参阅分配和比较。
在程序中的游标和预编译语句 :当程序结束时,在调用程序中打开的所有游标(非结果集游标)将被关闭,在调用程序中预编译的所有语句将被销毁。
存储过程的结果集 :使用 WITH RETURN 子句指定的游标,当存储过程返回时,游标处于打开状态,这表示结果集。 在用Java™编写的程序中,所有游标都隐式定义为带返回。
仅当从CLI、 JDBC 或SQLJ调用该过程时,才会返回结果集。 如果从CLI或Java调用该过程,并且打开的游标不止一个,则只能按照打开游标的顺序处理结果集。 只有未读的行可以被获取。 例如,如果游标的查询结果集有500行,在程序终止时,其中150行已被程序读取,那么第151-500行将返回给程序。
程序错误 :程序可能会像其他SQL语句一样返回错误或警告,使用SQLSTATE。 应用程序应了解调用过程时可能出现的SQLSTATEs。 可能的SQL状态取决于程序的编码方式。 如果 Db2 在执行过程时遇到问题,程序可能还会返回SQLSTATEs,例如以“38”或“39”开头的SQLSTATEs。 因此,应用程序应做好应对任何错误SQLSTATE的准备,这些错误可能是由发出CALL语句引起的。
提高性能 :提供调用存储过程的功能,以提高DRDA分布式访问的性能。 该功能对于本地运营也很有用。 服务器可以是本地的 Db2。 在这种情况下,仍然需要打包。
所有参数的所有值都从请求者传递到服务器。 为了提高操作性能,在执行CALL语句之前,应将长度超过几个字节的OUT参数变量设置为空。
在触发器中使用CALL语句 :当触发器发出CALL语句调用存储过程时,CALL语句中指定的参数不能是变量,也不能指定USING DESCRIPTOR子句。
嵌套CALL语句 :以存储过程、用户定义函数或触发器形式执行的程序可以发出CALL语句。 当存储过程、用户定义的函数或触发器调用存储过程、用户定义的函数或触发器时,该调用被视为嵌套调用。 存储过程、用户定义的函数和触发器在单个系统中的嵌套深度可达64级。 嵌套可能发生在单个 Db2 子系统内,也可能发生在远程服务器调用存储过程或用户定义函数时。
某些存储过程不能嵌套。 存储过程、用户定义的函数或触发器不能调用带有COMMIT ON RETURN属性的存储过程。 具有AUTONOMOUS属性的程序不能调用其他具有AUTONOMOUS属性的程序。
对同一个存储过程的多次调用 :您可以在应用程序中,在同一嵌套级别多次调用存储过程。 每次调用同一个存储过程时,都会运行一个唯一的存储过程实例。 如果存储过程返回结果集,则存储过程的每个实例都会打开自己的结果集游标集。
如果CALL语句导致超出活动存储过程的最大数量或打开游标的最大数量,应用程序可能会收到“资源不可用”消息。 现场最大存储过程(在安装面板DSNTIPX上)的值定义了每个线程允许的最大活动存储过程数。 MAX OPEN CURSORS(在安装面板DSNTIPX上)定义了每个线程允许打开的最大游标数量(包括结果集游标和常规游标)。
如果您在应用程序中多次调用同一个存储过程,请注意以下几点:
- DESCRIBE PROCEDURE 语句用于描述存储过程的最后一个实例。
- ASSOCIATE LOCATORS语句在存储过程的最后一个实例中起作用。
- ALLOCATE CURSOR 语句必须为存储过程实例返回的结果集指定唯一的游标名称。 否则,您将丢失之前实例或调用存储过程返回的结果集中的数据。
每次调用存储过程后,您应该发出一个关联定位器语句(或描述过程语句),以便为每个结果集获取唯一的定位器值。
使用变量 :如果CALL语句包含变量,则假定变量的内容采用绑定包含该语句的程序包或计划时ENCODING参数中指定的编码方案。
例子 CALL
EXEC SQL CONNECT TO BETA;
V1 = 528671;
IV = -1;
EXEC SQL CALL SUMARIZE(:V1,:V2 INDICATOR :IV);-- Invoke stored procedure MYPROC that returns several result sets
EXEC SQL CALL MYPROC (....);
-- Copy the locator values for the result sets into result set locator variables
EXEC SQL ASSOCIATE RESULT SET LOCATORS (:RS1, :RS2, :RS3) WITH PROCEDURE MYPROC;
-- Allocate cursors for the result set cursors
EXEC SQL ALLOCATE CSR1 CURSOR FOR RESULT SET :RS1;
EXEC SQL ALLOCATE CSR2 CURSOR FOR RESULT SET :RS2;
EXEC SQL ALLOCATE CSR3 CURSOR FOR RESULT SET :RS3;
-- Process data returned with the result set cursors
DO WHILE (SQLCODE = 0);
EXEC SQL FETCH CSR1 INTO .....
END;
EXEC SQL CLOSE CSR1;
-- do similar processing with other result sets
...示例3 :假设程序FIND_CUSTOMERS具有以下参数:
- IN参数是一个电话号码数组
- IN参数,用于搜索匹配项的前缀值
- OUT参数,用于返回电话号码数组
FIND_CUSTOMERS 用于在输入数组变量中搜索与前缀值匹配的电话号码,并返回一个包含与前缀值匹配的电话号码的数组。
输入和输出数组变量的定义如下:

CREATE TYPE PHONENUMBERS AS VARCHAR(20) CCSID UNICODE ARRAY[10];
-- Create an array type
CREATE VARIABLE PNUMBER_ARRAY PHONENUMBERS; -- Create input array variable
CREATE VARIABLE PNUMBER_ARRAY_OUT PHONENUMBERS;
-- Create output array variable
FIND_CUSTOMERS 如下所示:
---------------------------------------------------------------------------
-- Create an SQL procedure with array parameters. The array parameters are
-- defined with the PHONENUMBERS array type. The procedure searches for
-- numbers in IN_PHONENUMBERS that begin with the given prefix, and returns
-- the phone numbers in the NUMBERS_OUT parameter.
---------------------------------------------------------------------------
CREATE PROCEDURE FIND_CUSTOMERS(
IN NUMBERS_IN PHONENUMBERS,
IN PREFIX CHAR(3),
OUT NUMBERS_OUT PHONENUMBERS)
BEGIN
DECLARE I, J INTEGER;
SET I = 1;
SET J = 1;
-- Initialize NUMBERS_OUT to an empty array using an array constructor
-- with no elements
SET NUMBERS_OUT = ARRAY[ ];
WHILE i < CARDINALITY(NUMBERS_IN) DO
IF SUBSTR(NUMBERS_IN[I], 1, 3) = PREFIX THEN
SET NUMBERS_OUT[J] = NUMBERS_IN[I];
SET J = J + 1;
END IF;
SET I = I + 1;
END WHILE;
END %
在客户端程序中,用数组构造器的值初始化输入数组,然后调用过程:

SET PNUMBER_ARRAY = ARRAY['416-305-3745',
'905-414-4565',
'416-305-3746'];
CALL FIND_CUSTOMERS(PNUMBER_ARRAY, -- NUMBERS_IN parameter (IN parm)
‘416’, -- PREFIX parameter (IN parm)
PNUMBER_ARRAY_OUT); -- NUMBERS_OUT parameter (OUT parm)

CALL语句返回一个数组值,其参数中包含以下信息,对应于设置PNUMBER_ARRAY_OUT变量的NUMBERS_OUT参数:
[‘416-305-3745’,
‘416-305-3746’]
