Oracle 到 DB2 Version 9.1 for z/OS 迁移揭密!

 

本文来自:http://www.ibm.com/developerworks/cn/data/library/techarticle/dm-1102DB2zOSdemystified/

简介

促使组织把他们的应用程序或产品迁移到另一种 RDBMS 上有许多原因,包括成本、可伸缩性、遵从性、性能、战略等等。无论原因是什么,如果您打算把数据库从 Oracle 10g 迁移到 DB2 Version 9.1 for z/OS,本文会向您提供一些最实用、很容易实现的解决方案、处理方法和技巧,可以把迁移工作量至少降低 25%,还可以节约大量咨询成本。

本文中提到的迁移问题只针对 DB2 Version 9.1 for z/OS。在 DB2 10 for z/OS 中,其中的许多问题已经解决了。关于 DB2 10 for z/OS 的更多信息,请查阅 IBM 信息中心

数据库迁移活动的目的是确保相同的应用程序层能够与另一个 RDBMS 交互。这通常涉及应用程序层移植和数据库对象迁移。这是任何项目的关键活动,需要全面的分析,因为两个 RDBMS 有内在差异,迁移可能不顺利。要考虑的另一点是,在把应用程序迁移到新的 RDBMS 之后,您是希望继续使用现有的环境,还是要放弃它。您可能希望维护两个环境,以便能够灵活地选择 RDBMS。在这种情况下,维护两个环境会有额外的开销,而且要确保它们保持同步。

本文源自在一个 Oracle 10g 到 DB2 z/OS 9.1 数据库迁移项目中获得的经验。可以使用多种工具帮助迁移,包括 IBM 的 Migration Toolkit (MTK)。但是,这些工具的输出并不完全准确,需要许多手工干预才能够让输出满足 DB2 的要求。本文会帮助您修改工具生成的输出,让输出在 DB2 上有效。本文会介绍各类对象可能遇到的问题及其解决方案。

本文帮助产品和应用程序开发人员以及 DBA 把应用程序从 Oracle 10g 迁移到 DB2 Version 9.1 for z/OS 数据库。目标读者应该具备 PL/SQL 的基本知识,能够有效地使用文档。本文的范围是如何解决在迁移活动中面对的与数据库相关的技术问题。功能性问题超出了本文的范围。

 

     对于所有数据库迁移都要关注的领域

 

数据库迁移是一种复杂的活动,因为可能需要做大量修改。所有数据库对象和与数据库交互的所有应用程序代码都可能需要修改。对于数据库迁移活动,关注的主要领域包括:

· 两个 RDBMS 之间的架构差异:两个 RDBMS 可能具有不同的架构,可能使用不同的对象层次结构。

· 应用程序代码中的嵌入式 SQL:可能会在应用程序代码中加入嵌入式 SQL 以执行数据库交互。需要分析所有原始 SQL 语句,判断它们是同时适用于两个数据库,还是需要修改。

· 数据库对象:可能必须根据目标数据库采用的语法部分或完全修改数据库对象,包括表、视图、存储过程、触发器或用户定义函数。

· 两个数据库之间的关键字差异:一些函数可能在两个数据库中都可用,但是名称不同。需要处理所有这类差异。

· 数据类型差异:在两个 RDBMS 之间数据类型可能有显著的差异。

 

   问题、解决方案和技巧

 

下面讨论一些可能会遇到的问题、解决它们的方法和技巧,帮助您从 Oracle 10g 迁移到 DB2 9.1

 

 Oracle 10g 和 DB2 Version 9.1 for z/OS 的架构对比

 

在 Oracle 10g 中,一个数据库实例包含多个表空间。每个表空间存储一个或多个表。表常常根据它们的功能关系和访问模式分组在表空间中。

在 DB2 Version 9.1 for z/OS 中,层次结构的顶部是 DB2 子系统,它包含多个存储组。存储组是大型机上物理存储设备 DASD(直接访问存储设备)上的一组卷。存储组包含一个或多个数据库,数据库包含表空间。根据表空间的类型,每个表空间包含一个或多个表。

