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
函数返回 () 中表达式列表中第一个不为空的表达式,可以带多个表达式。
   
sqlserver isnull 类似,但 isnull 好象只能两个表达式; oracle NVL
     

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.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                                       


1.12.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

1.12.3
动态 SQL 写法
     DECLARE CURSOR C1 FOR STMT1; 
     PREPARE STMT1 FROM
        'ALLOCATE C2 CURSOR FOR RESULT SET ?';
1.12.4
注意:
(1) 如果一个 sp 调用好几次,只能取到最近一次调用的结果集。  
(2) 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

1.22 日期和时间的使用
要使用 SQL 获得当前的日期、时间及时间戳记,请参考适当的 DB2 寄存器:

SELECT current date FROM sysibm.sysdummy1

SELECT current time FROM sysibm.sysdummy1

SELECT current timestamp FROM sysibm.sysdummy1

sysibm.sysdummy1 表是一个特殊的内存中的表,用它可以发现如上面演示的 DB2 寄存器的值。您也可以使用关键字 VALUES 来对寄存器或表达式求值。例如,在 DB2 命令行处理器( Command Line Processor CLP )上,以下 SQL 语句揭示了类似信息:

VALUES current date

VALUES current time

VALUES current timestamp

在余下的示例中,我将只提供函数或表达式,而不再重复 SELECT ... FROM sysibm.sysdummy1 或使用 VALUES 子句。

要使当前时间或当前时间戳记调整到 GMT/CUT ,则把当前的时间或时间戳记减去当前时区寄存器:

current time - current timezone

current timestamp - current timezone

给定了日期、时间或时间戳记,则使用适当的函数可以单独抽取出(如果适用的话)年、月、日、时、分、秒及微秒各部分:

YEAR (current timestamp)

MONTH (current timestamp)

DAY (current timestamp)

HOUR (current timestamp)

MINUTE (current timestamp)

SECOND (current timestamp)

MICROSECOND (current timestamp)

从时间戳记单独抽取出日期和时间也非常简单:

DATE (current timestamp)

TIME (current timestamp)

因为没有更好的术语,所以您还可以使用英语来执行日期和时间计算:

current date + 1 YEAR

current date + 3 YEARS + 2 MONTHS + 15 DAYS

current time + 5 HOURS - 3 MINUTES + 10 SECONDS

要计算两个日期之间的天数,您可以对日期作减法,如下所示:

days (current date) - days (date('1999-10-22'))

而以下示例描述了如何获得微秒部分归零的当前时间戳记:

CURRENT TIMESTAMP - MICROSECOND (current timestamp) MICROSECONDS

如果想将日期或时间值与其它文本相衔接,那么需要先将该值转换成字符串。为此,只要使用 CHAR() 函数:

char(current date)

char(current time)

char(current date + 12 hours)

要将字符串转换成日期或时间值,可以使用:

TIMESTAMP ('2002-10-20-12.00.00.000000')

TIMESTAMP ('2002-10-20 12:00:00')

          DATE ('2002-10-20')

          DATE ('10/20/2002')

          TIME ('12:00:00')

          TIME ('12.00.00')

TIMESTAMP() DATE() TIME() 函数接受更多种格式。上面几种格式只是示例,我将把它作为一个练习,让读者自己去发现其它格式。

 

