ERP俱乐部
ERP爱好者、ERP从业者互相交流、互相学习的乐园;我们的愿景是成为全球一流的中文ERP(Enterprise Resource Planning)交流平台
网站首页 论坛首页 搜索 用户列表 FAQ 注册 登录  
ERP俱乐部 -> 数据库专栏 -> DB2数据库 -> DB2 存储过程开发最佳实践
  DB2 存储过程开发最佳实践
帖子发起人: charlieokok   发起时间: 2007-09-23 09:57 上午   回复数: 6
? 上一主题 下一主题 ?
楼主
  2007-09-23, 09:57 上午
charlieokok 离线,最后访问时间: 2009/2/8 13:50:49 charlieokok

发帖数前10位
男

130级
等级: 130级
注册: 2007年8月3日
区域: 上海浦东
经验: 12,450
积分: 8,738
精华: 0
发贴: 2,427
排名: 2
Global ModeratorsSite ModeratorsSite Registered Users每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星
DB2 存储过程开发最佳实践
 
本文以 DB2 开发人员的角度介绍了在 DB2 存储过程开发中需要注意的事项和技巧。新手如果能够按照本文介绍的最佳实践来开发存储过程,可以避免一些常见的错误,从而编写出高效的程序。本文从初始化参数、游标、异常处理、临时表的使用以及如何寻找并 rebind 非法存储过程等常见问题进行了着重讨论,并且给出了示例代码。

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

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

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

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

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


-
分享按钮 IP 地址: 已登录   来自: 已登录    返回顶部
第 2 楼
  2007-09-23, 09:57 上午
charlieokok 离线,最后访问时间: 2009/2/8 13:50:49 charlieokok

发帖数前10位
男

130级
等级: 130级
注册: 2007年8月3日
区域: 上海浦东
经验: 12,450
积分: 8,738
精华: 0
发贴: 2,427
排名: 2
Global ModeratorsSite ModeratorsSite Registered Users每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星
Re: 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 子句,在存储过程体中声明游标。
为结果集打开游标。当存储过程返回的时候,保持游标打开。
在创建存储过程时指定返回结果集的个数可以帮助程序员验证存储过程是否返回了所期待数量的结果集,提高了程序的完整性。



-
IP 地址: 已登录   来自: 已登录    返回顶部
第 3 楼
  2007-09-23, 09:57 上午
charlieokok 离线,最后访问时间: 2009/2/8 13:50:49 charlieokok

发帖数前10位
男

130级
等级: 130级
注册: 2007年8月3日
区域: 上海浦东
经验: 12,450
积分: 8,738
精华: 0
发贴: 2,427
排名: 2
Global ModeratorsSite ModeratorsSite Registered Users每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星
Re: DB2 存储过程开发最佳实践
 
最佳实践 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表用来存储个人的基本信息,其定义如下:


-
分享按钮 IP 地址: 已登录   来自: 已登录    返回顶部
第 4 楼
  2007-09-23, 09:57 上午
charlieokok 离线,最后访问时间: 2009/2/8 13:50:49 charlieokok

发帖数前10位
男

130级
等级: 130级
注册: 2007年8月3日
区域: 上海浦东
经验: 12,450
积分: 8,738
精华: 0
发贴: 2,427
排名: 2
Global ModeratorsSite ModeratorsSite Registered Users每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星
Re: DB2 存储过程开发最佳实践
 
最佳实践 3:正确设定游标的返回类型

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


CREATE PROCEDURE getPeople(IN piAge INTEGER)
DYNAMIC RESULT SETS 2
READS SQL DATA
LANGUAGE SQL
BEGIN
DECLARE rs1 CURSOR WITH RETURN TO CLIENT FOR
SELECT name, age FROM person
WHERE age<piAge;
DECLARE rs2 CURSOR WITH RETURN TO CALLER FOR
SELECT NAME, age FROM person
WHERE age>piAge;
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,那么结果集会返回给存储过程PROY,Client Application是不会得到PROZ返回的结果集的。


-
IP 地址: 已登录   来自: 已登录    返回顶部
第 5 楼
  2007-09-23, 09:57 上午
charlieokok 离线,最后访问时间: 2009/2/8 13:50:49 charlieokok

发帖数前10位
男

130级
等级: 130级
注册: 2007年8月3日
区域: 上海浦东
经验: 12,450
积分: 8,738
精华: 0
发贴: 2,427
排名: 2
Global ModeratorsSite ModeratorsSite Registered Users每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星
Re: DB2 存储过程开发最佳实践
 
