Prayer

在一般中寻求卓越
posts - 1256, comments - 190, trackbacks - 0, articles - 0
  C++博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

讲解DB2数据库编程所应掌握的基本知识

Posted on 2008-08-19 18:29 Prayer 阅读(368) 评论(0)  编辑 收藏 引用 所属分类: DB2

1. DB2数据库编程

◆1.1 建存储过程时Create 后一定不要用TAB键


create procedure

的create后只能用空格,而不可用tab健,否则编译会通不过。

切记,切记。


◆1.2 使用临时表


要注意,临时表只能建在user tempory tables space 上,如果database只有system tempory table space是不能建临时表的。


另外,DB2的临时表和sybase及oracle的临时表不太一样,DB2的临时表是在一个session内有效的。所以,如果程序有多线程,最好不要用临时表,很难控制。


建临时表时最好加上 with replace选项,这样就可以不显示的drop 临时表,建临时表时如果不加该选项而该临时表在该session内已创建且没有drop,这时会发生错误。


◆1.3 从数据表中取指定前几条记录


select * from tb_market_code fetch first 1 rows only

 

但下面这种方式不允许:


select market_code into v_market_code from tb_market_code fetch first 1 rows only;

 

选第一条记录的字段到一个变量以以下方式代替:


declare v_market_code char(1); declare cursor1 cursor for select market_code from tb_market_code fetch first 1 rows only for update; open cursor1; fetch cursor1 into v_market_code; close cursor1;

 

◆1.4 游标的使用


注意commit和rollback

使用游标时要特别注意如果没有加with hold 选项,在Commit和Rollback时,该游标将被关闭。Commit 和Rollback有很多东西要注意。特别小心。


游标的两种定义方式:


一种为:


declare continue handler for not found begin set v_notfound = 1; end; declare cursor1 cursor with hold for select market_code from tb_market_code for update; open cursor1; set v_notfound=0; fetch cursor1 into v_market_code; while v_notfound=0 Do --work set v_notfound=0; fetch cursor1 into v_market_code; end while; close cursor1;

 

这种方式使用起来比较复杂,但也比较灵活。特别是可以使用with hold 选项。如果循环内有commit或rollback 而要保持该cursor不被关闭,只能使用这种方式。


另一种为:


pcursor1: for loopcs1 as cousor1 cursor as select market_code as market_code from tb_market_code for update do end for;

 

这种方式的优点是比较简单,不用(也不允许)使用open,fetch,close。

但不能使用with hold 选项。如果在游标循环内要使用commit,rollback则不能使用这种方式。如果没有commit或rollback的要求,推荐使用这种方式(看来For这种方式有问题)。

修改游标的当前记录的方法


update tb_market_code set market_code='0' where current of cursor1;

 

不过要注意将cursor1定义为可修改的游标


declare cursor1 cursor for select market_code from tb_market_code for update;

 

for update 不能和GROUP BY、 DISTINCT、 ORDER BY、 FOR READ ONLY及UNION, EXCEPT, or INTERSECT但 UNION ALL除外)一起使用。

 

◆1.5 类似decode的转码操作

oracle中有一个函数


select decode(a1,'1','n1','2','n2','n3') aa1 from

 

db2没有该函数,但可以用变通的方法。


select case a1 when '1' then 'n1' when '2' then 'n2' else 'n3' end as aa1 from

 

◆1.6 类似charindex查找字符在字串中的位置


Locate(‘y’,’dfdasfay’)

查找’y’ 在’dfdasfay’中的位置。


◆1.7 类似datedif计算两个日期的相差天数


days(date(‘2001-06-05’)) – days(date(‘2001-04-01’))

days 返回的是从 0001-01-01 开始计算的天数


◆1.8 写UDF的例子


C写见sqllib\samples\cli\udfsrv.c


◆1.9 创建含identity值(即自动生成的ID)的表


建这样的表的写法:


CREATE TABLE test (t1 SMALLINT NOT NULL GENERATED ALWAYS AS IDENTITY (START WITH 500, INCREMENT BY 1), t2 CHAR(1));

 

在一个表中只允许有一个identity的column。


◆1.10 预防字段空值的处理