警告 :
摘自 DB2 UDB V8.1 SQL Cookbook ,作者 Graeme Birchall (see http://ourworld.compuserve.com/homepages/Graeme_Birchall).

如果你在日期函数中偶然地遗漏了引号,那将如何呢?结论是函数会工作,但结果会出错:

SELECT DATE(2001-09-22) FROM SYSIBM.SYSDUMMY1;

结果 :

======

05/24/0006

为什么会产生将近 2000 年的差距呢?当 DATE 函数得到了一个字符串作为输入参数的时候,它会假定这是一个有效的 DB2 日期的表示,并对其进行适当地转换。相反,当输入参数是数字类型时,函数会假定该参数值减 1 等于距离公元第一天( 0001-01-01 )的天数。在上面的例子中,我们的输入是 2001-09-22 ,被理解为 (2001-9)-22, 等于 1970 天,于是该函数被理解为 DATE(1970)

 

 

 

 

 

 

 

 

 

 

 

 

日期函数

有时,您需要知道两个时间戳记之间的时差。为此, DB2 提供了一个名为 TIMESTAMPDIFF() 的内置函数。但该函数返回的是近似值,因为它不考虑闰年,而且假设每个月只有 30 天。以下示例描述了如何得到两个日期的近似时差:

timestampdiff (<n>, char(

          timestamp('2002-11-30-00.00.00')-

          timestamp('2002-11-08-00.00.00')))

对于 <n> ,可以使用以下各值来替代,以指出结果的时间单位:

  • 1 = 秒的小数部分
  • 2 =
  • 4 =
  • 8 =
  • 16 =
  • 32 =
  • 64 =
  • 128 = 季度
  • 256 =

当日期很接近时使用 timestampdiff() 比日期相差很大时精确。如果需要进行更精确的计算,可以使用以下方法来确定时差(按秒计):

(DAYS(t1) - DAYS(t2)) * 86400 +  

(MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2))

为方便起见,还可以对上面的方法创建 SQL 用户定义的函数:

CREATE FUNCTION secondsdiff(t1 TIMESTAMP, t2 TIMESTAMP)

RETURNS INT

RETURN (

(DAYS(t1) - DAYS(t2)) * 86400 + 

(MIDNIGHT_SECONDS(t1) - MIDNIGHT_SECONDS(t2))

)

@

如果需要确定给定年份是否是闰年,以下是一个很有用的 SQL 函数,您可以创建它来确定给定年份的天数:

CREATE FUNCTION daysinyear(yr INT)

RETURNS INT

RETURN (CASE (mod(yr, 400)) WHEN 0 THEN 366 ELSE

        CASE (mod(yr, 4))   WHEN 0 THEN

        CASE (mod(yr, 100)) WHEN 0 THEN 365 ELSE 366 END

        ELSE 365 END

          END)@

最后,以下是一张用于日期操作的内置函数表。它旨在帮助您快速确定可能满足您要求的函数,但未提供完整的参考。有关这些函数的更多信息,请参考 SQL 参考大全。

SQL 日期和时间函数

DAYNAME

返回一个大小写混合的字符串,对于参数的日部分,用星期表示这一天的名称(例如, Friday )。

 

DAYOFWEEK

返回参数中的星期几,用范围在 1-7 的整数值表示,其中 1 代表星期日。

 

DAYOFWEEK_ISO

返回参数中的星期几,用范围在 1-7 的整数值表示,其中 1 代表星期一。

 

DAYOFYEAR

返回参数中一年中的第几天,用范围在 1-366 的整数值表示。

 

DAYS

返回日期的整数表示。

 

JULIAN_DAY

返回从公元前 4712 1 1 日(儒略日历的开始日期)到参数中指定日期值之间的天数,用整数值表示。

 

MIDNIGHT_SECONDS

返回午夜和参数中指定的时间值之间的秒数,用范围在 0 86400 之间的整数值表示。

 

MONTHNAME

对于参数的月部分的月份,返回一个大小写混合的字符串(例如, January )。

 

TIMESTAMP_ISO

根据日期、时间或时间戳记参数而返回一个时间戳记值。

 

TIMESTAMP_FORMAT

从已使用字符模板解释的字符串返回时间戳记。

 

TIMESTAMPDIFF

根据两个时间戳记之间的时差,返回由第一个参数定义的类型表示的估计时差。

 

TO_CHAR

返回已用字符模板进行格式化的时间戳记的字符表示。 TO_CHAR VARCHAR_FORMAT 的同义词。

 

TO_DATE

从已使用字符模板解释过的字符串返回时间戳记。 TO_DATE TIMESTAMP_FORMAT 的同义词。

 

WEEK

返回参数中一年的第几周,用范围在 1-54 的整数值表示。以星期日作为一周的开始。

 

WEEK_ISO

返回参数中一年的第几周,用范围在 1-53 的整数值表示。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

改变日期格式

在日期的表示方面,这也是我经常碰到的一个问题。用于日期的缺省格式由数据库的地区代码决定,该代码在数据库创建的时候被指定。例如,我在创建数据库时使用 territory=US 来定义地区代码,则日期的格式就会像下面的样子:

values current date

1

----------

05/30/2003

 

1 record(s) selected.

也就是说,日期的格式是 MM/DD/YYYY. 如果想要改变这种格式,你可以通过绑定特定的 DB2 工具包来实现 . 其他被支持的日期格式包括 :

DEF

使用与地区代码相匹配的日期和时间格式。

EUR

使用欧洲日期和时间的 IBM 标准格式。

ISO

使用国际标准组织( ISO )制订的日期和时间格式。

JIS

使用日本工业标准的日期和时间格式。

LOC

使用与数据库地区代码相匹配的本地日期和时间格式。

USA

使用美国日期和时间的 IBM 标准格式。

 

 

 

 

 

Windows 环境下,要将缺省的日期和时间格式转化成 ISO 格式( YYYY-MM-DD ),执行下列操作:

1.       在命令行中,改变当前目录为 sqllibbnd

例如 :
Windows 环境 : c:program filesIBMsqllibbnd
UNIX 环境 : /home/db2inst1/sqllib/bnd

2.       从操作系统的命令行界面中用具有 SYSADM 权限的用户连接到数据库 :

3.             db2 connect to DBNAME

4.             db2 bind @db2ubind.lst datetime ISO blocking all grant public

( 在你的实际环境中, 用你的数据库名称和想使用的日期格式分别来替换 DBNAME and ISO )

现在,你可以看到你的数据库已经使用 ISO 作为日期格式了:

values current date

1

----------

2003-05-30

 

  1 record(s) selected.

 

定制日期 / 时间格式

在上面的例子中,我们展示了如何将 DB2 当前的日期格式转化成系统支持的特定格式。但是,如果你想将当前日期格式转化成定制的格式(比如 ‘yyyymmdd’ ),那又该如何去做呢?按照我的经验,最好的办法就是编写一个自己定制的格式化函数。

下面是这个 UDF 的代码 :

create function ts_fmt(TS timestamp, fmt varchar(20))

returns varchar(50)

return

with tmp (dd,mm,yyyy,hh,mi,ss,nnnnnn) as

(

    select

    substr( digits (day(TS)),9),

    substr( digits (month(TS)),9) ,

    rtrim(char(year(TS))) ,

    substr( digits (hour(TS)),9),

    substr( digits (minute(TS)),9),

    substr( digits (second(TS)),9),

    rtrim(char(microsecond(TS)))

    from sysibm.sysdummy1

    )

select

case fmt

    when 'yyyymmdd'

        then yyyy || mm || dd

    when 'mm/dd/yyyy'

        then mm || '/' || dd || '/' || yyyy

    when 'yyyy/dd/mm hh:mi:ss'

        then yyyy || '/' || mm || '/' || dd || ' ' ||

               hh || ':' || mi || ':' || ss

    when 'nnnnnn'

        then nnnnnn

    else

        'date format ' || coalesce(fmt,'  ') ||

        ' not recognized.'

    end

from tmp

乍一看,函数的代码可能显得很复杂,但是在仔细研究之后,你会发现这段代码其实非常简单而且很优雅。最开始,我们使用了一个公共表表达式( CTE )来将一个时间戳记(第一个输入参数)分别剥离为单独的时间元素。然后,我们检查提供的定制格式(第二个输入参数)并将前面剥离出的元素按照该定制格式的要求加以组合。

这个函数还非常灵活。如果要增加另外一种模式,可以很容易地再添加一个 WHEN 子句来处理。在使用过程中,如果用户提供的格式不符合任何在 WHEN 子句中定义的任何一种模式时,函数会返回一个错误信息。

使用方法示例:

values ts_fmt(current timestamp,'yyyymmdd')

 '20030818'

values ts_fmt(current timestamp,'asa')

 'date format asa not recognized.

 

 


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=
信息目录管理器

win

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
为不记录信息
为仅记录错误
记录服务和非服务错误
缺省是 3 ,记录 db2 的错误和警告
是记录全部信息,包括成功执行的信息
一般情况下,请不要用 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

 

 

5. DB2 SQL 概述

5.1 模式

