第一部分DB2系统管理命令node
1. Db2有域,实例,和数据库三层的概念。程序员
2. 查看数据库服务器中有几个数据库。包括网络中数据库的引用。web
进入数据库安装目录下的bin目录:C:\Program Files\IBM\SQLLIB\BINsql
执行db2 list database directory命令数据库
3. 查看命令选项说明express
list command options 编程
4. 查看运行的数据库服务器中关联了多少个引用程序对数据库的访问。缓存
进入数据库安装目录下的bin目录:C:\Program Files\IBM\SQLLIB\BIN安全
db2 list applications命令服务器
能够经过db2 force application(进程id) 杀死对应的进程。
5. 如何强制断开应用程序和数据库的链接。
进入数据库安装目录下的bin目录:C:\Program Files\IBM\SQLLIB\BIN
行下列的命令 db2 force applications 能够强制断开应用程序和数据库的链接。
6. 如何备份数据库
进入db2的操做环境,而后运行
backup database 数据库别名 user 用户名 using 密码命令
7. 中止数据库的服务器。
进入数据库安装目录下的bin目录:C:\Program Files\IBM\SQLLIB\BIN
或db2操做环境中,若是在db2操做环境中必须经过的db2 terminate命令终结db2操做环境中启动的全部子进程(即中止全部命令行处理器回话)
再执行db2stop命令。
注意:
在执行此命令的时候,必须没有应用程序或用户和数据库链接。
能够在执行中止命令以前查看于db2服务器链接的应用程序和用户。而后执行牵制断开命令断开链接的数据库和用户。
8. 如何从旧版本中把数据库迁移到新的安装版本中(在新版数据库种运行下列代码)
db2ckmig /e 数据库别名 /l 验证信息保存路径 /u 用户名 /p 密码
MIGRATE database 数据库别名 user 用户名 using 密码命令
9. 启动DB2服务器
进入数据库安装目录下的bin目录:C:\Program Files\IBM\SQLLIB\BIN
或db2操做环境中
执行db2start命令
10. 关于命令行编辑器的使用
使用命令行编辑器以前要链接到一个数据库。在该数据库中能够执行想要执行的命令和 SQL语句。
首先要启动数据库服务器。登录到数据库的服务器上。
而后用在 CA (配置助手)菜单栏上(在 所选 下面)选择 使用向导添加数据库。
添加的数据库能够是网络中的已经运行的数据库。
而后选择手工配置至数据库的链接
若是是网络链接选TCP/IP,若是是本地的数据库则选择本地链接
还要知道数据库服务器中所在的Ip和端口号码,以及数据库的名称。
对于安全性的认证通常采用dbm自带的安全认证。经过以上的配置完成数据库的 链接。
注意若是不知道网络中有那些数据库能够经过配置助手的发现功能搜索网络中的 数据库。能够直接把网络中已知系统中的数据库搜索到。包括已经链接的数据库和 没有链接的数据库
ii. 使用命令行处理器来配置数据库的链接
数据库服务器节点的概念:
为了链接网络上的数据库服务器,访问数据库提出了节点的概念。一个节点惟一对 应一个网络中的数据库。因此不能重复。创建了节点后,能够把节点与一个网络数 据库对应。创建一一之间的映射。注意这个数据库必须是在节点对应的数据库服务 器中存在的。
1) 在客户机上配置TCP/IP的节点
catalog tcpip node 自定义节点名 remote ip地址 server 端口号
terminate(做用是刷新目录的告诉缓存,若是不刷新,只能在重启计算机后 才会起做用)
2) 编目数据库
catalog database 数据库名称(必须在网络中已经存在)as 数据库别名
at node nod名称 authentication 链接数据库时所采用的认证方法
(通常是 server或client)
terminate
3) 创建数据库
create db dbName
4) 链接数据库
经过以上的配置设置。数据库服务进程会保存配置信息。
在db2的会话进程中能够经过
connect to 数据库的别名
链接数据库。这是能够执行sql语句;或用!开头能够执行操做系统的命令
用“\”能够做为多行的分割符。
5) 查看数据库的结构信息命令
链接到数据库后能够查看数据库的结构信息,包括有什么表,什么视图,什么触发 器等等
1) 查看数据库中有多少表或视图
list tables;
2) 查看表或试图的结构
describe table tableName获describe Select * from tableName
10. 数据的导入导出操做
首先链接上数据库;
用export命令
格式以下:
Export to c:\org.txt of del messages d:\msgs.txt select * from org
数据来源 |
保存格式 |
数据保存的位置 |
操做状况保存位置 |
1) 如何导出大对象
export to d:\myfile.del of del lobs to d:\lob\ lobfile lobs modified by
Lobs in file select * from emp_photo
该句的含义是将从“select * from emp_photo”中得到的数据放到“d:\myfile.del of
del”文件中存放的格式是del,其中大对象的位置存放在 d:\lob\,文件名是lobs。
最后modified by lobsinfile指明指定要将大对象(LOB)数据导出到 LOBS TO 子 句中所指定的位置。
2) 如何导入数据
import from D:\TABLE1.ixf of ixf lobs from d:\lob lobfile lobs modified by lobsinfile
savecount 1000 messages D:\msg.txt insert intoTABLE1
// 其中,savecount表示完成每1000条操做,记录一次。将D:\TABLE1.ixf文件中 的数据以ixf格式导入到表table1中。并把d:\lob目录下的文件是lobs的大对象文 件导入到表中
11. 如何执行批处理命令:
首先进现链接数据库
db2 => connect to dbName user xxx using password
退出命令处理器:
db2 => quit
在dos环境下输入sql脚本文件的路径全名
c:\> db2 -tvf 文件名.sql
注意脚本的每一条命令以分号做为结束标志。命令之间永换行符进行分割。
查看要移动的数据库的表空间。表空间是孩子,数据库是父母,一个数据库可有不少表表空间。一个表空间只能属于一个数据库。
List tablespaces
查看每一个表空间的属性
有两种方法
1) 利用dblook命令
db2look –d dbname –e –o db.sql –i username –w password
把数据库名是dbname的数据库的结构信息输入到db.sql的脚本中,username
是链接数据库时的用户名,password时密码
而后创建一个新的空数据库。
再把sql脚本中connect to 新的数据库名
再经过db2 -tvf db.sql运行db.sql的数据库编程脚本。这样就把原来的数据库中全部表再新数据库中创建。只是没有数据
最后用export和import命令把数据导入新的数据库。
2) 在特定的目录下面执行db2move dbname export -u username -p password命
令
把整个数据库移动到该目录下自动创建的5个文件上
(db2move.lst;import.out;export.out;tabl.ixf;tab1.msg)
而后建立一个新的数据库;
最后回到特定的目录(有上述的5个文件),执行
db2move dbname import -u username -p password
第二种方法能够把数据一次所有导入和导出,比较好。
13. 了解数据库服务器的配置是必要的。在某些特定的时候有可能要根据应用程序的要求来 更改数据库服务器的配置。
用命令db2 get dbm cfg命令来运行数据库的配置的相关信息
14. 如何设置数据库服务器的配置
db2 update dbm cfg using 参数名 参数值
15. 读数据库的配置
db2 get db cfg for dbname
16. 设定数据库链接的配置
db2 update db cfg for o_yd using 参数名 参数值
删除数据库链接。(首先要断开关联到数据库应用程序的链接)
drop db dbName
对于本地数据库执行删除
对于网络数据库删除节点编目。
附录:
选项 描述 当前设置
------ ---------------------------------------- ---------------
-a 显示 SQLCA OFF
-c 自动落实 ON
-e 显示 SQLCODE/SQLSTATE OFF
-f 读取输入文件 OFF
-l 将命令记录到历史文件中 OFF
-n 除去换行字符 OFF
-o 显示输出 ON
-p 显示交互式输入提示符 ON
-r 将输出保存到报告文件 OFF
-s 在命令出错时中止执行 OFF
-t 设置语句终止字符 OFF
-v 回送当前命令 OFF
-w 显示 FETCH/SELECT 警告消息 ON
-x 不打印列标题 OFF
-z 将全部输出保存到输出文件 OFF
第二部分数据库的sql语法
与Oracle一致
第三部分编写存储过程
本文以 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 语句,若是使用,其类型如何。它的可能值以下所示:
若是没有明确声明 allowed-SQL,其默认值是 MODIFIES SQL DATA。不一样类型的存储过程执行的效率是不一样的,其中 NO SQL 效率最好,MODIFIES SQL DATA 最差。若是存储过程只是读取数据,可是由于没有声明 allowed-SQL 使其被看成对数据进行修改的存储过程来执行,这显然会下降程序的执行效率。所以建立存储过程时,应当明确声明其 allowed-SQL。
返回结果集个数(DYNAMIC RESULT SETS n)
存储过程可以返回 0 个或者多个结果集。为了从存储过程当中返回结果集,须要执行以下步骤:
在建立存储过程时指定返回结果集的个数能够帮助程序员验证存储过程是否返回了所期待数量的结果集,提升了程序的完整性。
最佳实践 2:对输入参数进行必要的的检查和预处理
不管使用哪一种编程语言,对输入参数的判断都是必须的。正确的参数验证是保证程序良好运行的前提。一样的,在 DB2 中对输入参数的验证和处理也是很重要的。正确的验证和预处理操做包括:
在 DB2 储存过程开发中,如须要遇到对空(NULL)进行初始化,咱们可使用 COALESCE 函数。COALESCE函数返回第一个非空的参数,语法以下:
清单1:COALESCE 函数
.---------------. (1) V | >>-COALESCE-------(--expression----,--expression-+--)---------->< |
COALESCE函数会依次检查输入的参数,返回第一个不是NULL的参数,只有当传入COALESCE函数的全部的参数都是NULL的时候,函数才会返回NULL。例如, COALESCE(piName,''),若是变量piName为NULL,那么函数会返回'',不然就会返回piName自己的值。
下面的例子展现了如何对参数进行检查何初始化。
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字段,多个空格咱们也认为是空值,因此在进行判断前咱们调用RTRIM和COALESCE对其进行处理,而后使用 piName = '',对其进行非空判断;对于Rank字段,咱们但愿若是用户输入的NULL,咱们把它设置成"0",对其咱们也使用COALESCE进行初始化;对于"Age"和"Num" 咱们直接使用 IS NULL进行非空判断就能够了。
若是输入参数没有经过非空判断,咱们就对输出参数poGenStatus设置一个肯定的值(例子中为 34100)告知调用者:输入参数错误。
下面是对参数初始化规则的一个总结,供你们参考:
1. 输入参数为字符类型,且容许为空的,可使用COALESCE(inputParameter,'')把NULL转换成'';
2. 输入类型为整型,且容许为空的,可使用COALESCE(inputParameter,0),把空转换成0;
3. 输入参数为字符类型,且是非空非空格的,可使用COALESCE(inputParameter,'')把NULL转换成'',而后判断函数返回值是否为'';
4. 输入类型为整型,且是非空的,不须要使用COALESCE函数,直接使用IS NULL进行非空判断。
最佳实践 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返回的结果集的。
图1:存储过程递归调用
游标返回给客户应用(CLIENT)表示由发出最初 CALL 语句的客户应用接收结果集,即便结果集由嵌套层次中的 15 层深的嵌套存储过程发出也是如此。图1中存储过程 PROZ 若是声明为 WITH RETURN TO CLIENT,那么结果集会返回给 Client Application。返回给客户应用(CLIENT)的游标声明是咱们常用的,也是默认的结果集类型。
在声明返回类型时,咱们要认真考虑一下,咱们须要把结果集返回给谁,以避免丢失返回集,致使程序错误。
最佳实践 4:异常(condition)处理
在存储过程执行的过程当中,常常由于数据或者其余问题产生异常(condition)。根据业务逻辑,存储过程应该对异常进行相应处理或直接返回给调用者。此处暂且将condition译为异常以方便读者理解。实际上有些异常(condition)并不是是因为错误引发的,下面将详细讲述。
当存储过程当中的语句返回的SQLSTATE值超过00000的时候,就代表在存储过程当中产生了一个异常(condition),它表示出现了错误、数据没有找到或者出现了警告。为了响应和处理存储过程当中出现的异常,咱们必须在存储过程体中声明异常处理器(condition handler),它能够决定存储过程怎样响应一个或者多个已定义的异常或者预约义异常组。声明条件处理器的语法以下,它会位于变量声明和游标声明以后:
清单4:声明异常处理器
DECLARE handler-type HANDLER FOR condition handler-action |
异常处理器类型(handler-type)有如下几种:
异常处理器能够处理基于特定SQLSTATE值的定制异常,或者处理预约义异常的类。预约义的3种异常以下所示:
若是产生了NOT FOUND 或者SQLWARNING异常,而且没有为这个异常定义异常处理器,那么就会忽略这个异常,而且将控制流转向下一个语句。若是产生了SQLEXCEPTION异常,而且没有为这个异常定义异常处理器,那么存储过程就会失败,而且会将控制流返回调用者。
如下示例声明了两个异常处理器。 EXIT处理器会在出现SQLEXCEPTION 或者SQLWARNING异常的时候被调用。EXIT处理器会在终止SQL程序以前,将名为stmt的变量设为"ABORTED",而且将控制流返回给调用者。UNDO处理器会将控制流返回给调用者以前,回滚存储过程体中已经完成的SQL操做。
清单5:异常处理器示例
DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING SET stmt = 'ABORTED'; |
DECLARE UNDO HANDLER FOR NOT FOUND; |
若是预约义异常集不能知足需求,就能够为特定的SQLSTATE值声明定制异常,而后再为这个定制异常声明处理器。语法以下:
清单6:定制异常处理器
DECLARE unique-name CONDITION FOR SQLSATE 'sqlstate' |
处理器能够由单独的存储过程语句定义,也可使用由BEGIN…END块界定的复合语句定义。注意在执行符合语句的时候,SQLSATE和SQLCODE的值会被改变,若是须要保留异常前的SQLSATE和SQLCODE,就须要在执行复合语句的第一个语句把SQLSATE和SQLCODE赋予本地变量或参数。
一般,咱们会为存储过程定义一个执行状态的输出参数(例如:poGenStatus)。
根据这个输出状态,能够代表存储过程是否正确执行完毕。咱们须要定义一些异常处理器为这个输出参数赋值。下面是一个例子:
清单7:定义为输出参数赋值的异常处理器
-- Generic Handler DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND BEGIN NOT ATOMIC -- Capture SQLCODE & SQLSTATE SELECT SQLCODE, SQLSTATE INTO hSqlcode, hSqlstate FROM SYSIBM.SYSDUMMY1;
-- Use the poGenStatus variable to tell the procedure -- what type of error occurred CASE hSqlstate WHEN '02000' THEN SET poGenStatus=5000; WHEN '42724' THEN SET poGenStatus=3; ELSE IF (hSqlCode < 0) THEN SET poGenStatus=hSqlCode; END IF; END CASE; END;
|
上面的异常处理器会在出现SQLEXCEPTION, SQLWARNING, NOT FOUND异常的时候触发。异常处理器会取出当前的SQLCODE, SQLSTATE,而后根据它们的值来设置输出参数(poGenStatus)的值。
咱们还能够定制一些异常处理器。例如,咱们能够定义一些对参数进行初始化的异常处理器。这里,异常处理器能够看做是一个供存储过程本身调用的内部函数。下面是这种状况的一个例子:
清单8:供存储过程本身调用的内部函数
----------------------------------------------------- -- CONDITION declaration ----------------------------------------------------- -- (80100~80199) SQLCODE & SQLSTATE DECLARE sqlReset CONDITION for sqlstate '80100';
----------------------------------------------------- -- EXCEPTION HANDLER declaration ----------------------------------------------------- -- Handy Handler DECLARE CONTINUE HANDLER FOR sqlReset BEGIN NOT ATOMIC SET hSqlcode = 0; SET hSqlstate = '00000'; SET poGenStatus = 0; END; ………… ----------------------------------------------------- -- Procedure Body ----------------------------------------------------- SIGNAL sqlreset;
-- insert the record …………
|
上面定制的异常处理器负责对参数hSqlcode,hSqlstate和poGenStatus初始化。当咱们在程序中须要对它们初始化时,咱们只须要调用SIGNAL sqlreset就能够了。
最佳实践 5:合理使用临时表
咱们在储存过程开发中常用临时表。合理的使用临时表能够简化程序的编写,提供执行效率,然而滥用临时表一样也会使得程序运行效率下降。
临时表通常在以下状况下使用:
1. 临时表用于存储程序运行中的临时数据。例如,若是在一个程序中第一条查询语句执行的结果会被后续的查询语句用到,那么咱们能够把第一次查询的结果存储在一个临时表中供后续查询语句使用,而不是在后续查询语句中从新查询一次。若是第一条查询语句很是复杂和耗时,那么上面的策略是很是有效的。
2. 临时表能够用于存储在一个程序中须要返回屡次的结果集。例如,程序中有一个很耗资源的多表查询,同时,该查询在程序中须要执行屡次,那么就能够把第一次查询的结果集存储在临时保中,后续的查询只须要查临时表就能够了。
3. 临时表也能够用于让SQL访问非关系型数据库。例如,能够编写程序把非关系型数据库中的数据插入到一个全局临时表中,那么咱们就能够对其数据进行查询。
咱们可以使用 DECLARE GLOBAL TEMPORARY TABLE 语句来定义临时表。DB2的临时表是基于会话的,且在会话之间是隔离的。当会话结束时,临时表的数据被删除,临时表被隐式卸下。对临时表的定义不会在SYSCAT.TABLES中出现 下面是定义临时表的一个示例:
清单9:定义临时表
DECLARE GLOBAL TEMPORARY TABLE gbl_temp LIKE person ON COMMIT DELETE ROWS NOT LOGGED IN usr_tbsp |
此语句建立一个名为 gbl_temp 的用户临时表。定义此用户临时表 所使用的列的名称和说明与 person 的列的名称和说明彻底相同。
清单10:建立有两个字段的临时表
DECLARE GLOBAL TEMPORARY TABLE SESSION.TEMP2 ( ID INTEGER default 3, NAME CHAR(30) ) --WITH REPLACE NOT LOGGED; --IN USER_TEMP_01;
|
此语句建立了一个有两个字段的临时表。
理论上临时表是不须要显示DROP的,由于它是基于会话的,当临时表基于的链接关闭的时候,临时表也就不存在了。可是在实际开发中会有一些状况须要咱们对临时表加以注意。
一种状况就是被调用的存储过程的返回值是一个基于临时表的结果集。当存储过程执行完毕的时候,临时表并不会消失,由于返回的结果集至关于一个指针,指向临时表所在的内存地址,此时临时表是不会被DROP掉的。这种状况下,既不能在存储过程当中删除这个临时表,也不该该由客户应用显示的删除临时表,这就容易出现一些问题。下面咱们经过一个例子来讲明这个问题。
下面示例代码是返回临时表的存储过程(get_temp_table):
清单11:返回临时表的存储过程
----------------------------------------------------- -- TEMPORARY TABLE & CURSOR declaration ----------------------------------------------------- DECLARE GLOBAL TEMPORARY TABLE SESSION.TEMP ( ID INTEGER, NAME CHAR(30) ) --WITH REPLACE NOT LOGGED;
P2: BEGIN
DECLARE R_CRSR CURSOR WITH RETURN TO CLIENT FOR SELECT * FROM SESSION.TEMP FOR READ ONLY;
INSERT INTO SESSION.TEMP VALUES(1,piName);
OPEN R_CRSR;
END P2;
|
存储过程当中声明了有两个字段的临时表TEMP,声明了一个游标R_CRSR返回临时表中全部记录,最后在临时表中插入两条记录。
程序第一次执行的结果以下:
图2:程序第一次执行的结果
能够从图中看出,运行结果是咱们指望的。那么若是咱们再运行一次,会有什么结果呢?下图是其运行结果:
图3:程序再次执行的结果
第二次执行的时候程序却出错了,这是由于在同一个链接中,临时表并无被DROP掉,因此在第二次调用存储过程的时候就会出现临时表已经存在的错误。
另一种状况,就是不少时候例如在websphere中经过JDBC链接数据库时使用了链接池的技术,这带来了一些效率的提高,同时在某些状况下也容易让人误解。客户应用程序中关闭了数据库链接,可是并不必定真正关闭了数据库链接,若是客户应用程序使用了临时表而数据库链接并无关闭,那么临时表就不会被DROP。当链接池把这个链接分给另外一个客户程序的时候,新的客户程序仍然可使用旧的临时表,这不是咱们但愿的。若是想避免上述问题,能够在建立临时表时,加上WITH REPLACE;或者根据业务逻辑在合适的地方显示的DROP临时表。
下面是使用WITH REPLACE建立临时表的执行状况。
图4:使用WITH REPLACE建立临时表
能够看出在一个链接里面,屡次调用存储过程get_temp_table,也不会出现问题。临时表在某些状况下也是须要避免使用的。你们知道临时表是存放在内存中的,若是一个临时表有上万或者十几万条记录,同时程序的并发数很大,那么在内存中创建的临时表耗费的资源就很庞大,此时数据库的性能会急剧降低,甚至会致使数据库崩溃。所以,你们在使用临时表的时候,须要考虑它对资源的耗费,避免盲目使用临时表。
最佳实践 6:寻找并rebind 非法的存储过程
存储过程会由于其涉及和引用的对象发生了改变而致使其非法(invalid),例如:修改了表结构,致使引用该表的存储过程非法,或者从新编译一个存储过程,会使调用这个存储过程的父存储过程非法。此时咱们须要对非法的存储过程从新编译(rebind)。可是,对非法的存储过程进行rebind的时候,须要肯定其引用的对象是合法的,不然非法的存储过程也不能rebind成功。
这里咱们介绍一下发现和rebind非法存储过程的方法。咱们是经过判断SYSCAT.routines中VALID字段的值来查找非法存储过程的。下面是查找非法存储过程的一段代码:
清单12:查找非法存储过程
SELECT RTRIM(r.routineschema) || '.' || RTRIM(r.routinename) AS spname , ' ( '|| RTRIM(r.routineschema) || '.' || 'P'||SUBSTR(CHAR(r.lib_id+10000000),2)||' )' FROM SYSCAT.routines r WHERE r.routinetype = 'P' AND ((r.origin = 'Q' AND r.valid != 'Y') OR EXISTS ( SELECT 1 FROM syscat.packages WHERE pkgschema = r.routineschema AND pkgname = 'P'||SUBSTR(CHAR(r.lib_id+10000000),2) AND valid !='Y' ) ) ORDER BY spname;
|
得到的结果以下:
清单13:查找非法存储过程的结果
SPNAME ---------------------------------- TEST.DEMO_INFO_8 (TEST. P3550884)
|
可使用下面的命令rebind它们
清单14:Rebind 非法存储过程语法
rebind package packagename resolve any@ |
Packagename就是查询结果中括号里的值。例如,若是rebind上面查出来的存储过程。咱们只须要执行下面语句
清单15:Rebind 非法存储过程
rebind package TEST.P3550884 resolve any@ |
固然,若是此存储过程程序自己有问题,须要先修改存储过程代码后再进行编译。
相似的,经过下面的代码能够得到非法的视图。
清单16:得到非法的视图
SELECT RTRIM(viewschema) || '.' || RTRIM(viewname) AS viewname FROM SYSCAT.views WHERE valid = 'X' ORDER BY viewname;
|
本文介绍了咱们在 DB2 存储过程开发中常常用到的一些技巧。同时这些技巧也是编写优秀存储过程的基本要求。本文介绍的一些技巧只是揭开了高效使用 DB2 的冰山一角。DB2 为咱们提供了丰富和强大的功能。在使用 DB2 的时候,咱们应当深刻理解其原理,找出更多的最佳实践与你们分享。