SELECT DEPTNO ,DEPTNAME ,COALESCE(MGRNO ,'ABSENT'),ADMRDEPT FROM DEPARTMENT

 

COALESCE函数返回()中表达式列表中第一个不为空的表达式,可以带多个表达式。

和oracle的isnull类似,但isnull好象只能两个表达式。


◆1.11 取得处理的记录数


declare v_count int; update tb_test set t1=’0’ where t2=’2’; --检查修改的行数,判断指定的记录是否存在 get diagnostics v_ count=ROW_COUNT;

 

只对update,insert,delete起作用.

不对select into 有效


◆1.12 从存储过程返回结果集(游标)的用法


(1)建一sp返回结果集


CREATE PROCEDURE DB2INST1.Proc1 ( ) LANGUAGE SQL result sets 2(返回两个结果集) ------------------------------------------------------------------------ -- SQL 存储过程 ------------------------------------------------------------------------ P1: BEGIN declare c1 cursor with return to caller for select market_code from tb_market_code; --指定该结果集用于返回给调用者 declare c2 cursor with return to caller for select market_code from tb_market_code; open c1; open c2; END P1

 

(2)建一SP调该sp且使用它的结果集


CREATE PROCEDURE DB2INST1.Proc2 ( out out_market_code char(1)) LANGUAGE SQL ------------------------------------------------------------------------ -- SQL 存储过程 ------------------------------------------------------------------------ P1: BEGIN declare loc1,loc2 result_set_locator varying; --建立一个结果集数组 call proc1; --调用该SP返回结果集。 associate result set locator(loc1,loc2) with procedure proc1; --将返回结果集和结果集数组关联 allocate cursor1 cursor for result set loc1; allocate cursor2 cursor for result set loc2; --将结果集数组分配给cursor fetch cursor1 into out_market_code; --直接从结果集中赋值 close cursor1; END P1

 

(3)动态SQL写法


DECLARE CURSOR C1 FOR STMT1; PREPARE STMT1 FROM 'ALLOCATE C2 CURSOR FOR RESULT SET ?';

 

(4)注意:

一、 如果一个sp调用好几次,只能取到最近一次调用的结果集。

二、 allocate的cursor不能再次open,但可以close,是close sp中的对应cursor。


◆1.13 类型转换函数


select cast ( current time as char(8)) from tb_market_code

 

◆1.14 存储过程的互相调用


目前,c sp可以互相调用。

Sql sp 可以互相调用,

Sql sp 可以调用C sp,

但C sp 不可以调用Sql sp(最新的说法是可以)。


◆1.15 C存储过程参数注意


create procedure pr_clear_task_ctrl( IN IN_BRANCH_CODE char(4), IN IN_TRADEDATE char(8), IN IN_TASK_ID char(2), IN IN_SUB_TASK_ID char(4), OUT OUT_SUCCESS_FLAG INTEGER ) DYNAMIC RESULT SETS 0 LANGUAGE C PARAMETER STYLE GENERAL WITH NULLS(如果不是这样,sql 的sp将不能调用该用c写的存储过程,产生保护性错误) NO DBINFO FENCED MODIFIES SQL DATA EXTERNAL NAME 'pr_clear_task_ctrl!pr_clear_task_ctrl'@

 

◆1.16 存储过程fence及unfence


fence的存储过程单独启用一个新的地址空间,而unfence的存储过程和调用它的进程使用同一个地址空间。一般而言,fence的存储过程比较安全。有时一些特殊的要求,如要取调用者的pid,则fence的存储过程会取不到,而只有unfence的能取到。

 


◆1.17 SP错误处理用法


如果在SP中调用其它的有返回值的,包括结果集、临时表和输出参数类型的SP,DB2会自动发出一个SQLWarning。而在我们原来的处理中对于SQLWarning都会插入到日志,这样子最后会出现多条SQLCODE=0的警告信息。


处理办法:


定义一个标志变量,比如DECLARE V_STATUS INTEGER DEFAULT 0,

在CALL SPNAME之后, SET V_STATUS = 1,

DECLARE CONTINUE HANDLER FOR SQLWARNING

BEGIN

IF V_STATUS <> 1 THEN

--警告处理,插入日志

