技术开发 频道

Oracle向DB2迁移:关键性函数及常见问题

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

  变量定义和BEGIN END

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

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

  DB2:

CREATE PROCEDURE PRO1()
LANGUAGE SQL
P1:
BEGIN
--变量定义
DECLARE INSERT_DATE TIMESTAMP;
DECLARE ALLDEPT_NO VARCHAR(20);
--具体操作
SELECT a FROM TAB_1;
.........
END P1

  Oracle:

CREATE PROCEDURE PRO1
IS
--变量定义
INSERT_DATE TIMESTAMP;
ALLDEPT_NO
VARCHAR(20);
BEGIN
--具体操作
SELECT a FROM TAB_1;
.........
END PRO1;

  空值的处理

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

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

  SELECT 'abc' || c1 FROM t1 (c1 IS NULL)

  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 * FROM TABLE WHERE ('' IS NULL OR ID is null) AND ('' IS NULL OR NAME = '') AND NUM = '0'

  在DB2中可翻译为:

SELECT * FROM TABLE WHERE (cast(null as varchar(10)) IS NULL OR ID is null) AND (cast(null as varchar(10)) IS NULL OR NAME is null) AND NUM = '0'

  隐形转换处理

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

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

select * from employee where empno='1010';

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

  SQLCODE: -408, SQLSTATE: 42821。

  修正为:

  select * from employee where empno=1010;

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

  select * from employee where empno =cast(V_name as bigint)

  
select * from employee where empno =cast(V_name as varchar(10))

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

  日期时间函数的实现

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

CREATE FUNCTION sysdate()
RETURNS timestamp
LANGUAGE SQL
BEGIN ATOMIC
RETURN
(
current timestamp
);
END
!

  DECODE函数的实现

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

IF 条件 =1 THEN RETURN( 返回值 1)
IF 条件 =2 THEN RETURN( 返回值 2)
......
IF 条件 = 值 n THEN RETURN( 返回值 n)
ELSE  RETURN( 缺省值 )

  从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(
int intMaxInputNumber) {
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";
int m = 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函数。

CREATE FUNCTION DECODE(P0 SMALLINT,P1 SMALLINT,
P2 TIME,P3
SMALLINT,P4 TIME)
RETURNS TIME
LANGUAGE SQL
BEGIN ATOMIC
RETURN
(
CASE P0
WHEN P1 THEN P2
WHEN P3 THEN P4
END
);
END
!

  总 结

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

1
相关文章