db2迁移oracle的null值问题,Oracle向DB2迁移:关键性函数及常见问题

【IT168 技术】为了使得将数据库和应用程序从Oracle数据库产品迁移到IBM DB2更方便,本文具体探讨在迁移过程中的一些常见问题以及,ORACLE数据库移植到DB2中的变量定义、空值处理、隐形转换、时间函数及DECODE函数的解决。

变量定义和BEGIN END

DB2中变量定义在BEGIN END体内,并且每个变量都要用DECLARE声明;存储过程结束时,END后跟P1,并且不需要分号。

Oracle中变量定义必须在BEGIN END体外,变量都不需要用DECLARE声明(有种说法是,第一个变量需要DECLARE,其他变量不需要);存储过程结束时,END后跟存储过程的名称,并且需要分号。

DB2:

CREATEPROCEDUREPRO1()

LANGUAGE SQL

P1:BEGIN--变量定义DECLAREINSERT_DATETIMESTAMP;DECLAREALLDEPT_NOVARCHAR(20);--具体操作SELECTaFROMTAB_1;

.........ENDP1

Oracle:

CREATEPROCEDUREPRO1IS--变量定义INSERT_DATETIMESTAMP;

ALLDEPT_NOVARCHAR(20);BEGIN--具体操作SELECTaFROMTAB_1;

.........ENDPRO1;

空值的处理

Oracle空值处理通过 nvl 函数实现,DB2中通过COALESCE函数实现。在DB2 V9.5中已经实现了 NVL 函数。

在Oracle中,对于null数据的处理比较灵活,在与NULL值进行比较和拼接时与DB2的结果完全不同,例如:

SELECT'abc'||c1FROMt1 (c1ISNULL)

ORACLE得到 abc 的结果。

在DB2中为null,要想得到 abc 的结果,按照如下语法修改,

SELECT'abc‘ || COALESCE(c1,'') FROM t1

还有在Oracle中select * from table where id = null这种语法是允许的,在DB2中不可。但需要说明的是在Oracle中虽然select * from table where id = null是可以通过语法检查,但与select * from table where id is null语句得到结果集是不同的,所以在移植时要考虑真实的业务意义,在翻译成DB2的语法。

另外有些应用有如下用法:

SELECT*FROMTABLEWHERE(''ISNULLORIDisnull)AND(''ISNULLORNAME='')ANDNUM='0'

在DB2中可翻译为:

SELECT*FROMTABLEWHERE(cast(nullasvarchar(10))ISNULLORIDisnull)AND(cast(nullasvarchar(10))ISNULLORNAMEisnull)ANDNUM='0'

隐形转换处理

在程序迁移过程中我们需要注意一点的是:Oracle支持数据类型之间的隐形转化,而DB2是不支持数据这个特性的,因此在使用SQL进行数据查询或更新时必须配置字段的类型。

例如:在表中employee 字段empno 定义为数字类型:

select*fromemployeewhereempno='1010';

该语句在oracle数据库环境可执行通过,但在DB2下报错:

SQLCODE: -408, SQLSTATE: 42821。

修正为:

select*fromemployeewhereempno=1010;

如果在程序中使用变量,可以使用cast关键字进行数据类型转换工作。语法如下:

select*fromemployeewhereempno=cast(V_nameasbigint)select*fromemployeewhereempno=cast(V_nameasvarchar(10))

以上主要讲了Oracle向DB2迁移的3种常见问题的处理,下面引用 IBM高级工程师 戴慰 的一篇文章《从Oracle数据库移植到 DB2 V9.1 过程中几个关键性函数的实现》的里面的2种常见关键性函数的解决方法。

日期时间函数的实现

Oracle采用SYSDATE作为取当前时间,而DB2中采用CURRENTTIMESTAMP获得当前时间,为了减少代码的修改量,我们编写SYSDATE的UDF函数,只需要在SYSDATE后面增加双括号,既然由Oracle中的Sysdate修改成Sysdate(),即可以调用新编写的SYSDATE()函数,见下载章节中的SYSDATE函数。