SET V_STATUS = 0;

END IF;

END;


◆1.18 import用法


db2 import from gh1.out of DEL messages err.txt insert into db2inst1.tb_dbf_match_ha


注意要加schma。


◆1.19 values的使用


如果有多个 set 语句给变量付值,最好使用values语句,改写为一句。这样可以提高效率。


但要注意,values不能将null值付给一个变量。

values(null) into out_return_code;

这个语句会报错的。


◆1.20 给select 语句指定隔离级别


select * from tb_head_stock_balance with ur

 

◆1.21 atomic及not atomic区别


atomic是将该部分程序块指定为一个整体,其中任何一个语句失败,则整个程序块都相当于没做,包括包含在atomic块内的已经执行成功的语句也相当于没做,有点类似于transaction。

2.DB2编程性能注意


◆2.1 大数据的导表


应该是export后再load性能更好,因为load不写日志。比select into 要好。


◆2.2 SQL语句尽量写复杂SQL


尽量使用大的复杂的SQL语句,将多而简单的语句组合成大的SQL语句对性能会有所改善。DB2的 SQL Engieer对复杂语句的优化能力比较强,基本上不用当心语句的性能问题。Oracle 则相反,推荐将复杂的语句简单化, SQL Engieer的优化能力不是特别好。这是因为每一个SQL语句都会有reset SQLCODE和SQLSTATE等各种操作,会对数据库性能有所消耗。一个总的思想就是尽量减少SQL语句的个数。


◆2.3 SQL SP及C SP的选择


首先,C的sp的性能比sql 的sp 的要高。一般而言,SQL语句比较复杂,而逻辑比较简单,sql sp 与 c sp 的性能差异会比较小,这样从工作量考虑,用SQL写比较好。而如果逻辑比较复杂,SQL比较简单,用c写比较好。


◆2.4 查询的优化(HASH及RR_TO_RS)


db2set DB2_HASH_JOIN=Y (HASH排序优化)

指定排序时使用HASH排序,这样db2在表join时,先对各表做hash排序,再join,这样可以大大提高性能。

剧沈刚说做实验,7个一千万条记录表的做join取10000条记录,再没有索引的情况下 72秒。


db2set DB2_RR_TO_RS=Y

该设置后,不能定义RR隔离级别,如果定义RR,db2也会自动降为RS.

这样,db2不用管理Next key,可以少管理一些东西,这样可以提高性能。


◆2.5 避免使用count(*) 及exists的方法


(1)首先要避免使用count(*)操作,因为count(*)基本上要对表做全部扫描一遍,如果使用很多会导致很慢。

(2)exists比count(*)要快,但总的来说也会对表做扫描,它只是碰到第一条符合的记录就停下来。


如果做这两中操作的目的是为select into服务的话,就可以省略掉这两步。


直接使用select into 选择记录中的字段。


如果是没有记录选择到的话,db2 会将 sqlcode=100 和 sqlstate=’20000’

如果是有多条记录的话,db2会产生一个错误。


程序可以创建 continue handler for exception

continue handler for not found 来检测。

这是最快速的方法。


(3)如果是判断是不是一条,可以使用游标来计算,用一个计数器,累加,达到预定值后就离开。这个速度也比count(*) 要快,因为它只要扫描到预定值就不再扫描了,不用做全表的scan,不过它写起来比较麻烦。


3. DB2表及sp管理


◆3.1 看存储过程文本


select text from syscat.procedures where procname='PROC1';

 

◆3.2 看表结构


describe table syscat.procedures describe select * from syscat.procedures

 

◆3.3 查看各表对sp的影响(被哪些sp使用)


select PROCNAME from SYSCAT.PROCEDURES where SPECIFICNAME in(select dname from sysibm.sysdependencies where bname in ( select PKGNAME from syscat.packagedep where bname='TB_BRANCH'))

 

◆3.4 查看sp使用了哪些表


select bname from syscat.packagedep where btype='T' and pkgname in(select bname from sysibm.sysdependencies where dname in (select specificname from syscat.procedures where procname='PR_CLEAR_MATCH_DIVIDE_SHA'))

 

◆3.5 查看function被哪些sp使用