最佳实践 4:异常(condition)处理

在存储过程执行的过程中,经常因为数据或者其他问题产生异常(condition)。根据业务逻辑,存储过程应该对异常进行相应处理或直接返回给调用者。此处暂且将condition译为异常以方便读者理解。实际上有些异常(condition)并非是由于错误引起的,下面将详细讲述。

当存储过程中的语句返回的SQLSTATE值超过00000的时候,就表明在存储过程中产生了一个异常(condition),它表示出现了错误、数据没有找到或者出现了警告。为了响应和处理存储过程中出现的异常,我们必须在存储过程体中声明异常处理器(condition handler),它可以决定存储过程怎样响应一个或者多个已定义的异常或者预定义异常组。声明条件处理器的语法如下,它会位于变量声明和游标声明之后:


-
分享按钮 IP 地址: 已登录   来自: 已登录    返回顶部
第 6 楼
  2007-09-23, 09:58 上午
charlieokok 离线,最后访问时间: 2009/2/8 13:50:49 charlieokok

发帖数前10位
男

130级
等级: 130级
注册: 2007年8月3日
区域: 上海浦东
经验: 12,450
积分: 8,738
精华: 0
发贴: 2,427
排名: 2
Global ModeratorsSite ModeratorsSite Registered Users每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星
Re: DB2 存储过程开发最佳实践
 
最佳实践 5:合理使用临时表

我们在储存过程开发中经常使用临时表。合理的使用临时表可以简化程序的编写,提供执行效率,然而滥用临时表同样也会使得程序运行效率降低。

临时表一般在如下情况下使用:

1. 临时表用于存储程序运行中的临时数据。例如,如果在一个程序中第一条查询语句执行的结果会被后续的查询语句用到,那么我们可以把第一次查询的结果存储在一个临时表中供后续查询语句使用,而不是在后续查询语句中重新查询一次。如果第一条查询语句非常复杂和耗时,那么上面的策略是非常有效的。

2. 临时表可以用于存储在一个程序中需要返回多次的结果集。例如,程序中有一个很耗资源的多表查询,同时,该查询在程序中需要执行多次,那么就可以把第一次查询的结果集存储在临时保中,后续的查询只需要查临时表就可以了。

3. 临时表也可以用于让SQL访问非关系型数据库。例如,可以编写程序把非关系型数据库中的数据插入到一个全局临时表中,那么我们就可以对其数据进行查询。

我们可使用 DECLARE GLOBAL TEMPORARY TABLE 语句来定义临时表。DB2的临时表是基于会话的,且在会话之间是隔离的。当会话结束时,临时表的数据被删除,临时表被隐式卸下。对临时表的定义不会在SYSCAT.TABLES中出现 下面是定义临时表的一个示例:

-
IP 地址: 已登录   来自: 已登录    返回顶部
第 7 楼
  2007-09-23, 09:58 上午
charlieokok 离线,最后访问时间: 2009/2/8 13:50:49 charlieokok

发帖数前10位
男

130级
等级: 130级
注册: 2007年8月3日
区域: 上海浦东
经验: 12,450
积分: 8,738
精华: 0
发贴: 2,427
排名: 2
Global ModeratorsSite ModeratorsSite Registered Users每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星每日发帖之星
Re: DB2 存储过程开发最佳实践
 
最佳实践 6:寻找并rebind 非法的存储过程

存储过程会因为其涉及和引用的对象发生了改变而导致其非法(invalid),例如:修改了表结构,导致引用该表的存储过程非法,或者重新编译一个存储过程,会使调用这个存储过程的父存储过程非法。此时我们需要对非法的存储过程重新编译(rebind)。但是,对非法的存储过程进行rebind的时候,需要确定其引用的对象是合法的,否则非法的存储过程也不能rebind成功。

这里我们介绍一下发现和rebind非法存储过程的方法。我们是通过判断SYSCAT.routines中VALID字段的值来查找非法存储过程的。下面是查找非法存储过程的一段代码:


-
分享按钮 IP 地址: 已登录   来自: 已登录    返回顶部
 第 1 页 总共 1 页 [共有 7 条记录]
ERP俱乐部 -> 数据库专栏 -> DB2数据库 -> DB2 存储过程开发最佳实践
(C)Copyright 2005-2020 www.erpclub.org All Rights Reserved.
Tel:+86-755-26444630
Email:webmaster@yok.com.cn