首页 > 数据库 > DB2 > 正文

DB2存储过程开发最佳实践

2023-06-10 13:16:33
字体:
来源:转载
供稿:网友

本文以 DB2 开发人员的角度介绍了在 DB2 存储过程开发中需要注意的事项和技巧。新手如果能够按照本文介绍的最佳实践来开发存储过程,可以避免一些常见的错误,从而编写出高效的程序。本文从初始化参数、游标、异常处理、临时表的使用以及如何寻找并 rebind 非法存储过程等常见问题进行了着重讨论,并且给出了示例代码。

DB2 提供的强大功能可以让开发人员创建出非常高效稳定的存储过程。但对于初学者来说,开发出这样的程序并不容易。本文主要讨论开发高效稳定的 DB2 存储过程的一些常用技巧和方法。

读者定位为具有一定开发经验的 DB2 开发经验的开发人员。

读者可以从本文学习到如何编写稳定、高效的存储过程。并可以直接使用文章中提供的 DB2 代码,从而节省他们的开发和调试时间,提高效率。

本文以 DB2 开发人员的角度介绍了在 DB2 存储过程开发中需要注意的事项和技巧。新手如果能够按照本文介绍的最佳实践来开发存储过程,可以避免一些常见的错误,从而编写出高效的程序。本文从初始化参数、游标、异常处理、临时表的使用以及如何寻找并 rebind 非法存储过程等常见问题进行了着重讨论,并且给出了示例代码。

在存储过程中,开发人员能够声明和设置 SQL 变量、实现流程控制、处理异常、能够对数据进行插入、更新或者删除。同时,客户应用(这里指调用存储过程的应用程序,它可以是 JDBC 的调用,也可以是 ODBC 和 CLI 等)和存储过程之间可以传递参数,并且从存储过程中返回结果集。其中,使用 SQL 编写的 DB2 存储过程是在开发中常见的一种存储过程。本文主要讨论此类存储过程。

最佳实践 1:在创建存储过程语句中提供必要的参数

创建存储过程语句(CREATE PROCEDURE)可以包含很多参数,虽然从语法角度讲它们不是必须的,但是在创建存储过程时提供它们可以提高执行效率。下面是一些常用的参数

容许 SQL (allowed-SQL)

容许 SQL (allowed-SQL)子句的值指定了存储过程是否会使用 SQL 语句,如果使用,其类型如何。它的可能值如下所示:

NO SQL: 表示存储过程不能够执行任何 SQL 语句。

CONTAINS SQL: 表示存储过程可以执行 SQL 语句,但不会读取 SQL 数据,也不会修改 SQL 数据。

READS SQL DATA: 表示在存储过程中包含不会修改 SQL 数据的 SQL 语句。也就是说该储存过程只从数据库中读取数据。

MODIFIES SQL DATA: 表示存储过程可以执行任何 SQL 语句。即可以对数据库中的数据进行增加、删除和修改。

如果没有明确声明 allowed-SQL,其默认值是 MODIFIES SQL DATA。不同类型的存储过程执行的效率是不同的,其中 NO SQL 效率最好,MODIFIES SQL DATA 最差。如果存储过程只是读取数据,但是因为没有声明 allowed-SQL 使其被当作对数据进行修改的存储过程来执行,这显然会降低程序的执行效率。因此创建存储过程时,应当明确声明其 allowed-SQL。

返回结果集个数(DYNAMIC RESULT SETS n)

存储过程能够返回 0 个或者多个结果集。为了从存储过程中返回结果集,需要执行如下步骤:

在 CREATE PROCEDURE 语句的 DYNAMIC RESULT SETS 子句中声明存储过程将要返回的结果集的数量(number-of-result-sets)。如果这里声明的返回结果集的数量小于存储过程中实际返回的结果集数量,在执行该存储过程的时候,DB2 会返回一个警告。

使用 WITH RETURN 子句,在存储过程体中声明游标。

为结果集打开游标。当存储过程返回的时候,保持游标打开。

在创建存储过程时指定返回结果集的个数可以帮助程序员验证存储过程是否返回了所期待数量的结果集,提高了程序的完整性。

最佳实践 2:对输入参数进行必要的的检查和预处理

无论使用哪种编程语言,对输入参数的判断都是必须的。正确的参数验证是保证程序良好运行的前提。同样的,在 DB2 中对输入参数的验证和处理也是很重要的。正确的验证和预处理操作包括:

如果输入参数错误,存储过程应返回一个明确的值告诉客户应用,然后客户应用可以根据返回的值进行处理,或者向存储过程提交新的参数,或者去调用其他的程序。

根据业务逻辑,对输入参数作一定的预处理,如大小写的转换,NULL 与空字符串或 0 的转换等。

在 DB2 储存过程开发中,如需要遇到对空(NULL)进行初始化,我们可以使用 COALESCE 函数。COALESCE函数返回第一个非空的参数,语法如下:

清单1:COALESCE 函数

---------------. (1) V |>>-COALESCE-------(--expression----,--expression-+--)----------><

COALESCE函数会依次检查输入的参数,返回第一个不是NULL的参数,只有当传入COALESCE函数的所有的参数都是NULL的时候,函数才会返回NULL。例如, COALESCE(piName,''),如果变量piName为NULL,那么函数会返回'',否则就会返回piName本身的值。

下面的例子展示了如何对参数进行检查何初始化。

Person表用来存储个人的基本信息,其定义如下:

表1: Person
表1: Person

下面是用于向表Person插入数据的存储过程的参数预处理部分代码:

SET poGenStatus = 0; SET piName = RTRIM(COALESCE(piName, '')); SET piRank = COALESCE(piRank, 0); -- make sure all required input parameters are not null IF ( piNum IS NULL OR piName = '' OR piAge IS NULL ) THEN SET poGenStatus = 34100; RETURN poGenStatus; END IF;

表Person中num、name和age都是非空字段。对于name字段,多个空ge我们也认为是空值,所以在进行判断前我们调用RTRIM和COALESCE对其进行处理,然后使用 piName = '',对其进行非空判断;对于Rank字段,我们希望如果用户输入的NULL,我们把它设置成"0",对其我们也使用COALESCE进行初始化;对于"Age"和"Num" 我们直接使用 IS NULL进行非空判断就可以了。

如果输入参数没有通过非空判断,我们就对输出参数poGenStatus设置一个确定的值(例子中为 34100)告知调用者:输入参数错误。

下面是对参数初始化规则的一个总结,供大家参考:

1. 输入参数为字符类型,且允许为空的,可以使用COALESCE(inputParameter,'')把NULL转换成'';

2. 输入类型为整型,且允许为空的,可以使用COALESCE(inputParameter,0),把空转换成0;

3. 输入参数为字符类型,且是非空非空ge的,可以使用COALESCE(inputParameter,'')把NULL转换成'',然后判断函数返回值是否为'';

4. 输入类型为整型,且是非空的,不需要使用COALESCE函数,直接使用IS NULL进行非空判断。

最佳实践 3:正确设定游标的返回类型

前面我们已经讨论了如何声明存储过程的返回结果集。这里我们讨论一下结果集返回类型的问题。结果集的返回类型有两种:调用者(CALLER) 和客户应用(CLIENT)。首先我们看一下声明这两种游标的例子:

CREATE PROCEDURE getPeople(IN piAge INTEGER)DYNAMIC RESULT SETS 2READS SQL DATALANGUAGE SQLBEGIN DECLARE rs1 CURSOR WITH RETURN TO CLIENT FOR SELECT name, age FROM person WHERE agepiAge; OPEN rs1; OPEN rs2;END

代码中rs1游标的DECLAER语句中包含WITH RETURN TO CLIENT子句,表示结果集返回给客户应用(CLIENT)。rs2游标的DECLARE语句中包含WITH RETURN TO CALLER子句,表示结果集返回给调用者(CALLER)。

游标返回给调用者(CALLER)表示由存储过程的调用者接收结果集,而不考虑调用者是否是另一个存储过程,还是客户应用。图(1)中存储过程PROZ如果声明为WITH RETURN TO CALLER,那么结果ji hui返回给存储过程PROY,Client Application是不会得到PROZ返回的结果集的。

图1:存储过程递归调用
存储过程递归调用

游标返回给客户应用(CLIENT)表示由发出最初 CALL 语句的客户应用接收结果集,即使结果集由嵌套层次中的 15 层深的嵌套存储过程发出也是如此。图1中存储过程 PROZ 如果声明为 WITH RETURN TO CLIENT,那么结果ji hui返回给 Client Application。返回给客户应用(CLIENT)的游标声明是我们经常使用的,也是默认的结果集类型。

在声明返回类型时,我们要认真考虑一下,我们需要把结果集返回给谁,以免丢失返回集,导致程序错误。

发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表