5.1.1 模式是已命名的对象(如表和视图)的集合。模式提供了数据库中对象的逻辑分类。

5.1.2 当在数据库中创建对象的时候,系统就隐性的创建了模式。当然,也可以使用 CREATE SCHEMA 显式的创建模式。

5.1.3 当命名对象的时候,需要注意对象的名称有两个部分,即,模式 . 对象名称 , 形如: pjj.TempTable1 。如果不显示指定模式,则系统使用默认模式(默认用户的 ID )。

5.2 数据类型

 

定长字符串     

CHAR(x)             x 值域( 1 254 )       一个字节序列

 

变长字符串 

VARCHAR(X)

LONG VARCHAR(X)

LOB( 大对象 )

 

定长图形字符串  

GRAPHCI(X)         x 值域( 1 127 )       两个字节序列

 

变长图形字符串  

VARGRAPHCI(X)

LONG GRAPHCI(X)

DBCLOB( 大对象 )

  BLOB( 大对象 )

数字           ( 所有数字都有精度,精度是指除符号位以外的位数或者数字数 )

SMALLINT           精度为 5             2 字节整数

INTEGER           精度为 10            4 字节整数

BIGINT             精度为 19            8 字节整数

REAL              实数的 32 位近似值

DOUBLE            实数的 64 位近似值

DECIMAL(P,S)     P, 精度, S, 小数位数,十进制数, P 必须 <=32 S 必须 <=P ,缺省 :P=5,S=0

日期时间型      14 位字符串,即非数字类型也非字符串类型

日期            DATE              年月日

时间            TIME               24 小时制,分为 小时分钟秒

时间戳记        TIMESTAMP          1 日期和时间的值,分为 年月日小时分钟秒微秒

空值            不同于任何非空值

 

5.3 其他

DB2 不区分大小写(单引号或者双引号内的内容除外)

 

 

5.4 创建表和视图

 

5.4.1 创建表

 

CREATE TABLE PERS

(ID   SMALLINT    NOT NULL,

NAME           VARCHAR(9),

DEPT            SMALLINT    WITH DEFAULT 10,

JOB             CHAR(5),

YEARS           SMALLINT,

SALARY          DECIMAL(7,2),

COMM           DECIMAL(7,2),

BIRTH_DATE     DATE)

 

5.4.2 在表中插入值 ( 三种方式 )

 

INSERT INTO PERS

VALUES (12,'Harris',20,'Sales',5,18000,1000,'1950-1-1')

 

INSERT INTO PERS (NAME,JOB,ID)

VALUES     ('Swagerman','Pramr',500),('Limoges','Prgmr',510),                 ('Li','Prgmr',520)

 

INSERT INTO PERS (ID,NAME,DEPT,JOB,YEARS,SALARY,COMM,BIRTH_DATE) SELECT ID,NAME,DEPT,JOB,YEARS,SALARY,COMM,BIRTH_DATE     FROM STAFF WHERE ID = 58

 

5.4.3 更新数据

 

UPDATE PERS SET JOB = 'Prgmr',SALARY = SALARY + 300 WHERE ID = 410

UPDATE PERS SET SALARY = SALARY * 1.15 WHERE JOB = 'Sales'

 

5.4.4 删除数据

 

DELETE FROM PERS WHERE ID = 120

 

5.4.5 删除表

 

DROP TABLE PERS

 

5.4.6 创建视图

 

( 可以选用 WITH CHECK OPTION 选项,该选项针对 WHERE 的条件进行限定 )

CREATE VIEW STAFF_ONLY AS SELECT ID,NAME,DEPT,JOB,YEARS   FROM STAFF   WHERE JOB <> 'Mgr' AND DEPT = 20 WITH CHECK OPTION

 

 

5.5 使用 SQL 语句存取数据 

 

(? CREATE 显示一般帮助提示信息 )

 

5.5.1 连接数据库

 

CONNECT TO MYDB2 USER USERID USING PASSWORD

 

5.5.2 谓词

 

    x=y x<>y x<y x>y x>=y x<=y

 

    IS NULL

 

    IS NOT NULL

 

5.5.3 其他的一些去 SQL SERVER 类似的东西就省略

 