在 DB2 9.1 中,对于表中的每个 BLOB/CLOB 列,必须创建 LOB 表空间、辅助表和索引。如果 CURRENT RULES 寄存器设置为 DB2,那么必须为每个 BLOB/CLOB 列显式地创建所有这些对象。如果 CURRENT RULES 寄存器设置为 STD,那么 DB2 负责为每个 BLOB/CLOB 列隐式地创建所有这些对象。可以使用以下命令设置 CURRENT RULES 寄存器的值:SET CURRENT RULES = 'STD'。应该在运行表创建脚本之前使用这个命令。

 

创建用户

在 Oracle 10g 中,在数据库级上创建用户。在 DB2 中,在操作系统级上创建用户。这意味着,如果在同一操作系统上创建两个 DB2 9.1 子系统,那么两个子系统中的相同用户 ID 会使用相同的密码。DB2 Version 9.1 for z/OS 的另一个限制是用户名不能超过 个字符。

  DDL 转换问题

Data Definition Language (DDL) 语句用于定义数据库模式。本节讨论 DDL 语句(比如表和索引创建语句)面对的转换问题。

  表创建

Oracle 10g 隐式地为主键和惟一键创建惟一索引。但是在 DB2 Version 9.1 for z/OS 中,如果使用 CREATE TABLE 语句的 IN 子句指定表空间和数据库的名称,就需要为表的主键和惟一键显式地创建索引。但是,如果隐式地创建表,没有指定表空间和数据库名称,就会隐式地创建主键和惟一键索引。

   数据类型

下表给出 Oracle 10g 数据类型和相应的 DB2 z/OS 9.1 数据类型的概况。在把表创建脚本从 Oracle 10g 转换到 DB2 z/OS 9.1 时可以使用这些映射。这也有助于在迁移存储过程和触发器时为临时变量选择合适的数据类型。


表 1. 数据类型

Oracle 10g 数据类型

DB2 z/OS 9.1 数据类型

VARCHAR2(n) n<=4000

VARCHAR(n) n<=32762

