Professional Documents
Culture Documents
Database Migration From Oracle To DB2-20120314pdf
Database Migration From Oracle To DB2-20120314pdf
Demystified!
By Gunjan Verma and Neeraj Kakar
Some of the many reasons which drive organizations to migrate their applications or
products onto a different RDBMS are related to costs, scalability, compliance, performance,
strategic and others. Whatever your reasons may be, if you are in for a database migration
from Oracle 10g to DB2 Z/OS 9.1, this paper will provide you some of the most pragmatic,
easy to implement resolutions, workarounds and tips which can save your migration effort
at least by 25% and a majority of your consultant costs.
Database migration activity is done to ensure that the same application layer is able to talk
to a different RDBMS. It typically involves application layer porting and database objects
migration. This is a critical activity in any project and requires a comprehensive analysis as
the two RDBMS are inherently different and things might not work on the fly. Another
point the needs to be considered is whether you want to continue using the existing
environment or plan to abandon it once the application is ported to the new RDBMS. The
intent of maintaining two environments is to provide customers the flexibility to choose the
RDBMS. In this case there is an overhead of maintaining two environments and ensuring
that they remain in sync.
This paper is a result of experience gained from a specific case of migration from Oracle 10g
to DB2 Z /OS 9.1 database. There are multiple tools available in the market including
Migration tool Kit – MTK [1] from IBM which help in the migration process but the output
of these tools is not 100% accurate and there is a lot of manual intervention required to make
the output DB2 ready. This paper would come handy when one has to fix a tool generated
output to make it work on DB2. The specific issues that come up for each type of objects
along with their resolution have been listed.
This paper would help product and application developers and DBAs who want to port
their application from Oracle 10g to DB2 Z /OS 9.1 database. The target audience should
have a basic knowledge of PL/SQL to be able to use the document effectively. The scope of
this paper is troubleshooting of database specific technical issues faced in a migration
activity. Functional issues are out of scope for this paper.
The two RDBMS might have a different architecture and might use a different object
hierarchy.
Embedded SQL queries might be placed in the application code for database interaction. All
the raw SQLs need to be analyzed to see whether they work on both databases or changes
are needed.
Database objects like Tables, Views, Stored Procedures, Triggers or User Defined Functions
might have to be changed partially or completely based on the syntax followed in the target
database.
Same function might be available in both the databases but with a different name. All such
differences need to be taken care of.
There might be considerable differences in the data types between the two RDBMS.
This section would talk about specific issues faced, resolutions and tips for Oracle 10g to
DB2 9.1 Migration
Oracle 10g
Database
Table1 Table2
Table2
DB2
Subsystem
Database
Tablespace Tablespace
Tablespace
Table Table
In Oracle 10g, there is a database instance which contains multiple tablespaces. Each
tablespace stores one/multiple tables. Usually tables are grouped in a tablespace based on
their function relation and access pattern.
In DB2 Z /OS 9.1, there is a DB2 subsystem on the top of the hierarchy. A subsystem
contains multiple storage groups. A storage group is a set of volumes on physical storage
device, DASD (Direct Access Storage devices) on the mainframe. A storage group contains
database(s) and a database contains tablespaces. Each tablespace contains one or more tables
based on the type of tablespace [2].
In DB2 9.1, for every BLOB/CLOB column in a table, an LOB tablespace, an auxiliary
table and an index need to be created. If the CURRENT RULES register is set to value DB2,
all these objects will have to be created explicitly for every BLOB/CLOB column. If the
CURRENT RULES register is set to value STD, DB2 takes care of creating all these objects
implicitly for every BLOB/CLOB column. The value of the CURRENT RULES [3] register
can be set using the following command:
The above command should be used before running the table creation script for the sub-
system.
2.1.2 USERS
In Oracle 10g, users are created at database level but in DB2 users are created at operating
system level. This means that if two DB2 9.1 sub-systems are created on the same OS, then
Oracle 10g implicitly creates unique indexes for primary key and unique keys but in DB2 Z
/OS 9.1, explicit indexes need to be created for primary and unique keys of the table.
CHAR[255..max]=>
VARCHAR(255…Max)
The above table gives a brief of Oracle 10g data types and their DB2 Z /OS 9.1 equivalents.
This mapping can be used while converting table creation scripts from Oracle 10g to DB2 Z
/OS 9.1. This is also useful to find appropriate data types for temporary variables while
porting stored procedures and triggers.
In DB2 Z /OS 9.1, columns participating in creation of primary key, foreign key or indexes
cannot have a data type of DECFLOAT. If in Oracle 10g, such columns are declared to be of
data type NUMBER (38), then corresponding data type in DB2 is DECFLOAT (34). One
needs to be careful and ensure that primary key, foreign key or index columns are
declared as DECIMAL (31) or BIGINT in DB2.
When a UNIQUE index is created on a column in Oracle 10g, it ensures that the NOT NULL
values entered in that column are unique. If the column is NULLABLE, any number of
NULLs can be inserted in that column. The uniqueness is ensured on the NOT NULL
values. But, in DB2 Z /OS if a UNIQUE index is created on a column, then only one NULL
value can be inserted into it. In order to emulate the Oracle 10g behavior, UNIQUE WHRE
NOT NULL [4] index needs to be created in DB2.
Oracle 10g supports implicit typecasting but DB2 Z /OS 9.1 does not. For example, in
Oracle, a string „1‟ can be compared with a numeric 1 but in DB2 explicit typecasting needs
to be done. Although implicit type casting is supported by Oracle, but as a good
programming practice, it should be avoided. Similar columns in different tables should be
declared with same data types, so that implicit typecasting facility of Oracle is not used.
In case, implicit type casting has already been used in application code or database objects,
then while migrating to DB2 explicit type casting should be done at all places.
Example:
Here the original query is comparing a string to a number but in the modified query,
explicit typecasting has been done.
Oracle 10g supports non ANSI syntax for JOINS but DB2 Z /OS 9.1 does not. For
Example: The following join works in Oracle but not in DB2:
SELECT A, B FROM TEST1, TEST2 WHERE A.TEST1 = B.TEST2(+)
In DB2, the above JOIN needs to be converted into an ANSI JOIN by using:
Following ANSI standards is a good coding practice, so in case of a migration activity, all
queries should be converted so that they follow ANSI format [5].
Certain Oracle 10g functions like CHAR, CONCAT, TRIM, ROUND etc are either not
available in DB2 Z /OS directly or use a different set of arguments. UDFs can be coded for
all such functions in DB2 so that they exactly replicate the Oracle functionality. All these
UDFs can placed into a single schema say MIG schema and SQL function path can be set in
such a way that this migration schema is searched first for UDF calls. The SQL function path
can be set as:
There are certain functions or keywords which are available both in Oracle 10g and DB2 Z
/OS 9.1, but with different names. Example there is NVL function in Oracle and COALESCE
in DB2, DECODE in Oracle and CASE in DB2, SYSDATE in Oracle and CURENT
TIMESTAMP in DB2. Such keywords or functions might be used in raw queries coded in
the application code. If the same application code has to cater to both Oracle and DB2
databases, then IF-ELSE blocks will have to be coded for all such instances where the Oracle
specific keyword or function name is supplied in the IF part and DB2 specific keyword or
function name is supplied in the ELSE part. This type of code is error prone and less
maintainable because there is a high possibility of a developer updating the Oracle part and
missing the DB2 part or vice-versa.
An alternative approach that may be followed is to have a utility class as in case of JAVA.
This utility class can have functions for all such keywords or functions. Example a utility
class function called NVL would return NVL if the Database connection is with Oracle and
COALESCE if the DB connection is with DB2. Let‟s name this utility class as MigrationClass.
Now all instances of NVL in the application will have to be replaced with
MigrationClass.NVL.
MigrationClass.Nvl(string COL1,int
number)
{
If (oracle server)
{
Return “NVL(COL1,1)”;
}
Else If (db2 server)
{
Return “COLESCE(COL1,1)”;
}
}
2.3.5 ROWNUM
The equivalent for ROWNUM in DB2 Z /OS 9.1 is FETCH FIRST N ROWS ONLY. So if an
Oracle 10g query uses ROWNUM < 10 in WHERE clause, the DB2 Z /OS 9.1 equivalent
would be FETCH FIRST 9 ROWS ONLY.
Oracle treats Empty string and NULL as the same but DB2 treats them differently. Whatever
is entered as empty string in Oracle gets stored as NULL internally in the database.
Example: Let‟s take an example of a TEST table created in Oracle and DB2:
Now let‟s see the behavior of various SELECT commands in Oracle 10g and DB2 Z /OS 9.1:
It‟s evident from the above examples that an empty string comparison in Oracle 10g is
redundant and does not fetch anything.
In order to fetch the same results in DB2 Z /OS 9.1 on a NULL comparison, the first query
needs to be re-coded in DB2 as
GRANT and REVOKE statement syntax is different for sequences, procedures and functions
in Oracle 10g and DB2 Z /OS 9.1.
In DB2, the type of object needs to be mentioned on the GRANT or Revoke statement.
Example:
There are two options to port AFTER triggers from Oracle 10g to DB2 Z /OS 9.1:
Move the trigger logic to application layer and get away with the trigger.
Move the trigger logic to a Stored Procedure and call the Stored Procedure from the
trigger. An illustration for this follows:
In DB2 Z /OS 9.1, BEFORE triggers have an additional limitation that they cannot have a
CALL statement inside them.
In this case, even the split logic (Trigger-SP pair) that can be used for AFTER triggers won‟t
work. One of the options is to try and recode the BEFORE trigger, so that it follows DB2
standards:
Original Oracle Trigger DB2 ZOS Trigger
CREATE OR REPLACE TRIGGER ORAEMP CREATE TRIGGER ORAEMP NO
BEFORE INSERT ON EMPLOYEE CASCADE BEFORE INSERT ON
FOR EACH ROW EMPLOYEE
DECLARE REFERENCING NEW AS NEW FOR
EMPID NUMBER; EACH ROW
BEGIN MODE DB2SQL
IF (:NEW.EMPLOYEEID IS NULL) THEN BEGIN ATOMIC
SELECT SEQEMPVALID.NEXTVAL INTO SET (NEW.EMPLOYEEID) =
EMPID FROM DUAL ; (CASE WHEN NEW.EMPLOYEEID
:NEW.EMPLOYEEID := EMPID ; IS NULL THEN
END IF; NEXT VALUE FOR
END; SEQEMPVALID
/ ELSE
NEW.EMPLOYEEID
END);
END!
Declare block present No declare statements
4 lines of Trigger Code block Trigger code reduced to single line.
The third option is to move trigger logic to application layer and get away with the trigger.
In Oracle 10g, if there is a BEFORE INSERT TRIGGER and a NOT NULL constraint on a
table, then the BEFORE TRIGGER is executed first and then constraint check happens. For
example: if a before trigger supplies value to a NOT NULL column, then the BEFORE
trigger is executed first and a value is supplied to the column so that the NOT NULL
constraint is not violated. In DB2 Z /OS 9.1, on the other hand, the NOT NULL constraint is
evaluated before the BEFORE trigger. So in the example above, the NOT NULL constraint
would get violated and the INSERT statement would error out.
A workaround to this is to supply a default value to the NOT NULL column whose value
comes from a BEFORE INSERT TRIGGER, so that the constraint is not violated.
In DB2 Z /OS 9.1, a UDF can have a single statement which is a RETURN statement. This
brings a bring challenge when an Oracle UDF needs to be ported to DB2. The options
available are:
1. Modify the UDF so that it has a single statement. Example:
2. Convert the UDF to a Stored Procedure. A point to note here is that if this approach is
followed, the CALLs to the original UDF will have to be modified so that they now
execute the Stored Procedure and supply an extra OUT parameter. Example:
In DB2 Z /OS 9.1, if the above UDF is converted to a Stored Procedure, the definition gets
modified as:
Which option to choose from the above three, depends on the requirement. If the UDF is
performance critical then creating it as an external UDF in DB2 would make it slow. The
first option that one should try is to create it as an SQL UDF in DB2 by modifying the code.
Unlike Oracle 10g, in DB2 Z /OS 9.1 it is not possible to create synonyms of Stored
Procedures or Functions. Let‟s take an example of an Oracle scenario. A Stored Procedure
SP_TEST created in schema „MAIN‟ and its synonym SP_TEST is created in schema
„TARGET‟.
Since synonyms cannot be created for procedures and functions in DB2 Z /OS 9.1, so in
order to replicate the Oracle 10g behavior, a copy of SP_TEST needs to be created in schema
„TARGET‟. While creating the copy, there are two options:
We can take the code of SP_TEST and create it in schema „TARGET‟. All references to objects
of schema „MAIN‟ in the code will need to be prefixed with schema name „MAIN‟. Example:
We can create SP_TEST in schema „TARGET with a single line CALL statement to SP_TEST
of schema „MAIN‟. Example:
DB2 Z /OS 9.1 does not support collections as Oracle 10g. DB2 Global Temporary Table
(GTT) can be used to implement the concept of Oracle COLLECTIONS.
PACKAGES can be used in ORACLE 10g to group a set of procedures or functions. DB2 Z
/OS does not support this concept of packages. While porting an Oracle package to DB2, all
package objects need to be created as standalone objects. Global variables of the package
will have to be handled using GTTs.
2.6.1 COMMIT
In Oracle 10g, COMMIT does not close the cursors but in DB2 Z /OS 9.1 COMMIT closes all
open cursors. In order to keep the cursor open after commit, they should be declared as
WITH HOLD cursors in DB2.
2.6.2 ROLLBACK
In Oracle 10g, ROLLBACK does not close the cursors but in DB2 Z /OS 9.1 ROLLBACK
closes all open cursors. One approach is to use SAVEPOINTS, use a ROLLBACK to the
SAVEPOINT and keep the OPEN CURSOR statement before the SAVEPOINT in order to
keep the cursor open on the ROLLBACK. Another approach is to explicitly open the cursor
again after ROLLBACK and skip the cursor pointer till the record read at the time of
ROLLBACK.
The following table shows the mapping between isolation levels and their value in Oracle
10g and DB Z /OS 9.1 [6]
In Oracle 10g, triggers and constraints can be enabled and disabled but this is not possible in
DB2 Z /OS 9.1. To achieve the same functionality in DB2, the trigger needs to be dropped at
the point where a DISABLE is issued in Oracle and CREATEd at the point where ENABLE
is issued in Oracle [7].
@ Syntax in Oracle 10g is used to invoke other SQL files from a main SQL file. In DB2 Z /OS
9.1, one SQL file cannot be invoked from another SQL file. In order to replicate this
functionality, the main SQL file needs to be converted into a shell script. The shell script will
have commands to invoke SQL files from it. An example follows:
The first statement in the shell file would be database connection statement. After that
individual SQL files can be invoked using db2 –td syntax of DB2.
3 CONCLUSION
This paper brings out certain specific issues faced during Oracle 10g to DB2 Z /OS 9.1
migration. Workarounds have been suggested in order to circumvent the issues. The best
workaround would vary on a case to case basis. References have been given for a detailed
description of specific DB2 features mentioned in the paper.
4.1 http://www.ibm.com/developerworks/data/downloads/migration/mtk/
4.2 http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.d
b29.doc.intro/db2z_tablespaces.htm
4.3 http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.d
b29.doc.sqlref/db2z_sql_setcurrentrules.htm
4.4 http://publib.boulder.ibm.com/infocenter/dzichelp/v2r2/index.jsp?topic=/com.ibm.d
b29.doc.sqlref/db2z_sql_createindex.htm
4.5 http://www.dbasupport.com/oracle/ora9i/ansi_joins.shtml
4.6 http://webcache.googleusercontent.com/search?q=cache:I7qc2aJ8QG0J:www.devbg.or
g/seminars/seminar-26-july-2005/Transactions-in-Oracle-Evgenya-
Kotzeva.ppt+isolation+levels+oracle&cd=1&hl=en&ct=clnk&gl=in
4.7 http://www.ibm.com/developerworks/data/library/techarticle/0211swart/0211swart
.html
4 GLOSSARY
Author Profile
Gunjan is a Project Manager with over eight years of experience advising financial services
companies in defining and driving their database strategy. Most recently, she has led the
adoption of DB2 for a leading banking product. She can be reached at
gunjan_verma@infosys.com or gunjan.verma@rediffmail.com.
Neeraj Kakar is a Senior Project Manager with Infosys Technologies with expertise in
Database Migration Projects. He is an also an active blogger and on the Editorial Panel of
„Security‟ Defense Journal. He can be reached at neeraj_kakar@infosys.com or
neeraj.kakar@gmail.com.