5.5.4 运算次序

 

    FROM

 

    WHERE

 

    GROUP BY

 

    HAVING

 

    SELECT

 

    ORDER BY

 

5.5.5 函数

5.5.5 .1 列函数

( 列函数对列中的一组值进行运算以得到单一的结果值! )

 

        AVG

 

        COUNT

 

        MAX

 

        MIN

 

       

 

5.5. 5 .2 标量函数

 

( 标量函数对一个单一值进行运算以返回另一个单一的结果值! )

 

        ABS        绝对值

 

        HEX        十六进制

 

        LENGTH    返回字节数(对于图形字符串则返回双字节字符串)

 

        YEAR

 

5.5.5 .3 表函数

 

( 表函数仅可用于 FROM 子句,返回表的列! )

 

5.6 表达式和子查询

 

5.6.1 标量全查询

 

( 返回一行,该行只包括一个值,用于从数据库中检索值 )

 

SELECT LASTNAME,FIRSTNAME

 

FROM EMPLOYEE

 

WHERE SALARY > (SELECT AVG(SALARY) FROM EMPLOYEE)

 

 

SELECT AVG(SALARY) AS "Average_Employee",

 

(SELECT AVG(SALARY) AS "Average_Staff" FROM STAFF)

 

FROM EMPLOYEE

 

 

 

 

 

注意 :

 

SQL SERVER , 字符串用单引号 , DB2 中则使用双引号 !

 

SELECT XX AS "OO" 也可以写为 SELECT XX "XX"

 

 

 

 

 

5.6.2 转换数据类型

 

(使用 CAST,CAST 的另外一个用法是截断数据)

 

SELECT CAST(NAME AS VARCHAR(2)) AS "NAME" FROM EMPLOYEE

 

 

 

 

 

5.6.3 条件表达式

 

(CASE 注意,单引号和双引号 )

 

 

 

 

 

SELECT DEPTNAME

 

CASE DEPTNUMB

 

WHEN 10 THEN 'Market'

 

WHEN 20 THEN 'Sales'

 

WHEN 30 THEN 'Development'

 

ELSE 'NULL'

 

END AS FUNCTION

 

FROM ORG

 

 

 

 

 

-- 避免产生被 0

 

SELECT NAME,WORKDEPT

 

FROM EMPLOYEE

 

WHERE (CASE WHEN BONUS = 0 THEN NULL ELSE SALARY/BONUS END) > 10

 

 

 

 

 

-- 替代简单的函数功能

 

CASE WHEN X<0 THEN -1 WHEN X=0 THEN 0 ELSE 1 END

 

 

 

 

 

5.6.4 表表达式(临时的)

 

5.6.4 .1 嵌套表表达式

 

(嵌套于 FROM 字句中)

 

 

 

 

 

SELECT EDLEVEL, HIREYEAR, DECIMAL(AVG(TOTAL_PAY),7,2)

 

FROM (SELECT EDLEVEL, YEAR(HIREDATE) AS HIREYEAR,

 

SALARY+BONUS+COMM AS TOTAL_PAY

 

FROM EMPLOYEE

 

WHERE EDLEVEL > 16) AS PAY_LEVEL

 

GROUP BY EDLEVEL, HIREYEAR

 

ORDER BY EDLEVEL, HIREYEAR

 

 

 

 

 

5.6.4 .2 公共表达式

 

(以 WITH 开头,对公共表达式的重复引用使用同一结果,而使用嵌套表达式则可能会出现不同的结果。)

 

 

 

 

 

WITH

 

PAYLEVEL AS

 

(SELECT EMPNO, EDLEVEL, YEAR(HIREDATE) AS HIREYEAR,

 

SALARY+BONUS+COMM AS TOTAL_PAY

 

FROM EMPLOYEE

 

WHERE EDLEVEL > 16),

 

 

 

 

 

PAYBYED (EDUC_LEVEL, YEAR_OF_HIRE, AVG_TOTAL_PAY) AS

 

(SELECT EDLEVEL, HIREYEAR, AVG(TOTAL_PAY)

 

FROM PAYLEVEL

 

GROUP BY EDLEVEL, HIREYEAR)

 

 

 

 

 