select PROCNAME from SYSCAT.PROCEDURES where SPECIFICNAME in(select dname from sysibm.sysdependencies where bname in ( select PKGNAME from syscat.packagedep where bname in (select SPECIFICNAME from SYSCAT.functions where funcname='GET_CURRENT_DATE')))

 

使用function时要注意,如果想drop 掉该function必须要先将调用该function的其它存储过程全部drop掉。

必须先创建function,调用该function的sp才可以创建成功。

 


◆3.6 修改表结构


一次给一个表增加多个字段


db2 "alter table tb_test add column t1 char(1) add column t2 char(2) add column t3 int"


4.DB2系统管理


◆4.1 DB2安装


在Windows 98 下安装db2 7.1 或其他版本,如果有Jdbc错误或者是Windwos 98不能启动,则将autoexec.bat 中的内容用如下内容替换:


C:\PROGRA~1\TRENDP~1\PCSCAN.EXE C:\ C:\WINDOWS\COMMAND\ /NS /WIN95 rem C:\WINDOWS\COMMAND.COM /E:32768 REM [Header] REM [CD-ROM Drive] REM [Miscellaneous] REM [Display] set PATH=%PATH%;C:\MSSQL\BINN;C:\PROGRA~1\SQLLIB\BIN; C:\PROGRA~1\SQLLIB\FUNCTION;C:\PROGRA~1\SQLLIB\SAMPLES\REPL; C:\PROGRA~1\SQLLIB\HELP IF EXIST C:\PROGRA~1\IBM\IMNNQ\IMQENV.BAT CALL C:\PROGRA~1\IBM\IMNNQ\IMQENV.BAT IF EXIST C:\PROGRA~1\IBM\IMNNQ\IMNENV.BAT CALL C:\PROGRA~1\IBM\IMNNQ\IMNENV.BAT set DB2INSTANCE=DB2 set CLASSPATH=.;C:\PROGRA~1\SQLLIB\java\db2java.zip; C:\PROGRA~1\SQLLIB\java\runtime.zip;C:\PROGRA~1\SQLLIB\java\sqlj.zip; C:\PROGRA~1\SQLLIB\bin set MDIS_PROFILE=C:\PROGRA~1\SQLLIB\METADATA\PROFILES set LC_ALL=ZH_CN set INCLUDE=C:\PROGRA~1\SQLLIB\INCLUDE;C:\PROGRA~1\SQLLIB\LIB; C:\PROGRA~1\SQLLIB\TEMPLATES\INCLUDE set LIB=C:\PROGRA~1\SQLLIB\LIB set DB2PATH=C:\PROGRA~1\SQLLIB set DB2TEMPDIR=C:\PROGRA~1\SQLLIB set VWS_TEMPLATES=C:\PROGRA~1\SQLLIB\TEMPLATES set VWS_LOGGING=C:\PROGRA~1\SQLLIB\LOGGING set VWSPATH=C:\PROGRA~1\SQLLIB set VWS_FOLDER=IBM DB2 set ICM_FOLDER=信息目录管理器

 

◆4.2 创建Database


create database head using codeset IBM-eucCN territory CN;

 

这样可以支持中文。


◆4.3 手工做数据库远程(别名)配置


db2 catalog tcpip node node1 remote 172.28.200.200 server 50000 db2 catalog db head as test1 at node node1

 

然后既可使用:


db2 connect to test1 user … using …

 

连上head库了。


◆4.4 停止启动数据库实例


db2start db2stop (force)

 

◆4.5 连接数据库及看当前连接数据库


连接数据库

db2 connect to head user db2inst1 using db2inst1


当前连接数据库

db2 connect


◆4.6 停止启动数据库head


db2 activate db head

db2 deactivate db head


要注意的是,如果有连接,使用deactivate db 不起作用。

如果是用activate db启动的数据库,一定要用deactivate db才会停止该数据库。(当然如果是db2stop也会停止)。

使用activate db,这样可以减少第一次连接时的等待时间。

Database如果不是使用activate db启动而是通过连接数据库而启动的话,当所有的连接都退出后,db也就自动停止。


◆4.7 查看及停止数据库当前的应用程序


查看应用程序:

db2 list applications show detail