DATE(默认格式是 DD-MON-YY

· 如果需要 MM/DD/YYYY,使用 DATE

· 如果需要 HH:MM:SS,使用 TIME

· 如果需要 MM/DD/YYYY-HH:MM:SS.000000,使用 TIMESTAMP

CLOB

CLOB(n)

BLOB

BLOB(n)

NUMBER*

FLOAT

NUMBER*[1..4](p,0)

SMALLINT

NUMBER[5..9](p,0)

INTEGER

NUMBER* [10..18](p,0)

BIGINT

NUMBER* [19..31](p,0)NUMBER*

DECIMAL(p,s)

[1.31,min..31](p,0) NUMBER* [1..31,min..31](p,s) DECIMAL(p,s)

NUMBER* [32..max](p,0) NUMBER* [32..max,32..max](p,s)

DECFLOAT(34)

CHAR

CHAR [1..254]=>CHAR (l….254) CHAR[255..max]=>VARCHAR(255…Max)

    主键列、外键列和索引上使用的列的数据类型

在 DB2 z/OS 9.1 中,参与创建主键、外键或索引的列的数据类型不能是 DECFLOAT。如果在 Oracle 10g 中这些列声明为数据类型 NUMBER (38),那么在 DB2 中相应的数据类型是 DECFLOAT (34)。需要确保 DB2 中的主键、外键或索引列声明为 DECIMAL (31) 或 BIGINT

   惟一索引

当在 Oracle 10g 中的列上创建 UNIQUE 索引时,会确保此列中输入的 NOT NULL 值是惟一的。如果此列可以包含 NULL 值,就可以在此列中插入任意数量的 NULL 值。确保 NOT NULL 值的惟一性。但是在 DB2 z/OS 中,如果在列上创建 UNIQUE 索引,那么只能在其中插入一个 NULL 值。要想模拟 Oracle 10g 行为,在 DB2 中需要创建 UNIQUE WHERE NOT NULL 索引,例如:CREATE UNIQUE WHERE NOT NULL INDEX IX_TEST ON TEST(COL1)

   DML 转换问题

Data Manipulation Language (DML) 语句帮助管理数据库中的数据。本节讨论 SELECT 等 DML 语句的转换会遇到的问题。

   类型转换

Oracle 10g 支持隐式的类型转换,但是 DB2 Version 9.1 for z/OS 不支持。例如,在 Oracle 中字符串 '1' 可以与数字 比较,但是在 DB2 中需要执行显式的类型转换。尽管 Oracle 支持隐式的类型转换,但是最好应该避免它。不同的表中相似的列应该声明为相同的类型,这样就可以不使用 Oracle 的隐式类型转换。

如果在应用程序代码或数据库对象中已经使用了隐式类型转换,那么在迁移到 DB2 时应该改为显式的类型转换。下表给出一个类型转换示例。


    表 2. 类型转换

原来的查询

修改后的查询

SELECT * FROM TEST WHERE COL1 = 1

SELECT * FROM TEST WHERE COL1 = ‘1’

假设TEST 表中的 COL1 的类型是 CHAR(20)。原来的查询比较一个字符串和一个数字,但是在修改后的查询中执行了显式的类型转换。

在类型转换期间绕过索引:这里要注意一点,当对建立了索引的列执行类型转换时,会绕过索引。假设上面示例中的 COL1 列上有索引,如果对 COL1 而不是 RHS 执行类型转换,那么会绕过索引,查询会执行全表扫描。

结论:可以执行类型转换,但是要谨慎。如果会绕过索引,应该对比较表达式的 RHS 执行类型转换。

   ANSI 联结

Oracle 10g 支持用非 ANSI 语法执行联结,但是 DB2 Version 9.1 for z/OS 不支持。例如,下面的联结在 Oracle 中是有效的,但是在 DB2 中无效:SELECT A, B FROM TEST1, TEST2 WHERE A.TEST1 = B.TEST2(+)

在 DB2 中,上面的联结需要转换为 ANSI 联结:SELECT A, B FROM TEST1 LEFT OUTER JOIN TEST2 ON A.TEST1 = B.TEST2

最好遵守 ANSI 标准。对于迁移活动,应该转换所有查询,让它们符合 ANSI 格式。

    在 DB2 中访问不可用的 Oracle 函数

某些 Oracle 10g 函数(比如 CHARCONCATTRIM 和 ROUND)在 DB2 Version 9.1 for z/OS 中不能直接使用,或者要使用不同的参数集。可以在 DB2 中为这些函数编写 UDF,让它们准确地模仿 Oracle 功能。可以把所有这些 UDF 放在一个模式中,比如 MIG 模式,通过设置 SQL 函数路径让数据库在执行 UDF 调用时首先搜索这个模式。可以这样设置 SQL 函数路径:SET PATH MIG, SYSTEM PATH, USER

   关键字差异

某些函数或关键字在 Oracle 10g 和 DB2 Version 9.1 for z/OS 中都可用,但是名称不一样。下表给出名称对比示例:


    表 3. Oracle 10g 和 DB2 z/OS 9.1 中可对比的名称

Oracle 10g 中的名称

DB2 z/OS 9.1 中的名称

NVL

COALESCE

DECODE

CASE

SYSDATE

CURRENT TIMESTAMP

在应用程序代码中的原始查询中可能使用了这些关键字或函数。如果相同的应用程序代码必须同时适用于 Oracle 和 DB2 数据库,那么对于这些情况必须使用 IF-ELSE 块,在 IF 部分中提供 Oracle 关键字或函数名,在 ELSE 部分中提供 DB2 关键字或函数名。这种代码很容易出错,不便维护,因为更新 Oracle 或 DB2 部分的开发人员很可能会忘了更新另一部分。

另一种方法是像 Java 那样使用实用程序类。这个实用程序类可以包含针对所有这类关键字或函数的函数。例如,如果连接的是 Oracle 数据库,那么名为 NVL 的实用程序类函数返回 NVL;如果连接的是 DB2,那么返回 COALESCE。如果把这个实用程序类命名为 MigrationClass,那么只需把应用程序中的所有 NVL 替换为 MigrationClass.NVL

如果在应用程序中有查询 SELECT NVL(COL1,1) from TEST,那么在 MigrationClass 中需要编写下面的 NVL 函数:

              

MigrationClass.Nvl(string COL1,int number)

{

If (oracle server)

      {

       Return “NVL(COL1,1)”;

      }

Else If (db2 server)

      {

       Return “COLESCE(COL1,1)”;

      }

}

查询应该改为:SELECT MigrationClass.NVL(COL1,1) from TEST

在运行时,对于 Oracle 生成的查询是 SELECT NVL(COL1,1) from TEST

对于 DB2,生成的查询是 SELECT COALESCE (COL1,1) from TEST

ROWNUM

在 DB2 z/OS 9.1 中与 ROWNUM 等效的是 FETCH FIRST N ROWS ONLY。因此,如果 Oracle 10g 查询在 WHERE 子句中使用 ROWNUM < 10,那么在 DB2 z/OS 9.1 中等效的是 FETCH FIRST 9 ROWS ONLY

如果查询使用 ROWNUM = 100,那么怎么办?在 DB2 中没有直接等效的语法。可以在 DB2 中使用 SUBTRACT 操作符(见下表),但这只是可以实现相同结果的众多方法之一。


    表 4. SUBTRACT 操作符

Oracle 10g 查询

等效的 DB2 z/OS 9.1 查询

SELECT * FROM TEST WHERE ROWNUM = 10

SELECT * FROM TEST FETCH FIRST 10 ROWS ONLY SUBTRACT SELECT * FROM TEST FETCH FIRST 9 ROWS ONLY

   NULL 和空字符串

Oracle 以相同的方式对待空字符串和 NULL,但是 DB2 以不同方式处理它们。在 Oracle 中,输入的空字符串在数据库内部存储为 NULL。下面给出一个在 Oracle 和 DB2 中创建的 TEST 表示例:

              

CREATE TABLE TEST (ID INT, NAME CHAR(20) 

INSERT INTO TEST VALUES (1, NULL) 

INSERT INTO TEST VALUES (2, ‘’) 

INSERT INTO TEST VALUES (3, NULL) 

INSERT INTO TEST VALUES (4, NULL) 

INSERT INTO TEST VALUES (5, ‘’) 

下表说明各种 SELECT 命令在 Oracle 10g 和 DB2 z/OS 9.1 中的表现:


     表 5. Oracle 和 DB2 z/OS 9.1 中的 SELECT 命令

查询

Oracle 结果

DB2 结果

SELECT ID FROM TEST WHERE NAME IS NULL

1,2,3,4,5

1,3,4

SELECT ID FROM TEST WHERE NAME = ‘’

没有结果,因为所有值都存储为 NULL

2,5

SELECT ID FROM TEST WHERE NAME IS NOT NULL

没有结果,因为所有值都存储为 NULL

2,5

通过表中的示例可以看出,在 Oracle 10g 中空字符串比较是多余的,它不会选择任何记录。

要想在 DB2 Version 9.1 for z/OS 中获得相同的 NULL 比较结果,第一个查询需要改写为 SELECT ID FROM TEST WHERE NAME IS NULL or NAME =’’

    DCL 转换问题

本节讨论 GRANT 和 REVOKE 等 Data Control Language (DCL) 语句的转换会遇到的问题。

   GRANT/REVOKE 语法

对于 Oracle 10g 和 DB2 z/OS 9.1 中的序列、过程和函数,GRANT 和 REVOKE 语句的语法不一样。

在 DB2 中,需要在 GRANT 或 REVOKE 语句中指出对象的类型。例如:

              

GRANT SELECT ON SEQUENCE TESTID TO USER1

GRANT EXECUTE ON PROCEDURE SP_TEST TO USER1

GRANT EXECUUTE on FUNCTION FN_TEST TO USER1

   PL/SQL 特有的问题

在 Oracle 和 DB2 之间存在与 PL/SQL 对象(比如过程、函数和触发器)有关的许多语法差异。本节讨论这些语法差异和转换问题。

   AFTER 触发器

在 DB2 z/OS 9.1 中,AFTER 触发器有一些限制,例如:

· 不允许多个 BEGIN-END 

· 不允许 Exception 

· 在触发器体中不允许 DECLARE 语句

· 不允许 IF-ELSE

把 AFTER 触发器从 Oracle 10g 迁移到 DB2 z/OS 9.1 可以使用两种方法:

· 把触发器逻辑转移到应用程序层,放弃触发器。

· 把触发器逻辑转移到存储过程中并从触发器调用存储过程。下表说明其工作方式。


   表 6. Oracle 和 DB2 z/OS AFTER 触发器

Oracle 触发器

DB2 z/OS 9.1 触发器

CREATE OR REPLACE TRIGGER TR_EMPLOYEE AFTER INSERT ON EMPLOYEE REFERENCING NEW AS NEW FOR EACH ROW DECLARE MANAGERID INTEGER; MANAGERTYPE CHAR(1); BEGIN MANAGERID := :NEW.MANAGER; MANAGERTYPE := :NEW.MANAGERTYPE; IF(MANAGERTYPE = 'O') THEN SP_UPDATE(MANAGERID); ELSE SP_INSERT(MANAGERID); END IF; END; /

DROP TRIGGER TR_EMPLOYEE! CREATE TRIGGER TR_EMPLOYEE AFTER INSERT ON EMPLOYEE REFERENCING NEW AS NEW FOR EACH ROW MODE DB2SQL BEGIN ATOMIC CALL SP_TR_EMPLOYEE(NEW.MANAGER,NEW.MANAGERTYPE); END! DROP PROCEDURE SP_TR_EMPLOYEE! CREATE PROCEDURE SP_TR_EMPLOYEE(IN NEW_MANAGER INTEGER, IN NEW_MANAGERTYPE CHAR(1)) BEGIN IF NEW_MANAGERTYPE = 'O' THEN CALL SP_UPDATE(NEW_MANAGER); ELSE CALL SP_INSERT(NEW_MANAGER); END IF; END!

   BEFORE 触发器

在 DB2 z/OS 9.1 中,BEFORE 触发器有以下限制:

· 不允许多个 BEGIN-END 

· 不允许 Exception 

· 在触发器体中不允许 DECLARE 语句

· 不允许 IF-ELSE

· 不允许 DML 语句

在大多数情况下,BEFORE 触发器用于设置临时变量的值。在这种情况下,方法之一是重新编写 BEFORE 触发器,让它符合 DB2 标准,见下表:


    表 7. Oracle 和 DB2 z/OS BEFORE 触发器

原来的 Oracle 触发器

DB2 z/OS 9.1 触发器

CREATE OR REPLACE TRIGGER ORAEMP BEFORE INSERT ON EMPLOYEE FOR EACH ROW DECLARE EMPID NUMBER; BEGIN IF (:NEW.EMPLOYEEID IS NULL) THEN SELECT SEQEMPVALID.NEXTVAL INTO EMPID FROM DUAL ; :NEW.EMPLOYEEID := EMPID ; END IF; END; /

CREATE TRIGGER ORAEMP NO CASCADE BEFORE INSERT ON EMPLOYEE REFERENCING NEW AS NEW FOR EACH ROW MODE DB2SQL BEGIN ATOMIC SET (NEW.EMPLOYEEID) = (CASE WHEN NEW.EMPLOYEEID IS NULL THEN NEXT VALUE FOR SEQEMPVALID ELSE NEW.EMPLOYEEID END); END!

在这里,DECLARE 和 IF ELSE 语句出现在触发器中。

在这里,DECLARE 语句已经删除了。IF ELSE 已经替换为 CASE

另一种方法是把 BEFORE 触发器转换为 AFTER 触发器,前提条件是这不会影响功能。

第三种方法是把触发器逻辑转移到应用程序层,放弃触发器。

   BEFORE 触发器和 NOT NULL 约束的优先次序

在 Oracle 10g 中,如果表上同时存在 BEFORE INSERT 触发器和 NOT NULL 约束,那么先执行 BEFORE 触发器,然后执行约束检查。例如,如果一个 BEFORE 触发器给一个 NOT NULL 列提供值,那么先执行 BEFORE 触发器,给列提供值,所以不会违反 NOT NULL 约束。另一方面,在 DB2 Version 9.1 for z/OS 中,先检查 NOT NULL 约束,然后再执行 BEFORE 触发器。因此,在上面的示例中,会违反 NOT NULL 约束,INSERT 语句会出错。

一种解决方法是给从 BEFORE INSERT 触发器取得值的 NOT NULL 列提供默认值,这样就不会违反约束。

   用户定义函数 (UDF)

在 DB2 Version 9.1 for z/OS 中,一个 UDF 只能有一个 RETURN 语句,当需要把 Oracle UDF 迁移到 DB2 时这会造成难题。可以采用的方法是:

· 修改 UDF,让它只有一个 RETURN 语句,见下表。


   表 8. 修改 UDF

Oracle 函数

DB2 z/OS 9.1 函数

CREATE OR REPLACE FUNCTION FN_TEST( ID IN INTEGER) RETURN INTEGER AS RET_VAL INTEGER; BEGIN IF ID = 1 RET_VAL := 1 ELSE RET_VAL := 2 END IF; RETURN RET_VAL; END FN_TEST; /

CREATE FUNCTION FN_TEST (ID IN INTEGER) RETURNS INTEGER LANGUAGE SQL RETURN (CASE WHEN (ID = 1) THEN 1 ELSE 2 END)!

· 把 UDF 转换为存储过程。这里要注意一点:如果采用这种方法,就必须修改对原 UDF 的调用,改为执行存储过程并提供一个额外的 OUT 参数。例如,如果在 Oracle 10g 中有 UDF 定义 CREATE OR REPLACE FUNCTION FN_TEST( ID IN INTEGER) RETURN INTEGER,在 DB2 Version 9.1 for z/OS 中要把它转换为存储过程,那么定义应该修改为 DROP PROCEDURE FN_TEST; CREATE PROCEDURE FN_TEST( IN ID INTEGER, OUT RETURN_VAR INTEGER)。必须相应地修改对 UDF 的调用。

· 作为使用 Java 或 C++ 等语言编写的外部 UDF 创建 UDF。应该选择这三种方法中的哪一个取决于需求。如果 UDF 的性能很重要,在 DB2 中作为外部 UDF 创建它会降低性能。应该首先尝试通过修改代码创建 DB2 内部的 SQL UDF。其次考虑把 UDF 转换为存储过程。创建外部 UDF 应该作为最后的手段。

   存储过程和函数的同义词

与 Oracle 10g 不同,在 DB2 Version 9.1 for z/OS 中不可能为存储过程或函数创建同义词。以一个 Oracle 场景为例。在 MAIN 模式中创建存储过程 SP_TEST,在 TARGET 模式中创建它的同义词 SP_TEST

因为在 DB2 Version 9.1 for z/OS 中不能为存储过程或函数创建同义词,要想模拟 Oracle 10g 行为,就需要在 TARGET 模式中创建 SP_TEST 的拷贝。在创建拷贝时,有两种方法。可以复制 SP_TEST 的代码并在 TARGET 模式中创建它。代码中对 MAIN 模式中的对象的所有引用都需要在前面加上模式名 MAIN。下表给出一个示例。


   表 9. 在 TARGET 模式中创建 SP_TEST

MAIN 模式

TARGET 模式

CREATE PROCEDURE SP_TEST(ID INTEGER) LANGUAGE SQL BEGIN DECLARE EMPID INTEGER; SET EMPID = 2; INSERT INTO TEST (EMPID) VALUES(EMPID); END!

CREATE PROCEDURE SP_TEST(ID INTEGER) LANGUAGE SQL BEGIN DECLARE EMPID INTEGER; SET EMPID = 2; INSERT INTO MAIN.TEST (EMPID) VALUES(EMPID); END!

可以在 TARGET 模式中创建 SP_TEST,让它用 CALL 语句调用 MAIN 模式的 SP_TEST。下表给出一个示例。


    表 10. 在 TARGET 模式中创建包含 CALL 语句的 SP_TEST

MAIN 模式

TARGET 模式

CREATE PROCEDURE SP_TEST(ID INTEGER) LANGUAGE SQL BEGIN DECLARE EMPID INTEGER; SET EMPID = 2; INSERT INTO TEST (EMPID) VALUES(EMPID); END!

CREATE PROCEDURE SP_TEST(ID INTEGER) LANGUAGE SQL BEGIN CALL MAIN.SP_TEST(ID); END!

  Oracle 集合

与 Oracle 10g 不同,DB2 z/OS 9.1 不支持集合。可以使用 DB2 Global Temporary Table (GTT) 实现 Oracle 集合的概念。

  Oracle 

在 Oracle 10g 中可以使用包对过程或函数进行分组。DB2 z/OS 9.1 不支持包的概念。在把 Oracle 包迁移到 DB2 时,需要作为单独的对象创建所有包对象。必须使用 GTT 处理包的全局变量。

  与事务控制相关的问题

Transaction Control (TCL) 语句帮助把语句组织为逻辑事务,以便能够提交或回滚它们。本节讨论 COMMIT 和 ROLLBACK 等 TCL 语句的转换问题。

   COMMIT

在 Oracle 10g 中,COMMIT 并不关闭游标;但是在 DB2 z/OS 9.1 中,COMMIT 关闭所有打开的游标。在 DB2 中,要想让游标在提交之后仍然打开,应该把它们声明为 WITH HOLD 游标。

  ROLLBACK

在 Oracle 10g 中,ROLLBACK 并不关闭游标;但是在 DB2 z/OS 9.1 中,ROLLBACK 关闭所有打开的游标。一种方法是使用 SAVEPOINT,对 SAVEPOINT 使用一次 ROLLBACK,并在 SAVEPOINT 之前保留 OPEN CURSOR 语句,这样就可以让游标在 ROLLBACK 上保持打开。另一种方法是在 ROLLBACK 之后再次显式地打开游标,然后在 ROLLBACK 时把游标指针跳到读取的记录。

注意,在游标内使用 ROLLBACK 是不好的做法,应该避免这么做。

  隔离级别

下表说明在 Oracle 10g 和 DB2 z/OS 9.1 之间隔离级别及其值的对应关系。


  表 11. 隔离级别映射

Oracle 10g

DB2 z/OS 9.1

Read uncommitted

Dirty read/uncommitted read

1

Read committed

Cursor stability

2

Repeatable read

Read stability

4

Serializable

Repeatable read

8

  其他问题

本节讨论其他转换问题。

  启用或禁用触发器和约束

在 Oracle 10g 中,可以启用和禁用触发器和约束,但是在 DB2 z/OS 9.1 中不能这么做。要想在 DB2 中实现相同的功能,需要在 Oracle 中执行 DISABLE 的位置删除触发器,在 Oracle 中执行 ENABLE 的位置创建触发器。

  Oracle 中的 语法

在 Oracle 10g 中,可以使用 语法从主 SQL 文件调用其他 SQL 文件。在 DB2 z/OS 9.1 中,不能从一个 SQL 文件调用另一个 SQL 文件。要想模拟这个功能,需要把主 SQL 文件转换为 shell 脚本。这个 shell 脚本通过命令调用 SQL 文件,见下表。


   表 12. shell 脚本

Oracle SQL 文件 - main.sql

DB2 shell 脚本 - main.sh

@"./Table/CreateTable.sql" @"./Sequence/CreateSequence.sql"

db2 connect to DBDEV user master using test db2 -td! -vf"./Table/CreateTable.sql" db2 -td! -vf"./ Sequence/CreateSequence.sql "

shell 脚本中的第一个语句是数据库连接语句。在此之后,使用 DB2 的 db2–td 语法调用各个 SQL 文件。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
DB2® 9 for z/OS® is an exciting new version, with many improvements in performance and little regression. DB2 V9 improves availability and security, as well as adds greatly to SQL and XML functions. Optimization improvements include more SQL functions to optimize, improved statistics for the optimizer, better optimization techniques, and a new approach to providing information for tuning. V8 SQL procedures were not eligible to run on the IBM® System z9® Integrated Information Processor (zIIP), but changing to use the native SQL procedures on DB2 9 makes the work eligible for zIIP processing. The performance of varying length data can improve substantially if there are large numbers of varying length columns. Several improvements in disk access can reduce the time for sequential disk access and improve data rates. The key DB2 9 for z/OS performance improvements include reduced CPU time in many utilities, deep synergy with IBM System z® hardware and z/OS software, improved performance and scalability for inserts and LOBs, improved SQL optimization, zIIP processing for remote native SQL procedures, index compression, reduced CPU time for data with varying lengths, and better sequential access. Virtual storage use below the 2 GB bar is also improved. This IBM Redbooks® publication provides an overview of the performance impact of DB2 9 for z/OS, especially performance scalability for transactions, CPU, and elapsed time for queries and utilities. We discuss the overall performance and possible impacts when moving from version to version. We include performance measurements that were made in the laboratory and provide some estimates. Keep in mind that your results are likely to vary, as the conditions and work will differ. In this book, we assume that you are somewhat familiar with DB2 V9. See DB2 9 for z/OS Technical Overview, SG24-7330, for an introduction to the new functions. In this book we have used the new official DB2 9 for z/OS abbreviated name for IBM Database 2 Version 9.1 for z/OS as often as possible. However, we have used the old DB2 V9 notation for consistency when directly comparing DB2 V9 to DB2 V8 or previous versions.

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值