SELECT EMPNO, EDLEVEL, YEAR_OF_HIRE, TOTAL_PAY, DECIMAL(AVG_TOTAL_PAY,7,2)

 

FROM PAYLEVEL, PAYBYED

 

WHERE EDLEVEL = EDUC_LEVEL

 

AND HIREYEAR = YEAR_OF_HIRE

 

AND TOTAL_PAY < AVG_TOTAL_PAY

 

 

 

 

 

5.6.4 .3 相关名

 

(注意,一旦使用了相关名,则不能再在上下文中使用原名,否则出错!)

 

 

SELECT NAME, DEPTNAME

 

FROM STAFF S, ORG O

 

WHERE O.MANAGER = S.ID

 

 

 

 

 

-- 另外,相关名还可以用来复制对象,例如说自身

 

SELECT E2.FIRSTNME, E2.LASTNAME, E2.JOB, E1.FIRSTNME AS MGR_FIRSTNAME,

 

E1.LASTNAME AS MGR_LASTNAME, E1.WORKDEPT

 

FROM EMPLOYEE E1, EMPLOYEE E2

 

WHERE E1.WORKDEPT = E2.WORKDEPT

 

AND E1.JOB = 'MANAGER'

 

AND E2.JOB <> 'MANAGER'

 

AND E2.JOB <> 'DESIGNER'

 

 

 

 

 

5.6.4 .4 / 相关子查询

 

5.6.4 .4.1 不相关子查询

 

SELECT EMPNO, LASTNAME

 

FROM EMPLOYEE

 

WHERE WORKDEPT = 'A00'

 

AND SALARY > (SELECT AVG(SALARY)

 

FROM EMPLOYEE

 

WHERE WORKDEPT = 'A00')

 

 

5.6.4 .4.2 相关子查询

 

SELECT E1.EMPNO, E1.LASTNAME, E1.WORKDEPT

 

FROM EMPLOYEE E1

 

WHERE SALARY > (SELECT AVG(SALARY)

 

FROM EMPLOYEE E2

 

WHERE E2.WORKDEPT = E1.WORKDEPT)

 

ORDER BY E1.WORKDEPT

 

 

 

 

 

5.7 在查询使用运算符与谓词

 

5.7.1 集合运算符

 

5.7.1 .1UNION

 

组合两个表,并消除重复行;如果 UNION ALL 则不消除重复行

 

SELECT ID, NAME FROM STAFF WHERE SALARY > 21000

 

UNION

 

SELECT ID, NAME FROM STAFF WHERE JOB='Mgr' AND YEARS < 8

 

ORDER BY ID

 

 

 

 

 

5.7.1 .2 EXCEPT:

 

包括所有在表 1 中而不在表 2 中的行并消除所有重复行;如果 EXCEPT ALL 则不消除重复行

 

 

 

 

 

SELECT ID, NAME FROM STAFF WHERE SALARY > 21000

 

EXCEPT

 

SELECT ID, NAME FROM STAFF WHERE JOB='Mgr' AND YEARS < 8

 

 

-- 也就是说,凡是满足 EXCEPT 后面语句的数据都不在选择的范围内

 

 

 

 

 

5.7.1 .3 INTERSECT

 

只包括表 1 和表 2 都有的行并消除所有重复行;如果 INTERSECT ALL 则不消除重复行

 

 

SELECT ID, NAME FROM STAFF WHERE SALARY > 21000

 

INTERSECT

 

SELECT ID, NAME FROM STAFF WHERE JOB='Mgr' AND YEARS < 8

 

 

 

 

 

5.7.2 谓词

 

5.7.2 .1 IN/NOT IN

 

SELECT NAME

 

FROM STAFF

 

WHERE DEPT IN (20, 15)

 

 

 

 

 

SELECT LASTNAME

 

FROM EMPLOYEE

 

WHERE EMPNO IN

 

(SELECT RESPEMP

 

FROM PROJECT

 

WHERE PROJNO = 'MA2100'

 

OR PROJNO = 'OP2012')

 

 

 

 

 

5.7.2 .2 BETWEEN/NOT BETWEEN

 

SELECT LASTNAME

 

FROM EMPLOYEE

 

WHERE SALARY BETWEEN 10000 AND 20000

 

 

 

 

 