授权标识 | 应用程序名 | 应用程序句柄 | 应用程序标识 | 序号# | 代理程序 | 协调程序 | 状态 | 状态更改时间 | DB 名 | DB 路径 |


| 节点号 | pid/线程


其中:

1、应用程序标识的第一部分是应用程序的IP地址,不过是已16进制表示的。

2、pid/线程即是在unix下看到的线程号。


停止应用程序:

db2 "force application(236)"

db2 “force application all”


其中:该236是查看中的应用程序句柄。


◆4.8 查看本instance下有哪些database


db2 LIST DATABASE DIRECTORY [ on /home/db2inst1 ]

 

◆4.9 查看及更改数据库head的配置


请注意,在大多数情况下,更改了数据的配置后,只有在所有的连接全部断掉后才会生效。


查看数据库head的配制


db2 get db cfg for head


更改数据库head的某个设置的值


◆4.9.1 改排序堆的大小


db2 update db cfg for head using SORTHEAP 2048

将排序堆的大小改为2048个页面,查询比较多的应用最好将该值设置比较大一些。


◆4.9.2 改事物日志的大小


db2 update db cfg for head using logfilsiz 40000

该项内容的大小要和数据库的事物处理相适应,如果事物比较大,应该要将该值改大一点。否则很容易处理日志文件满的错误。


◆4.9.3 出现程序堆内存不足时修改程序堆内存大小


db2 update db cfg for head using applheapsz 40000

该值不能太小,否则会没有足够的内存来运行应用程序。


◆4.10 查看及更改数据库实例的配置


查看数据库实例配置

db2 get dbm cfg

更改数据库实例配制


◆4.10.1 打开对锁定情况的监控


db2 update dbm cfg using dft_mon_lock on

 

◆4.10.2 更改诊断错误捕捉级别


db2 update dbm cfg using diaglevel 3

0 为不记录信息

1 为仅记录错误

2 记录服务和非服务错误

缺省是3,记录db2的错误和警告

4 是记录全部信息,包括成功执行的信息

一般情况下,请不要用4,会造成db2的运行速度非常慢。

 


◆4.11 db2环境变量


db2 重装后用如下方式设置db2的环境变量,以保证sp可编译将set_cpl 放到AIX上, chmod +x set_cpl, 再运行之。


set_cpl的内容:


db2set DB2_SQLROUTINE_COMPILE_COMMAND="xlc_r -g \ -I$HOME/sqllib/include SQLROUTINE_FILENAME.c \ -bE:SQLROUTINE_FILENAME.exp -e SQLROUTINE_ENTRY \ -o SQLROUTINE_FILENAME -L$HOME/sqllib/lib -lc -ldb2" db2set DB2_SQLROUTINE_KEEP_FILES=1

 

◆4.12 db2命令环境设置


db2=>list command options db2=>update command options using C off--或on,只是临时改变 db2=>db2set db2options=+c --或-c,永久改变

 

◆4.13 改变隔离级别


DB2SET DB2_SQLROUTINE_PREPOPTS=CS|RR|RS|UR

 

交互环境更改session的隔离级别,db2 change isolation to UR,请注意只有没有连接数据库时可以这样来改变隔离级别。


◆4.14 管理db\instance的参数


get db cfg for head(db) get dbm cfg(instance)

 

◆4.15 升级后消除版本问题


db2 bind @db2ubind.lst db2 bind @db2cli.lst

 

◆4.16 查看数据库表的死锁


再用命令中心查询数据时要注意,如果用了交互式查询数据,命令中心将会给所查的记录加了s锁.这时如果要update记录,由于update要使用x锁,排它锁,将会处于锁等待。


首先,将监视开关打开,


db2 update dbm cfg using dft_mon_lock on

 

快照


db2 get snapshot for Locks on cleardb >snap.log tables bufferpools tablespaces database

 

然后再看snap.log中的内容即可。


对Lock可根据Application handle(应用程序句柄)看每个应用程序的锁的情况。


监视完毕后,不要忘了将监视器关闭。


db2 update dbm cfg using dft_mon_lock off

文章来源:动态网站制作(www.knowsky.com) 出处:http://www.knowsky.com/396856.html


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理