用 SQL PL 在不同平台上开发 DB2 存储过程已经变得非常流行。尽管用于 DB2 for iSeries、DB2 for Linux、UNIX and Windows(它们也被称为分布式平台)和用于 DB2 for z/OS 的 SQL PL 语言基本相同,但在不同操作系统实现和 DB2 版本之间,仍然存在一些差异。
本文将简单概述不同平台上和各种 DB2 版本中的 SQL PL 实现之间的差异,为编写可移植数据库应用程序或者将数据库应用程序从一个平台移植到另一个平台的 SQL 过程开发人员提供帮助。
请注意,如果您正在 z/OS 上运行 Linux,那么您可能要在 Linux 上处理 DB2,所有这些规则也适用于 DB2 for Linux、UNIX and Windows 。
CREATE PROCEDURE 语句
该语句的语法在平台间非常类似,如下所示:
CREATE PROCEDURE procname
( IN/OUT/INOUT parameter_name DB2_data_type )
specific_name list_of_options SQL_body
以下是各种平台在 CREATE PROCEDURE 实现方面的一些差异。
- 尽管在分布式平台上存储过程可以被重载(比如说,您可以用过程 abc(p1, p2, p3) 来重载过程 abc(p1,p2)),但在 z/OS 平台上,不允许存储过程重载,因此,如果您正在设计必须在两个平台上都能获得实现的应用程序,那么最好避免重载。
- 尽管这两种平台都支持所有 DB2 本机数据类型,但是 z/OS 平台上的 DB2 v8 支持
TABLE LIKE__table-name__AS LOCATOR,因此它允许在转换表(transition table)中对参数进行详细说明。 - 在调用存储过程时,并没有将转换表中的实际值传递给存储过程,而是只传递了一个单值。这个单值是转换表的定位器,存储过程用它来访问转换表的列。带有表参数的过程只能从触发器的触发操作调用。
- 尽管对于用于 z/OS 上的 DB2 的 SQL 过程而言,LANGUAGE SQL 是强制性子句,但是现在,对于分布式系统上的 UDB v8,它是可选的,不过还是建议您总是为平台独立的过程指定这个子句。
- 指定的名称对于 UDB 是推荐的(但亦是可选的),而对于 z/OS 上的 DB2 是不被支持的。相反,z/OS 上的 DB2 支持一个可选的外部名称,正如下面您将看到的那样。
现在来比较其他选项。以下选项在两种平台上都受支持。它们是可选的,并且可以按任意顺序指定:
- DYNAMIC RESULT SETS 0 / 整数 —— 指定存储过程可以返回的查询结果集的最大数量。默认值是 DYNAMIC RESULT SETS 0,该值表示没有结果集。这个值必须在 0 到 32767 之间。
- NOT DETERMINISTIC / DETERMINISTIC —— 指定对于包含相同 IN 和 INOUT 参数的每次调用,存储过程是否返回相同的结果集。DB2 并没有检验该存储过程代码是否与 DETERMINISTIC 或 NOT DETERMINISTIC 的规格说明一致。
- MODIFIES SQL DATA / READS SQL DATA / CONTAINS SQL —— 指定了对存储过程可以执行的 SQL 语句进行分类的方法。默认值是 MODIFIES SQL DATA。
- CALLED ON NULL INPUT —— 指定将调用的过程,即使任何参数值或所有参数都为 null,这意味着必须对过程进行编码,来测试那些 null 参数值。该过程可以返回 null 或非 null 值。默认值是 CALLED ON NULL INPUT。
以下选项只被 z/OS 上的 DB2 支持,它们是可选的,并且可以按任何既定顺序对它们进行选择。如果您希望存储过程在两种环境中都能运行,那么对于分布式实现,应该将这些选项注释掉,但要在 DB2 for z/OS 环境下使用:
- NO COLLID / COLLID 集合 ID —— 识别执行存储过程时使用的包集合(package collection)。与存储过程相关的 DBRM 被绑定到这个包集合中。该选项的默认值为 NO COLLID。
- WLM ENVIROMENT 名称 —— 识别 WLM(工作负载管理器)环境,当 DB2 存储过程的地址空间是 WLM 建立的时候,存储过程将在该环境中运行。WLM 环境的名称是一个 SQL 标识符。如果没有指定 WLM ENVIRONMENT,那么存储过程将在安装时指定的默认的 WLM 建立的存储过程地址空间中运行。
- PROGRAM TYPE MAIN / SUB —— 指定存储过程是作为主例程来运行,还是作为子例程来运行。对于 SQL 过程而言,MAIN 是默认值。
- EXTERNAL NAME 字符串 / 标识符 —— 在 SQL CALL 语句中指定过程名称时,指定程序的 z/OS 装入模块。该值必须遵守 z/OS 装入模块的命名约定:该值必须小于或等于 8 字节,并且必须遵守为普通标识符制定的规则,但有一个例外,它不能包含下划线。
以下存储过程就是一个例子,两种平台上都可以构建这个存储过程,无需任何更改:
|
第二个例子展示了一个用于 z/OS 的DB2 SQL 存储过程。这个存储过程运行在一个称为 PARTSA 的 WLM 环境中,并在执行时使用包集合 PROC_COL。SQL 的工作是在返回调用者那里时提交的。
|
对于 z/OS 上的 DB2 而言,CREATE PROCEDURE 语句的选项并不只局限于上述选项。其他特定的 z/OS 选项则要根据采用 z/OS 上的 DB2 的特定需要来使用。
变量的声明
在局部变量、游标和临时表的声明方面,两种平台没什么差别,但在这两种平台上,声明的顺序却很重要。必须总是在开头的代码块中对游标进行声明。声明顺序如下:
- 局部变量声明。
- 游标声明。
- 临时表声明。
- 条件声明。
- SQL 控制语句。
赋值语句
尽管在分布式平台和 DB2 v8 for z/OS 上,语法和语义方面没有什么不同,但是您应该注意到,DB2 v7 for z/OS 不支持赋值语句中的完全选择。所以该语句将如下所示:
|
这在 DB v7 中是不受支持的。
SQL 控制语句
z/OS 平台上的 DB2 v8 支持在分布式平台的 UDB 上受支持的所有语句,FOR 语句(或 FOR LOOP)除外。
以下语句在 DB2 for z/OS v7 上不受支持:
- RESIGNAL
- SIGNAL
- RETURN
错误处理
对于这两种平台上的数据库,您都可以声明错误处理程序,如果带有特殊的错误代码(SQLCODE 或 SQLSTATE)的 SQL 语句失败,那么该处理程序将判定应采取哪些措施。
一些一般性的语法是通用的:
|
尽管在 z/OS 平台的 DB2 上,能够执行的操作只有 CONTINUE 或 EXIT,但分布式平台上的 DB2 还支持 UNDO。
此外,z/OS 上的 DB2 要求您为每个条件指定 HANDLER,尽管对于多个条件,分布式平台上的 DB2 可以只支持一个 HANDLER。此外,z/OS 平台上的 DB2 不支持嵌套的复合语句,所以,将多条 SQL 语句放入 BEGIN..END 块中是不受支持的。例如下面来自分布式平台上的 DB2 的处理程序声明:
|
要将该声明用于 z/OS 平台上的 DB2,则必须将它更改如下:
|
或者:
|
GET DIAGNOSTICS 语句
GET DIAGNOSTICS 语句提供了有关最后被执行的 SQL 语句(GET DIAGNOSTICS 语句自身除外)的诊断信息。尽管用途相同,语法也大致相同,但该语句在不同的平台和版本之间存在很大的差异。
从 z/OS v7 上的 DB2 开始。
z/OS 上的 DB2 只支持返回 SQL 语句处理过的行数:
|
分布式平台上的 DB2(连同行数一起)可以返回调用过程中的状态(返回代码),同时还返回一个本地 DB2 错误消息,该消息对应于特定的 SQLCODE/SQLSTATE。所以在分布式平台上,这条语句的语法如下所示:
|
请注意,尽管在分布式平台以前的 DB2 版本中,只有关键字 RETURN_STATUS 和 MESSAGE_TEXT 是受支持的,但版本 8 为您提供了更大的灵活性,您还可以使用关键字 DB2_RETURN_STATUS 和 DB2_TOKEN_STRING。
GET DIAGNOSTICS 语句不受上述信息的限制。
GET DIAGNOSTICS 语句几乎支持对 SQLCA 区域的所有字段的检索,该区域由用于每条 SQL 语句的数据库来填充。关于该语句的完整语法,请参阅 DB2 UDB for z/OS V8 SQL Reference(SC18-7426-00)。
结束语
本文描述了在分布式平台(Linux、UNIX、Windows 等)和 z/OS 上使用 SQL 过程语言实现 DB2 存储过程的区别。
致谢
感谢来自硅谷实验室的 Tom Miller,感谢他审阅本文的初稿并给出了一些有建设性的建议。