5.7.2 .3 LIKE/NOT LIKE

 

注意 _ 表示任何单个字符, % 表示任何零个或者多个的字符

 

 

 

 

 

SELECT NAME

 

FROM STAFF

 

WHERE NAME NOT LIKE 'S%'

 

 

 

 

 

5.7.2 .4 EXISTS/NOT EXISTS

 

( 检查存在性 )

 

 

 

 

 

SELECT DEPTNO, DEPTNAME

 

FROM DEPARTMENT X

 

WHERE NOT EXISTS

 

(SELECT *

 

FROM PROJECT

 

WHERE DEPTNO = X.DEPTNO)

 

ORDER BY DEPTNO

 

 

 

 

 

5.7.2 .5 定量谓词

 

( 将一个值和一个值的集合进行比较 )

 

 

 

 

 

2.5.1 > ALL

 

( 必须全部符合,谓词结果才为真! )

 

查询所有收入超过所有经理收入的雇员的姓名和职位(其实后面的子查询中返回值有多个,所以用了 ALL

 

 

SELECT LASTNAME, JOB

 

FROM EMPLOYEE

 

WHERE SALARY > ALL

 

(SELECT SALARY

 

FROM EMPLOYEE

 

WHERE JOB='MANAGER')

 

5.7.2 .5.2 > ANY> SOME

 

( 两个谓词同意,只要有一个结果符合,谓词结果即为真 )

 

查询所有收入超过任何一个经理收入的雇员的姓名和职位(其实后面的子查询中返回值有多个,所以用了 ALL

 

 

SELECT LASTNAME, JOB

 

FROM EMPLOYEE

 

WHERE SALARY > ANY

 

(SELECT SALARY

 

FROM EMPLOYEE

 

WHERE JOB='MANAGER')

 

 

 

 

 

5.8 定制和增强数据操作

5.8.1 用户定义类型 UDT

5.8.1 .1 创建

CREATE DISTINCT TYPE PAY AS DECIMAL WITH COMPARISONS

 

5.8.1 .2 使用

SELECT * FROM EMPLOYEE WHERE DECIMAL(SALARY)=5120

 

5.8.1 .3 注意:

UDT 认为是于任何其他类型不同的类型,例如上例中的 PAY DECIMAL 类型是不同的,但是可以相互转换!

 

PAY(SALARY) 或者 DECIMAL (SALARY)

 

 

 

 

 

5.8.2 用户自定义函数 UDF

 

5.8.2 .1 创建

 

CREATE FUNCTION MAX(PAY) RETURNS PAY

 

SOURCE MAX(DECIMAL)

 

5.8.2 .2 使用

 

SELECT column1,FunctionName(XXX) FROM TableXXX

 

5.8.2 .3 注意:

UDF 可以调用其他已有库函数和其他 UDF

 

 

 

 

 

5.8.3 大对象 LOB

5.8.3 .1 简介

    BLOB,CLOB,DCLOB 分别代表二进制数大对象、字符大对象(多用于字符串)、双字节字符大对象(多用于图形)

5.8.3 .2 操作(略)

   

 

5.8.4 专用寄存器

5.8.4 .1 定义 :

    DBMS 为连接定义的存储区,用于 SQL 引用的信息。

5.8.4 . 2 存储的常用数据:

    CURRENT DATE USER CURRENT TIMESTAMP CURRENT TIME CURRENT TIMEZONE( 指定与世界时间的差别 ) CURRENT SERVER

5.8.4 .3 调用 VALUES(CURRENT DATE) 或者 SELECT CURRENT TIME FROM TABLENAME

 

5.8.5 常用系统视图

SYSCAT.CHECKS

 

SYSCAT.COLUMNS

 

SYSCAT.COLCHECKS

 

SYSCAT.KEYCOLUSE

 

SYSCAT.DATATYPES

 

SYSCAT.FUNCPARMS

 

SYSCAT.REFERENCES

 

SYSCAT.SCHEMATA

 

SYSCAT.TABCONST

 

SYSCAT.TABLES-- 模式

 

SYSCAT.TRIGGERS

 

SYSCAT.FUNCTIONS

 

SYSCAT.VIEWS