CREATEFUNCTIONsysdate()RETURNStimestampLANGUAGE SQLBEGINATOMICRETURN(currenttimestamp);END!

DECODE函数的实现

Oracle的Decode是多值判断函数,该函数有Oracle内核进行解析和判断,不属于普通的用户函数,所以DECODE对传入的调制值和返回值都可以动态调用。DECODE函数的应用非常广泛,DECODE(条件值1,返回值1,值2,返回值2,……值n,返回值n,缺省值),该函数的内容逻辑如下:

IF条件=值1THENRETURN( 返回值1)IF条件=值2THENRETURN( 返回值2)

......IF条件=值 nTHENRETURN( 返回值 n)ELSERETURN( 缺省值 )

从DECODE函数代码逻辑来看,DECODE的内部的原理非常的简单,难点就是在于如何解决DOUBLE,DATE,TIMESTAMPL等不同的参数数据类型和不同的返回数据类型。由于DECODE是ORACLE数锯库的内部函数,ORACLE内部的实现机制不得而知,如果想在DB2内实现如下功能必须利用UDF的可重载的特性。

IBM的基本的数据类型包括CHAR()、VarChar()、SMALLINT、INTEGER、BIGINT、DECIMAL、REAL、DOUBLE、DATE、TIME、TIMESTAMP数据类型,DECODE的函数的条件值和判断值的数据类型一致,但返回数据类型可以和条件值不同,按照排列组合的规律来看,输入、输出数据类型的组合式11n,当N>3以上,由于代础最和组合次数过多,很难采用手工写程序的方式来实现。

为丁解决这个难题,我们想到了采用代码生成机来实现所有的组合,考虑到使用的方便和跨平台,采用JAVA程序开发GenDecode的生成程序,具体执行过程中只需输入预计最大的DECODE的参数数量,GenDecode按照数据组合的顺序,逐步把所有的参数类犁的组合全部生成出来,并且导入到文件中,以下是GenDecode的主要功能函数:

//根据给定的参数值,生成各种组合的 DECODE 函数

private void GenDecode(intintMaxInputNumber) {

String strFlagType="";

String strReturnType="";

String strBuffer="";//DB2 数据类型

String[]strType=new String[11];

strType[0]="CHAR(128)";

strType[1]="VarChar(512)";

strType[2]="SMALLINT";

strType[3]="INTEGER";

strType[4]="BIGINT";

strType[5]="DECIMAL";

strType[6]="REAL";

strType[7]="DOUBLE";

strType[8]="DATE";

strType[9]="TIME";

strType[10]="TIMESTAMP";intm=0, n=0, intMax=3;while(intMax<=intMaxInputNumber) {

m=0;

n=0;while(m<11) {

n=0;

strFlagType=strType[m];while(n<11) {

strReturnType=strType[n];//生产 DB2 UDF DECODE 的函数头

strBuffer+=GenInputVal(intMax, strFlagType, strReturnType);//生成 DB2 UDF DECODE 的函数体

strBuffer+=GenWhenElse(intMax);//把生产的代码写入文件

WrtDecode(strBuffer);

strBuffer="";

n++;

}

m++;

}

intMax++;

}

}

通过GenDecode生产的DECODE函数的例子,在下载中您可以下载已经生成1到35个参数的DECODE函数,见下载章节中的DECODE.SQL函数。CREATEFUNCTIONDECODE(P0SMALLINT,P1SMALLINT,

P2 TIME,P3SMALLINT,P4 TIME)RETURNSTIME

LANGUAGE SQLBEGINATOMICRETURN(CASEP0WHENP1THENP2WHENP3THENP4END);END!

总 结

本文展示了一些SQL开发的用户定义函数(UDF)以实现ORACLE中的若干关键性函数。如果你对确切的实现细节很感兴趣,可以查阅这些代码。一旦变异?并连接了源代码(或安装了预编译的库)以及在数据库中注册了这些过程和函数之后,就可以按本文示例所演示的那样来使用它们了。另外值得注意的是,这些过程和函数已经在DB2 UDB v9.1平台被编译和执行过。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值