Table of Contents

< Day Day Up >
Next Section

Oracle to DB2 UDB Conversion Guide
Oracle to DB2 UDB Conversion Guide
by Whei-Jen Chen et al. ISBN:0738499455
IBM Redbooks © 2003 (448 pages)

This informative guide describes how to migrate the database system from Oracle to DB2 UDB Version 8.1 on AIX, Linux, and the Microsoft Windows platform. It presents the best practices in migration strategy and planning, migration tools, and more.

Table of Contents
 | Oracle to DB2 UDB Conversion Guide
 | Notices
 | Preface
 | Chapter 1 | - | Introduction
 | Chapter 2 | - | Oracle Migration Project Planning
 | Chapter 3 | - | MTK
 | Chapter 4 | - | Porting with MTK
 | Chapter 5 | - | Conversion Reference
 | Chapter 6 | - | Data Conversion
 | Chapter 7 | - | Application Conversion
 | Chapter 8 | - | Script Conversion
 | Chapter 9 | - | Testing
 | Appendix A | - | DB2 UDB Product Overview
 | Appendix B | - | Data Types
 | Appendix C | - | Oracle Call Interface (OCI) Mapping
 | Appendix D | - | Converter for SQL*Loader
 | Appendix E | - | Terminology Mapping
 | Appendix F | - | Example Oracle Database
 | Appendix G | - | Additional Material
 | Related Publications
 | Index
 | List of Figures
 | List of Tables
 | List of Examples

 < Day Day Up >
Next Section


BackCover

Previous Section
< Day Day Up >
Next Section

Back Cover

DB2 Universal Database (DB2 UDB) has long been known for its technology leadership. This IBM Redbook is an informative guide that describes how to migrate the database system from Oracle to DB2 UDB Version 8.1 on AIX, Linux, and the Microsoft Windows platform. This guide presents the best practices in migration strategy and planning, migration tools, and practical migration examples. It is intended for technical staff who are involved in an Oracle to DB2 UDB conversion project.

This Redbook provides migration planning guidelines, with step-by-step instructions for installing and using IBM Migration Toolkits (MTK) to port the database objects and data from Oracle to DB2 UDB. It illustrates with examples how to convert the stored procedures, functions, and triggers. Application programming and conversion considerations are discussed along with the differences in features and functionality of the two products.

In addition, you can find script conversion samples for data loading, database administration, and reports, which are useful for DBAs. The testing section provides procedures and tips for conversion testing and database tuning.

Previous Section


Oracle to DB2 UDB Conversion Guide

Whei-Jen Chen
Fadel Fiani
Marina Greenstein
Stefan Hummel
Ranjit K. Kalidasan
Ken Leonard
Art Sammartino
Artur Wronski
Redbooks
ibm.com/redbooks

Step-by-step guide to migrate from Oracle to DB2 UDB V8.1

Conversion examples

Step-by-step guide of MTK tool usage

Note

Before using this information and the product it supports, read the information in "Notices" on page xv.

First Edition (November 2003)

This edition applies to DB2 UDB Version 8.1, Fixpak 2, Oracle 8i, Oracle 9i, AIX 5.0, Linux Red Hat Version 8. Windows 2000 Server.

Copyright © International Business Machines Corporation 2003.

ISBN:0738499455

All rights reserved.

Note to U.S. Government Users Restricted Rights -- Use, duplication or disclosure restricted by GSA ADP Schedule Contract with IBM Corp.


Notices

This information was developed for products and services offered in the U.S.A.

IBM may not offer the products, services, or features discussed in this document in other countries. Consult your local IBM representative for information on the products and services currently available in your area. Any reference to an IBM product, program, or service is not intended to state or imply that only that IBM product, program, or service may be used. Any functionally equivalent product, program, or service that does not infringe any IBM intellectual property right may be used instead. However, it is the user's responsibility to evaluate and verify the operation of any non-IBM product, program, or service.

IBM may have patents or pending patent applications covering subject matter described in this document. The furnishing of this document does not give you any license to these patents. You can send license inquiries, in writing, to: IBM Director of Licensing, IBM Corporation, North Castle Drive Armonk, NY 10504-1785 U.S.A.

The following paragraph does not apply to the United Kingdom or any other country where such provisions are inconsistent with local law: INTERNATIONAL BUSINESS MACHINES CORPORATION PROVIDES THIS PUBLICATION "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Some states do not allow disclaimer of express or implied warranties in certain transactions, therefore, this statement may not apply to you.

This information could include technical inaccuracies or typographical errors. Changes are periodically made to the information herein; these changes will be incorporated in new editions of the publication. IBM may make improvements and/or changes in the product(s) and/or the program(s) described in this publication at any time without notice.

Any references in this information to non-IBM Web sites are provided for convenience only and do not in any manner serve as an endorsement of those Web sites. The materials at those Web sites are not part of the materials for this IBM product and use of those Web sites is at your own risk.

IBM may use or distribute any of the information you supply in any way it believes appropriate without incurring any obligation to you.

Information concerning non-IBM products was obtained from the suppliers of those products, their published announcements or other publicly available sources. IBM has not tested those products and cannot confirm the accuracy of performance, compatibility or any other claims related to non-IBM products. Questions on the capabilities of non-IBM products should be addressed to the suppliers of those products.

This information contains examples of data and reports used in daily business operations. To illustrate them as completely as possible, the examples include the names of individuals, companies, brands, and products. All of these names are fictitious and any similarity to the names and addresses used by an actual business enterprise is entirely coincidental.

COPYRIGHT LICENSE:

This information contains sample application programs in source language, which illustrates programming techniques on various operating platforms. You may copy, modify, and distribute these sample programs in any form without payment to IBM, for the purposes of developing, using, marketing or distributing application programs conforming to the application programming interface for the operating platform for which the sample programs are written. These examples have not been thoroughly tested under all conditions. IBM, therefore, cannot guarantee or imply reliability, serviceability, or function of these programs. You may copy, modify, and distribute these sample programs in any form without payment to IBM for the purposes of developing, using, marketing, or distributing application programs conforming to IBM's application programming interfaces.

Trademarks

The following terms are trademarks of the International Business Machines Corporation in the United States, other countries, or both:

 | DRDA® | Rational Suite®
Redbooks (logo) | Everyplace® | Rational®
iSeries™ | Informix® | Redbooks™
pSeries® | IBM® | RETAIN®
z/OS® | Lotus® | S/390®
Approach® | MQSeries® | SmartSuite®
AIX 5L™ | MVS™ | SP2®
AIX® | Net.Data® | SQL/DS™
AS/400® | Notes® | TestStudio®
Distributed Relational Database | OS/2® | WebSphere®
Architecture™ | OS/390® | 1-2-3®
DB2 Connect™ | OS/400® |
DB2 Extenders™ | PartnerWorld® |
DB2 Universal Database™ | QMF™ |
DB2® | Rational Rose® |

The following terms are trademarks of International Business Machines Corporation and Rational Software Corporation, in the United States, other countries or both.

The following terms are trademarks of other companies:

Intel, Intel Inside (logos), MMX, and Pentium are trademarks of Intel Corporation in the United States, other countries, or both.

Microsoft, Windows, Windows NT, and the Windows logo are trademarks of Microsoft Corporation in the United States, other countries, or both.

Java and all Java-based trademarks and logos are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States, other countries, or both.

UNIX is a registered trademark of The Open Group in the United States and other countries.

SET, SET Secure Electronic Transaction, and the SET Logo are trademarks owned by SET Secure Electronic Transaction LLC.

Other company, product, and service names may be trademarks or service marks of others.


Preface

This IBM® Redbook provides procedures and examples of converting Oracle to DB2® UDB. We focus on the technical considerations and methodology involved in performing the database and application conversion. The laboratory examples are performed under Oracle 8i and DB2 UDB V8.1. However, the migration process and examples can be applied to Oracle 7, 8, and 9i. The redbook is organized as follows.

  • Chapter 1 provides an overview of both Oracle and DB2 UDB to facilitate the understanding of both architectures.

  • Chapter 2 introduces the common process of migration and porting, the planning process, and the available tools and resources.

  • Chapter 3 describes the IBM Migration Toolkits functions and installation procedures.

  • Chapter 4 discuss and demonstrates the conversion of database objects and the extraction and loading of data into a DB2 UDB database using the IBM Migration Toolkit.

  • Chapter 5 explores some tools and methods for manually converting the triggers, store procedures, and functions. It also provide examples of implementing SQL features in DB2 UDB, and technics in building external procedures and functions using C/C++ and Java™.

  • Chapter 6 discusses the data conversion methods for deploying the data from Oracle to DB2 database.

  • Chapter 7 describes the application conversion from an Oracle to a DB2 UDB environment including planning, Proc*C, OCI, Java conversion, and package application migration such as SAP, PeopleSoft, and Siebel.

  • Chapter 8 discusses the administration script conversion from an Oracle environment to a DB2 UDB environment including data load script conversion, administration script conversion, and report tools available to DB2.

  • Chapter 9 describes the test objectives and a generic testing methodology that can be employed to test a migrated application.

The team that wrote this redbook

This redbook was produced by a team of specialists from around the world working at the International Technical Support Organization, San Jose Center.

Click To expand
Figure 0-1: From left to right, Ranjit, Ken, Fadel, Whei-Jen, Stefan, Artur

Whei-Jen Chen is a Project Leader at the International Technical Support Organization, San Jose Center. She has extensive experience in application development, database design and modeling, and DB2 system administration. Whei-Jen is an IBM Certified Solutions Expert in Database Administration and Application Development as well as an IBM Certified IT Specialist.

Fadel Fiani is a Certified IT Specialist with IBM Information Management Software. He has over ten years experience in both database administration and application development using a wide range of client/server and Web based platforms. His experience includes designing and implementing logical and physical database systems. He has been working for IBM for almost three years providing DB2 presales technical support, engaging in proof of concepts, and leading many competitive Oracle to DB2 migration initiatives. Fadel is based in Dublin, Ohio.

Marina Greenstein is a Certified Consulting IT Software Specialist with the IBM Database Migration Team. She is an IBM Certified Solutions Expert who joined IBM at 1995 with experience in database application architecture and development. During the 8 years Marina has been with DB2 Migration Team, she has assisted the customer in their migrations from Microsoft® SQL Server, Sybase, or Oracle databases to DB2 UDB. She presented migration methodology at numerous DB2 technical conferences and at SHARE. She is also author of multiple articles and a white paper on the DB2 migration subject.

Stefan Hummel is an IT Specialist for competitive database migrations in IBM, Germany. He has more than 9 years of IT experience using a wide range of client and server platforms. His experience includes application development as well as database design, implementation, and administration of Oracle and DB2 databases on UNIX®, Linux, and Windows®. He is a IBM Certified Solutions Expert for DB2 UDB Application Development and Administration.

Ranjit Kumar Kalidasan is a Database Consultant in Cognizant Technology Solutions, India, a major IT solutions provider and IBM Business Partner. He has more than 5 years of experience in the IT Industry. His areas of expertise are in technical and system support of IBM DB2 in all platforms, including DB2 for OS/390® to Universal Database on Windows NT®, UNIX, IBM iSeries™ server; and Oracle database administration on Windows and UNIX platforms. He is an IBM Certified Solutions Expert on Universal Database 8.1 Database administration and Oracle Certified Professional on Oracle 8i Database administration. He trains exclusively on Oracle and DB2 for OS/390 and Universal Database on Windows NT and UNIX at Cognizant.

Ken Leonard is an Information Technology Specialist with IBM Information Management group. He has 14 years experience in the areas of application development and database administration. Before joining IBM, he worked for Oracle Corporation for more than 7 years as a Senior Systems Engineer and a consultant. He became certified on Oracle 7.3 in 1998.

Art Sammartino is a Certified Consulting IT Software Specialist with the IBM Database Migration Team. He is an IBM Certified Solutions Expert who joined IBM with experience in Microsoft SQL Server, Sybase, and Oracle. In the 4 years that Art has been with IBM, he has assisted more than 200 clients in their migrations from Microsoft SQL Server, Sybase, and Oracle databases to DB2 UDB. He is also a co-author of the DB2 UDB V7.1 Porting Guide, SG24-6128.

Artur Wronski is a Advisory IT Specialist within IBM Software Group, Poland. He has more than nine years of experience in the IT Industry. He holds a master's degree in Knowledge Discovery in Databases, at Warsaw Technical University. His areas of expertise include DB2 UDB administration, troubleshooting and tuning, as well as Business Intelligence solution implementation.

Acknowledgement

The authors express their deep gratitude for the help they received from Paul Yip, IBM DB2 UDB Consulting Services. They would also like to thank the following people for their contributions to this project:

Kevin Decker
IBM Data Management Marketing

Barry Faust, David Dean, Debra Eaton, Burt Viaplando,
IBM Software Migration Office

Tom Christopher, Jean-Jacques Daudenarde, Gerry Fisher, Maxime Tiran
IBM Database Migration Toolkit Development, IBM Silicon Valley Laboratory

Drew Bradstock, Ted Wasserman, Bill Wilkins
IBM DB2 UDB Consulting Services, Toronto Laboratory

Alex Jarzebowicz
IBM Data Management User Technology, IBM Silicon Valley Laboratory

Dan Simchuk
IBM World Wide Consulting - Data Management group

Sotaro Izuha
DB2 UDB DM SW Technical Sales, IBM Japan

Murali Sankar, Ramasamy Senthilvel, Jaishankar Shanmugam
Cognizant Technology Solutions

Maritza M. Dubec - Technical Editing
Emma Jacobs
International Technical Support Organization, San Jose Center


Become a published author

Join us for a two- to six-week residency program! Help write an IBM Redbook dealing with specific products or solutions, while getting hands-on experience with leading-edge technologies. You'll team with IBM technical professionals, Business Partners and/or customers.

Your efforts will help increase product acceptance and customer satisfaction. As a bonus, you'll develop a network of contacts in IBM development labs, and increase your productivity and marketability.

Find out more about the residency program, browse the residency index, and apply online at:

  • ibm.com/redbooks/residencies.html


Comments welcome

Your comments are important to us!

We want our Redbooks™ to be as helpful as possible. Send us your comments about this or other Redbooks in one of the following ways:

  • Use the online Contact us review redbook form found at:

    • ibm.com/redbooks

  • Send your comments in an Internet note to:

    • <redbook@us.ibm.com>

  • Mail your comments to:

    • IBM Corporation, International Technical Support Organization
      Dept. QXXE Building 80-E2
      650 Harry Road
      San Jose, California 95120-6099


Chapter 1: Introduction

Overview

Since migrating from Oracle to DB2 UDB requires a certain level of knowledge in both environments, the purpose of this chapter is to introduce the architectural overview of both Oracle and DB2 UDB. This is meant to facilitate the understanding of both architectures, taking into consideration that the reader may be an Oracle or a DB2 DBA.

This chapter includes the following points:

  • DB2 family of products

  • Terminology

  • Architectural overview including:

    • Processes architecture

    • Memory architecture

    • Directory structure

    • Oracle data dictionary and DB2 catalog

    • Database connectivity

    • Replicating

    • Partitioned database architecture


1.1 DB2 family of products

In the era of Information on demand, IBM Information management software offers a wide range of products to accommodate different business needs and technical requirements in order to provide customers with a robust and scalable enterprise wide solution.

DB2 UDB offers database solutions that run on all platforms including Windows servers, AIX®, Sun, HP-UX, Linux, AS/400®, OS/390 and z/OS®. Furthermore, DB2 UDB technologies support both 32-bit and 64-bit environments. DB2 UDB product family comprises a variety of packages provide customers choices based on the business need. The following lists the DB2 UDB product offerings for Linux, UNIX, and Microsoft Windows:

  • DB2 UDB Enterprise Server Edition (ESE)

    DB2 UDB ESE is designed to meet the database server needs of midsize to large businesses. ESE's high scalability, availability, and reliability features provide customers an ideal database management system for all types of transactions:

    • The Database Partitioning Feature (DPF)

      The Database Partitioning Feature is a licensing option that allows ESE customers to partition a database within a single system or across a cluster of systems. The DPF capability provides the customer with multiple benefits including scalability to support very large databases, or complex workloads and increased parallelism for administration tasks.

  • DB2 Workgroup Server Edition (WSE)

    This Edition is designed for deployment at a departmental level or in a small business environment with a small number of users. It can be deployed on a server with up to 4 CPUs.

  • DB2 Workgroup Server Unlimited Edition (WSUE)

    This product offers a simplified per processor licensing for deployment at a departmental level or in a small business environment.

  • DB2 Personal Edition (PE)

    This flavor of DB2 provides a database management system for a single user database.

  • DB2 UDB Developer's Edition

    This product offers a package for single application developer to design and build an application.

  • DB2 UDB Personal Developer's Edition (PDE)

    Similar to the Developer's edition, this product enables the developer to build a single user desktop application.

  • DB2 Express

    This is the newest member of DB2 UDB product family. The key features include simplified deployment, autonomic management capabilities, and application development support and design for 7/24 operation. This flavor of DB2 UDB is aimed at Independent Software Vendors (ISV) who want to integrate DB2 UDB as part of their application with low cost, and have the capability to expand easily in the future.

Information Management software extends the functionality of DB2 UDB by offering different technologies called extenders, which serve as Web application tools. The extenders include: Text extender for performing text searches; Image extender for image manipulation operations; XML extender, which enables storing and retrieving data in the form of XML documents; Spatial extender to manipulate spatial data; and Audio and Video extenders, which handle both audio and video files respectively.

IBM also provides federated technologies to extend the functionality of DB2 UDB. With DB2 Information Integrator (DB2 II) you can access objects in many different databases such as Oracle and Sybase with a single query.

In addition, DB2 Connect™ Editions offer you the capability to extend your enterprise system to access the legacy system.

Appendix A, "DB2 UDB product overview" on page 335 provides a detailed description of the capabilities and features of DB2 UDB products.


1.2 Terminology

Before getting into conversion process, a clear understanding between the terminologies used in Oracle and DB2 UDB help the readers to understand and map each terminology between Oracle and DB2 UDB. This section discusses some of the terminologies, and a mapping between these terminologies is given.

1.2.1 Terminology mapping

Table 1-1 provides a quick reference of commonly used terminologies in Oracle and DB2 UDB. More information about the terminology mapping is provided in Appendix E, "Terminology mapping" on page 393.

Table 1-1: Mapping of Oracle terminology to DB2 UDB
Oracle | DB2 UDB
Instance | Instance
Database | Database
Initialization File | Database Manager Configuration File
Table spaces | Table spaces
Data blocks | Pages
Extents | Extents
Datafiles | DMS containers
Redo Log Files | Transaction Log Files
PL/SQL | SQL/PL
Data Buffers | Buffer Pool
SGA | Database Manager and Database shared memory
Data Dictionary | Catalog
Library Cache | Package Cache
Large Pool | Utility heap
Data Dictionary cache | Catalog cache
SYSTEM tablespace | SYSCATSPACE tablespace


1.3 Architecture overview

It is very useful to understand the differences between Oracle's architecture and that of DB2 UDB before attempting the Oracle to DB2 UDB migration process. Both products include their own memory architecture, back ground processes, database related files, and different configuration files. Both Oracle and DB2 UDB consist of an instance and the database(s) attached to that instance. This section provides a general description of the architectures of each vendor.

Figure 1-1 is an overview of the Oracle architecture. The upper level shows the memory architecture, the middle level is the process component, and the bottom level shows the database component.

Click To expand
Figure 1-1: Oracle architecture overview

Figure 1-2 shows the DB2 UDB architecture overview. DB2 UDB implements a dedicated process architecture. From a client-server view, the client code and the server code are separated into different address spaces. The application code runs in the client process, while the server code runs in separate processes. The client process can run on the same machine as the database server or a different one, accessing the database server through a programming interface. The memory units are allocated for database managers, database, and application.

Click To expand
Figure 1-2: DB2 architecture overview

The following section discusses both architectures, detailing memory components and background processes of both databases.

1.3.1 Memory architecture

This section discusses the memory architecture in Oracle and DB2 UDB. Oracle and DB2 UDB allocate and uses memory for instance and database operation. There are various memory structures used for different process. This section gives a broader overview about how memory is allocated and used in a simple Oracle and DB2 UDB server.

The memory architecture of an Oracle database consists of the memory area allocated to the Oracle instance and database upon startup. The amount of memory allocated is controlled by parameters defined in the Oracle configuration file.

The memory architecture of DB2 UDB is slightly different than Oracle's. Unlike Oracle, the DB2 UDB server can run multiple databases under one instance and hence has configuration files at both the instance level (Database Manager configuration file) and at the database level (database configuration file).

Oracle

Oracle uses memory to run the code and share data among the users. The two basic components of the Oracle memory structure are the Program Global Area (PGA) and the System Global Area (SGA). Figure 1-3 shows the primary memory architecture of an Oracle server.

Click To expand
Figure 1-3: Oracle memory architecture

The PGA is associated with the Server process and contains the data and control information. For the dedicated server configuraiton, the primary contents of the PGA are the sort area, session information, cursor state and stack space. This is a non sharable memory which writable only by the server process. The PGA are allocated whenever a server process starts and the total size of the PGA is controlled by the PGA_AGGREGATE_TARGET initialization parameter in version 9i.

The SGA is the shared memory region allocated for the entire Oracle Instance. The SGA is a group of shared memory structures in which the basic components comprises of the shared pool, data buffer cache and the Redo log buffer. The shared pool contains the library cache and data dictionary cache. The library cache holds the SQL statement text, the parsed SQL statement and the execution plan. The data dictionary cache contains reference information about tables, views, object definitions and object privileges. The shared pool size is controlled by SHARED_POOL_SIZE initialization parameter. The data buffer cache stores the most recently used Oracle data blocks. Oracle reads the data blocks from the datafiles and places it in data buffers before processing the data. The number of buffers allocated is controlled by DB_BLOCK_BUFFERS in version 8i and DB_CACHE_SIZE in version 9i. The redo log buffer is circular buffer that contains redo entries of the change information made to the database. These redo log buffers are written into the redo log files and is required for the database recovery. The size of the redo log buffers are controlled by the LOG_BUFFER initialization parameter. The other memory structures of the SGA include the large pool and the Java pool used for backup process and Java objects respectively. For a shared server configuration in version 9i (or multi threaded server in 8i) the session information and the sort areas are in SGA instead of PGA.

DB2 UDB

The three primary memory structures in DB2 UDB are the Instance Shared Memory (also known as Database Manager shared memory), the Database Shared memory and the Application Shared Memory. Figure 1-4 shows the basic memory architecture of a DB2 server.

Click To expand
Figure 1-4: DB2 UDB memory architecture

Instance Shared Memory is allocated when the database is started. All other memory is attached or allocated from the instance shared memory. The Instance Shared Memory is controlled by INSTANCE_MEMORY DBM configuration parameter. By default this parameter is set to automatic which enables the DB2 server to allocate the necessary memory for the instance.

Database Shared Memory also known as Database Global Memory is allocated when the database is first activated or connected for the first time. This memory is shared by all the applications that might connect to the database as well as the database EDU's (Engine Dispatchable Units) or database process that runs within each database. The memory allocated for database process includes:

  • Buffer pools - equivalent to Data Buffers in Oracle

  • Locklist

  • Database heap (This includes log buffer)

  • Utility heap - equivalent to Large Pool in Oracle

  • Package cache - equivalent to library cache in Oracle

  • Catalog cache - equivalent to data dictionary cache in Oracle

The buffer pools can be compared to the database buffers in Oracle, the package cache and catalog cache can be compared to library cache and data dictionary cache in Oracle respectively. Database Shared Memory is controlled by DATABASE_MEMORY database configuration parameter. By default this parameter is set to automatic which enables the DB2 UDB to calculate and allocate the memory for the database. Table 1-2 shows the DB2 database memory segments and the associated parameters.

Table 1-2: Database memory segments and parameters
Database memory | Parameter
Buffer pools | BUFFPAGE
Locklist | LOCKLIST
Database heap (includes log buffer) | DBHEAP
Utility heap size | UTIL_HEAP_SZ
Package cache | PCKCACHESZ
Catalog cache - equivalent to data | CATALOGCACHE_SZ

Application Shared Memory is allocated when an application connects to a database. This happens only in partitioned database environment or in a non-partitioned database environment where intra-partition is enabled or if the connection concentrator is enabled. This memory is used by the connecting agents to execute the work requested by the clients. The database manager configuration parameter MAX_CONNECTIONS limits the maximum number of applications that connects the database which in turn sets the upper limit for the maximum Application Shared Memory allocated.

Note

For more information on DB2 Memory Management refer to chapter 8 "Operational Performance: Memory Usage" in the DB2 Administration Guide: Performance, SC09-4821-00.

1.3.2 Process architecture

Any database instance is nothing but a collection of processes and memory structures. This section discusses about the processes in Oracle and DB2 UDB.

Oracle

There are two major types of Oracle process: the user processes and the background processes (see Figure 1-5).

Click To expand
Figure 1-5: Oracle process architecture
User process

Oracle creates a user process when the user or application connects to the database. For each user process, a server process is created by Oracle to handle the user process request to Oracle instance. This architecture works when the client is on the different machine. When the client and the server is on the same machine, the user process and server process are combined to a single process. The function of the server process is to parse the SQL statement, read the Oracle data blocks from the datafile to the data buffer, and return the result set to the client.

Oracle background processes

Oracle requires a number of processes to be running in the background in order to be operational and open to users. These processes are:

  • Database writer (DBWR): This background process writes all dirty data blocks from the database buffer cache to the datafiles on disk. The DBA can configure multiple DBWR processes in order to improve performance.

  • Log writer (LGWR): This is the process that handles writing data from the redo log buffer cache onto the redo log files.

  • System monitor (SMON): This process has two functions. First, it performs an instance recovery when the Oracle instance fails, and second it coalesces smaller fragments of disk space together.

  • Process Monitor (PMON): This process cleans up any remaining Oracle processes resulting from a failing user process. Furthermore, it rollbacks any uncommitted transactions that were performed by the user.

  • Ckeckpoint (CKPT): This process writes log sequence numbers to the database headers and control files.

DB2 UDB

For a DB2 instance to start and run, several process are created and interact with each other, which maintains the applications connected and the database created on the instance. There are several background processes in DB2 that are pre-started, and some start on a need-only basis. This section explains some of the important background processes.

DB2 UDB background processes

The DB2 server activities are performed by Engine Dispatchable Units (EDU) that are defined on a Windows environment as threads and as background processes on both UNIX and Linux systems.

Such as Oracle, there are many background processes dedicated to the operation of the DB2 instance. As mentioned in the previous paragraph, some DB2 background processes are started with the instance, and others are initialized when the database is activated by a connection. Figure 1-6 shows the necessary background processors of the DB2 UDB server at the instance, application, and database level. In the following sections, we discuss some of the important process in each level of DB2 UDB.

Click To expand
Figure 1-6: DB2 processor architecture
Instance level processes

The following background processes will start as soon as the DB2 UDB server is started with the db2start command.

  • DB2 daemon spawner (db2gds): This is a global daemon processor started for each instance. This process starts all the EDUs (process) in UNIX.

  • DB2 system controller (db2sysc): This is the system controller processor. This is the main process without this process the instance cannot function.

  • DB2 watchdog (db2wdog): This process is required only in UNIX platforms. This process is the parent process for all the processes.

  • DB2 format log (db2fmtlg): This pre-allocates log files in the log path when the LOGRETAIN database configuration parameter is set to ON, and the USEREXIT parameter is set to OFF. This is similar to the optional Archiver log process (ARCn) process in Oracle and is enabled when the database is set in ARCHIVELOG mode.

  • DB2 system logger (db2syslog): This is the system logger process responsible for the writing operating system error log.

Database level processes

The following background processes are started when an active connect to the database as established:

  • DB2 log reader (db2loggr): This process reads the log files during transaction rollback, restart recovery, and rollforward operations. It does part of the functions of Oracle PMON process.

  • DB2 log writer (db2logw): This is the log writer process that flushes the database log from the log buffer to the transaction log files on disk. This is equivalent to the LGWR process in Oracle.

  • DB2 page cleaner (db2pclnr): This process is presented to make room in the buffer pool before prefetchers read pages on disk storage and move into the buffer pool. Page cleaners are independent of the application agents that look for and write out pages from and to the buffer pool to ensure that there is room in the buffer pool. This is equivalent to DBWR process in Oracle.

  • DB2 prefetcher (db2pfchr): This process retrieves data from disk and moves it into the buffer pool before the application needs the data. This does part of the functions of the Oracle server process.

  • DB2 deadlock detector (db2dlock): This is the database deadlock detector process. This process scans the locklist (the lock information memory structure of DB2) and looks for deadlock connections.

Application level processes

These process are started for each application connecting to the database:

  • DB2 communication manager (db2ipccm): This is the inter-process communication (IPC) process started for each application connecting locally. This process communicates with the coordinating agent to perform database tasks. This can be thought of as an Oracle user process connecting locally.

  • DB2 TCP manager(db2tcpcm): This is the TCP communication manager process. This process is started when the remote client or applications connects to the database using TCP/IP communication. This process communicates with the coordinating agent to perform database tasks. This is equivalent to a user process in Oracle.

  • DB2 coordinating agent (db2agent): This process handles requests from applications or connections. This performs all database requests on behalf of the application. There will be one db2agent per application unless the connection concentrator is established. If intra-partition parallelism is enabled, the db2agent will call DB2 subagents to perform the work.

  • DB2 subagent (db2agnta): This is an idle subagent, which works with the db2agent process when intra-partition parallelism is enabled.

  • Active subagent (db2agntp): This is the active subagent that is currently performing work. This process is used when enabling SMP parallelism, which means having more processes achieving the same task. In order to enable this feature in DB2, we must set the intra-parallelism database parameter to true.

The db2agent process, with or without the combination sub agents, performs the similar function of the Oracle server process.

1.3.3 Files and directory structure

This section discusses about important files and the common directory structure used in Oracle and DB2 UDB. A instance and database requires a number of files like datafiles, configuration files, log files etc. to operate and store data. This section looks at some of these important files and gives an overview of its uses. The directory structure gives an idea of how a product is installed and how some files are placed on this structure.

Oracle

Every Oracle instance needs a set of files to comprise itself and operate. These files include the datafiles, redo log files, control file, parameter file, the alert log file, and the password file as shown in the Figure 1-7. The physical files to mount a tablespace in Oracle are called datafiles. The datafiles stores the data, index and rollback segments of the Oracle database. Oracle maintains the database transactions in a transactional log files called redo log files. There should be at least one set of redo log files created for a database to operate. Every Oracle database has a control file. The control file contains the entries that describes the physical structure of the database. Every time a instance is started, the control file is used to identify the datafiles and redo log files to start the database.

Click To expand
Figure 1-7: Oracle database files

The initialization file or the parameter file is used by the Oracle instance during startup. The file contains the values for many initialization parameters used to allocate memory and start the process for the instance to run. The password file is a security file used for authenticating which users are permitted to start up or shut down an instance or perform other privileged maintenance on a database with SYSDBA or SYSOPER (8i) privileges and additionally OSDBA or OSOPER (9i) privileges. The alert log file is the diagnostics file used by the Oracle instance to record all the dump information of the database like internal errors, block corruption errors, etc.

Oracle installation follows Optimal Flexible Architecture (OFA) standards in creating the directories and placing the files. The OFA is a set of file naming and placement standards. Oracle recommends following OFA standards. Using OFA, the Oracle installation process places the Oracle software in $ORACLE_BASE\ORACLE_HOME and datafiles in $ORACLE_BASE\oradata directory. Figure 1-8 shows a sample installation directory structure on the 8i version of Oracle. The initialization file and the password file reside under dbs path in the UNIX server and database directory in Windows server. The bin directory contains all the executable binary files.

Click To expand
Figure 1-8: Oracle directory structure using OFA

The $ORACLE_HOME\rdbms\admin directory contains the DDL scripts to create the data dictionary tables and views, the administration procedures, and package scripts. These scripts are run when creating the database manually. The $ORACLE_HOME\network\admin directory contains the listener.ora and tnsnames.ora files for communication process. Section 1.3.5, "Communication" on page 21 explains more about these files.

DB2 UDB

The primary files and directories for a DB2 instance and database include the DMS containers, SMS containers (directory or path), DBM cfg file, DB cfg file, the Transaction log files, and the db2diag.log file. This structure is shown in Figure 1-9. The DBM cfg file is created per DB2 instance and contains the configuration parameters and values. This file resides under the sqllib directory of the instance home named as db2systm. This can be related to the initialization parameter file in Oracle but unlike Oracle this is not a text file rather a binary file and can be updated only using UPDATE DBM CFG command.

Click To expand
Figure 1-9: DB2 Instance and database files

The DB cfg file the configuration file for each database which stores the database configuration values. This file is stored with the name SQLDBCON under the database directory SQLnnnnn where nnnnn is the database number assigned. This file is also a binary file and can be updated only using the UPDATE DB CFG command. Each database contains the table space containers, which can be either DMS containers as a physical file or partition, or SMS containers, which is either a directory in Windows and file system path in the UNIX environment. Under SMS, a number of different files are created to store the data and the index. The transactional log files records the database transactions, which is required for database recovery. The NEWLOGPATH database configuration parameter identifies the log path if the log files are stored in other than the default log path. The db2diag.log file is like the Oracle Alert log file that records the DB2 error dump information. The DIAGPATH DBM configuration parameter identifies the location of db2diag.log.

Figure 1-10 shows the default directory structure for a simple CREATE DATABASE command with no tablespace options specified. By default the tablespace created will be SMS containers, and the log files will be created in the SQLLOGDIR directory, which can be changed by updating the NEWLOGPATH DB cfg parameter.

Click To expand
Figure 1-10: DB2 directory structure for a simple create database command

DB2 Installation path depends on the operating system in which it is installed. On Windows operating system the default installation goes under ProgramFiles\IBM\SQLLIB directory. This path can also be changed during the installation. On AIX system the default installation path is /usr/opt/db2_version, on Solaris, Linux and HP-UX system the default installation path is /opt/IBM/db2/db2_version. On UNIX systems a sqllib directory will created under the instance home directory and has symbolic links to actual files under the installation directory. Figure 1-11 shows the installation directory structure for Windows environment and sqllib directory structure for UNIX environment.

Click To expand
Figure 1-11: DB2 UDB directory structure

The adm directory consists of instance administration commands, license management commands and other commands. The backup directory consists of DBM configuration file backup and node configuration backup. The bin directory consists of all DB2 command binaries. The bnd directory contains various database bind files. The db2dump directory holds db2diag.log file and other trace files. All the external stored procedures and routines executable programs are stored under function directory. The Java directory contains the JDBC driver files. The samples directory contains all the program samples that comes shipped with DB2 software.

Configuration files

Since the Oracle instance can only support one database, its background processes are enabled as soon as the instance is started. Therefore, Oracle has one configuration file which is used to configure and tune the database.

The DB2 instance however can support multiple databases, and therefore, consists of an instance level shared memory and a database shared memory running on the server side. Starting the DB2 instance will only start the instance level processes. Database level processes such as those that control transactional processing tasks, logging, and writing to containers on disk are only enabled when the database itself is activated by a user or an application connection.

Therefore, there are two files controlling the configuration and tuning of the DB2 server and database. The first file is used to configure and tune the DB2 server at the instance level is called the Database Manager Configuration (DBM CFG) file. The second is a database level configuration file (DB CFG) used to control database level parameters.

1.3.4 Data Dictionary and Catalog

Every RDBMS has a form of metadata that describes the database and its objects. Essentially, the metadata contains information about the logical and physical structure of the database, integrity constraints, users and schema information, authorization, and privilege information, etc.

In the Oracle database, this metadata is stored in a set of read-only tables and views called the Data Dictionary. These tables and views are updated by the Oracle server. The Data Dictionary is owned by the user SYS and stored in the SYSTEM table space. The base tables are all normalized and are seldom accessed directly, hence, user accessible views are created using the catalog.sql script. The Data Dictionary is organized under three qualifiers: the USER_xxx views, the ALL_xxx views, and the DBA_xxx views. The USER_xxx views show the object information owned by the current user; the ALL_xxx views show all the object information that can be accessed by the current user; and the DBA_xxx view is the database administrator view and contains information on all the objects in the database. Apart from these Data Dictionary, Oracle maintains another set of virtual tables called the dynamic performance views, and the views created on them are prefixed by V$. These views are called the fixed views, and are available when the instance is started without the need of the database to be opened.

In DB2 UDB, the metadata is stored in a set of base tables and views called the Catalog. The Catalog contains information about the logical and physical structure of the database objects, object privileges, Integrity information, etc.

The DB2 database catalog is automatically created when the database is created. The base tables are owned by the SYSIBM schema and stored in the SYSCATSPACE tablespace. On top of the base tables, the SYSCAT and SYSSTAT views are created. SYSCAT views are the read-only views that contain the object information, and SYSSTAT is the updateable view, which contains the statistical information. View the catalog information through the SYSCAT view, but base tables are recommended.

Unlike in Oracle, DB2 does not maintain any dynamic performance views, but uses the commands to get the information from the system directory like: LIST DATABASE DIRECTORY, LIST TABLESPACES, LIST APPLICATIONS etc. Table 1-3 shows some of the commonly used views available in Oracle Data Dictionary and DB2 Catalog.

Table 1-3: Data Dictionary and Catalog
Oracle Data Dictionary | DB2 Catalog
DBA_TABLES | SYSCAT.TABLES
DBA_TAB_COLUMNS | SYSCAT.COLUMNS
DBA_TABLESPACES | SYSCAT.TABLESPACES
DBA_INDEXES | SYSCAT.INDEXES
DBA_TAB_PRIVS | SYSCAT.TABAUTH
DBA_TRIGGERS | SYSCAT.TRIGGERS
DBA_VIEWS | SYSCAT.VIEWS
DBA_SEQUENCES | SYSCAT.SEQUENCES
DBA_PROCEDURES | SYSCAT.ROUTINES

The complete DB2 UDB catalog views can be found in DB2 UDB SQL Reference Volume 1 and 2, SC09-4484 and SC09-4485.

1.3.5 Communication

This sections gives an overview of the communication architecture that enables a simple client-server communication in Oracle and DB2 UDB environment and some of the tools used to communicate from the client.

Database accessing

Both DB2 and Oracle support dynamic and embedded static SQL interfaces. Oracle provides the SQL*Plus tool for command line access to the database server. SQL*Plus also comes with a GUI version. DB2 provides Command Line Processor (CLP) for a command line access to the database server. The GUI version for this tool is called as Command Center. The Oracle client installation installs the SQL*Plus tool, Oracle Net Services software, ODBC drivers and other tools. These software provides a basic client server communication to access the database server. DB2 client installation provides the DB2 runtime client, Command Line Processor, Configuration Assistant, Command Center, ODBC drivers etc. for a basic client server communication.

Oracle communication

The client server communication in Oracle Server is handled by Oracle Net Services. Oracle Net Services support communications on all major protocols. The Oracle Net Services provides a communication interface between the client user process and the Oracle server process, enabling the data transmission and messages exchange between Oracle server and client. The Oracle Net Services use the technology called Transparent Network Substrate (TNS) to perform these tasks. The TNS enables the peer-to-peer application connectivity where the two nodes communicate each other directly.

The Oracle Net Services provides the listener process that resides in the Oracle server, which listens for incoming client connection requests, and maps it to the Oracle instance. The listener is configured with one or more protocol addresses; the client configured with one of these protocol address can send connection requests to listener. A configuration file listener.ora is maintained in the Oracle server that contains the protocol address, database service information, and listener configuration parameters. The listener process is controlled by the LSNRCTL utility; the LSNRCTL utility reads the listener.ora file and starts the listener process. The server services information in client is maintained in a file called tnsnames.ora. Oracle Net8 Assistant is a graphical utility used to configure the Oracle Net Services like listener, service naming, etc.

DB2 UDB communication

DB2 supports several communication protocol for client server communication like TCP/IP, APPC, NPIPE, NetBIOS etc. Most protocols are automatically detected and configured during an instance creation. The DB2COMM registry variable identifies the protocol detected in a server. To enable a specific protocol, use the db2set DB2COMM command. For TCP/IP, a unique port address has to be specified in the database manager configuration. This port is registered in the services file. For example, to reserve a port 50000 with the service name db2cidb2, the entry in services file is:

   db2icdb2 50000/tcp

Update this information in the database manager using the command:

   db2 UPDATE DBM CFG USING SVCENAME db2icdb2

These tasks can also be performed using the DB2 Configuration Assistant utility. At the client, the database information is configured using either the CATALOG command or using the Configuration Assistant. The database are configured under a node which describes the host information like protocol and port etc. To configure a remote TCP/IP node the command used is:

   db2 CATALOG TCPIP NODE node-name REMOTE host-name SERVER service-name

The service name registered in the server or the port number can be specified in the SERVER option. To catalog a database under this node the command used is:

   db2 CATALOG DATABASE database-name AS alias-name AT NODE node-name

The Configuration Assistant is the GUI tool used in client to configure a database. Figure 1-12 shows how the Configuration Assistant is used to add a database connection. The option "Search the network" is used to add a database using DB2 Discovery Method. Using this option the DB2 servers installed in the entire network can be searched and used to add database connection. This is possible when the DB2 administration server process is created in the server and enabled for discovery.

Click To expand
Figure 1-12: Configuring the database connection using Configuration Assistant
Note

DB2 Discovery method is enabled at the instance level using the DISCOVER_INST parameter, and at database level using DISCOVER_DB parameter.

1.3.6 Data replication

Both Oracle and DB2 UDB provide replication capabilities in their databases. The main purpose of enabling replication is to have the same set of date records in more than one location. Having two copies of the same database can be a part of a high availability solution. This section discusses the replication approach by both Oracle and DB2 UDB.

Oracle replication

Oracle has the ability to replicate data from one Oracle database to another. Changes to an Oracle database are replicated to another Oracle database through the capture and apply processes. Oracle replication uses triggers in order to capture transactional changes and stores them in a local queue. Oracle then uses packages in order to apply the replicated changes to the target database. Oracle Enterprise Manager (OEM) may be used to perform replication tasks.

DB2 UDB replication

IBM Data management software provides products that enable customers to replicate data from both relational and non-relational sources. Data Propagator (DPROP) is widely used by DB2 customers to replicate data from one DB2 database to another. Furthermore, DB2 Information Integrator or DB2 II is known in DB2 UDB V7.x as the data joiner, which has the ability to propagate data among many relational databases such as Sybase and MS-SQL Server.

DB2 UDB replication can be used to replicate data between DB2 databases in a distributed environment such as Microsoft Windows, UNIX, and Linux. It also can be used to propagate data from and to a main frame OS/390 or an AS/400 environment. All replication operations can be done through the capture and apply processes.

The replication process in DB2 UDB consists of identifying and setting up three databases:

  • Source database: A database containing source tables that need to be replicated.

  • Target database: A database server where the target tables will reside and the apply process will take place.

  • Control database: A database that contains the control tables storing the necessary information for the apply program and which can reside on either the source or target database.

DB2 UDB replication is an asynchronous process. The frequency of replication can be set to minimize any delay. There are two administration interfaces through which we can set up replication. The first is the DB2 Replication Center, which are GUI tools provided by DB2 UDB to define, manage, and monitor replication. The second is the asnclp tool, which provides command line definition of replication objects.


1.4 Parallel database architecture

Both Oracle and IBM offer parallel architecture or clustering environments for their databases in order to provide customers with the ability to support very large databases (VLDB). This is achieved by partitioning the database over multiple nodes or servers. Oracle offers Real Application Cluster (RAC) formerly known as Oracle Parallel Server, and IBM offers DB2 UDB ESE with the Database Partitioning Feature (DPF), formerly known as DB2 UDB Extended Enterprise Edition (EEE).

There are three major architectures used to implement a partitioned environment Shared memory, Shared disk and Shared nothing. This book briefly discusses both Shared disk (Figure 1-13) and Shared nothing (Figure 1-14) architecture. Table 1-4 shows the differences of both technologies.

Click To expand
Figure 1-13: Shared disk architecture
Click To expand
Figure 1-14: Shared nothing architecture
Table 1-4: Shared disk architecture vs. shared nothing architecture
Shared disk Architecture | Shared nothing architecture
Requires special hardware | Does not require special hardware
Non linear scalability | Provides near linear scalability
Balanced CPU or node fail-over | Balanced/Unbalanced CPU or node fail-over
Requires CPU level communication at disk access | Minimal communication
Non disruptive maintenance | Non disruptive maintenance

1.4.1 Real Application Clusters

Real Application Clusters (RAC) is Oracle 9i's clustering technology, which provides an environment capable of supporting large databases. RAC is based on a shared disk architecture aimed at achieving high availability of a distributed environment.

RAC is an extension to the Oracle database, which enables building a multi node database environment. RAC requires an Oracle database, and the clustering technology provided by the platform vendor in order to achieve successful installation and implementation.

RAC consists of three major components: nodes containing CPUs, cluster interconnect, and storage units. The nodes are processing nodes. Typically, every node is a symmetric multi processing node (SMP). As shown in Figure 1-13, in a shared disk environment every processing node has access to every storage unit. However, every node in the cluster has its own memory, operating system, and database instance. The nodes do not share memory among each other.

1.4.2 DB2 UDB ESE with the Database Partitioning Feature

IBM Data management software extends DB2 UDB to the parallel multi node environment in order to provide a scalable solution capable of supporting large amounts of data.

The partitioning feature in DB2 UDB is based on a shared nothing architecture. As shown in Figure 1-14, every node in the cluster has its own dedicated memory, operating system, and storage units. An application of a shared nothing architecture is aimed at achieving high scalability and improving performance. This option in DB2 UDB ESE DPF does not require any clustering technologies to run. However, a high availability solution can be implemented in conjunction with the clustering technology provided by the platform vendor.

DB2 UDB ESE DPF uses two levels of parallelism in order to achieve good performance:

  • Intra-partition parallelism, which is the ability to have multiple processors process different parts of an SQL query, index creation, or a database load within a database partition. This level of parallelism can be specified in the DBM configuration file by setting the INTRA_PARALLEL parameter to ON.

  • Inter-partition parallelism, which provides the ability to break up a query into multiple parts across multiple partitions of a partitioned database, on one server or multiple database servers. This can be accomplished on both SMP servers and MPP clustered servers.


Chapter 2: Oracle Migration Project Planning

Overview

Migrating from the Oracle RDBMS to DB2 UDB requires proper planning, whether you perform the migration on your own or use IBM resources. Many migration tools are available, most notably the IBM DB2 Migration ToolKit (MTK). Furthermore, resources are available to assist with estimating the actual cost of the migration, and the estimation of required resources. Unexpected delays in project execution can be avoided by following well planned migration procedures.

This chapter introduces the common process of migration and porting. The planning process, as well as the available tools and resources are documented in this chapter. Detailed migration steps can be found in Chapters 4 through Chapter 7. The migration tasks discussed in this chapter include:

  • Project planning

  • Migration preparation

  • Database structure porting

  • Performance tuning

  • IBM migration service offering


2.1 Migration planning

Migration planning tasks include the activities before actually setting up the system and porting the database, database objects, and data. The planning stage is also a good time to consider items mentioned in 2.5, "After the port" on page 44. Section 2.5, "After the port" on page 44 introduces other DB2 offerings that can help meet the architectural needs of your project. For the purposes of migration planning, the major processes are:

  • Migration assessment

  • Understanding and choosing migration tools

  • Estimating

  • Planning the project

2.1.1 Migration assessment

Planning a migration begins with an assessment of the size of the project and an understanding of the resources that can be utilized.

Architecture profiling

An accurate profile of the system wide architecture is key to the success of the migration. The following questions provide a sampling of the considerations that require attention:

  • What best characterizes the workload type? (OLTP, OLAP/DSS)

  • What language is the application written in? (Java, C, C++, VB, C#)

  • What is the client target operating system and the version/release/FixPak number? (Windows NT SP2®, Browser Based, etc.)

  • What is the server target hardware platform? (IBM_Series, Compaq, HP, Sun, etc.)

  • What is the server target operating system and version/release/FixPak number? (Windows NT SP2, AIX 4.3, REDHAT LINUX 8.0, etc.)

  • What is the typical configuration of your database server? (Number of boxes, number of CPUs, RAM, and disks, etc.)

2.1.2 Understanding and choosing migration tools

Although a migration can be performed without the help of tools, IBM has created a tool that is specifically designed to make migration as simple as possible. The tool is introduced here and covered in detail in later chapters. There may also be special circumstances, which warrant the use of a third party tool in conjunction with the IBM DB2 Migration Toolkit.

IBM DB2 Migration Toolkit

The IBM DB2 Migration Toolkit (MTK) helps you migrate from Oracle, Microsoft SQL Server, and Sybase databases to DB2 UDB databases on any supported DB2 UDB workstation platform. This tool can be used to generate DDL scripts to create database objects like tables, indexes, views, triggers, stored procedures, and user defined functions. It also aids in moving data from the original system to DB2 UDB. For instance, the IBM DB2 Migration Toolkit can either connect directly to the source system and perform its own extraction of the DDL, or it can use a syntax valid SQL-PL/SQL script extracted by other tools. The MTK supports Oracle, Sybase, and Microsoft SQL Server, DBMSs, and MySQL conversion to DB2 UDB.

Other porting tools

There are a number of migration tools available to assist you in moving your database, application, and data from its existing DBMS to DB2 UDB. These tools and services are not provided by IBM, nor does IBM make guarantees as the performance of these tools:

  • ArtinSoft

    Oracle Forms to J2EE. The Oracle Forms to J2EE migrating service produces a Java application with an n-tier architecture, thus allowing you to leverage the knowledge capital invested in your original application, preserving functionality and the "look and feel" evolving into a cost-effective, rapid, and secure fashion to a modern platform.

  • Kumaran

    Kumaran offers DB2 UDB migration services for IBM Informix® (including 4GL), Accell/Unify, MS Access, Oracle (including Forms and Reports), Ingres, and Microsoft SQL Server.

  • Techne Knowledge Systems, Inc

    Techne Knowledge Systems' JavaConvert/PB product is a software conversion solution that transforms PowerBuilder applications into Java-based ones.

  • Ispirer Systems

    Ispirer Systems offers SQLWays, a database and data migration tool

  • Ascential DataStage

    The DataStage product family is an extraction, transformation, and loading (ETL) solution with end-to-end metadata management and data quality assurance functions.

  • DataJunction

    DataJunction data migration tool provides assistance in moving data from Source Database to DB2 UDB. This tool accounts for data type differences, and can set various filters to dynamically modify target columns during the conversion process.

Modeling tools

There are a number of modeling tools that can help you capture the entity-relation (E-R) descriptions of your database. By capturing this information, you can then instruct the tool to transform the information into DDL that is compatible with DB2 UDB. A few modeling tools are:

  • Rational® Rose® Professional Data Modeler Edition

    A database design tool that allows database designers, business analysts, and developers to work together through a common language.

  • CA AllFusion ERwin Data Modeler

    A data modeling solution that helps create and maintain databases, data warehouses, and enterprise data models.

  • Embarcadero Technologies ER/Studio

    ER/Studio can reverse-engineer the complete schema for many database platforms by extracting object definitions and constructing a graphical data model. Other tools are available for application development (Rapid SQL and DBArtisan).

  • Borland Together

    Borland's enterprise development platform provides a suite of tools that enables development teams to build systems quickly and efficiently. Borland Together Control Center is an application development environment that encompasses application design, development, and deployment. Borland Together Edition for WebSphere® Studio offers IBM-centric development teams a complete models-to-code solution. Borland Together Solo provides an enterprise class software development environment for small development teams.

2.1.3 Estimating

An accurate estimation of the scope of project, resource needed and total migration cost requires knowledge of the products, applications, and migration experience.

The IBM MTK can be used as an assessment tool to determine the complexity of the migration. Using the MTK in this manner will simply reveal stored procedures or SQL that may require manual intervention. A working knowledge of the MTK is mandatory when using the MTK in this manner. Estimating the number of "man-hours" required depends on the skill level of those performing the work.

The cost of new RDBMS software and migration tools should be considered when estimating the project cost. The IBM DB2 Migration Toolkit is provided free of cost. DB2 UDB is priced significantly less the Oracle RDBMS. Contact your IBM Sales Representative for more details.

Training costs, such as DBA and end user education, should also be figured into your project plan. The recommended course for experienced DBAs is Fast Path to DB2 UDB for experienced relational DBAs, course code CF281. Go to the IBM Learning Services for more details:

  • http://www-3.ibm.com/services/learning/

Finally, hardware procurement must also be planned if your existing data server does not have the capacity to run the existing Oracle instance, the IBM MTK, and DB2 UDB.

The IBM Software Migration Project Office (SMPO) can provide porting estimates. Contact the SMPO at: http://www-3.ibm.com/software/solutions/softwaremigration/

2.1.4 Planning the project

Each project is different, but there are some factors that are a good indicator of the overall effort. For instance, for applications that frequently use stored procedures, the number and complexity of the stored procedures to be converted will greatly affect the length of the application port. The same applies to the use of special data types and large objects. Another area might be the use of times and dates (each DBMS uses at least a slightly different internal format and display technique). Physical requirements (use of raw and cooked disk areas, spaces, nodes, etc.) can also represent a large amount of work, especially if the data will grow significantly over time.

A porting plan can be as simple as a spreadsheet that lists the main tasks of the port and some of the associated information for each task (start date, end date, elapsed time, dependencies, who is assigned, etc.). There are also project planning tools (such as Microsoft Project, Primavera TeamPlay, and Primavera Enterprise) that are specifically designed to not only plan, but also track the project. These tools let you assign tasks to specific people (or roles), establish dependencies among the various steps of the port (for instance, you cannot start testing until you move the database structure and the test data), and chart the original plan against what actually happens.


2.2 Porting preparation overview

This section briefly discusses the different steps needed to prepare the environment to receive the data. These steps include installation of DB2 UDB, instance and database creation, and table space planning. We also include special consideration for the partitioning environment. Chapter 4., "Porting with MTK" on page 63 discusses these steps in more detail as we prepare the migration environment. Before attempting DB2 UDB installation, we strongly recommend you to read the installation instructions provided in the Quick Beginnings for DB2 Servers, GC09-4836. The DB2 UDB manuals can be found in the Web site: http://www-3.ibm.com/cgi-bin/db2www/data/db2/udb/winos2unix/support/v8pubs.d2w/en_main

The latest FixPaks and client code can be found on the DB2 support site at: http://www-3.ibm.com/software/data/db2/udb/winos2unix/support/

The tasks needed in preparing the DB2 UDB environment are:

  • DB2 UDB V8 ESE installation

    First task is to decide which Edition of DB2 UDB fits your business requirement. The application assessment step provides you the base criteria to select the DB2 UDB Edition. Regardless of the platform, you need to verify whether or not the system satisfies hardware and software requirements. For the DB2 UDB installation process, we use both AIX and Windows as the main platforms for installation in this redbook. Installing DB2 UDB ESE on a platform such as SUN Solaris and HPUX requires modifying the operating system kernel parameters. System reboot is required afterwards.

  • Additional software requirements

    There are software considerations to take into account when running a database environment. These considerations will revolve around the type of applications accessing the database. If database development is desired, then the proper versions of the different software components must also be installed on the server, such as C or Java compilers.

  • Instance and database creation

    The next task to perform is to proceed with creating a DB2 instance and database. You need to consider details such as Instance and database location, user IDs required, permission requirements, etc. Chapter 4., "Porting with MTK" on page 63 discusses the ways to create DB2 instances and databases.

  • Table space planning

    Once the database has been created, it becomes ready for object creation. This is the space planning for data. DB2 UDB allows for two types of table spaces, System Managed Space (SMS), which is maintained by the system, and Data Managed Space (DMS), which is maintained by the DB2 administrator. If you are satisfied with the way the data is organized in the source database, you can look for the compatible way to organization the data in the DB2 UDB database. This is also the chance for you to change the way the data is placed so the maintenance is easier and the performance is better. The DB2 UDB manuals Administrant Guide: Planing, Administration Guide, SC09-4822, and Performance and Administration Guide: Implementation, SC09-4821 provide detailed information.


2.3 Porting

The steps required to perform a database and application port are introduced in this section. The methods employed can vary, but at a minimum, the following steps are required. This chapter introduces:

  • Porting the database structure

  • Porting the database objects

  • Modifying the application

  • Modifying the database interface

  • Migrating the data

2.3.1 Porting the database structure

After you assess and plan the port, the first step to take is to either move or duplicate the structure of the source database onto a DB2 UDB system. Before this can happen, differences between the source and destination (DB2 UDB) structures must be addressed. These differences can result from different interpretation of SQL standards, or the addition or omission of particular functions. The differences can often be fixed syntactically, but in some cases, you must add functions or modify the application.

Metadata is the logical Entity-Relationship (E-R) model of the data, and describes the meaning of each entity, the relations that exist, and the attributes. From this model, the SQL data definition language (DDL) statements that can be used to create a database that can be captured. If the database structure is already in the form of metadata (that is, a modeling tool was used in the design of the system), it is often possible to have the modeling tool generate a new set of DDL that is specific to DB2 UDB. Otherwise, the DDL from the current system must be captured and then modified into a form that is compatible with DB2 UDB. After the DDL is modified, it can be loaded and executed to create a new database (tables, indexes, constraints, and so on.).

There are three approaches that can be used to move the structure of a DBMS:

  • Manual methods: Dump the structure, import it to DB2 UDB, and manually adjust for problems

  • Metadata transport: Extract the metadata (often called the "schema") and import it to DB2 UDB

  • Porting and migration tools: Use a tool to extract the structure, adjust it, and then implement it in DB2 UDB

Manual methods

Some DBMSs offer a utility that extract the database structure and deposit it into a text file. The structure is represented in DDL, and can be used to recreate the structure on another database server. However, before the DDL will properly execute in DB2 UDB, it is likely that changes are needed to bring the syntax from the source system into line with DB2 UDB. So, after you extract the DDL, and transport it to DB2 UDB, you will likely have to edit the statements.

Besides syntactic differences, there may also be changes needed in data type names and in the structure. It is often easiest to simply run a small portion of the source DDL through DB2 UDB, and examine the errors. From this, most of the corrections that will be needed will become evident. Chapter 5, "Conversion reference" on page 149 provides detailed discussion of the manual conversion process and examples. Please also see the appropriate DB2 UDB porting guide for more detail on the differences in syntax, names, and structure that you can expect at:

http://www-3.ibm.com/software/data/db2/migration/

Metadata transport

Many database structures are designed and put in place using modeling tools. These tools let the designer specify the database structure in the form of entities and relationships. The modeling tool then generates database definitions from the E-R description. If the system to be ported was designed (and maintained) using one of these tools, porting the database structure to DB2 UDB can be as simple as running the design program, and specifying an output of the form compatible with DB2 UDB.

Porting and migration tools

Probably the most popular means of porting a database structure (and other portions of a DBMS) today is the use of a porting and migration tool that cannot only connect to and take structural information from the source database, but can also modify and then deposit it in the destination database. As mentioned above, the IBM DB2 Migration Toolkit can be used to perform the migration using this method.

2.3.2 Porting the database objects

Database objects (stored procedures, triggers, and user-defined functions) are really part of the application logic that is contained within the database. Unfortunately, most of these objects are written in a language that is very specific to the source DBMS, or are written in a higher-level language that then must be compiled and somehow associated or bound to the target DBMS for use.

Capturing the database objects can often occur at the same time that the database structure is captured if the objects are written in an SQL-like procedural language and stored within the database (for this, you would use one of the porting and migration tools). For those objects written in higher-level languages (Java, C, PERL, etc.), capture and import means transferring the source files to the DB2 UDB system and finding a compatible compiler and binding mechanism.

Stored procedures and triggers will have to be converted manually unless the tool used to extract the objects understands the stored procedure languages of both the source DBMS and DB2 UDB. The IBM DB2 Migration Toolkit is an example of a tool that can aid in the conversions of stored procedures and triggers from various DBMSs to DB2 UDB. Expect many inconsistencies between the dialects of procedural languages, including how data is returned, how cursors are handled, and how looping logic is used (or not used).

Objects that are written in higher-level languages must usually be dealt with manually. If embedded SQL is included in the objects, it can be extracted and run through a tool that might be able to help convert the SQL code to be compatible with DB2 UDB. After that, each section can be replaced and then compiled with the modified higher-level code.

Note that conversion of objects will require testing of the resulting objects. This may mean that test data will be needed (and must be populated into the database structure) before testing can occur. This would require that you do at least some of the work in Porting step 7. Migrating the data before you complete this conversion phase.

After the conversion is completed, some adjustments will probably still be required. Issues such as identifier length may still need to be addressed. This can be done manually (looking at statistics, i.e. all database names over a certain length, and then doing a global search and replace on the names that appeared), or by using a tool (such as the IBM DB2 Migration Toolkit) that understands what to look for and how to fix it.

2.3.3 Modifying the application

While the porting of the database structure and objects can be automated to some extent using porting and migration tools, application code changes will mostly require manual conversion. If all database interaction is restricted to a database access layer, then the scope and complexity of necessary changes is well defined and manageable. However, when database access is not isolated to a database access layer (that is, it is distributed throughout application code files, contained in stored procedures and/or triggers, or used in batch programs that interact with the database), then the effort required to convert and test the application code depends on how distributed the database access is and on the number of statements in each application source file that require conversion.

When porting an application, it is important to first migrate the database structure (DDL) and database objects (stored procedures, triggers, user-defined functions, and so on). It is then useful to populate the database with a test set of data so that the application code can be ported and tested incrementally.

Few tools are available to port actual application code since much of the work is dependent upon vendor-specific issues. These issues include adjustments to logic to compensate for differing approaches to transaction handling, join syntax, use of special system tables, and use of internal registers and values. Manual effort is normally required to make and test these adjustments. Often, proprietary functions used in the source DBMS will have to be emulated under DB2 UDB, usually by creating a DB2 UDB user defined function and/or stored procedure with the same name as the proprietary one being ported. This way, any SQL statements in the application code that call the proprietary function in question will not need to be altered. Migration tools such as the IBM DB2 Migration Toolkit are equipped with some of the most commonly used vendor-specific functions and will automatically create a DB2 UDB-equivalent function (or stored procedure) during the migration process.

The vendor-specific DB2 UDB outline the necessary code changes that are needed to work successfully with DB2 UDB. Send an e-mail to <db2mig@us.ibm.com> to obtain the latest version of the porting guide. Contacts for EMEA and AP are <emeadbct@uk.ibm.com> and <APDB2@nz1.ibm.com> respectively. Applications written in a high level language with embedded SQL (DML) can be converted automatically by extracting the SQL portion from the source, adjusting it with porting and migration tools, and then reinserting it into the source.

Another issue when porting high-level language code (C, C++, Java, COBOL, etc.) involves compiler differences. Modifications to the application code may be required if a different compiler and/or object library are used in the DB2 UDB environment (which may be caused by the selection of a different hardware or OS platform). It is vital to fully debug and test such idiosyncrasies before moving a system into production.

For more information on various application development topics relating to DB2 UDB, and to view various code samples, visit the DB2 Universal Database™ v8 Developer Domain Web page on the IBM Web site:

http://www7b.software.ibm.com/dmdd/

2.3.4 Modifying the database interface

Applications that connect to the source database using a standardized interface driver, such as ODBC and JDBC, usually require few changes to work with DB2 UDB. In most cases, simply providing the DB2 UDB supported driver for these interfaces is enough for the application to be up and running with a DB2 UDB database.

There are certain circumstances where the DB2 UDB-supported driver for an interface does not implement or support one or more features specified in the interface standard. It is in these cases where you must take action to ensure that application functionality is preserved after the port. This usually involves changing application code to remove references to the unsupported functions and either replacing them with supported ones, or simulating them by other means.

Applications that use specialized or native database interfaces (Oracle's OCI as an example) will require application code changes. Such applications can be ported using the DB2 UDB's native CLI interface, or by using a standardized interface such as ODBC, JDBC, etc. If porting to CLI, many native database-specific function calls will need to be changed to the CLI equivalents; this is not usually an issue as most database vendors implement a similar set of functions. DB2 UDB's CLI is part of the SQL standard and mappings of functions between other source DBMSs and DB2 UDB CLI can be found in the applicable DB2 UDB porting guide.

DB2 UDB also provides a library of administrative functions for applications to use. These functions are used to develop administrative applications that can administer DB2 UDB instances, backup and restore databases, import and export data, and perform operational and monitoring functions. These administrative functions can also be run from the DB2 UDB Command Line Processor (CLP), Control Center, and DB2 UDB scripts.

The following lists some of the common interfaces used with DB2 UDB. Most of these interfaces are described more fully in the IBM DB2 UDB Application Development Guide: Programming Client Applications V8, SC09-4826. Additional useful vendor-specific database information can be found in the applicable DB2 UDB porting guide.

JDBC and SQLj

DB2 UDB provides several JDBC drivers to write dynamic SQL programs in Java. DB2 UDB provides support for the Type 2, Type 3, and, new to Version 8, the Type 4 drivers.

SQLj offers developers a way to write static SQL programs using Java. SQLj programs generally outperform their JDBC counterparts because the query access plans of executable statements have been optimized before run-time.

More information about the Java supported interfaces can be found on

  • DB2 Java Application Development Web page at: thttp://www7b.software.ibm.com/dmdd/zones/java/.

  • The article DB2 and Java: The Big Picture posted on the DB2 Developer Domain also provides a good summary about the different Java options available for DB2 UDB version 8. The link to this article is: http://www7b.software.ibm.com/dmdd/zones/java/

  • Considering SQLj for Your DB2 V8 Java Applications is a white paper that addresses access to relational data from Java. This paper can be found at http://www7b.software.ibm.com/dmdd/library/techarticle/0302tsui/0302tsui.html

  • Optimal DB2 performance with SQLj and JDBC explores some of the performance issues related to using Java with DB2 UDB. This article can be accessed with a Developer Works logon ID through the link: https://www6.software.ibm.com/reg/devworks/dw-db2sqlj-i?S_TACT=102B7W81&S_CMP=DB2DD

Embedded SQL (static and dynamic)

DB2 UDB provides programmers the option of writing applications with SQL statements directly embedded within the host language. The SQL statements provide an interface to the database while the host language provides facilities to perform the application logic. DB2 UDB supports several host languages including C/C++, FORTRAN, COBOL, and Java (SQLj). Programmers have the option of using static or dynamic SQL, depending on the nature of the application.

ODBC

Microsoft's ODBC standard provides a set of APIs for accessing a vendor's database. Vendors must supply their own driver that implements a subset of the API for accessing the database. The DB2 UDB's CLI driver can be used on its own to access a DB2 UDB database or as an ODBC driver. DB2 UDB conforms to most of the Level 3 compliance level for ODBC.

ADO and OLE DB

Microsoft's ActiveX Data Objects provide a set of methods for accessing data from a wide variety of data sources including relational databases, HTML, video, text, and just about any other source of data. Access to the data is handled by ADO and is accessed through a service such as OLE DB or ODBC. In order to use OLE DB with DB2 UDB, you must first download the newest driver from the OLE DB Web page.

Microsoft .NET

.NET is Microsoft's new development platform that competes with the J2EE standard. The .NET framework programming model that enables developers to build Web-based applications, smart client applications, and XML Web services applications, which expose their functionality programmatically over a network using standard protocols such as SOAP and HTTP. Full support for the .NET standard for DB2 UDB is on the way. Currently, IBM is offering a .NET driver program for developers interested in writing applications using the .NET standard. More information about the .NET Framework program and DB2 UDB's support for .NET can be found on the DB2 UDB .NET Program Web page at:

http://www7b.software.ibm.com/dmdd/zones/vstudio/

Perl DBI

DBI is an open standard API that provides database access for client applications written in Perl. DBI defines a set of functions, variables, and conventions that provide a platform-independent database interface. The latest DB2 UDB Perl driver and information about Perl can be found at the DB2 UDB Perl DBI support Web page:

http://www-3.ibm.com/software/data/db2/perl/

DB2 UDB CLI

DB2 UDB's CLI Driver implements most of the function set defined in the ODBC standard as well as additional functionality specific to DB2 UDB. This interface offers more available functionality than do the other non-embedded and driver options. The latest information about developing applications with CLI can be found in the DB2 UDB reference manuals: Call Level Interface Guide and reference CLI Volume 1, SC09-4849, and Volume 2, SC09-4850.

Stored procedures

Another popular method of interfacing with the database is through stored procedures. Stored procedures can be written in DB2 UDB's SQL procedural language, or in an external programming language such as C/C++ or Java. Restricting database access through stored procedures offers numerous benefits such as a reduction in network traffic (all processing takes place on the server), and providing an additional layer of isolation between the application code and business logic. An excellent reference for building SQL stored procedures can be found in the book DB2 SQL Procedural Language for Linux, UNIX, and Windows, ISBN 0-13-100772-6. Additional material can also be found in Application Development Guide: Programming Server Applications, SG09-4827.

2.3.5 Migrating the data

You can move data (often called migration) from one DBMS to another by using numerous commercially available tools (including porting and migration tools such as the IBM DB2 Migration Toolkit, Ascential DataStage, and others).

In many cases, as the data is moved, it is also converted to a format that is compatible with the new DBMS (DATE/TIME data is a good example). This process can be quite lengthy when there is a large amount of data, which makes it quite important to have the conversions well defined and tested.

In some cases, it will still be necessary to do some customized conversions (specialized data, such as time series, geospatial, etc. may require extensive adjustments to work in the new DBMS). This is usually accomplished through the creation of a small program or script.


2.4 Performance tuning

Performance tuning is the process of increasing the effectiveness of your queries and decreasing the amount of time that they take to execute. However, the actual process of tuning the performance is not simply limited to modifying queries until they work better and faster. Rather, the process includes hardware configurations, operating system adjustments, application code optimization, interface considerations, database parameter changes, and finally query optimization.

While it is beyond the scope of this book to offer a full treatment on performance tuning, you will find here a list of links and resources that will allow you to learn about tuning the performance of your DB2 UDB-based application:

http://www7b.software.ibm.com/dmdd/zones/porting/tuning.html

Methodology

Here is a set process that works well when conducting any type of performance tuning:

  • Define the objectives: What is wrong or what do you want to accomplish?

  • Determine information to be analyzed

  • Determine the monitor(s) to be used

  • Test and obtain monitor data

  • Analyze the information

  • Determine the changes required

  • Implement changes (one at a time) and go back to step four

By following this process, and carefully recording your settings, adjustments, and results, you should be able to achieve incremental improvements in performance, or determine that you have reached an optimal set of parameters, and move on to the next tuning task.

Training and tutorials

One of the best ways to learn about DB2 UDB performance tuning is to take the IBM course entitled "DB2 Universal Database Performance Tuning and Monitoring Workshop." This course fits in well with the "DB2 UDB system administration courses" that are recommended for the DBAs at your site.

There are also a number of tutorials that address specific performance issues.

Documentation

There is also a rich source of information on performance tuning in the DB2 UDB documentation. Look at the DB2 UDB Administration Guide: Performance manual on-line or under the document name of db2d3e80.pdf on the product CD. This manual offers an extensive description of the tuning process (at various levels) and addresses many of the common areas where tuning can be most beneficial.

Information sources

The IBM DB2 Developer Domain contains a number of helpful articles that will help you increase the effectiveness of your use of DB2 UDB. Enter the key words performance tuning into the search box at the top of the page:

http://www7b.software.ibm.com/dmdd/zones/porting/index.html

The following articles will be provided:

  • SQL Procedures Performance: Hints and Tips

  • SQL Access to DB2 Monitoring Data: Capturing Snapshots

  • Tuning DB2 Universal Database Using the Statement Event Monitor

  • When We Think That the Optimizer Doesn't Get It Right

  • Tuning DB2 SQL Access Paths

As you address more specific issues in performance tuning (or in other aspects of porting), be sure to keep this search mechanism in mind.

Useful tools

Part of performance tuning is being able to monitor and measure the items to be analyzed. Here are some tools that will be helpful:

  • IBM Performance Expert: This IBM tool integrates performance monitoring, reporting, buffer pool analysis, and a Performance Warehouse function into one tool.

  • Configuration Advisor: One of the DB2 wizards that provides configuration recommendation based on the workload provided. This tool can be accessed through DB2 Control Center.

There are also a number of other tools that will be of value as you administer your DB2 UDB system. Also review the DB2 UDB documentation for information on the EXPLAIN facilities, the Snapshot Monitor, the Event Monitor, and the Health Monitor. These tools also help determine problem areas and the solutions that can eliminate them.


2.5 After the port

IBM offers a variety of products and solutions that extend the capabilities of DB2 UDB.

  • Information integration: Integration of the information in the database with other data sources. Contains facilities for implementing replication and federation of data and databases.

  • Content management: Management and coordination of sophisticated data types

  • Business intelligence: Sophisticated querying and analysis of data

  • Web integration: Inclusion of Web access to the database

  • DB2 UDB Tools: Tools and utilities that assist you in using DB2 UDB

In addition to the fundamentals of database administration (establishing tablespaces, creating databases, maintaining indexes, and so on), do not forget these other key administrative functions:

  • Backup and recovery: To prevent loss of data, you should have an adequate strategy for saving the data in your databases and for being able to restore it in case of a failure or error. The larger the amount of data you have, the longer and more sophisticated your strategy will become, especially if you need your database always on line. This section gives you some of the basics, and points you to much more information.

  • Replication: The DB2 UDB replication feature enables you to transfer data between systems for the purpose of building new data stores, or for duplicating some, or all of the original data in another DBMS.

  • High availability: High availability ensures that your data sources are always available for use (regardless of failures in hardware and software). This concept is closely related to the backup and recovery process, and is often implemented at the same time.

  • Federation: Federation allows access to data in numerous, heterogeneous data stores from one query. This section introduces the federation concepts and guides you to resources that will assist in creating a federated design.


2.6 IBM migration service offering

IBM migration specialists have provided advice and counsel to over 70 customers and performing over 3500 migrations to DB2 from non-IBM database systems like CA-IDMS, CA-Datacom, Oracle, Sybase, ADABAS, SUPRA, TOTAL, Microsoft SQL Server, and VSAM. If you would like IBM to perform your migration, please send an e-mail to <db2mig@us.ibm.com> or go to the following URL for contact information:

http://www-3.ibm.com/software/solutions/softwaremigration/contacts.html

Technical training

IBM PartnerWorld® offers a workshop designed for ISVs and IBM Business Partners intending to sell applications on DB2 UDB, and assumes you are new to DB2 UDB. It begins with building fundamental DB2 UDB skills, where you will learn how to migrate your existing database to DB2 UDB. You actually bring your own database to the workshop! In some cases (depending on database complexity), attendees have been able to completely migrate their database within the five day period. The workshop is also available to IBM customers. Send an e-mail to <db2mig@us.ibm.com> to obtain the latest version of the porting guide.

Contacts for EMEA and AP are <emeadbct@uk.ibm.com> and <APDB2@nz1.ibm.com> respectively. The SMPO office at EMEA and AP will forward the customers' mail to local technical sales. The local technical sales representatives will then contact the customers for their needs.


Chapter 3: MTK

Highlights

IBM DB2 Migration Toolkit (MTK) is a free tool to simplify and improve your migration to DB2 Universal Database (UDB). With MTK, you can automatically convert database objects such as tables, views, data types, etc. into equivalent DB2 database objects. MTK provides database administrators (DBAs) and application programmers with the tools needed to automate previously inefficient and costly migration tasks. You can reduce downtime, eliminate human error, and cut back on person hours and other resources associated with traditional database migration by using the MTK.

In this chapter we introduce the IBM DB2 Migration Toolkit and the following topics are discussed:

  • MTK overview

  • MTK planning

  • MTK setup


3.1 MTK overview

The IBM DB2 Migration Toolkit (MTK) (Figure 3-1) is available free of charge from IBM at the following URL: http://www.ibm.com/software/data/db2/migration/mtk

Click To expand
Figure 3-1: The IBM DB2 Migration Toolkit (MTK)

MTK was developed by the IBM Silicon Valley Laboratory in San Jose, California with assistance and contributions from the Watson Laboratory in Hawthorne, NY. Some driving factors in creating MTK are:

  • The need to develop a tool that was closely linked and kept pace with the technical development of DB2 and the databases with which it interacts.

  • The need to address "real world" migration concerns. Because of IBM's significant experience in this area, the developers have created a tool that meets the requirements of IBM migration teams while addressing the significant issues involved in customer migrations.

  • The need for a tool that would convert as much, and as accurately as possible.

  • The need for a tool that would be available, free of charge to those interested in engaging in a migration.

3.1.1 MTK facts

The following operating systems, conversion sources, and conversion targets are supported by MTK.

  • MTK can be installed on the following operating systems:

    • Windows NT 4.0, Windows 2000, Windows XP

    • Linux

    • AIX 4.3.3.0 or later

    • Sun Solaris 5.7

  • MTK supports the following databases as conversion sources:

    • Sybase Enterprise, Versions 11 and 12

    • Microsoft SQL Server, versions 6, 7, and 2000

    • Oracle 8i

    Note

    Oracle 8i is the officially supported version. MTK can also work with Oracle 7 and 9i databases except for some of the special functionality.

  • MTK supports the following versions of DB2 UDB as conversion targets:

    • DB2 UDB v7.2 (FixPak 6 or later) (EE/EEE)

    • DB2 UDB v8.1 (FixPak 2 or later), multiplatform, all editions

    • DB2 UDB for iSeries Version 5.2 or later

3.1.2 MTK features

MTK converts the following Oracle source database constructs into equivalent DB2 UDB database objects:

  • Data types

  • Tables

  • Columns

  • Views

  • Indexes

  • Constraints

  • Packages

  • Stored procedures

  • Functions

  • Triggers

  • Sequences

MTK enables the following tasks:

  • Obtaining source database metadata (DDL) by EXTRACTING information from the source database system catalogs through (JDBC/ODBC)

  • Obtaining source database metadata (DDL) by IMPORTING DDL scripts created by SQL*Plus or third-party tools

  • Automating the conversion of database object definitions, including stored procedures, triggers, packages, tables, views, indexes, and sequences

  • Deploying SQL and Java compatibility functions that permit the converted code to "behave" functionally similar to the source code

  • "On the fly" conversion of PL/SQL statements using SQL Translator tool. Also effective as a DB2 SQL PL learning aid for PL/SQL developers.

  • Viewing conversion information and messages

  • Deployment of the converted objects into a new or existing DB2 UDB database

  • Generating and running data movement (unload/load) scripts or performing the data movement on-line.

  • Tracking the status of object conversions and data movement, including error messages, error location, and DDL change reports using the detailed migration log file and report

3.1.3 MTK GUI interface

The MTK GUI interface (Figure 2-2) presents five tabs each of which represents a specific task in the conversion process. The tabs are organized from left to right and are titled:

  • Specify Source

  • Convert

  • Refine

  • Generate Data Transfer Scripts

  • Deploy to DB2

The menu bar contains Application, Project, Tools, and Help:

  • Application: Allows you to set up your preferences such as an editor.

  • Project: You can tart a new project, open or modify an exiting project, import SQL source file, or perform backup restore function through here.

  • Tools: You can launch to SQL Translator, reports, and the log.

  • Help: MTK help text

Click To expand
Figure 3-2: MTK GUI interface

3.1.4 Migration tasks

The five tabs in the MTK user interface first screen represent the five phases of the migration process. The following is an overview of these five tasks:

  • Task 1: Specify source

    The SPECIFY SOURCE task (Figure 3-3) focuses on Extracting or Importing database metadata (DDL) into the tool. The database objects defined in this DDL will then be used as the source code for conversion to DB2 UDB equivalent objects. Extraction requires a connection to the source database through ODBC or JDBC. Once the ODBC/JDBC connection is established, MTK will 'read' the system catalogs of the source database and extract the definitions for use in the conversion process. IMPORTING, on the other hand, requires an existing file, or files, which contain database object DDL. The Import task copies the existing DDL from the file system into MTK project directory for use in the database structure conversion process. Using MTK to perform data movement will be limited if IMPORTING is chosen.

    Figure 3-3: Specify source

  • Task 2: Convert

    During the CONVERT task (Figure 3-4) the user may complete several optional tasks before the actual conversion of the source code. These are:

    • Selecting format options for the converted code. Examples of options are: including the source code as comments in the converted code; including DROP before create object statements, among others.

    • Making changes to the default mapping between a source data type and its target DB2 data type.

    Figure 3-4: Convert

    Once the optional tasks are completed the user can click the Convert button and the source DDL statement is converted into DB2 DDL.

    Each conversion generates two files:

    • db2 file contains all of the source code converted to DB2 UDB target code.

    • .rpt file can be opened and viewed from this pane, it is best to examine it during the next task, which is Refine.

  • Task 3: Refine

    During the REFINE task (Figure 3-5) the user may:

    • Examine the results of the conversion

    • View various types of messages generated by the tool and, if necessary specify changes to be made to the converted DDL

    Click To expand
    Figure 3-5: Refine

    If the user makes any changes to the converted DDL, one must return to the Convert step to apply the changes.

    You can use other tools such as the SQL Translator, Log, and Reports to help you refine the conversion. After you have refined the DB2 DDL statements to your satisfaction, you can move on to the Generate data transfer scripts step to prepare the data transfer scripts, or the Deploy to DB2 step to execute the DB2 DDL statements.

  • Task 4: Generate data transfer scripts

    In the GENERATE DATA TRANSFER task (Figure 3-6), scripts are generated that will be used to:

    • Unload data from the source environment

    • Load or Import data into DB2 UDB

    Figure 3-6: Generate Data Transfer script

    Before creating the scripts one may choose some advanced options that will affect how the IMPORT or LOAD utility operates. This will allow the user to refine the Load or Import specifications to correspond with the requirements of their data and environment.

  • Task 5: Deploy to DB2

    The DEPLOY task (Figure 3-7) is used to install database objects and Import/Load data into the target DB2 database. In this task, one can:

    • Choose to create the database or install the objects in an existing database.

    • Execute the DDL to create the database objects.

    • Extract data from the source database.

    • Load/import the source data into the target DB2 tables or choose any combination of the above three.

    Click To expand
    Figure 3-7: Deploy to DB2

An overview of all the tasks in the MTK conversion process is shown in Figure 3-8.

Click To expand
Figure 3-8: MTK conversion tasks overview

3.1.5 The MTK SQL Translator

The MTK SQL Translator (Figure 3-9) enables "on-the-fly" conversion of individual statements, a series of statements, or stored procedures. The translator requires that all of the dependent objects for the SQL that you wish to convert are available to MTK. This may be accomplished in either of two ways:

  • The current project already contains all of the converted objects on which the desired SQL depends (tables, views, etc.)

  • The objects on which the SQL statement depends will be created in the SQL Translator window by placing them before the SQL that is to be converted.

Click To expand
Figure 3-9: The MTK SQL Translator


3.2 MTK planning

MTK runs on a variety of operating system platforms including AIX, Linux, Sun Solaris, and Windows. Before installing MTK, please verify the hardware and software requirements provided in this section.

3.2.1 Operating system and version requirements

MTK will run on the following operating systems and versions:

  • AIX 4.3.3.0 or later

  • Linux

  • Windows NT 4.0, Windows 2000, Windows XP

  • Sun Solaris 5.7

3.2.2 Hardware requirements

The hardware requirements for installation of MTK on UNIX platforms are:

  • 50 MB of disk space for installation

  • 5 MB per project plus space to unload data

  • 128 MB minimum memory recommended. This should be increased for large DDL files (for example, a 10 Mb PL/SQL script file would need approximately 512 Mb of memory)

The hardware requirements for installation of MTK on Windows platforms are:

  • 50 MB of disk space for installation

  • 5 MB per project plus space to unload data

  • 128 MB minimum memory recommended. This should be increased for large SQL files (for example, a 10 Mb PL/SQL script file would need approximately 512 Mb of memory)

  • 300 MHz or higher processor

3.2.3 MTK software requirements

MTK support various source databases management system. Here are the software requirements.

UNIX

These are the software requirements for installation of MTK on UNIX platforms:

  • DB2 UDB V7.2 with FixPak 6, or DB2 UDB v8.1 with FixPak 2 installed and configured in the $PATH.

  • Java 1.3 installed and configured in the system $PATH and $CLASSPATH.

  • Depending on your data source, either:

    • Sybase JConnect 5_2 installed and configured in the $PATH and $CLASSPATH, OR

    • Oracle 8.i Client installed and configured in your environment

Windows

These are the software requirements for installation of MTK on Windows platforms:

  • DB2 UDB V7.2 with FixPak 6, or DB2 UDB v8.1 with FixPak 2 installed.

  • Depending on your data source, either:

    • Sybase JConnect 5_2 installed and configured in the PATH and

    • CLASSPATH, OR

    • Oracle 8.i Client installed and configured in your environment

Note

DB2 UDB is not required to run the MTK until the deployment step.

3.2.4 Where to install MTK

MTK can be installed in source database server, target database server, or at a client, which has connectivity to both source and target database server established. Deciding where to install MTK depends on the data to be migrated.

MTK places the extracted data ont he server of where the MTK is installed. Hence, there is a performance advantage to installing MTK where the source database resides, since it is faster to unload data locally than across a network. However, DB2 requires that LOB datafiles be on the local machine, so that MTK cannot load data into LOB columns unless MTK is running on the target database server.

For example, if the Oracle database is located on an AIX system and the DB2 UDB target will be deployed onto a Linux system, and there is no data to be migrated to LOB columns, MTK should be installed on the AIX system.


3.3 MTK setup

MTK installation step is simple and requires minimum preparation. This section provides MTK installation procedures and the preparation tasks for each platform.

3.3.1 MTK environment preparation

Before installing MTK, you need to verify and set up the environment. Here we provide the procedure and commands you can use in each platform to have the installation environment prepared.

ALL environments

If you choose to manually create a database for migration, rather than let the IBM DB2 Migration Toolkit create it during deployment, then ensure that you execute the following DB2 commands before creating a database:

   update database manager configuration using KEEPDARI NO
   db2stop force
   db2start
Note

These commands must be run each time that you manually create a new database.
UNIX environments

You need to make sure that some DB2 related environment variables are set properly, and the needed libraries are included in the path variables. Please check the following:

  • Verify that the $INSTHOME environment variable is set to your DB2 instance directory and that it is properly exported when you start a new environment. For example, in Korn shell type this command:

    echo $INSTHOME

    The result should be equivalent to:

    /home/db2inst1

  • Verify that you can access Java and that it is at least at level 1.3.0. The command is:

       java -version

  • For Oracle migrations in UNIX environments, you must include the following libraries in the $CLASSPATH:

    {ORACLE_HOME}/jdbc/lib/classes12.zip

    Also, include the following entries in the $LIBPATH (AIX):

    {ORACLE_HOME}/lib
{ORACLE_HOME}/lib32

  • Do not attempt to install and run MTK in a shared environment (for example, /usr/local/mtk). If you want multiple users to run MTK on the same system, they should install and run their own copies, using projects and files local to their home directory. Sharing projects and logs will most likely result in conflicts and overwritten files.

  • Ensure the Netscape directory is in the $PATH. If Netscape is unavailable, MTK will view reports using a Java HTML viewer with limited capability.

  • For Linux, increase the message queue number to at least 128 using command:

    sysctl -w kernel.msgmni=128.

Windows environments

To simplify the deployment step, we recommend that you run MTK while logged in with a system user ID that has system administrative authority to the DB2 database, for example, the user ID used to install DB2 UDB.

Note

For the installation and setup of the components to deploy SQL stored procedures to a UNIX or Windows system, please refer to the following IBM DB2 UDB publications:

  • v7.2: Application Development Guide, SG09-2949

  • v8.1: Application Development Guide: Building and Running Applications, SC09-4825

3.3.2 MTK UNIX installation

Here are the steps to install MTK on UNIX:

  1. Ensure you have the necessary hardware and software requirements, as listed in the preceding section.

  2. Log in with the user ID under which you will install MTK.

  3. Do not install MTK as root. If you are not going to deploy to DB2 UDB on this machine, use any user ID but root. If you are going to deploy to a DB2 database, install MTK using a user ID in the db2admin group.

  4. Download MTK from the MTK download page into a newly created directory.

  5. Expand the package:

    Please note that the MTK distribution file name may vary in releases. The command to expand the package on each platform remains the same though.

    AIX:

    uncompress db2mtk_V1_1_a_aix.tar.Z using the command

       tar -xvf db2mtk_V1_1_a_aix.tar

    Solaris:

    Uncompress db2mtk_V1_1_a_sun.tar.Z using the command:

       tar -xvf db2mtk_V1_1_a_sun.tar

    Linux:

    Uncompress the file using command:

       tar zxvf db2mtk_V1_1_a_linux.tar.GZ

  • Launch the IBM DB2 Migration Toolkit from the directory in which it was installed by typing:

    ./MTKMain

3.3.3 MTK Windows installation

Here are the steps to install MTK on Windows:

  1. Ensure you have the necessary hardware and software requirements, as listed in the preceding section.

  2. Download MTK from the MTK Download page into any directory.

  3. Unzip and extract the package contents.

  4. Run Setup.exe

    The installation will default to the C:\MTK directory.

  5. To launch the IBM DB2 Migration Toolkit, click:

    Start -> Programs -> DB2 Migration Toolkit -> Toolkit


Chapter 4: Porting with MTK

Overview

In this chapter we discuss and demonstrate the conversion of database objects, and the extraction and loading of data into a DB2 UDB database using the IBM DB2 Migration Toolkit (MTK).

The following items are discussed:

  • Preparation for porting

  • Running MTK

  • Extracting or Importing metadata into MTK

  • The Convert task

  • The Refine task

  • The Generate Data Transfer Scripts task

  • Deploy to DB2 considerations

  • Next steps

  • Converting the remaining objects

  • Deployment of stored procedures, functions, packages, and triggers

  • MTK conversion conclusion


4.1 Preparation for porting

Before you start migrating the database using the MTK, you need to prepare the target system DB2 UDB environment. This section outlines the tasks to perform in order to have a functional and accessible DB2 UDB ESE database.

4.1.1 DB2 UDB V8 ESE installation

Regardless of the platform, you need to verify whether or not the system satisfies hardware and software requirements. In this redbook, we use both AIX and Microsoft Windows as the main platforms for installation. Installing DB2 UDB ESE on a platform such as SUN Solaris, HP-UX, or Linux requires modifying the operating system kernel parameters. System reboot is required afterwards.

DB2 UDB ESE installation on Linux

The DB2 UDB ESE installation on Linux consists of the following steps:

Verifying hardware requirements

The hardware specifications must satisfy one of the following:

  • Intel® 32-bit or 64-bit

  • DB2 UDB ESE requires 256 MB of RAM at a minimum. More memory is required to efficiently run other applications.

  • The amount of disk space needed by DB2 UDB ESE may vary depending on the type of installation. Table 4-2 shows the disk space requirements.

Table 4-1: Disk space requirements on AIX
Installation type | Disk space
Compact | 350 MB-350 MB
Typical | 450 MB-500 MB
Custom | 200 MB-800 MB
Verify software requirements

The following software components must be installed on the server before attempting the DB2 installation.

  • For Intel 32-bit architecture, you require a recent Linux operating system distribution with:

    • Kernel level 2.4.9 or later

    • glibc 2.2.4 or later

    • RPM 3 or later

  • For Intel 64-bit architecture, the following software is required:

    • Red Hat Linux 7.2 or higher or SuSE Linux SLES-7 or higher

    • gcc 3.0.2

    • gcc3 libstdc++ runtime libraries

  • The IBM Developer Kit for Java 1.3.1.

Verifying communication requirements

Ensure having the proper communication protocols installed on the server in order to achieve successful communication

  • No additional software is needed if TCP/IP is used for connectivity.

Please refer to the Quick beginnings for DB2 Servers, GC09-4826 for a list of supported communication protocols.

Performing DB2 UDB ESE installation on Linux

The following steps explain the DB2 installation procedure:

  1. Log on to the Linux system as root.

  2. Modify kernel parameters for DB2.

  3. Mount the CD-ROM using command mount /cdrom

  4. Change to the CD-ROM directory cd /cdrom

  5. Launch the DB2 Setup wizard with command ./db2setup which will start a graphical user interface (GUI) that will guide you through the installation process. Once the installation is successfully terminated, the DB2 server and components will be located in /opt/IBM/db2/V8.1. At this point the DBA may proceed with applying the recent FixPak and creating instances and databases. The db2setup interface also allows the user to generate a response file if a silent install is desired.

DB2 UDB ESE installation on AIX

The DB2 UDB ESE installation on AIX consists of the following steps:

Verifying hardware requirements

The hardware specifications must satisfy one of the following:

  • IBM RISC/6000, eSeries or pSeries®

  • DB2 UDB ESE requires 256 MB of RAM at a minimum. More memory is required to efficiently run other applications.

  • The amount of disk space needed by DB2 UDB ESE may vary depending on the type of installation. Table 4-2shows the disk space requirements.

    Table 4-2: Disk space requirements on AIX

    Installation type

    Disk space

    Compact

    350MB–400 MB

    Typical

    450MB–550 MB

    Custom

    350MB–700 MB
Verify software requirements

The following software components must be installed on the server before attempting the DB2 installation:

  • AIX V4.3.3 with maintenance level 9 or later (32-bits) or AIX V5.1.0 maintenance level 2 or later (32 and 64 bits)

  • Java runtime environment (JRE) V1.3.1

Verifying communication requirements

Ensure having the proper communication protocols installed on the server in order to achieve successful communication:

  • No additional software is needed if TCP/IP is used for connectivity.

Please refer to the Quick beginnings for DB2 Servers, GC09-4826 for a list of supported communication protocols.

Performing DB2 UDB ESE installation on AIX

The following steps explain the DB2 installation procedure:

  1. Log on to the AIX system as root.

  2. Mount the CD-ROM using command mount /cdrom

  3. Change to the CD-ROM directory cd /cdrom

  4. Launch the DB2 Setup wizard with command ./db2setup which will start a graphical user interface that will guide you through the installation process. Once the installation is successfully terminated, the DB2 server and components will be located in /opt/IBM/db2/V8.1. At this point the DBA may proceed with applying the recent FixPak and creating instances and databases. The db2setup interface also allows the user to generate a response file if a silent install is desired.

DB2 UDB ESE installation on Windows

The DB2 UDB ESE installation on AIX consists of the following steps:

Verifying hardware requirements

The hardware specifications must satisfy one of the following

  • DB2 UDB ESE 32-bit requires a Pentium® level processor while 64-bit DB2 UDB ESE requires an Itaneum processor.

  • DB2 UDB ESE requires 256 MB of RAM at a minimum. More memory would be required to efficiently run other applications.

  • The amount of disk space needed by DB2 UDB ESE may vary depending on the type of installation. Table 4-3 shows disk space requirements on Windows.

    Table 4-3: Disk space requirements on Windows

    Installation type

    Disk space

    Compact

    300MB

    Typical

    350MB

    Custom

    300MB
Verifying software requirements

The following software components must be installed on the server before attempting the DB2 installation:

  • Windows NT V4 with Service Pack 6a or higher, Windows 2000 with Service Pack 2, Windows XP or Windows .Net

  • Java Runtime Environment (JRE) V1.3.1 is required. The installer will install the JRE if the DB2 graphical tools are being installed.

Verifying communication requirements

DB2 UDB ESE V8 requires TCP/IP for remote administration. No additional software is required if TCP/IP is used for connectivity. Please refer to the Quick beginnings guide for a list of supported communication protocols.

Performing DB2 UDB ESE installation on Windows

The following steps explain the DB2 installation procedure:

  1. Log on to the Windows system as an administrator user.

  2. Close all running applications.

  3. Insert the CD-ROM into the drive and a graphical user interface DB2 Setup wizard should be launched automatically. If the auto-run feature is not enabled, you can launch the DB2 installer by executing the setup.exe program from the CD-ROM.

  4. The DB2 Setup wizard will guide you through installation process. Once the installation is successfully terminated, the DB2 server and components should be located in the X:\IBM\SQLLIB directory where X is the disk drive identifier. At this point, the DBA may proceed with applying the recent FixPak and creating instances and databases.

4.1.2 Multiple partition installation

In the multiple partition environment, you need to install DB2 UDB in each physical database server. To ease the installation process, DB2 UDB provides the facility to generate an installation file call response file during installing the first machine. The file contains the installation specification and setup information, which can be used to install the reset of systems in the partitioned environment. DB2 UDB also provides you the sample response file. You can modify the sample response file to fit your system requirements, and use it to install DB2 UDB, create required a user ID, and create DB2 instance, etc. in all the systems in partitioned environment.

The basic DB2 UDB installation procedure in the multi-partitioned environment is the same as the single partition installation, except you need to specify the multiple partition database during installation. However, there are additional considerations that should be taken in environment preparation or user ID setup. For example, in an AIX or Linux environment, only one DB2 instance is created on the instance-owing machine. The home directory of the instance should be shared among all the participating servers. NFS-mounted instance home directory on the instance-owning machine is commonly used. In Windows, DB2 UDB utilizes Windows clustering technology and domain server setup is required.

The DB2 UDB Version 8 manual Quick Beginnings for DB2 Servers, GC09-4836 contains the procedures of setting up multi partitioned database. The following IBM Redbooks also provide detailed information on setting up the DB2 UDB multiple partitioned database:

  • Scaling DB2 UDB on Windows Server 2003, SG24-7019

  • Up and Running with DB2 for Linux, SG24-6899

4.1.3 Instance and database creation

You can have DB2 UDB create the DB2 instance automatically while installing DB2 UDB. You also can create the DB2 instance manually after the installation is completed. On Linux or AIX, the DB2 instance can be created by executing db2setup program used to install DB2 manually through the command line by issuing the db2icrt command, or by using the Control Center provided by DB2. This section discusses the first two methods on a Red Hat Linux system.

Using the db2setup/db2isetup utilities

Using the ./db2setup utility provides an easy way to create a DB2 instance. As root perform the following:

  1. Launch the db2setup utility.

  2. Check the Create a new DB2 instance or set up an existing DB2 instance option.

  3. This screen will allow you to configure the DB2 administration server and user used as a repository for the GUI administration tools provided with DB2 such as the Control Center. The default value for this user is dasusr1 with a default home directory of /home/dasusr1

  4. Click on the Instance setup option and choose the Create DB2 instance - 32 bit option.

  5. For a single partition instance choose the first option.

  6. On the Set User Information for the DB2 Instance Owner screen, you need to identify a system user who will be the instance owner. If you choose a new user, then specify the name of the user and his password. The default values are user db2inst1 and group db2grp1. You also have to specify the home directory for this user i.e. /home/db2inst1. By default any databases created under this instance will be created in this directory unless otherwise specified. Both the user and the home directory will be created by the installer.

  7. The Set User Information for the Fenced User screen allows you to specify its username and password. The default user is db2fenc1 assigned to group db2fgrp1 in home directory /home/db2fenc1.

  8. The tools Catalog screen is meant for preparing the DB2 Tools catalog on the server. Choose the Do not prepare the DB2 tools catalog on this computer if you do not need the tools catalog installed.

  9. Finally, set the administrator contact information and click Finish.

As part of the instance creation, the installer will create all three users identified mainly as db2inst1, db2fenc1, and dasadm1. If you do not want to use the default user IDs, you can create the user IDs and groups ahead of time and use the IDs during creating the instance. The installer will also add the following entry to the /etc/services file in order to allow communication from DB2 clients:

db2c_db2inst1 50000

Where db2c_db2inst1 indicates the service name and 50000 indicates the port number. Subsequent instances may be created on the same server simply by invoking the /opt/IBM/db2/V8.1/instance/db2isetup utility and going through the above steps.

Using DB2 command

We can also create a DB2 instance manually by following the following steps.

  1. Log on to the Linux system as root.

  2. Create the necessary groups for DB2 Instance owner, administration server, and Fenced ID using the following commands:

    groupadd db2grp1
groupadd db2fenc1
groupadd dasadm1

  3. Create the DB2 Instance user ID, administration server user ID, and Fenced ID and assign them to their respective groups using the following commands

    useradd -g db2grp1 -d /home/db2inst1 db2inst1 -p my_password
useradd -g db2fenc1 -d /home/db2fenc1 db2fenc1 -p my_password
useradd -g dasadm1 -d /home/dasusr1 dasusr1 -p my_password

  4. Issue the command:

    db2icrt -u db2fenc1 db2inst1

  5. Edit the /etc/services file and add the following entries:

    db2c_db2inst1 50000/tcp    #DB2 port for remote clients
db2idb2inst1 50001/tcp    #interrupt ports for DB2 1.x clients

  6. Log on as the instance owner and update the Database Manager Configuration (dbm cfg) file to reflect the service name in the /etc/services file update dbm cfg using SVCENAME db2c_db2inst1

  7. Set up the default communication protocol:

    db2set -i db2inst1 -i DB2COMM=TCPIP

  8. Set the instance to auto-start with the system if desired:

    db2set - i db2inst1 DB2AUTOSTART=TRUE

At this point the server is ready to create the database. To simply database connectivity test, you can create a sample database in four easy steps:

  1. Log on the Linux system as the instance owner db2inst1.

  2. Execute the command db2sampl located at sqllib/bin directory under the home directory of the DB2 instance. The db2sampl executable is a script that automatically creates a small database called SAMPLE.

  3. Connect to the SAMPLE database by issuing the db2 connect command. In our example the command becomes:

    db2 connect to sample, this should display a the following connection
confirmation on the screen

    The Database Connection Information returned:

    Database server        = DB2/LINUX 8.1.3
SQL authorization ID   = DB2INST1
Local database alias   = SAMPLE

  4. To see the results, issue a SQL query such as:

    db2 "select * from staff"

A DB2 database can either be created by the Control Center or by using the command line. In order to create a DB2 database manually you may follow the following steps:

  1. Log on to the Linux system as the instance owner db2inst1.

  2. Since DB2 allows for one instance to have multiple databases, it is always recommended to attach to the desired instance before the create database command is issued:

    db2 attach to instance_name

    where the instance name in our case is db2inst1.

  3. Issue the create database command. The simplest create database command can take the form:

    db2 "create database my_database on /db_path"

    This command will create a database and the following three table spaces:

    • SYSCATSPACE to store system catalog tables

    • USERSPACE1 to store user defined objects

    • TEMPSPACE1 to store temporary objects

    These table spaces can be viewed by issuing the command: db2 list tablespaces

There are many options that can be included in the database command. Example 4-1 includes some of the available options. Please refer to the DB2 SQL Reference Volume 2, SC09-4845 for more details on the create database command.

Example 4-1: Create database
Start example
CREATE DATABASE my_db ON /db_path ALIAS warehouse_db
USING CODESET code_set TERRITORY US COLLATE USING SYSTEM USER TABLESPACE
MANAGED BY SYSTEM USING ('/user_tablespace_path') CATALOG TABLESPACE MANAGED BY
SYSTEM USING ('/catalog_tablespace_path') TEMPORARY TABLESPACE MANAGED BY
SYSTEM USING ('/temp_tablespace_path')
End example

The default value for db_path is the home directory of the instance owner db2inst1 /home/db2inst1.

We have created an Oracle database ORA_EMP to demonstrate the conversion process. Before running the script created by MTK to deploy the database object, we need to create a DB2 database. Example 4-4 outlines the create database command we used to create the DB2_EMP database. Any database objects will be created in this directory. Therefore, we recommend that the db_path is explicitly set to a different value in order to prevent the /home/db2inst1from utilizing all of its allowed space which can cause an instance failure.

Example 4-2: Example of the create database command
Start example
CREATE DATABASE DB2_EMP on /db2/data CATALOG TABLESPACE MANAGED BY DATABASE
USING (FILE '/db2/data/system' 25600) user tablespace managed by database using
(file '/db2/data/user' 25600) temporary tablespace managed by system using
('/db2/temp')
End example

4.1.4 Table space planning

DB2 UDB allows for two types of table spaces, SMS and DMS. Both types of table spaces have containers or data files associated with them. In this section we discusses both types of table spaces. Table 4-4 outlines the differences between both types of table spaces. There are three categories of table space:

  • Regular tablespace that can store regular, index, and long data. Nevertheless, this type of table spaces is not optimized for long type data.

  • Large tablespace is designed to store long character or LOB type data.

  • Temporary tablespace is designed to store temporary tables. A user cannot define a permanent table in a temporary table space.

    Note

    Only users with SYSADM or SYSCTRL authority can create table spaces.

Table 4-4: Differences between SMS and DMS table spaces
Table space type | SMS | DMS
Can dynamically increase the number of containers in a table space | No | Yes
Can store index data for a table stored in a separate table space | No | Yes
Can store long data for a table stored in a separate tablespace | No | Yes
One table can span multiple table spaces | No | Yes
Space allocated only when needed | Yes | No
Table space can be placed on different disks | Yes | Yes
Extent size can be change after creation | Yes | No

SMS table space

This type of table space stores its containers in the form of operating system directories. Since this type of table spaces cannot be resized manually, enlarging the underlying file system would then increase the size of the table space. SMS table spaces acquire more space only when needed.

There are few advantages associated with creating SMS table spaces such as ease of creation and maintenance. The main disadvantage of an SMS table space is that it cannot separate out table indexes and large data types into their own table spaces.

DMS table space

The containers associated with a DMS table space are either operating system files or raw devices. A DMS table space can be resized manually with the ALTER TABLESPACE command using the RESIZE option. The database administrator decides the location of containers belonging to the table space and when to add containers. A DMS table space may be defined as regular, large or temporary.

Table 4-4 provides the summary of the differences between DMS and SMS.

When planning for table spaces, you should consider the table space size, type, and the placement on the physical drive. Migration time is a good time to re-design the table spaces of your database if you have been considering it. Oracle datafiles are similar to the DB2 UDB DMS table space container. You should also consider to take advantage of the DB2 UDB SMS table space type while you are planing the table spaces for your database.

Creating table spaces

The command used to create a table space can be in the following form. The outlines the use of the create tablespace command is outlined as following:

   CREATE Tablespace_data_type TABLESPACE Tablespace_name PAGESIZE Integer K
   MANAGED BY Tablespace_type USING Container_path

Where:

  • Tablespace_data_type indicates if a table space is regular, large or temporary.

  • Tablespace_name indicates the name of the table space.

  • Integer indicates the size of a memory page in Kbytes.

  • Tablespace_type indicates either SYSTEM or DATABASE for SMS and DMS table spaces.

  • Container_path indicates the path and name of a container.

There are three table spaces in the example Oracle database USER_EMP_TBS, USER_LOB_TBS and USER_LOB_TBS. We will keep the same table space names in our migration demo. Following are DB2 table space creation commands we used.

Example 4-3 shows the command to create table space USER_EMP_TBS.

Example 4-3: Create table space command
Start example
CREATE REGULAR TABLESPACE USER_EMP_TBS
managed by database using ('/db2/user_data 25600').
End example

Example 4-4, shows the syntax used to create the USER_LOB_TBS table space used to store Long objects in the DB2_EMP database.

Example 4-4: Creating a table space of type Large
Start example
CREATE LARGE TABLESPACE user_lob_tbs
MANAGED BY DATABASE USING (FILE '/db2/lob/user_lobs.dbf' 25600)
End example

Example 4-5, shows the syntax used to create the USER_IND_TBS used to stored the indexes in the DB2_EMP database.

Example 4-5: Creating a table space to store indexes
Start example
CREATE TABLESPACE user_ind_tbs MANAGED BY DATABASE USING (FILE
'/db2/indx/user_indx.dbf' 25600)
End example

In order to obtain information about existing table spaces the DBA can issue the following command from the CLP:

db2 list tablespaces

If detailed information is required the following command may be issued:

db2 list tablespaces show detail

4.1.5 Security consideration

DB2 UDB uses existing operating system users as database users. On an environment like AIX, users are simply added to specific operating system groups, which provide them with the necessary rights to access the database.

DB2 provides two levels of security to users. The first is authentication which is to identify who the user is and determines if the user has any access to the database. The authentication process is done using a security facility outside of DB2 like a operating system's security facility. The second one is authorization which determines what DB2 system and object privileges the authenticated user has. Authorization is performed by DB2. There ar two types of permissions: authority and privileges. The authority level, which controls the user specific privileges on instance level and over the database in its entirety such as creating a database, creating a table space, performing backup and recovery tasks, etc. The privilege level, which allows a user to access, create or manipulate a specific database object in the database such as a table, view, or an index.

DB2 UDB authorities

An authority in DB2 UDB is defined as a Group in AIX and granting a specific user this authority simply means that this user is assigned to this group in the /etc/group file. The levels of authorities in DB2 UDB are classified as follows:

  • SYSADM: Administrative authority, system administrators are given full privileges over the entire DB2 instance. SYSADM cannot be granted with a SQL statement.

  • SYSCTRL: System control authority, system controllers are given full privileges for managing the system, but are not allowed access to data. SYSCTRL cannot be granted with a SQL statement.

  • SYSMAINT: System maintenance authority. System maintainers are given a subset of privileges to manage the system. SYSMAINT cannot be granted with a SQL statement.

  • DBADM: Administrative authority. Database administrators have control over an individual database. DBADM can be granted with a SQL statement.

  • LOAD: The LOAD authority is granted in the database level. The users with LOAD authority can load data to a table, Quiesce tablespace for table, perform Runstats and List Tablespaces commands. To load data to a table, the INSERT privilege on the table is also required. Depending on the load activity, the UPDATE and DELETE privilege on the table may also needed.

DB2 UDB privileges

Database privileges are granted in the database through the SQL command GRANT. Privileges are stored in the system catalog tables within the database There are three types of privileges: ownership, individual, and implicit:

  • Ownership or CONTROL privileges: In most cases the database user who creates a database object is automatically granted the CONTROL privilege. This privilege permits the user to grant other database users certain privileges on this object. The GRANT privilege can be granted through the GRANT statement.

  • Individual privileges: A classic example of this type of privileges is the SELECT, INSERT, UPDATE and DELETE privileges.

  • Implicit privilege: This is a sub privilege, which is automatically granted to a user when this user is granted a high level privilege.

Grant command syntax

MTK does not convert GRANTS from Oracle to DB2. You'll need to perform the security conversion manually. The syntax to use the Grant or Revoke command is as follows:

GRANT privilege ON Object_name TO USER username
REVOKE privilege ON object_name FROM username

Example 4-6 includes examples of granting database privilege and table access authority to a user.

Example 4-6: Granting Create table privilege to user smith
Start example
GRANT CREATETAB TO USER smith
GRANT INSERT ON emp_table TO USER smith
End example

4.1.6 Creating DB2 database users

The main difference between creating users in an Oracle environment and creating them in a DB2 UDB environment is that in Oracle users are created at the database level using SQL commands, where as in DB2 UDB, users are created at the operating system level using operating system commands and utilities.

For example, if we need to create a new database user called db2usr and grant him select, insert, and update privileges on table accounts on an AIX environment, we will need to perform the following steps:

  1. Log on to the AIX server as root and create a group: mkgroup id=995 accttab

  2. Create a user and assign him to group accttab: mkuser id=1001 pgrp=accttab groups=accttab home=/home/db2user db2user

  3. Edit the .profile file for user db2usr and add the db2profile path to it, and execute the .profile in order to reflect the changes:

    . /db2/home/db2inst1/sqllib/db2profile
. ./.profile

  4. Log on to the AIX server as the instance owner or any authorized user and connect to the database:

    su - db2inst1
db2 connect to sample

  5. Grant the desired privileges to the group: db2 "grant select, insert, update on accounts to group accttab"

  6. Log on as user db2user, connect to database sample, and issue a SQL statement against table accounts:

    su - db2user
db2 connect to sample
db2 "select * from db2inst1.staff"


4.2 Running MTK

It is efficient to use MTK to port the database objects from Oracle to DB2 UDB, extract and load data into DB2 database. In the following sections, we demonstrate step-by-step the migration process using MTK.

4.2.1 Migration details

MTK is a multi platform migration tool. In our lab, we run MTK on AIX, Linux and Windows platform. This section describes the lab environment and database structure used for MTK demonstration.

Environment

Before we begin to describe the details of our migration from Oracle 8i to DB2 UDB v8.1 using the IBM DB2 Migration Toolkit (MTK), here is some information about the source and target environments in our laboratory:

  • Oracle source operating system:

    AIX 5L™ for POWER, Version 5.1

  • MTK source O/S:

    Same as above

  • MTK build:

    030627.0321, converter [030627.0309]

  • DB2 target O/S:

    Linux - Red Hat v8.0

  • Oracle Version:

    8.1.7

  • DB2 Version:

    V8.1 FixPak2

We chose to install MTK on the AIX platform because that is where the Oracle database resides. Based on our experiences unloading data with MTK, it is most effective to install the tool on the operating system where the source system resides.

Oracle source database

The Oracle source database consists of the following kinds and numbers of objects:

  • Nine tables

  • Two views

  • Four indexes

  • Six foreign keys

  • Three functions

  • Five procedures

  • Three packages

  • Seven triggers

Appendix F, "Example Oracle database" on page 397 lists the definition of these objects. You also can download the code from IBM redbook Web site. The download information is provided in Appendix G, "Additional material" on page 415.

4.2.2 Creating/Opening a MTK project

When starting MTK, the Project management screen opens requesting the user to enter required and optional information for a new project or the ability to open a previously created object. When creating a new project the following information can be entered:

  • Project Name - Required. If a project name is not entered, it will default to Unknown. The Project Name given here will become the subdirectory name created on the operating system under the install directory of MTK. Therefore, the Project Name has to conform to the operating system naming standards that MTK is installed on.

  • Source Database - Required, choices include Sybase Enterprise, Microsoft SQL Server, and Oracle 8i.

  • DB2 target Platform - Required. Choices are DB2 UDB EE/EEE v7.2 or v8.1, DB2 UDB iSeries V5R2 or V5R3.

  • Project description - Optional.

Figure 4-1 shows the Project management screen with information completed for our Oracle migration project.

Click To expand
Figure 4-1: MTK Project management screen


4.3 Extracting or Importing metadata into MTK

Once the project is created, the Specify Source screen opens. During this task we will:

  • Specify how the metadata is obtained.

  • Obtain the metadata.

Figure 4-2 shows the Specify Source tab; on the left side of the screen are the buttons Import and Export.

Click To expand
Figure 4-2: The Specify Source tab

  • Import

    If a metadata file already exists (a script from SQL*Plus, or a third-party tool) and no data movement by MTK is required, then Import should be selected. Selecting this option will allow an individual DDL file or multiple DDL files from your file system to be selected and imported into MTK as the conversion source.

    Note

    When importing objects for conversion, it must be emphasized that some objects will not convert unless all of the objects on which it depends are also available within the imported file or files. For example, if you choose to import the source for an individual procedure, you must also ensure that you include all of the underlying definitions for tables that are referenced within that procedure. Also, you must ensure that the definitions for all dependent objects must precede the objects that rely on them. For example, definitions of tables referenced in stored procedures must precede the definition of the stored procedure.

  • Extract

    For our example conversion, we chose Extract. Choosing this option allows us to connect to the Oracle source system and extract all the metadata (DDL). This is accomplished by "reading" the system catalogs and then creating a file that will be imported into the tool. The extracted DDL, converted DDL and generated data movement scripts, and actual extracted data (during data movement) are defaulted to the server where MTK is installed, in the MTK installation subdirectory path.

    Note

    The Oracle source system to which MTK connects can either be on a local or a remote server. For a valid connection, it is required that the Oracle Client be installed and configured in the CLASSPATH on the local machine except for Windows systems when ODBC drivers are used.

After Extract is chosen, the Connect to Database screen opens, which requires that we complete the following information:

  • Service Name: The service name for the local/remote Oracle database

  • User ID: The User ID for the schema, which owns the Oracle source

  • Password: The Password for the schema, which owns the Oracle source

Figure 4-3 shows the Connect to Database screen completed for the service name oracle; the user ID ora_usr; and the corresponding password for the ora_usr schema.

Figure 4-3: Detail of the Connect to Database screen

4.3.1 Choosing objects to extract

After a successful connection to the database, the Extract screen opens. This screen shows Available objects (on the left side of the screen) and Objects to extract (on the right side of the screen). Once a schema is chosen, the Available objects will expand to show five categories of objects (Figure 4-4), even if the current database does not contain any objects of that category. The categories of objects are:

  • Tables

  • Views

  • Procedures/functions

  • Triggers

  • Packages

Click To expand
Figure 4-4: The Extract screen with the ORA_USR schema selected

Once a category is selected, if the plus sign (+) is chosen, the category expands to show the individual objects that exist for that category. From here it is possible to make various selections of objects to be extracted from each category. For example, it is possible to choose any of the following for extraction:

  • Individual objects from a single category (a single table, view, sequence, etc.)

  • Individual objects from a multiple categories (a table, a view, a sequence, etc.)

  • All objects from single categories (all tables, all views, all sequences, etc.)

  • All objects from multiple categories (all tables and all views, all sequences and all triggers, etc.)

  • All objects from all categories (the entire database schema)

Example 4-5 shows that multiple categories tables, views, and sequences are selected for extraction.

Click To expand
Figure 4-5: The Extract screen with tables, views and sequences selected

Figure 4-6 shows the Extract screen with the ORA_USR schema selected with the categories expanded to show individual objects in each category.

Click To expand
Figure 4-6: The Extract screen with schema and categories expanded
Note

When extracting objects for conversion, it must be emphasized that some objects will not convert correctly (or at all) unless all of the objects on which it depends are also extracted. For example, when selecting an individual procedure for conversion, you must take care to also extract all of the underlying definitions for tables that are referenced by that procedure, Or, choose the include other needed objects option on the Extract screen. When the include other needed objects option is chosen, MTK will automatically include all the pertinent definitions to correctly convert the selected objects. Also, MTK will extract the objects in correct dependent order.

4.3.2 Import or extract strategies

As previously stated, it is possible to choose one single object, or the entire database for extraction. Although it may seem initially attractive to choose the entire database, we recommend that the extraction strategy be dictated by the size of the source database.

Some aspects of database sizing in regard to MTK should be briefly mentioned here. The accurate sizing of a database, from a migration point of view, should entail thorough analysis on several different levels. This analysis yields the information such as the number of lines of code; the complexity of the code; the code conformance/non-conformance to ANSI standards; the number of objects; the types of objects - just to name a few.

One of the best uses of MTK is as an aid in engaging in the type of analysis. MTK can be used to find, in detail, much of the information that is required to successfully analyze the database.

With that said, a general and simplistic approach to sizing the database can be used in the initial stages of analysis. In the initial stage we might not have any information about, for example, complexity or conformance to ANSI standards. In order to gather that information we would have to arrive at some guidelines for beginning the analysis. The guidelines at this stage are usually along these lines:

  • Large database

    More than 200 stored procedures and functions (stand-alone or in Oracle Packages), and triggers.

  • Small database

    Less than 200 stored procedures and functions (stand-alone or in Oracle Packages), and triggers.

Large database

For large databases, the extraction strategy should focus on creating separate files for each individual category. For example, a separate extraction file should be created for all tables, sequences, views, triggers, procedures, and functions. This strategy will facilitate "tracking-down," analyzing, and perhaps "fixing" possible issues that may arise in the conversion of a particular category. This is usually easier than trying to understand several interrelated issues, which may arise across the whole spectrum of categories.

Small database

For smaller databases, we recommend that the extraction files be grouped according to dependencies and dependents. For example, one file may consist of all tables, views, and sequences; and another file of procedures, functions, packages, and triggers. In this strategy, the first file will allow the objects on which the second file depends to be created and analyzed before converting the second file. In this way, we are also able to contain the messages and the interrelated issues that may occur.

Sample conversion

Considering the size of our database, we choose to follow the recommendation for small databases. For our extraction, the first file will contain all tables, views, and sequences; a second file will contain all procedures, functions, packages, and triggers.

For the first file, all objects in the categories: tables; views; and sequences are selected and moved to the Objects to extract panel. For File name, we choose and entered tabs_views_seqs.src (Figure 4-7).

Click To expand
Figure 4-7: The Extract screen with tables, views and sequences selected

Once this is completed, we clicked the Extract button, and extraction of the metadata began (Figure 4-8).

Click To expand
Figure 4-8: MTK during the Extract process

After the first file is created, we repeated the process, this time selecting all procedures, functions, packages, and triggers. For this file we choose and entered the name: procs_pkgs_trigs (Figure 4-9).

Click To expand
Figure 4-9: The categories for the second Extract file

4.3.3 Viewing Extracted files

When extraction has completed, we are returned to the Specify Source tab. Figure 4-10 shows the Specify Source tab after the extraction that was just completed. In the right hand panel, the files that were created during the extraction of tab_views_seqs.src and procs_pkgs_trgs.src are visible.

Click To expand
Figure 4-10: The Specify Source tab after all extraction files have been created

We can examine the extracted files by choosing one and then clicking the View button located on the lower right side of the panel. In our example, when tabs_views_seqs.src is selected and then viewed, we see the following screen displayed (Figure 4-11).

Click To expand
Figure 4-11: Viewing extracted files in the Text Editor
Note

You can edit and save this file when it is viewed from this panel. This is sometimes useful for making changes to source code before it is to be converted.

The file was imported, the edited file is a copy in the project directory, and the original file will neither be changed nor damaged, and it can be re-imported in case of user errors during editing.
Note

You can use the default editor or set up your preferred editor through the menu bar selecting Applications -> User Preferences.


4.4 The Convert task

Once the extraction files have been created we proceed to the next task - Convert. On the Convert tab (Figure 4-12), there are a few requirements that need to be completed:

  1. Select the files in left-hand pane to be converted.

  2. Enter a prefix for the generated files (i.e., enter a name for the file that will be generated from the conversion).

  3. Select the Convert button to begin the conversion.

Click To expand
Figure 4-12: The Convert tab

In addition to the required fields, there are several options that may be chosen that will affect the contents of the generated conversion file:

  • Global Type Mapping

  • Advanced Options

  • Set Context

Global Type Mapping

If the Global Type Mapping button is selected, a screen opens (Figure 4-13) that allows some of the default MTK data type mappings to be changed. Only fields that have the "pad and pencil" icon are available to be edited. For example, the Date field in Oracle is typically mapped to Timestamp in DB2 UDB; in this screen it is possible to replace TIMESTAMP with DATE or TIME as the default mapping. It is important to remember that whatever data type mappings are altered, it will be applied to all objects in the entire project. It is not possible, from this screen, to set different data type for each individual object.

Click To expand
Figure 4-13: The Global Type Mapping screen

Advanced options

If the Advanced Options button is selected, a screen opens (Figure 4-14), which shows several features that will affect the content of the generated conversion file. The features are grouped into three categories:

  • General converter options

  • Converter options for tables, views, indexes

  • Converter options for procedures, functions, triggers

Click To expand
Figure 4-14: The Advanced Options screen

Most of the options pertain to whether the converted code will contain the Oracle source code, as comments, in the generated file. On this screen, the following options are checked by default:

  • Copy inter-statement source comments to the translated code.

  • Copy source (as comments) to the translated code.

  • Copy full source for procedures before their translation.

  • Copy source separately for statements in stored procedures.

Leaving the options checked generates a conversion file that contains all of the Oracle source code (as comments) along with the converted DB2 UDB code. When first using the tool, we recommend to leave the defaults checked. This will allow examination and comparison between the Oracle source and the DB2 target within the same file. Also, in many cases, the comparison serves as an excellent teaching tool for those who may not be familiar with the syntax of the DB2 SQL Procedure Language.

For our example, we retain all the defaults, but we also added the Translate tablespaces to DB2 option. Choosing this option causes the converter to include tablespace names that retain the names from the Oracle source code. The create tablespace statements are also added at the beginning of the script file. This is important for our sample porting project because we intend to deploy the converted objects into a DB2 UDB database that will contain tables, indexes, and blob/clob data in table spaces that have been created using these names. In the case where the table space mapping from Oracle to DB2 is different, the table space reference can be modified easily.

Once the options have been entered, we perform the following required steps:

  1. Choose the file to be converted: For our example, we choose tabs_views_seqs.src.

  2. Choose and enter a Prefix for generated files: For our example, we allowed it to default to the name of the currently selected file.

  3. Click the Convert button.

The conversion process now begins (Figure 4-15).

Click To expand
Figure 4-15: Executing the conversion

During the conversion, the message Please wait…Converting files… is displayed along with the elapsed time . Eventually the message will change to Please wait…Initializing Refine as the tool begins to automatically shift to the Refine tab.

Set Context

The context of a conversion means the source files that MTK will refer to when it begins its conversion. Choosing Set Context tab allows you specify source DDL file which contains other objects MTK needs for conversion. The detail is discussed in Section 4.9, "Converting the remaining objects" on page 122.


4.5 The Refine task

Once the conversion task has completed, by default, the tool automatically shifts to the Refine tab (Figure 4-16). The Refine tab is subdivided, on the lower left hand side of the left pane, into four separate sub-tabs titled Oracle, DB2, Report and Messages.

Click To expand
Figure 4-16: The Refine tab

  • Oracle

    This tab displays all of the objects from Oracle source script

  • DB2

    This tab displays all of the corresponding objects that have converted in DB2 UDB.

  • Report

    The Report view displays the message, sorted by database object. When you click the Report tab, the right panel displays the messages, grouped by message number, in decreasing order of importance. You can expand the source file in a tree view to display objects that contain messages. Often the same message will occur in many places. You can filter the messages that appear in the tree by clicking Hide message in the tree for each message you do not want to see. Click the button again to have the message reappear.

  • Messages

    The Messages view displays the messages, sorted by message category and number. When you click the Messages tab, the right panel displays the messages, grouped by message number in decreasing order of importance. You can expand a message category in a tree view to display the list of messages that occurred in the file.

4.5.1 Message categories and migration impact

As previously stated, the Messages view displays the messages sorted by message category. The message categories are:

  • Input Script Error

  • Translator Information

  • Translator Warning

  • Translator Error

Input Script Error

This message category occurs when the input script or set of objects to be converted is incomplete. Most frequently, messages in this category occur when an object is missing the definition for an object on which it depends. For example, a stored procedure, which refers to a table for which the definition is missing. Sometimes an object definition does exist, but its use may require qualification with a database or owner name. Other errors in this category include PL/SQL syntax errors.

Migration impact - LOW

Since this type of message is easily understood and corrected (usually by including the missing definition in the source file), the migration impact is low and has little bearing on the final product or on the level-of-effort to achieve that product.

This type of message occurs most frequently when files are taken into the tool through IMPORT. As can be expected, it is more likely that due to human error, an incomplete DDL may be gathered as the conversion source.

Translator information

This category occurs when a correct DB2 translation exists, but when more information is necessary to describe some unusual or exceptional property of the translation. For example, messages in this category are used to highlight the fact that the name of a PL/SQL object or identifier has been changed to satisfy the DB2 restrictions on identifier formation (such a change might be relevant to client programs that refer to the object by name).

Migration impact - LOW/MEDIUM

This type of message should be examined to understand the scope of the message. If the message indicates that an object name has been changed to conform to a DB2 specification - this may have little or no impact on the migration effort. If, however, the changes generated by the converter require alterations to the client code, the effort may be more extensive.

Translator Warning

This category occurs when the translation of the PL/SQL code to which the message refers might be incomplete or incorrect in certain unusual or exceptional cases. The message typically describes the circumstances in which the translation will not be correct.

Migration impact -MEDIUM

This type of message needs to be examined to determine if the circumstances described are relevant to your application. If so, manual intervention may be required to successfully convert and deploy the object.

Translator Error

This category is used for PL/SQL statements for which no translation is possible. Most frequently, this message category is used when no equivalent DB2 functionality exists. It is also used in cases where a correct translation requires application-specific information. It also occurs for certain complex or rarely used constructs.

Migration impact -HIGH

This type of error usually indicates that some degree of manual intervention will most likely be required. It is important that the analyst review the code to understand for which objects, and to what degree, the manual intervention will be necessary.

4.5.2 The Messages sub-tab

The messages sub-tab (Figure 4-17) is divided into left and right-hand panes. From these panes it is possible to perform the following actions:

  • View translator messages by message number

  • View the corresponding location in the Oracle source code to which a message pertains

  • View the corresponding location in the DB2 converted code to which a message pertains

  • Obtain additional information regarding a particular message

  • Search the source/converted code for a word or phrase

  • Go to a specified line number in the source/converted code

Click To expand
Figure 4-17: The Messages sub-tab

View Translator messages by message number

Figure 4-17 shows the Messages tab for our example. In this example, the messages are grouped into three categories:

  • Translator error

  • Translator warning

  • Translator information

For each category we can "drill-down" to a specific instance of a particular message. To accomplish this, follow these steps:

  1. Expand the category.

  2. Expand message number.

  3. Expand the message description.

View the source/converted code

Once the message description is expanded, if you highlight a specific instance of the message, the right-hand pane opens to the corresponding line in the Oracle source code to which the message refers. In our example (Figure 4-18), we open to the source code pertaining to message number 120, for the tabs_views_seqs file, at line numbers 9–14.

Click To expand
Figure 4-18: The Messages sub-tab opened to a specific line in the Oracle source

It is possible to toggle from the Oracle source code to the converted DB2 code by choosing from the right-hand pane, either the source file: <your_source_file_name.src> tab or the DB2 file: <your_conversion_file_name.db2> tab. In our example (Figure 4-19), we have toggled to the DB2 file: tabs_views_seqs.db2 from the Source file: tabs_views_seqs.src.

Click To expand
Figure 4-19: The DB2 file view for message 120

Additional message information

If we click the Message Help button in the upper right-hand corner of the Message sub-tab, the following screen opens (Figure 4-20). This help screen contains additional context sensitive information about the message number in question. In our example, the Message Help screen shows additional information regarding message 120.

Click To expand
Figure 4-20: Message Help screen displayed for message 120

4.5.3 Translator messages

The following section contains information regarding the messages that were generated for each category during our example migration. In our example, we received messages in the following categories:

  • Translator Error

  • Translator Warning

  • Translator Information

Translator Error messages

In the Translator Error category the following message occurred:

   Message 120: the CREATE SEQUENCE statement contains a value that is out of
   range

This message occurred for two objects; first for employee_sequence and again for office_sequence. Message Help indicates:

   The CREATE SEQUENCE statement contains a MINVALUE, MAXVALUE or START VALUE
   clause with a value that is outside the range that can be handled by the
   converter.

When the DDL is investigated, it is discovered that the statement:

   MAXVALUE 999999999999999999999999999

Contains a value that exceeds the maximum value allowed by DB2. If we toggle to the DB2 file: tabs_views_seqs.db2 we see that the converter has indeed made an adjustment so that the conversion will be accepted by DB2. The adjustment consists of changing the MAXVALUE to 9223372036854775807 - the largest possible size for a BIGINT value.

Translator warning messages

The following translator warning messages occurred:

   Msg number 20: object name has been changed to <new name>
   Msg number 34: No DB2 translation available, but statement has been taken
   into account.
   Msg number 59: Input ignored, not translated.

  • Message number 20

    There are four occurrences of message 20 in this category. The message descriptions state:

    Object name has been changed to M_DEPT_CODE_ACCT_1
Object name has been changed to EMP_RESUME_UK11051
Object name has been changed to EMP_PHOTO_PK110581
Object name has been changed to ACCOUNTS_DEPT_COD1

    Message Help indicates:

    Object names that are too long for DB2 are truncated. Names that are DB2
reserved words are enclosed in double quotes. Names that conflict with
other names in DB2 (because the name is already in use) are renamed.

    After examining the source code, we find that the names for the corresponding objects in Oracle, all of which are constraints, were:

    M_DEPT_CODE_ACCT_ID
EMP_RESUME_UK11058551798461
EMP_PHOTO_PK11058611148823
ACCOUNTS_DEPT_CODE_ACCT_ID

    For these objects, the converted truncated the constraint names to conform to the DB2 limit of 18 characters for constraints.

  • Message number 34

    There is one occurrence of message 34 in this category. The message description states:

    No DB2 translation available, but statement has been taken into account

    Message Help indicates:

    There is no DB2 translation available, but the information in the statement
will be used by the converter in translating the statements that follow.

    The Oracle source indicates that the message refers to the connection statement:

    CONNECT ORA_USR;

    The conversion indicates that although the connection statement is not expressly converted, the implications of the connection statement will be handled by DB2.

  • Message number 59

    There four occurrences of message 34 in this category. The message description states:

    Msg 59: Input ignored - not translated

    Message Help indicates:

    This input is ignored. It is not supported in DB2. This omission should not
cause the DB2 code to produce different results from the corresponding
Oracle code.

    The Oracle source indicates that the following statements contain references for creation in particular tablespaces:

    ALTER TABLE ACCOUNTS ADD CONSTRAINT
CREATE INDEX IND_DEPT_NAME
ALTER TABLE EMPLOYEES ADD CONSTRAINT
CREATE INDEX IND_OFFICE_BLD

    Specifying tablespaces for index and constraint creation, outside of the create table statement is not allowed in DB2. As indicated by the converter message however:

    This omission should not cause the DB2 code to produce different results
from the corresponding Oracle code

Translator Information messages

In the Translator Error category the following messages occurred:

   Message number 0
   Message number 108

  • Message number 0:

    There is one occurrence of this message in this category. The message description states:

    MTK Oracle Converter. Version: <mtk version>

    Message Help states:

    Specifies the version of the Oracle converter.

    This is a General Message displaying the MTK Oracle converter version.

  • Message number 108:

    There is one occurrence of this message in this category. The message description states:

    Translation Ratio: <percentage>% (<absolute ratio> statements were
translated successfully)

    Message Help indicates:

    This provides an assessment of the provided translation by giving the ratio
of Oracle statements translated without producing any error message out of
the total number of statements. This number is provides a general
indication regarding the success of the automated translation and does not
intend to give an exact and accurate measure.

Statement here designates Oracle SQL and PL/SQL statements. For instance,
in a CREATE PROCEDURE, the whole SQL statement is counted as 1 and each
PL/SQL statement inside the body of the procedure are also counted as one.

    This is a General Message displaying a ratio of Oracle statements translated without producing an error message. In this case it is 100%.

When examining messages on the refine tab it is possible to switch between the four sub-tabs (Oracle, DB2, Messages, and Report) to view varying types of information related to the messages. For example, if a message is selected on MESSAGES, switching to REPORT will show the other messages around the selected message. Likewise, switching from REPORT to MESSAGE will allow you to see the other instances of a message number. In addition, switching to ORACLE will allow you to see, and edit, the source code of the object generating the error message, and switching to DB2 will allow you to see the converted DB2 source for that same object.

4.5.4 Refining the metadata conversion

In addition to viewing the results of the conversion, the Refine step gives you the opportunity to make changes in the source code. It is possible, for example, to make changes to table or column names, stored procedure or function names or source code, or trigger source code. To apply any changes made during the refine process, however, you must return to the Convert step to apply these changes. After reconverting, the converter merges the refinement changes with the original extracted source to produce updated target DB2 code. The original source code is not changed. This convert-refine process may be repeated until you are satisfied with the results.

If issues still remain after the refine-convert process, consider the following: First, see if any further changes can be made to the source metadata. If this approach is no longer feasible, you can change the DB2 metadata.

Before making any DB2 changes, prepare a backup copy of the .DB2 file you intend to change, and rename the backup. It is recommended that you make your changes to DB2 after leaving the Refine step. Do not return to the Convert step after making any manual DB2 SQL changes. Conversion of the source metadata replaces the existing DB2 file, destroying any manual changes.

Once you have the DB2 source tuned to your satisfaction, you can either go to the Generate Data Transfer Scripts page to prepare the scripts for data transfer or go directly to the Deploy to DB2 page to deploy the DB2 metadata. Please note that If you do go directly from Refine to Deploy by skipping the Generate Data Transfer Scripts, then moving data will not be an option for you, neither online nor off-line.

Making changes to the DB2 source

In our example, we made a change to the definition of the Employees table by altering the DB2 target code. This alteration involves changing the EMP_ID column to an IDENTITY column. Here is our reasoning:

  • In the Oracle source the EMP_ID column is defined as INTEGER NOT NULL; the values for this column are automatically generated by a sequence (Employee_Sequence) that is activated by a trigger CreateEmployeeID. We intend to replace this functionality by creating the EMP_ID column as an IDENTITY column; this will allow the table to automatically generate values for the EMP_ID without the need for a sequence or a trigger.

Identity columns

Here is some information on IDENTITY columns from the DB2 UDB Application Development Guide:

  • Rather than using cumbersome insert and update triggers, DB2 enables you to include generated columns in your tables using the GENERATED ALWAYS AS clause. Generated columns provide automatically updated values derived from an SQL expression.

  • DB2 application developers often need to create a primary key for every row in a table. If you create a table that uses an identity column for the primary key, DB2 automatically inserts a unique value. When you use identity columns, your applications can benefit from increased performance due to a reduction in lock contention.

Identity column considerations

Since the Employees table will be loaded with data that includes EMP_ID values that were already generated by an Oracle sequence, we need to take care to:

  • Preserve the original values of EMP_ID currently in the Employees table.

  • Preserve the increment of the original sequence.

  • Generate new values that will not conflict with the current values in the column.

Identity Column syntax

Here is a brief explanation of the syntax for creating an IDENTITY column. Syntax:

   GENERATED BY DEFAULT START WITH numeric-constant, INCREMENT BY
   numeric-constant

Where:

  • GENERATED BY DEFAULT

    Indicates that DB2 will generate a value for the column when a row is inserted into the table, or updated, specifying DEFAULT for the column, unless an explicit value is specified. BY DEFAULT is the recommended value when using data propagation or doing unload or reload.

  • START WITH numeric-constant

    Specifies the first value for the identity column.

  • INCREMENT BY numeric-constant

    Specifies the interval between consecutive values of the identity column.

Here is the Oracle definition of the EMP_ID column in the Employees table:

   CREATE TABLE EMPLOYEES (EMP_ID INTEGER NOT NULL, …

Here is the column definition we will create for the DB2 target:

   CREATE TABLE EMPLOYEES (EMP_ID INTEGER NOT NULL GENERATED BY DEFAULT AS
   IDENTITY (START WITH ???, INCREMENT BY ???), …

To complete the column definition we need only:

  • Supply a starting value that will be greater than the current maximum EMP_ID value that is currently in the table. The best/easiest way of doing this is to:

    • Execute Select MAX(EMP_ID) from the Employees table;

    • Retrieve the result and set the START WITH VALUE equal to that value plus one. In our example the result of that process is 10011.

  • Duplicate the increment value (increment by 1) from the Oracle Employee_Sequence.

Here is the completed definition for the EMP_ID column in the Employees table:

   CREATE TABLE EMPLOYEES (EMP_ID INTEGER NOT NULL GENERATED BY DEFAULT AS
   IDENTITY (START WITH 10011, INCREMENT BY 1), …

Editing the DB2 target code

To edit the DB2 code, we returned to the Convert tab; select tabs_views_seqs.db2 in the right-hand pane and then click View Output File button. When the Text Editor opens (Figure 4-21), enter the changes and then select File -> Save to save the changes. This edited definition will now be used when the table is created in DB2 during the Deployment phase of the conversion.

Click To expand
Figure 4-21: Editing the EMP_ID column in the Text Editor


4.6 The Generate Data Transfer Scripts task

The next task in our conversion is the Generate Data Transfer Scripts tab. From this tab it is possible to:

  • Generate scripts to unload data from the Oracle database

  • Generate scripts to Import or Load data into DB2 UDB

This tab is separated into three panes: left, middle, and right. When first opened, the left pane shows all the tables in the Oracle schema that are being converted; the right pane shows the file that contains all of the converted DB2 code; the middle pane contains options that may be specified when data import or load is selected (Figure 4-22).

Click To expand
Figure 4-22: The Generate Data Transfer Scripts tab

Choosing Data Import or Load

The choice of whether to import or load data into DB2 UDB is usually dictated by the amount of data.

For small amounts of data, Import is usually sufficient. This method inserts data into a database table from an external file, inserting one row at a time. During the import of data, the table remains accessible to other applications. All applicable constraints and triggers remain in effect, and are activated in the usual way as rows are inserted.

For large amounts of data, LOAD is usually preferable. The LOAD utility constructs page images containing many rows and inserts them into the database one page at a time. It requires exclusive access to the tablespace being loaded. During the loading of data, the tablespace that contains the table is not accessible to other applications. Applicable constraints and triggers are deactivated for the duration of the load. Applicable check constraints and foreign key constraints are enforced at the end of the load process. The enforcement of business rules that are implemented by triggers are not guaranteed after the load completes.

During load and import, MTK will disable the referential integrity. MTK deletes the foreign keys before load and import, and re-create them after.

Import or Load options

The following options are available for Import or Load:

  • MODE:

    • INSERT: IMPORT will insert new rows without affecting the existing content.

    • REPLACE: IMPORT will delete all existing data and replace it with the imported data.

  • File Formats:

    • DEL: delimited ASCII format

      Specifies that the data is represented in delimited text files. These files contain streams of data values, ordered by row, and then by column. Column delimiters separate the values (a comma is the default), and new line characters separate the rows. Character strings are enclosed in string delimiters (a double-quote is the default). NULL values are represented by nothing between the column delimiters for a particular column.

      If DEL is selected, some advanced options are automatically set by the IBM DB2 Migration Toolkit:

      • Character delimiter first: The character delimiter is given the highest priority, so that a special character between two character delimiters will be read as just another character.

      • Column delimiter: Set to a comma (,).

      • Character string delimiter: Set to a double quote (").

        Note

        During extraction, MTK doubles any string delimiter found within a string. This allows the use of any string delimiter without a problem. There is no need to search the database for a character never used in the data.

  • ASC: non-delimited ASCII format

    This format specifies that the data is represented in non-delimited text files, which have the columns of data in fixed positions. No delimiters are needed. Nulls are identified by a table of null value indicators at the end of the row.

    If ASC is chosen, MTK sets the record length advanced option. Instead of new line characters marking the end of each record, the length of the data is used to set the number of characters read for each row.

    Note

    For complete information about Import or Load options, please refer to the manual(s): IBM DB2 Universal Database Data Movement Utilities Guide and Reference (version 7), SC09-2955, or (version 8), SC09-4830.
Advanced Import or Load options

When the Advanced Options button is clicked, a screen opens that displays the options for the data movement that you have selected (Import or Load). Figure 4-23 shows the screen opened with the options available for Load. One parameter which we would like to bring to your attention is the message file. DB2 writes the output of Import and Load to the message file specified here. The default is message.txt in /tmp directory on UNIX and c:/temp on Windows.

Click To expand
Figure 4-23: Advanced Options screen for LOAD

4.6.1 Creating unload and load scripts

For our conversion we chose to load the data into DB2; all the defaults will be taken:

  • MODE: insert

  • File format: ASC non-delimited ASCII format

  • Directory for data extraction: MTK default

  • Advanced Options: none

Figure 4-24 shows the screen after the Create Scripts button is clicked, and scripts have been generated.

Click To expand
Figure 4-24: The Generate Data Transfer Scripts screen after scripts generated

4.6.2 Files generated by the Generate Data Transfer Script task

After the Create script button is clicked on the Generate Data Transfer Scripts task, the following files are created:

  • DataMove_your_file_name_data.bat

  • DataMove_your_file_name_data.sh

    The files ending in _data.bat, or _data.sh contain statements to extract data from the source database.

  • DataMove_your_file_name.qry

    The file ending in .qry contains examples of statements generated for selecting and converting the data from the source database.

  • DataMove_your_file_name_db2.bat

  • DataMove_your_file_name_db2.sh

    The files ending in _db2.bat, or _db2.sh contain statements to execute the load data into DB2.

  • DataMove_your_file_name.bat

  • DataMove_your_file_name.sh

    The files ending in .bat, or .sh contain DB2 load scripts.

For our example, the following scripts were created:

  • DataMove_tabs_views_seqs_data.bat

  • DataMove_tabs_views_seqs _data.sh

  • DataMove_tabs_views_seqs.qry

  • DataMove_tabs_views_seqs _db2.bat

  • DataMove_tabs_views_seqs _db2.sh

  • DataMove_tabs_views_seqs.bat

  • DataMove_tabs_views_seqs.sh

    Note

    In there are cases where not enough resources may be available on one machine, you might decide to convert and refine the metadata in a convenient location, such as on your desktop workstation, and later go to the server system to migrate the large amount of data. For these reasons, it is also possible to manually extract the data from the source, and load/import the data into DB2 using the scripts created in this task. Read the MTK documentation for more information.
Note

In addition to generating data movement files, MTK also generates the online data movement functionality "on the fly" from within the tool itself so that if you choose to move the data on-line within the GUI within the Deploy tab, the MTK tool knows how. That is why if you skip from the Refine tab to the Deploy tab, you will not have an online option of extracting and loading data; these options will remain in a "grayed out" state.


4.7 Deploy to DB2

From the Deploy task, it is possible to perform the following actions:

  • Have MTK Create (or recreate) a local database

  • Deploy the converted objects into a local or remote database

  • Extract and store data from the source database

Figure 4-25 shows the deployment screen.

Click To expand
Figure 4-25: The MTK Deploy to DB2 task screen

4.7.1 Considerations

Before you start the DB2 deployment, you should consider:

  • Database creation: Manually or by MTK

  • Objects deployment strategy

  • Database access

MTK database creation

If you choose to deploy to a database that is remote to the system on which the toolkit is running, then you cannot choose to create a new database during deployment. The database must first be created on the remote system and registered in the local catalog. See CATALOG DATABASE in the DB2 Command Reference for more information

If you plan on deploying to a database that MTK will create locally, then the following information is important:

  • When MTK creates the database, a bufferpool with pages of size 32 KB and three tablespaces of the same size is created.

    These provide enough space for the deployment of tables with any row length. Before launching the database into production, perform some performance tuning and adjust the size of the bufferpool as necessary.

  • When choosing MTK to create your database, only System Managed Tablespaces (SMS) can be created. If your database design requires that tables, indexes, or BLOB data be deployed into their own tablespaces, then you must use Database Managed Tablespaces (DMS). In this case, the database should be created (either locally or remotely) before the objects are deployed into it.

Deploying Objects: Extracting and deploying data

There are a few considerations for deploying objects and data depending on your environment and requirements:

  • When deploying to a local system, (Re)create must be selected unless you want to add the objects and data to what already exists on the database.

  • The converted objects and data can be deployed to DB2 at the same time or separately. For example, you might want to load the metadata during the day along with some sample data to test your procedures. Then, you can load the data at night when the database has been tested and when network usage is low.

  • You can deploy the database locally or to a remote system. No prerequisites exist for deploying the database locally. If you choose to deploy to a remote system, you can:

    • Specify that the IBM DB2 Migration Toolkit access the remote database directly. See the section "Considerations for remote database access" on page 116.

    • Copy the IBM DB2 Migration Toolkit and the project directory to the system running DB2 and then deploy the database locally.

  • If you are familiar with DB2 on operating systems other than Windows NT, the batch files can be modified to accommodate deployments on those systems. Ensure Java 1.3.0 is installed on the system, copy over the mtk.jar file and the batch files, and run the batch files.

  • Special consideration for large objects (BLOBS, CLOBs) should be made if there are many of them. When they are extracted, each individual LOB data type is put into its own file. Tables with many LOBs can create thousands of external files and supporting subdirectories for them. That means a file system can run out of directory space long before running out of actual mount point space. So, space planning for temporary data files during data movement of tables with these large objects should be carefully considered.

  • The Import and Load utilities use the memory area controlled by database parameter util_heap_sz. Medium to large table processing could benefit from a bump up in memory space if it is available on your server.

Considerations for remote database access

If you need to access database remotely during migration, please consider the following:

  • Make sure that the data extracted from the source database is of a type that is specific to the target DB2 database that is deployed in this step. Do not attempt to load the data into a database created by other means.

  • Ensure that you have not modified the conversion since the last time you have extracted data. You should extract and deploy the data only after the final conversion.

  • Make certain that any data that is being deployed is first extracted to the file system where the IBM DB2 Migration Toolkit is installed, and then it is loaded into DB2. If the table contains millions of rows, ensure the filesystem can accommodate the size of the largest object in the source database. On UNIX filesystems, you can modify the file size limit by using the ulimit command.

  • If you choose to deploy to a system that is remote to the system on which the toolkit is running, then you cannot choose to create a new database during deployment. The database must first be created on the remote system and registered in the local catalog. See CATALOG DATABASE in the DB2 Command Reference for more information.

  • Data cannot be loaded into LOB columns during remote deployment. The LOBPATH parameter in the LOAD or IMPORT command must refer to a directory on the DB2 server. You can load data into LOB columns by moving the generated scripts to the target machine and running them on the desired DB2 server (see Chapter 6., "Data conversion" on page 211).

  • During deployment, the connection to DB2 uses a Java native driver, not ODBC. If you encounter problems when connecting remotely (such as a "no suitable SQL driver" error), ensure the following directory and files are in the Java CLASSPATH:

    • %DB2PATH%/java/db2java.zip;

    • %DB2PATH%/java/runtime.zip;

    • %DB2PATH%/java/sqlj.zip;

    • %DB2PATH%/bin

4.7.2 Deployment strategy

The deployment information for the objects that were just converted is as follows:

  • The target database has been created and resides on a remote Linux server:

    • The database is designed with SMS table spaces. The tables will be stored in specified table space. The indexes and BLOB data will be stored in the table space where the associated table is placed.

    • The database has been cataloged, i.e., a connection can be made from the source system (AIX) to DB2 on the target system (Linux).

  • The Oracle data will be extracted onto the AIX machine where Oracle and MTK are installed.

  • All of currently converted objects will be created on the target DB2 UDB database.

  • The Oracle data will be loaded into DB2.

To follow the plan outlined above, we need to complete the required information on the Deployment screen:

  • DB2 database name

    db2_emp

  • Use remote database

    Selected

  • Use your system current user ID and password

    Unselected

  • User ID

    db2inst1

  • Password:

    Enter your password

  • Launch tabs_views_seq.db2 in the database

    Selected

  • Extract and store data on this system

    Selected

  • Load data to target database using generated scripts

    Selected

Figure 4-26 shows the Deploy to DB2 screen completed with all of the above information.

Click To expand
Figure 4-26: The Deploy to DB2 screen with deployment information entered

Once the deployment options are completed, we clicked the Deploy button and the deployment begins.

Deployment of Java and SQL User-Defined Functions

During deployment, MTK will automatically install JAVA and SQL User-Defined Functions (UDF). A schema called ORA8 will be specifically created to contain these functions. These UDFs are provided to simulate Oracle functions that do not have exact DB2 equivalents. The UDFs are programmed in SQL where possible but, in some cases, it is necessary to implement them in Java.

The installation of these functions in a database involves one to two files for every MTK target:

  • A script file (mtkora8.udf): containing a template for SQL UDF's source code

  • A JAR file (ora8UDFs.jar): containing the source code for Java UDFs

These files can be found in the directory where MTK was installed. That directory will also contain a script to drop all of the functions created by the mtkora8.udf script, mtkora8drop.udf, should it be necessary to drop these functions.

During deployment, the following takes place with these JAR and script files:

  1. In the mtkora8.udf file

    The JAVA CREATE FUNCTION statements are altered to specify the database under which the jar will be installed, such as:

    Portion of the original file:

       CREATE FUNCTION ORA8.jversion()
    RETURNS varchar(15)
    EXTERNAL NAME
    'ora8.udfjar:com.ibm.db2.tools.mtk.mtkora8udf.Ora8UDFsv2.jversion'

    After alteration:

       CREATE FUNCTION ORA8.jversion()
    RETURNS varchar(15)
    EXTERNAL NAME
    'ora8.db2_emp:com.ibm.db2.tools.mtk.mtkora8udf.Ora8UDFsv2.jversion'

    The altered version of this file is then placed in the PROJECTS directory under a subdirectory corresponding to your project name, for example:

         PROJECTS/MY_MTK_PROJECT/ mtkora8.udf.

  2. The ora8UDFs.jar file is installed in the database with the following command:

       CALL
   SQLJ.INSTALL_JAR('file:/home/db2inst1/mtk/ora8UDFs.jar','ora8.db2_emp')

    Once the jar file is installed on UNIX, it can be found in the following directory:

       DB2INSTHOME/sqllib/function/jar/ORA8/

The DEPLOY_YourProjectName_Udf.log file will contain all the information regarding the success, or failure, of UDF deployment in your environment. It is recommended that this be examined to determine if UDF has been successfully deployed. A successful deployment will return the following message:

   Creation of MTK UDFs...
   CALL
   SQLJ.INSTALL_JAR('file:/home/db2inst1/mtk/ora8UDFs.jar','ora8.db2_emp')
   DB20000I    The CALL command completed successfully.

If any other message is returned, you should verify the suitability of your DB2 Java environment.

4.7.3 Deployment results

When the deployment process has completed the Verification report opens. This report will give a clear indication of the status of your conversion project. It shows:

  • The number of objects in the source file.

  • The number of objects successfully deployed into DB2.

  • The number of objects missing from DB2.

    Objects missing from DB2 appear in red; they usually indicate some error during deployment. A warning message is presented in purple and a successful deployment item is shown in black.

  • The number of foreign keys found in DB2

  • Information about Unique, Primary, and Check constraints

  • The name of an object in the source and the name as it appears in the DB2 database

  • The DB2 schema into which it was deployed

  • The type of object

  • Whether a specific object was successfully deployed into DB2

  • Whether data was successfully extracted from the source

  • Whether data was successfully loaded into DB2

Figure 4-27 shows part of the Verification report for our conversion example.

Click To expand
Figure 4-27: The Verification report

Additional information about the conversion may be found in the Deploy_your_file_name.log, or by choosing other reports for this conversion from the Verification report screen, or by selecting Tools ->Migration reports on the MTK menu bar. You can navigate to the reports for the current or previous migrations using the contents listing in the left frame of the browser window.

The name and information for each report is as follows:

  • Conversion summary report

    The conversion summary report presents details on a particular conversion. You will most likely have many conversions during your migration of each database. You can view each of the conversion reports and compare the objects that were successfully converted, as well as various errors reported each time.

  • Translation error message reports

    The error message reports detail the specific error messages found during each translation. One report presents the messages by object and the other by message. These reports can be handy when determining how to prioritize your work, for example, if the same error exists for many objects it might be a good idea to solve that problem first. Or, when viewing the messages by category, you might choose to overlook the translator information messages until the omissions are taken care of.

  • Estimate of table size report

    The table size estimates are presented in this report to help you determine what kind of tablespace adjustments you might have to make.

  • Large statement warnings report

    During conversion some statements are too long to be properly handled. The large statement warnings report lists each of the statements that cannot be converted.

  • Verification report and deployment log

    The verification report and deployment log are generated to present to you any problems that might have occurred during deployment. If during deployment you specified in-context files, which contain objects that have not yet been deployed into DB2, both the report and log will show that the in-context files failed to deploy. Objects in in-context files are not deployed. This behavior is as designed.


4.8 Next steps

We have just completed the first part of our migration, i.e., converting all of the objects upon which the other objects (stored procedures, functions, packages, and triggers) depend. Based on information from the Verification report, we can declare success since all of the tables, views, and sequence objects from the original Oracle database were converted, and more importantly, were deployed correctly into DB2 UBD. We can also see that the data was extracted from Oracle, and that the same number of rows were loaded into DB2. We are now ready to begin the process of converting the stored procedures, functions, packages, and triggers.

Strategy

The strategy for the remainder of the project is:

  • Convert the remaining objects

  • Examine and evaluate the messages from the translator

  • Deploy the remaining objects into DB2

  • Manually convert objects that are not automatically converted by MTK


4.9 Converting the remaining objects

To convert the remaining objects we return to the Convert tab. Since the converter needs the definitions for the converted tables, sequences, and views to correctly convert the remaining objects, we use them as context for the next part of the conversion. To specify objects as Context files, we do the following:

  • Click Set Context on the Convert tab.

  • The Set Context screen will open displaying two panels. In the left panel it reads Source Files. Under Source Files all of the .src files that have been extracted from the source will be shown. In the right pane it reads Selected context files. When first opened, there will be no files indicated under this heading.

  • To select files as context files, choose one (or several) in the right hand panel and then select >. This will bring the file into the Selected context files panel. Figure 4-28 shows the screen for our conversion after having selected tabs_views_seqs.src as a context file.

    Click To expand
    Figure 4-28: The Set Context screen after a file has been selected as Context.

Once the context selections have been made, clicking the OK button returns us to the Convert tab.

On the convert tab, we can now see that the tabs_views_seqs.src file has the indication (context) beside it. This specifies that the file is now a context file and will not be reconverted.

To begin conversion, complete the required steps:

  1. Select the files in left-hand panel that will be converted. We choose the procs_pkgs_trgs.src file.

  2. Enter a prefix for the generated files (i.e., enter a name for the file that will be generated from the conversion). We accept the default.

  3. Click the Convert button to begin the conversion.

Figure 4-29 shows the Convert Tab, before conversion, with all required steps completed.

Click To expand
Figure 4-29: The Convert tab - context file indicated and the remaining file selected

4.9.1 Translator messages

In this section, we discuss the messages for the conversion of stored, procedures, functions, packages, and triggers. Although messages from the previous conversion file will still be available for viewing, our discussion will not include such messages. During examining the messages, if we find items which need to be convert manually, we will "mark" it as manual conversion items. These items will then be discuss further in this chapter.

Figure 4-30 shows the Refine tab after the conversion of the procs_pkgs_trigs.src file. We received messages in the following categories from our conversion:

  • Input Script error

  • Translator Error

  • Translator Warning

  • Translator Information

Click To expand
Figure 4-30: The Refine tab after the conversion of procs_pkgs_trigs.src

Input Script Error messages

The following message occurred in the Input Script Error category:

   Message 11: Reference to unknown cursor: pRow

This message occurs once, and it refers to the stored procedure Selectrow. Message Help indicates:

   The translator is not aware of the definition of this object.
   Ensure the definition exists in the data source file. Also, ensure the
   schema name is specified as indicated.

When the statement is investigated, we recognize that pRow is an Oracle Reference Cursor. The conversion of Reference Cursors to the corresponding DB2 UDB functionality will have to be converted manually. We mark this in project plan for manual conversion and move on.

Translator Error messages

We have three Translator Error messages:

  • Message 21

    Fourteen instances of message 21 occurred in the Translator error category:

       Message 21: Call to Procedure DBMS_SQL.PARSE is not supported
   Message 21: Call to Procedure DBMS_SQL.DEFINE_COLUMN is not supported
   Message 21: Call to Procedure DBMS_SQL.COLUMN_VALUE is not supported
   Message 21: Call to Procedure DBMS_SQL.CLOSE_CURSOR is not supported
   Message 21: Call to Procedure DBMS_SQL.BIND_VARIABLE is not supported
   Message 21: Call to Procedure DBMS_SQL.OPEN_CURSOR is not supported
   Message 21: Call to Procedure DBMS_SQL.FETCH_ROWS is not supported
   Message 21: Call to Procedure DBMS_SQL.EXECUTE is not supported

    The fourteen instances of this message all refer to the same object, the stored procedure EmployeeDynamicQuery. Message Help indicates:

       This Oracle function or procedure call is not translated to DB2.

    When the procedure is analyzed, we recognize that it contains references to Dynamic SQL that is implemented through the Oracle DBMS_SQL package. Dynamic SQL can be easily converted into DB2 UDB functionality, but the conversion will have to be done manually. We mark this procedure for manual conversion and continue.

  • Message 75

    Two instances of message 75 occur in the Translator error category:

       Message 75: This statement is not supported in a DB2 Before Trigger

    The first instance of this message occurs in relation to the trigger InsertEmployee, the second for the trigger ManagersChange. Message Help indicates:

       This statement is not supported in a DB2 Before Trigger.
   The following statements are not supported in this context: INSERT,
   DELETE and UPDATE.

    After examining the triggers, we can see that they include DML statements. DML statements are restricted in before triggers in DB2 UDB. The conversion of this is also not complicated, but will also have to be done manually.

  • Message 80

    This message occurs once in the Translator error category:

       Message 80: This package item is not translated.

    This message occurs in relation to the Package object REFPKG. Message Help indicates:

       Only the following items are supported inside a package: function
   specifications, functions, procedure specifications, procedures, and
   constants. Variable declarations, cursor declarations and type
   definitions are not translated.

    After examining the source code, we understand that although this package item will not be converted, it will not be necessary in our conversion. First, because MTK converts Oracle schema in the recommended manner, i.e., by converting the Oracle Package name to a DB2 Schema name. Second, because the package item, a reference cursor will be managed when the procedure SelectRow is converted manually.

Translator Warning Messages

In the following are Translator Warning messages we received:

  • Message 20

    15 instances of Message 20 occurred in the Translator Warning category:

       Message 20: Object name has been changed to <new name>.

    This message pertains to the following objects (Table 4-5).

    Table 4-5: Message 20 objects

    Source object name

    Conversion name

    Object type

    ACCT_ID

    ACCT_ID1

    Correlation name

    BAND

    BAND

    Correlation name

    c_RegisteredEmployees

    c_RegisteredEmplo1

    Cursor name

    DEPT_CODE

    DEPT_CODE1

    Correlation name

    EMP_MGR_ID

    EMP_MGR_ID1

    Correlation name

    EmployeesOfficesInsert

    EmployeesOfficesI1

    Trigger (insert)

    ManagersChange

    ManagersChange_FO1

    Trigger (insert)

    ManagersChange_FO2

    Trigger (delete)

    ManagersChange_FO3

    Trigger (update)

    office_summary_delete

    office_summary_de1

    Trigger

    UpdateDepartments

    UpdateDepartments1

    Trigger (insert)

    UpdateDepartments2

    Trigger (delete)

    UpdateDepartments3

    Trigger (update)

    UpdateEmployees

    UpdateEmployees_F1

    Trigger (update)

    Message Help indicates:

       Object names that are too long for DB2 are truncated. Names that are DB2
   reserved words are enclosed in double quotes. Names that conflict with
   other names in DB2 (because the name is already in use) are renamed.

    Upon examination of the source code, we observed that names were altered for three types of objects:

    • Triggers

      • Reason:

        Trigger names were changed in two cases. The first case was because the trigger name exceeded the maximum number of characters (18) allowed, as in the case of EmployeesOfficesInsert and office_summary_delete. In this case, the names were truncated to conform to the standard. In the second case, additional triggers needed to be created. This occurs when an Oracle trigger specifies more than one operation (INSERT, UPDATE, DELETE) for the source trigger. In this circumstance, DB2 requires and MTK creates an individual trigger for each operation.

    • Cursors

      • Reason:

        Cursor names cannot exceed 18 characters

    • Correlation names

      • Reason:

        Renaming these variables is related to a message that is best explained by the Message Help from message 71:

        DB2 does not accept references to OLD from an inserting trigger or
references to NEW from a deleting trigger. In the WHEN clause of the
trigger these references are translated to NULL. In the body of the
trigger they are translated to a variable generated for this purpose.

  • Message 34

    Four instances of message 34 occurred in the Translator warning category:

       Message 34: No DB2 translation available, but statement has been taken
   into account

    The four instances occur in relation to the following statements:

    • CONNECT ORA_USR

    • In the Create Package AccountPackage statement for:

      • Create Procedure AddEmployee

      • Create Procedure RemoveEmployee

      • Create Procedure AccountList

    Message Help indicates:

       There is no DB2 translation available, but the information in the
   statement will be used by the converter in translating the statements
   that follow.

    After examining the source we understand that:

    • Regarding CONNECT ORA_USR, the message indicates that although the connection statement is not expressly converted, the implications of the connection statement will be handled by DB2. ORA_USR will be used as the default schema for unqualified database objects names

    • Regarding the Create Procedure statements, we recognize that Oracle packages will be converted to objects within a specified schema. This schema name will be the same as the original Oracle Package name.

  • Message 47

    Four instances of message 47 occurred in the translator warning category:

       Message 47: BEFORE translated to NO CASCADE BEFORE

    The four instances of this message occur for the following triggers:

    • CreateEmployeeID

    • InsertEmployee

    • ManagersChange

    • UpdateEmployees

    Message Help indicates:

       Oracle triggers using the BEFORE event type are translated in DB2 by NO
   CASCADE BEFORE triggers. This type of trigger does not allow other
   triggers to fire from the trigger body, which might lead to incorrect
   behavior.

  • Message 50

    Two occurrences of message 50 occurred in this category:

       Message 50: This statement is not supported in a DB2 dynamic compound
   statement

    The two occurrences of this message are both in regard to a cursor created in the trigger UpdateDepartments. Message Help indicates:

       This statement is not supported in a DB2 dynamic compound statement.
   Dynamic compound statements are used as bodies for top-level anonymous
   blocks, user-defined functions, and triggers. Procedures use DB2
   compound statements as bodies that are less restrictive. Some statements
   that are not allowed inside a DB2 dynamic compound statement are:
   - Nested blocks
   - Statements containing CASE expressions
   - GOTO
   - Procedure calls
   - Cursors
   - COMMIT
   - Exception handlers

    Since this type of cursor statement is not allowed inside of a trigger in DB2, we will need to manually convert the cursor logic. We marked the object for manual conversion and continued.

  • Message 61

    Two occurrences of message 61 occurred in this category:

       Message 61: Parameter defaults are not supported in DB2 procedure
   definitions. Calls to the procedure are adjusted accordingly.

    The two occurrences of message 61 relate to the procedure EmployeeDynamicQuery. Message Help indicates:

       In procedure and function declarations, the optional DEFAULT value of a
   parameter is not translated, but the translator will use the value as
   necessary through the remainder of the translation.

    Additional information adds the following explanation:

       DB2 does not support default values for procedures and function
   parameters. Default values for parameters are not translated in the
   parameter list, but the converter remembers them and adds them to each
   procedure call when the corresponding argument is missing.

  • Message 71

    There are two occurrences of message 71 in this category:

       Message 71: Reference to OLD or NEW column translated to <NULL or
   variable>

    The two occurrences of this message relate to the ManagersChange trigger. Message Help indicates:

       DB2 does not accept references to OLD from an inserting trigger or
   references to NEW from a deleting trigger. In the WHEN clause of the
   trigger these references are translated to NULL. In the body of the
   trigger they are translated to a variable generated for this purpose

    This message is related to warning message 20 that was also received in this category.

  • Message 94

    There are two occurrences of message 94 in this category:

       Message 94: The function <function_name> is translated to DB2 as a
   Procedure.

    This message refers to the functions MaxProjects and AverageBand. Message Help indicates:

       This Oracle user-defined function is translated to DB2 as a procedure.
   This happens with functions with parameters in OUT mode. Since this
   feature is not available in DB2, the translator uses a DB2 procedure
   instead. The calls to the Oracle function will be translated
   accordingly, they will become procedure-calls.

Translator Information

The Translator Information received in our conversion example are:

  • Message 0

    There is one occurrence of this message in this category:

       Message 0: MTK Oracle Converter. Version: <mtk version>

    Message Help indicates:

       Specifies the version of the Oracle converter.

    The version number of the converter is specified.

  • Message 108

    There is one occurrence of this message in this category:

       Message 108: Translation Ratio: <percentage>% (<absolute ratio>
   statements were translated successfully)

    Message Help indicates:

       This provides an assessment of the provided translation by giving the
   ratio of Oracle statements translated without producing any error
   message out of the total number of statements. This number is provides a
   general indication regarding the success of the automated translation
   and does not intend to give an exact and accurate measure.

   Statement here designates Oracle SQL and PL/SQL statements. For
   instance, in a CREATE PROCEDURE, the whole SQL statement is counted as 1
   and each PL/SQL statement inside the body of the procedure are also
   counted as one.

    The translation ratio is reported as 85.94% - 110 of 128 statements were translated successfully.

4.9.2 Status

Before beginning the deployment task, let us take the time to evaluate the information that was just gathered. The most important aspect at this point of the conversion is to make sure that we understand all of the messages and all of the implications of the messages from each Translator message category. This evaluation will give us a fair idea of what we can expect as our final result, such as how many objects will successfully deploy into DB2.

Given the information we have collected about the objects from our conversion, we expect that most of the objects will deploy successfully. We expect however that after the completion of deployment that the Verification Report will indicate several objects did not deploy successfully. We expect that the following objects will be in that category, and that manual intervention will be required before they can be successfully deployed:

  • Stored procedures:

    • SelectRow

    • EmployeeDynamicQuery

  • Triggers:

    • InsertEmployee

    • ManagersChange

    • UpdateDepartments


4.10 Deployment of the remaining objects

We will skip the Generate Data Transfer Scripts task since we have already created scripts, extracted data, and loaded the data into DB2 in the earlier part of our conversion. Now let us focus on deploying the stored procedures, functions, packages, and triggers into our DB2 database.

During this phase, we will deploy the procs_pkgs_trgs.db2 file. This file is selected and the following required information is completed on the screen:

  • DB2 database name:

    Db2_emp

  • Use a remote database:

    Selected

  • User ID

    db2inst1

  • Password

    Enter db2inst1 password

  • Launch procs_pkgs_trgs.db2 in the database

    Selected

Figure 4-31shows the deployment screen before the Deploy button is clicked.

Click To expand
Figure 4-31: The Deployment screen before launching procs_pkgs_trgs.db2

4.10.1 Verification report

After deployment has completed, MTK will again open to the Verification Report ( Figure 4-32 ). It is important to remember that the information given by Verification Report is cumulative, such as the total number of items calculated will include objects from both parts of the conversion (tables, and procedures, etc.).

Click To expand
Figure 4-32: The Verification Report showing the tally of deployed objects

The information on the top of the report shows that of the 58 total objects in the conversion, 48 were successfully deployed.

We also can see that 10 objects are missing from DB2, i.e., were not successfully deployed. We selected the link 10 objects missing from DB2 from which we can see that the following objects are missing (Figure 4-33):

  • Procedures:

    • EmployeeDynamicQuery

    • SelectRow

  • Triggers:

    • CreateEmployeeID

    • InsertEmployee

    • ManagersChange: Three triggers one each for Insert, Update, and Delete.

    • UpdateDepartments: Three triggers one each for Insert, Update, and Delete.

Click To expand
Figure 4-33: The Verification Report showing objects missing from DB2

We expected that most of the items on this list would fail deployment for reasons that we previously noted. The only surprise here is the trigger CreateEmployeeID.

Upon inspection, we understand that the failure of this object to Deploy is actually irrelevant. This is because the generation of Employee IDs (the EMP_ID) column in the Employees table is now being implemented through an IDENTITY column; see "Identity columns" on page 106. This functionality replaces the necessity for the creation of the CreateEmployeeID trigger.


4.11 Manual conversion for ORA_EMP database objects

To this point, the conversion of all objects that are capable of being successfully converted and deployed automatically into DB2 by the IBM DB2 Migration Toolkit (MTK) is done. Indeed, the majority of the object and data conversions have been accomplished. Yet, there are still some "loose-ends" such as objects that we noted for manual conversion that must be dealt with.

The triggers and procedures in our example OR_EMP database, which will be converted manually are:

  • Triggers:

    • InsertEmployees

    • ManagersChange

    • UpdateDepartments

  • Procedures:

    • SelectRow

    • EmployeeDynamicQuery

These triggers and procedures use Oracle features, which either implemented differently in DB2 UDB, or are not supported by DB2 UDB, and can be converted by using other DB2 UDB features, or changing the logic. In this section, we show you the feature differences, how to convert these triggers and procedures from Oracle to DB2UDB, and how to deploy these objects to DB2 UDB.

4.11.1 Triggers

Both Oracle and DB2 UDB have triggers features. There are some differences in the implementation of triggers in these two database. Therefore, the manual conversion is required. In this section, we discuss the triggers conversion and deployment process using three examples:

  • InsertEmployees

  • ManagersChange

  • UpdateDepartments

Example 1: InsertEmployee

The conversion of the InsertEmployee trigger requires that the BEFORE trigger be converted to an AFTER trigger. This is necessary since DB2 does not permit any insert, update, or delete activity in a BEFORE trigger.

Oracle source

Example 4-7shows the Oracle source code of InsertEmployee. This trigger uses BEFORE INSERT which needs conversion.

Example 4-7: Trigger InsertEmployee Oracle source code
Start example
CREATE TRIGGER InsertEmployee
  BEFORE INSERT ON employees
  FOR EACH ROW
DECLARE
  v_num_projects accounts.num_projects%TYPE;
BEGIN
  SELECT num_projects
    INTO v_num_projects
    FROM accounts
    WHERE dept_code = :new.dept_code
    AND acct_id = :new.acct_id;
  UPDATE accounts
    SET current_employees = current_employees + 1
    WHERE dept_code = :new.dept_code
    AND acct_id = :new.acct_id;
END InsertEmployees;
End example
DB2 conversion

Example 4-8 shows the converted DB2 code of trigger InsertEmployee.

Example 4-8: Trigger InsertEmployee DB2 conversion code
Start example
CREATE TRIGGER InsertEmployee
AFTER INSERT ON employees
REFERENCING NEW AS new
FOR EACH ROW
MODE DB2SQL
BEGIN ATOMIC
    DECLARE v_num_projects SMALLINT;
    SET (v_num_projects) = (SELECT "NUM_PROJECTS"
          FROM ACCOUNTS
          WHERE "DEPT_CODE" = NEW."DEPT_CODE"
                AND "ACCT_ID" = NEW."ACCT_ID");
   UPDATE ACCOUNTS
          SET "CURRENT_EMPLOYEES" = "CURRENT_EMPLOYEES" + 1
          WHERE "DEPT_CODE" = NEW."DEPT_CODE"
                AND "ACCT_ID" = NEW."ACCT_ID";
END
End example

Please note that in some cases you cannot change a BEFORE trigger to an AFTER trigger. For example, if an application insert a row in table A which needs a parent row in another table B and the parent row in B has to be created/generated by the trigger, then a BEFORE trigger is needed. In this case you will need to implement through application logic.

Example 2: ManagersChange

MTK created three DB2 UDB triggers for the Oracle ManagersChange trigger. This was necessary because DB2 requires a separate trigger for each trigger activity: Insert, Update, or Delete. MTK named the triggers ManagersChange_FO1 (INSERT); ManagersChange_FO2 (DELETE); and ManagersChange_FO3 (UPDATE).

There were two alterations made on each of the three converted triggers: The first made the BEFORE triggers into AFTER triggers; the second changed the logic surrounding the update of the v_ChangeType variable. The second change was optional, but made for "cleaner" code.

Oracle source

Example 4-9 is the Oracle source code of trigger ManagersChange.

Example 4-9: Trigger ManagersChange Oracle source
Start example
CREATE TRIGGER ManagersChange
  BEFORE INSERT OR DELETE OR UPDATE ON Employees
  FOR EACH ROW
DECLARE
  v_ChangeType CHAR(1);
BEGIN
  /* Use 'I' for an INSERT, 'D' for DELETE, and 'U' for UPDATE. */
  IF INSERTING THEN
    v_ChangeType := 'I';
  ELSIF UPDATING THEN
    v_ChangeType := 'U';
  ELSE
    v_ChangeType := 'D';
  END IF;
  INSERT INTO manager_audit
    (change_type, changed_by, timestamp,
     old_employee_id, old_dept_code, old_acct_id, old_band,
     new_employee_id, new_dept_code, new_acct_id, new_band)
  VALUES
    (v_ChangeType, USER, SYSDATE,
     :old.emp_mgr_id, :old.dept_code, :old.acct_id, :old.band,
     :new.emp_mgr_id, :new.dept_code, :new.acct_id, :new.band);
END ManagersChange;
End example
DB2 conversion

The two alternatives of DB2 conversion:

  • First Change:

    BEFORE trigger changed to AFTER trigger; see Example 4-10.

    Example 4-10: Trigger ManagersChange DB2 code

    Start example

    CREATE TRIGGER ManagersChange_FO1
  AFTER INSERT ON EMPLOYEES
  REFERENCING NEW AS NEW
  FOR EACH ROW MODE DB2SQL
  BEGIN ATOMIC
    DECLARE v_ChangeType CHAR(1);
    DECLARE "EMP_MGR_ID" INTEGER DEFAULT NULL;
    DECLARE "DEPT_CODE" CHAR(3) DEFAULT NULL;
    DECLARE "ACCT_ID" SMALLINT DEFAULT NULL;
    DECLARE "BAND" CHAR(1) DEFAULT NULL;
    DECLARE INSERTING INTEGER DEFAULT 1;
    DECLARE UPDATING INTEGER DEFAULT 0;
    -- /* Use 'I' for an INSERT, 'D' for DELETE, and 'U' for UPDATE. */
    IF INSERTING = 1 THEN
       SET v_ChangeType = 'I';
    ELSEIF UPDATING = 1 THEN
       SET v_ChangeType = 'U';
    ELSE
       SET v_ChangeType = 'D';
    END IF;
    INSERT INTO MANAGER_AUDIT
               ("CHANGE_TYPE","CHANGED_BY","TIMESTAMP",
                "OLD_EMPLOYEE_ID","OLD_DEPT_CODE","OLD_ACCT_ID",
                "OLD_BAND","NEW_EMPLOYEE_ID","NEW_DEPT_CODE",
                "NEW_ACCT_ID","NEW_BAND")
    VALUES (v_ChangeType, USER, CURRENT TIMESTAMP,
            "EMP_MGR_ID","DEPT_CODE","ACCT_ID","BAND",
            NEW."EMP_MGR_ID", NEW."DEPT_CODE",
            NEW."ACCT_ID", NEW."BAND");
  END
    End example

  • Second change

    The second set of changes focuses on the logic of the following code:

       IF INSERTING = 1 THEN
           SET v_ChangeType = 'I';
       ELSEIF UPDATING = 1 THEN
           SET v_ChangeType = 'U';
       ELSE
           SET v_ChangeType = 'D';
   END IF;

    Since there will be individual triggers for INSERT, UPDATE, and DELETE, we need only set the variable v_ChangeType to whatever is appropriate for each particular trigger. For example, in an INSERT trigger we need only set v_ChangeType = 'I' (Example 4-11). For the remaining triggers we set v_ChangeType = 'U' for UPDATE, and v_ChangeType = 'D' for DELETE.

    Example 4-11: Alternative DB2 conversion of trigger ManagersChange

    Start example

    CREATE TRIGGER ManagersChange_FO1
  AFTER INSERT ON EMPLOYEES
  REFERENCING NEW AS NEW
  FOR EACH ROW MODE DB2SQL
  BEGIN ATOMIC
    DECLARE v_ChangeType CHAR(1);
    DECLARE "EMP_MGR_ID" INTEGER DEFAULT NULL;
    DECLARE "DEPT_CODE" CHAR(3) DEFAULT NULL;
    DECLARE "ACCT_ID" SMALLINT DEFAULT NULL;
    DECLARE "BAND" CHAR(1) DEFAULT NULL;
    SET v_ChangeType = 'I';     --** Insert trigger; set v_ChangeType = I'
    INSERT INTO MANAGER_AUDIT
               ("CHANGE_TYPE","CHANGED_BY","TIMESTAMP","OLD_EMPLOYEE_ID",
                "OLD_DEPT_CODE","OLD_ACCT_ID","OLD_BAND","NEW_EMPLOYEE_ID",
                "NEW_DEPT_CODE","NEW_ACCT_ID","NEW_BAND")
    VALUES
               (v_ChangeType,USER , CURRENT TIMESTAMP, "EMP_MGR_ID",
                "DEPT_CODE","ACCT_ID","BAND",NEW."EMP_MGR_ID",
                NEW."DEPT_CODE",NEW."ACCT_ID",NEW."BAND");
  END
    End example

    The changes for the above code were also incorporated into the ManagersChange_FO2 (DELETE) trigger:

       SET v_ChangeType = 'D'

    and the ManagersChange_FO3 (UPDATE) trigger:

       SET v_ChangeType = 'U'

Example 3: UpdateDepartments

This trigger employs a CURSOR declaration, which is not allowed in DB2 triggers. This example demonstrates how to change the explicit cursor (c_projects) to an implicit cursor using a DB2 FOR loop. This is accomplished by putting the cursor's SELECT statement directly in the FOR loop statement.

Oracle source

Example 4-12 shows the Oracle source code of trigger UpdateDepartments.

Example 4-12: Trigger UpdateDepartments Oracle source code
Start example
CREATE TRIGGER UpdateDepartments
AFTER INSERT OR DELETE OR UPDATE ON employees
DECLARE
  CURSOR c_projects IS
    SELECT dept_code
           ,COUNT(*) AS total_employees
           ,SUM(current_projects) AS total_projects
      FROM employees
      GROUP BY dept_code;
BEGIN
  FOR v_project_rec in c_projects LOOP
     UPDATE departments
     SET  total_projects  = v_project_rec.total_projects
         ,total_employees = v_project_rec.total_employees
     WHERE dept_code = v_project_rec.dept_code;
  END LOOP;
END UpdateDepartments;
End example
DB2 conversion

The DB2 conversion of trigger UpdateDepartments is shown in Example 4-13.

Listing 4-13: DB2 conversion of trigger UpdateDepartments
Start example
CREATE TRIGGER UpdateDepartments1
AFTER INSERT ON EMPLOYEES
REFERENCING NEW_TABLE AS new
FOR EACH STATEMENT
MODE DB2SQL
BEGIN ATOMIC
  X:                                                                 -- [1]
  for ROW as                                                         -- [2]
      SELECT dept_code                                               -- [3]
           ,COUNT(*) AS total_employees
           ,SUM(current_projects) AS total_projects
      FROM employees group by dept_code
  DO
      UPDATE departments                                             -- [4]
      SET    total_projects  = row.total_projects
            ,total_employees = row.total_employees
      WHERE dept_code = row.dept_code;
  END FOR X;
END
End example

Notes®

[1]

"X" is the specified label for the FOR statement.
[2]

The for-loop-name (ROW) is used to qualify the column names returned by the specified select-statement.
[3]

In a trigger, function, method, or dynamic compound statement, the SELECT statement must consist of only a FULL SELECT with optional common table expressions.
[4]

This section specifies a statement (or statements) that will be invoked for each row of the table.

Note

For complete information regarding FOR loop syntax and usage consult DB2 UDB V8 manual SQL Reference Volume, SC09-4845

Manual deployment of triggers

The triggers InsertEmployee, ManagersChange, and UpdateDepartments are deployed into DB2 UDB from a command window. Here is the process:

  1. After creating the trigger, save the script file on your file system.

    In order to execute multiple commands, your script file must end with a terminating character other than the Default semi-colon (;). Some typical termination character choices are !, or @. MTK uses !.

    • Open a DB2 Command Window in the directory where the converted procedure source resides:

      • To open the DB2 Command Window on Windows:

        Click Start and select Programs --> IBM DB2 --> Command Window

      • To open the DB2 Command Window on UNIX:

        Open any operating system command window.

    • Connect to the database:

         db2 connect to your_database_name

    • Execute the following from the command window. The termination character must be specified:

         db2 -td! -vf your_script_file_name

    • We recommend to pipe the output to another file so that any messages generated during the creation may be viewed at a later time. This may be done as follows:

         db2 -td! -vf your_script file_name > your_output_file_name

Here are the steps as they would be executed for the trigger InsertEmployee. Although not shown here, the steps will be the same, except for the file names, for the remaining triggers ManagersChange_F01/_F02/_F03 and UpdateDepartments1/2/3.

  • The source code below is saved as InsertEmployee.db2

Example 4-14: InsertEmployee.db2
Start example
CREATE TRIGGER InsertEmployee
  AFTER INSERT ON employees
  REFERENCING NEW AS new
  FOR EACH ROW MODE DB2SQL
  BEGIN ATOMIC
    DECLARE v_num_projects SMALLINT;
    SET (v_num_projects) = (SELECT "NUM_PROJECTS"
                            FROM ACCOUNTS
                            WHERE "DEPT_CODE" = NEW."DEPT_CODE"
                            AND "ACCT_ID" = NEW."ACCT_ID");
    UPDATE ACCOUNTS
           SET "CURRENT_EMPLOYEES" = "CURRENT_EMPLOYEES" + 1
           WHERE "DEPT_CODE" = NEW."DEPT_CODE"
           AND "ACCT_ID" = NEW."ACCT_ID";
  END ! --** the exclamation point (!) is the terminat
End example

  2. Open a DB2 Command Window.

  3. Connect to the database:

    db2 connect to db2_emp

  4. The following command is executed. The results are piped to the message.out file:

    db2 -td! -vf InsertEmployee.db2 > message.out

  5. DB2 responds with the message:

    DB20000I The SQL command completed successfully.

The message.out file should be viewed for messages, especially if any other message than The SQL command completed successfully is returned.

4.11.2 Procedures

In our example Oracle database we have five procedures. MTK has converted three of them automatically and flagged errors in procedure EmployeeDynmaicQuery and SelectRow. After examining the reports, we know that these two procedures use Oracle features that require manual intervention to convert to the format which can be accepted DB2 UDB.

Example 1: EmployeeDynamicQuery

This example shows how to convert Oracle Dynamic SQL, implemented through the DBMS_SQL package to equivalent DB2 UDB code. Here we show first the Oracle source, and then the corresponding DB2 conversion. The conversion source will be accompanied by some explanatory notes.

Oracle source

Example 4-15 shows the Oracle source code of procedure EmployeeDynamicQuery.

Example 4-15: EmployeeDynamicQuery Oracle source code
Start example
CREATE PROCEDURE EmployeeDynamicQuery (
  p_department1 IN employees.department%TYPE DEFAULT NULL,
  p_department2 IN employees.department%TYPE DEFAULT NULL) AS
  v_CursorID   INTEGER;
  v_SelectStmt VARCHAR2(500);
  v_FirstName  employees.first_name%TYPE;
  v_LastName   employees.last_name%TYPE;
  v_Department employees.department%TYPE;
  v_Dummy      INTEGER;
BEGIN
   v_CursorID := DBMS_SQL.OPEN_CURSOR;
   v_SelectStmt := 'SELECT first_name, last_name, department
                     FROM employees
                     WHERE department IN (:d1, :d2)
                     ORDER BY department, last_name';
  -- Parse the query.
  DBMS_SQL.PARSE(v_CursorID, v_SelectStmt, DBMS_SQL.NATIVE);
  -- Bind the input variables.
  DBMS_SQL.BIND_VARIABLE(v_CursorID, ':d1', p_department1);
  DBMS_SQL.BIND_VARIABLE(v_CursorID, ':d2', p_department2);
  DBMS_SQL.DEFINE_COLUMN(v_CursorID, 1, v_FirstName, 20);
  DBMS_SQL.DEFINE_COLUMN(v_CursorID, 2, v_LastName, 20);
  DBMS_SQL.DEFINE_COLUMN(v_CursorID, 3, v_Department, 30);
  v_Dummy := DBMS_SQL.EXECUTE(v_CursorID);
  LOOP
    IF DBMS_SQL.FETCH_ROWS(v_CursorID) = 0 THEN
      EXIT;
    END IF;
    DBMS_SQL.COLUMN_VALUE(v_CursorID, 1, v_FirstName);
    DBMS_SQL.COLUMN_VALUE(v_CursorID, 2, v_LastName);
    DBMS_SQL.COLUMN_VALUE(v_CursorID, 3, v_Department);
    INSERT INTO temp_table (char_col)
      VALUES (v_FirstName || ' ' || v_LastName || ' is a ' ||
              v_Department || ' department.');
  END LOOP;
  DBMS_SQL.CLOSE_CURSOR(v_CursorID);
  COMMIT;
EXCEPTION
  WHEN OTHERS THEN
      DBMS_SQL.CLOSE_CURSOR(v_CursorID);
    RAISE;
END EmployeeDynamicQuery;
End example
DB2 conversion

Example 4-16 shows the procedure EmployeeDynamicQuery converted into DB2. We number some statements and provide the explanation found in Example 4-16.

Listing 4-16: Converted DB2 code of Procedure EmployeeDynamicQuery
Start example
CREATE PROCEDURE EmployeeDynamicQuery (IN p_department1 VARCHAR(30),
                       IN p_department2 VARCHAR(30) )                    --[1]
  LANGUAGE SQL
  BEGIN
    DECLARE v_FirstName VARCHAR(20);
    DECLARE v_LastName VARCHAR(20);
    DECLARE v_Department VARCHAR(30);
    DECLARE at_end SMALLINT DEFAULT 0;                                   --[2]
    DECLARE v_SelectStmt VARCHAR(500);                                   --[3]
    DECLARE v_Cursor_stmt STATEMENT;                                     --[4]
    DECLARE v_Cursor cursor for v_Cursor_stmt;
    DECLARE EXIT HANDLER FOR SQLEXCEPTION, SQLWARNING, NOT FOUND         --[5]
    BEGIN
      set at_end =1;                                                     --[6]
      RESIGNAL;
    END;
    SET v_SelectStmt = 'SELECT first_name, last_name, department
                        FROM employees
                        WHERE department IN (?, ?)
                        ORDER BY department, last_name';                 --[7]
    PREPARE v_Cursor_stmt FROM v_SelectStmt;                             --[8]
    OPEN v_Cursor USING p_department1, p_department2;                    --[9]
    WHILE (at_end = 0) DO                                                --[10]
      FETCH v_cursor into v_FirstName,v_lastName, v_Department;          --[11]
      INSERT INTO TEMP_TABLE ("CHAR_COL")
      VALUES (COALESCE(v_FirstName, '') ||' ' ||
              COALESCE(v_LastName, '') || ' is in the ' ||
              COALESCE(v_Department, '') || ' department.');
    END WHILE;
    COMMIT;
END
End example

Notes

[1]

The Oracle %TYPE variables are converted to the base data types from the corresponding DB2 tables.

Note

When MTK encounters NUMBER as a parameter, FLOAT is automatically used (by default) for DB2. This may or may not be the desired conversion, and analysis is required. Often, the appropriate type should be INTEGER or BIGINT as they refer to some type of ID value. FLOAT is an imprecise data type and as numbers get very large or very small, they may get rounded.
[2]

The variable at_end is declared to hold a value that will be set when the EXIT Handler is executed at [5].
[3]

The v_SelectStmt variable as varchar(500) so that it will be large enough to hold the SQL statement for the declared cursor at [7].
[4]

A statement object is declared to hold prepared form of v_SelectStmt at [8].
[5]

An Exit Handler is declared. This will execute when NO DATA FOUND during the Fetch statement at [11].

[6]

When it executes, the Exit Handler will set the value of at_end to 1. This value will be checked to determine if the WHILE loop at [10] should continue.
[7]

Before opening the cursor at [9] the v_CursorStmt object is prepared.

Example 2: SelectRow

The conversion of SelectRow presents the issue of converting Oracle cursor variables. When the cursor variable is an OUT parameter, it can usually be converted to DB2 using a Dynamic Result Set. In general, although manual, this is a very simple conversion.

Oracle source

Example 4-17 shows the Oracle source code of procedure SelectRow.

Example 4-17: SelectRow Oracle source
Start example
CREATE PROCEDURE SELECTROW
    (pEmp_ID  IN  EMPLOYEES.EMP_ID%TYPE,
        pRow    OUT REFPKG.RCT1)
    IS
    BEGIN
        OPEN pRow FOR
        SELECT FIRST_NAME, LAST_NAME, DEPARTMENT, BAND
        FROM EMPLOYEES
        WHERE Emp_ID = pEmp_ID;
    END;
End example
DB2 conversion

Example 4-18 shows the procedure DB2 conversion of procedure SelectRow. Followed the example is the explanatory note.

Listing 4-18: SelectRow DB2 conversion
Start example
CREATE PROCEDURE SELECTROW (IN pEmp_ID INTEGER)
  LANGUAGE SQL
  DYNAMIC RESULT SETS 1                                          -- [1]
  BEGIN
    DECLARE v_Cursor cursor WITH RETURN                          -- [2]
      TO CALLER for                                              -- [3]
      SELECT first_anme,
             last_name,
             department,
             band
      FROM employees
      WHERE emp_id = pEmpID;
    OPEN v_Cursor ;                                              --[4]
  END
End example

Notes

[1] | DYNAMIC RESULT SETS: This clause specifies the maximum number of result to be returned.
[2] | WITH RETURN: This clause indicates that the cursor is intended for use as a result set from a stored procedure.
[3] | TO CALLER: Specifies that the cursor can return a result set to the caller. For example, if the caller is another stored procedure, the result set is returned to that stored procedure. If the caller is a client application, the result set is returned to the client application.
[4] | The cursor v_Cursor is opened, and stays open, to return the Result set.

4.11.3 Manual deployment of stored procedures

The stored procedures EmployeeDynamicQuery and SelectRow will be deployed into DB2 UDB from a Command Window. Here is the process:

  • After creating the procedure, save the script file on your file system:

    In order to execute multiple commands, as in a stored procedure, your script file must end with a terminating character other than the default semi-colon (;). Some typical termination character choices are !, or @.

  • Open a DB2 Command Window in the directory where the converted procedure source resides:

    • To open the DB2 Command Window on Windows:

      Click Start and select Programs -> IBM DB2 -> Command Window

    • To open the DB2 Command Window on UNIX, open any operating system command window.

  • Connect to the database using command:

    db2 connect to your_database_name

  • Execute the following from the command window (termination character must be specified):

    db2 -td! -vf your_script_file_name

  • We recommend to pipe the output to another file so that any messages generated during the creation may be viewed at a later time. This may be done as follows:

    db2 -td! -vf your_script file_name > your_output_file_name

    Here are the steps implemented for the procedure SelectRow. Although not shown here, the steps will be the same except for the file names for the procedure EmployeeDynamicQuery:

  • The following script is created and saved as SelectRow.db2:

       CREATE PROCEDURE SELECTROW (IN pEmp_ID INTEGER)
     LANGUAGE SQL
     DYNAMIC RESULT SETS 1
     BEGIN
       DECLARE v_sqlStmt VARCHAR (200);
       DECLARE v_stmt STATEMENT;
       DECLARE v_Cursor CURSOR WITH RETURN for v_stmt;
       SET v_sqlStmt = 'SELECT FIRST_NAME, LAST_NAME, DEPARTMENT, BAND
                        FROM EMPLOYEES
                        WHERE Emp_ID = ?';
       PREPARE v_stmt FROM v_sqlStmt;
       OPEN v_Cursor USING pEmp_ID;
     END !   ** the exclamation point (!) is the termination character.

  • Open a DB2 Command Window.

  • Connect to the database:

    db2 connect to db2_emp

    Execute the following command to pipe the output to the message.out file:

    db2 -td! -vf Selectrow.db2 > message.out

  • DB2 responds with the message:

    DB20000I The SQL command completed successfully.

    The message.out file should be viewed for messages, especially if any other message other than The SQL command completed successfully is returned.

To this point, all the objects in our example Oracle database ORA_EMP have been converted successfully into DB2 UDB.


Chapter 5: Conversion Reference

Overview

In the previous chapter, we showed you how the IBM Migration Toolkit (MTK) for Oracle is able to automate conversion of most Oracle database objects and proprietary SQL to DB2 UDB. If your database uses many Oracle proprietary features, there may be some SQL that the MTK cannot automate. In this chapter, we show you some examples of how to perform conversions manually, with a focus on converting Oracle objects and features that are not automated by MTK.

We start by exploring some tools and methods for building DB2 triggers, functions, and procedures. Through examples, we look at techniques for converting frequently used PL/SQL features to DB2 SQL PL code. We also discuss how to build external procedures and functions using C/C++ and Java.

Although we start this chapter by demonstrating basic syntax for creating procedures, triggers, and functions in both Oracle and DB2 UDB, the intent is to demonstrate how to convert these objects manually when needed - not to be a complete reference for developing DB2 SQL PL (other books are available for that). The reader is expected to have some prior application development experience in both Oracle PL/SQL and DB2 SQL PL in order to fully understand the examples used in this chapter.


5.1 Tools

There are two basic tools for manually creating or converting stored procedures triggers, and functions: the DB2 Development Center or the DB2 Command Window. The following sections provide a brief explanation of each tool. A complete discussion of the Development Center or the Command Window can be found in Redbooks:

  • The Exploitation of DB2 UDB on Windows Environment, SG24-6893

  • DB2 UDB Evaluation Guide for Linux and Windows, SG24-6934

The Development Center

The Development Center (Figure 5-1) is a Java-based GUI tool. From the Development Center you can:

  • Create, build, and deploy Java and SQL stored procedures

  • Create, build, and deploy user-defined functions (Linux, UNIX, and Microsoft Windows operating systems):

    • SQL and Java UDFs

    • UDFs that read MQSeries® messages

    • UDFs that access OLE DB data sources

    • UDFs that extract data from XML document

  • Debug SQL stored procedures using the integrated debugger (Linux, UNIX, Windows and z/OS Version 8 operating systems)

  • Import and build structured types

  • Development objects contained in multiple databases at the same time

  • View and work with database objects such as tables, triggers, and views

  • Export and import routines and project information

Click To expand
Figure 5-1: The Development Center

The DB2 Command Window

The DB2 Command Line Processor (CLP) behaves like a command window (Figure 5-2) from your operating system. From the DB2 Command Window you can enter operating system commands, DB2 commands, or SQL statements, and then view the output.

Click To expand
Figure 5-2: The DB2 Command Window on AIX

For the deployment of our manually converted procedures and triggers, we will be using the DB2 Command Window.

Books

DB2 SQL Procedural Language for Linux, UNIX, and Windows, ISBN0131007726 (available from most online book retailers) is recommended for learning DB2 SQL PL. This book has full coverage of SQL procedures, functions, and triggers. Paul Yip, a co-author of the book, provided technical consultation and some of the material for this chapter.

The following DB2 manuals are also good sources of information:

  • SQL Reference, Volume 1, SC09-4844, Volume 2, SC09-4845

  • Application Development Guide: Programming Server Application, SC09-4827

  • Application Development Guide: Building and Running Application, SC09-4825

  • Application Development Guide: Programming Client Application, SC09-4826


5.2 Comparing SQL PL and inline SQL PL

DB2 SQL procedures are created using a high level language called DB2 SQL Procedural Language (often called SQL PL) which has many direct equivalents and mappings to Oracle's PL/SQL language. Therefore, converting Oracle stored procedures to DB2 stored procedures is usually straight forward. For triggers, functions, and dynamic compound statements, DB2 uses a subset language called inline SQL PL. Before looking at code samples, it is important to clarify the difference between SQL PL and inline SQL PL.

The following is an excerpt from the book DB2 SQL Procedural Language for Linux, UNIX, and Windows by Paul Yip et. al.

"Although the language syntax for SQL PL is consistent throughout from an application development perspective, the language implementation in DB2 to support SQL PL for store procedures is completely different from that of triggers and UDFs.

When building an SQL procedure, DB2 will convert it into two components: a C language file and a DB2 bind file. The C file contains the procedural logic while the bind file contains the SQL for the procedure. The C code is then compiled into a library file that can be called by DB2 processes and the BIND file is bound to the database where it then becomes a package. When you execute the stored procedure, the library works hand in hand with the database package to execute SQL according to the stored procedure logic.

In contrast, SQL PL in triggers and UDFs are not implemented as libraries and packages. There is no compiled C component, nor is a bind file generated. When you use SQL PL in triggers and UDFs, the code is executed dynamically within the engine as a single dynamic compound statement.

The implementation differences result in some SQL PL elements that are supported in SQL procedures but not in triggers and UDFs. SQL PL support in triggers and UDFs is a subset of that in stored procedures and includes support for the following SQL PL elements:

  • DECLARE <variable>

  • FOR

  • GET DIAGNOSTICS

  • IF

  • ITERATE

  • LEAVE

  • SIGNAL

  • WHILE

  • SET

The following subsections discuss the basics of creating DB2 stored procedures, triggers, and user defined functions. We also compare variable declaration, conditional statements, and flow of control statements between Oracle PL/SQL and DB2 SQL PL. This chapter (section 5.2 onwards) has been organized to serve as a convenient quick reference for you when converting specific features of Oracle PL/SQL to DB2 SQL PL.

For the full documentation of features of SQL PL, please consult the DB2 UDB SQL Reference, Volume 1, SC09-4844, Volume 2, SC09-4845, or DB2 SQL Procedural Language for Linux, UNIX, and Windows.

Delimiter

In DB2 UDB, statements in trigger, function, and procedure are separated by a semi colon (;) which also is the default statement terminator when running a group of SQL statements in DB2 CLP. Therefore, in trigger, procedure, or function, a semi colon (;) cannot be used as the terminator. You can choose other characters such as @ or ! as the termination character. All the DB2 UDB examples in this chapter use ! as the termination character. To execute the file which contains the function, trigger, or procedure to create the object in DB2 UDB, use the following command:

db2 -td<termination_character> -f file-name

Where termination_character = @ or ! etc. For example, if the termination character is ! and file-name is testproc.db2, the command will be:

db2 -td! -f testproc.db2

5.2.1 Create procedure

Oracle uses the following syntax to create a stored procedure:

   CREATE OR REPLACE PROCEDURE process_withdrawal( Account_Id VARCHAR2
                                                  ,Cheque_No VARCHAR2
                                                  ,Amount NUMBER )
   IS
   ...

DB2 uses slightly different syntax:

   CREATE PROCEDURE process_withdrawal ( IN Account_Id VARCHAR(10)
                                        ,IN Cheque_No VARCHAR(10)
                                        ,IN Amount DECIMAL(10,2) )
   LANGUAGE SQL
   ...
Notes

  • DB2 does not support REPLACE clause in the create procedure statement, so you may want to drop the procedure before creating one. When developing procedures using the Development Center, procedures are automatically dropped for you if you choose to rebuild a procedure.

  • DB2 does not allow to specify data type without length, so you need to check declaration for the column (those parameters correspond to) to declare them properly. If converting with the migration toolkit; this is done for you automatically if your original code uses %TYPE.

  • LANGUAGE SQL is a mandatory statement in DB2 UDB V7.x, optional in V8.

5.2.2 Create trigger

In this section we give you a high-level overview of the differences in the trigger definition between Oracle and DB2 UDB. For a detailed description of triggers, please reference the DB2 UDB Application Development Guide and the SQL Reference.

Example 5-1 shows you a simple Oracle trigger, which has set a value to a table column before inserting a row.

Example 5-1: Simple Oracle trigger
Start example
CREATE OR REPLACE TRIGGER connect_audit_trg
   BEFORE INSERT ON connect_audit
   FOR EACH ROW
BEGIN
   :new.timestamp := SYSDATE;
END;
End example

The Example 5-2 shows how to define the corresponding trigger in DB2.

Example 5-2: Simple DB2 trigger
Start example
CREATE TRIGGER connect_audit_trg
   NO CASCADE BEFORE INSERT ON connect_audit
   REFERENCING NEW AS n
   FOR EACH ROW
   MODE DB2SQL
BEGIN ATOMIC
   SET n.timestamp = CURRENT TIMESTAMP;
END!
End example
Notes

  • DB2 does not support REPLACE clause in the create trigger statement, so you may want to drop the trigger before creating one.

  • The NO CASCADE statement is mandatory for BEFORE triggers. It specifies that the triggered action of the trigger will not cause other triggers to be activated.

  • With the REFERENCE NEW AS n clause, you can associate a qualifier n to the new values provided by the initiated insert statement.

  • MODE DB2SQL is a required clause that must be included as part of the definition.

  • DB2 UDB also supports BEFORE and AFTER trigger for UPDATE and DELETE (activated once FOR EACH ROW changed). AFTER triggers, which activate FOR EACH STATEMENT as well as INSTEAD OF triggers for INSERT, UPDATE, or DELETE statements, are also supported.

Example 5-3 is an Oracle trigger that inserts some values of a deleted row into a history table.

Example 5-3: Oracle trigger with DML command
Start example
CREATE TRIGGER emp_history_trg
   AFTER DELETE ON employees
   FOR EACH ROW
BEGIN
   INSERT INTO emp_history( emp_id
                           ,first_name
                           ,last_name)
   VALUES ( :old.emp_id
           ,:old.first_name
           ,:old.last_name );
END;
End example

Example 5-4 shows how to define the corresponding trigger in DB2.

Example 5-4: DB2 trigger with DML command
Start example
CREATE TRIGGER emp_history_trg
   AFTER DELETE ON EMPLOYEES
   REFERENCING OLD AS d
   FOR EACH ROW
   MODE DB2SQL
BEGIN ATOMIC
   INSERT INTO emp_history ( emp_id
                            ,first_name
                            ,last_name)
   VALUES ( d.emp_id
           ,d.first_name
           ,d.last_name);
END!
End example

5.2.3 Create function

A function that is created by a user that is not one of the built-in functions in DB2 UDB is called a user-defined function or UDF. DB2 supports five different kinds of functions:

  • SQL scalar, table, or row function

  • Sourced or template function

  • OLE DB function

  • External table function

  • External scalar function

In this chapter, we discuss only the SQL functions. For a description of the other function types please see the SQL Reference.

The most common UDF definition for SQL functions looks like the following:

   CREATE FUNCTION function_name ( parameters )
      RETURNS return_type
      LANGUAGE SQL
      READS SQL DATA
      RETURN statement
Notes

  • Input parameters are optional. However, the brackets are mandatory.

  • The mandatory return type is one of the following kinds

    • Scalar

      A scalar function returns a single value each time it is invoked, and is generally valid wherever an SQL expression is valid.

    • Table

      A table function may be used in a FROM clause and returns a table.

    • Row

      A row function may be used as a transform function and returns a row.

  • LANGUAGE SQL is mandatory statement in DB2 UDB V7.x, optional in V8.

  • READS SQL DATA is optional and implied by default for SQL function.

  • Following to the RETURN keyword you have to specify the SQL function body.

5.2.4 Variables declaration and assignment

Oracle PL/SQL permits declaring variables in four different places:

  • In a parameter list of a stored procedure or function

  • Within the body of a stored procedure, function, or trigger

  • Within a package declaration

  • Within a package body declaration

DB2 does not have a notion of package to group functions and procedures, instead, DB2 uses schema to group procedures and functions. So, variables can be declared:

  • In a parameter list of a stored procedure or function

  • In the body of a stored procedure, function, or trigger

DB2 SQL PL supports native data types and user defined distinct type for the variable declaration. It requires the DECLARE clause, and uses the optional DEFAULT clause to initialize variables. So, for example, PL/SQL declaration:

   l_balance NUMBER(10,2) :=0.0;

This is converted to SQL PL as:

   DECLARE l_balance NUMERIC(10,2) DEFAULT 0.0;
Note

Variable declarations need to be placed in the BEGIN ... END block.

SQL PL uses SET statement to assign values to variables. So, for example, PL/SQL assignment

   l_balance := 19.99;

will be converted as:

   SET l_balance = 19.99;
Note

SET statement also can be used to assign a local variable with table column value:

SET l_balance =(SELECT balance from account_info where account_no = actNo);

The SELECT statement should return one row only. Error will be returned if more then one row is selected. You can use a FETCH FIRST n ROW in SELECT statement to control the number of rows returned.

5.2.5 Conditional statements and flow control

SQL PL and PL/SQL provide similar functionality and syntax for conditional statements and a variety of LOOP statements to provide flow control. Table 5-1 maps Oracle PL/SQL statements to DB2 SQL PL.

Table 5-1: Mapping of conditional statements

Oracle PL/SQL

DB2 SQL PL

IF - THEN - END IF;
IF - THEN - ELSE - END IF;
IF - THEN - ELSIF - END IF;

IF - THEN - END IF;
IF - THEN - ELSE - END IF;
IF - THEN - ELSEIF - END IF;

LOOP
   statements;
END LOOP;

[L1:] LOOP
   statements;
   LEAVE L1;
END LOOP [L1];

WHILE condition LOOP
   statements;
END LOOP;

WHILE condition DO
   statements;
END WHILE;

LOOP
   statements;
EXIT WHEN condition;
END LOOP;

REPEAT
   statements;
UNTIL condition;
END REPEAT;

OPEN cursor_variable FOR
select_statement;

FOR variable AS cursor_name
CURSOR FOR select_statement DO
   statements;
END FOR;
Note: If cursor_variable is a REF
cursor, DB2 would define the cursor
and open it with RETURN TO
CLIENT/CALLER.

FOR l_count IN
lower_bound ..upper_bound
LOOP
  statements;
END LOOP;

No corresponding statements, but MTK will convert it as:

SET l_count = lower_bound;
WHILE l_count <= upper_bound DO
statements;
  SET l_count = l_count + 1;
END WHILE ;

Consider some conversion example that use condition statement IF THEN ELSE.

Oracle conditional statement:

   IF v_TotalStudents = 0 THEN
       INSERT INTO temp_table (char_col)
         VALUES ('There are no students registered');
     ELSIF v_TotalStudents < 5 THEN
       INSERT INTO temp_table (char_col)
         VALUES ('There are only a few students registered');
     ELSIF v_TotalStudents < 10 THEN
       INSERT INTO temp_table (char_col)
         VALUES ('There are a little more students registered');
     ELSE
       INSERT INTO temp_table (char_col)
         VALUES ('There are many students registered');
     END IF;

Will be converted as follow:

   IF v_TotalStudents = 0 THEN
           INSERT INTO temp_table (char_col)
                    VALUES ('There are no students registered');
     ELSEIF v_TotalStudents < 5 THEN
          INSERT INTO temp_table (char_col)
                     VALUES ('There are only a few students registered');
     ELSEIF v_TotalStudents < 10 THEN
          INSERT INTO temp_table (char_col)
                    VALUES ('There are a little more students registered');
     ELSE
          INSERT INTO temp_table (char_col)
                   VALUES ('There are many students registered');
     END IF;

Or, you can convert this statement using the CASE statement, supported by DB2:

   CASE
      WHEN v_TotalStudent = 0 THEN
           INSERT INTO temp_table (char_col)
                  VALUES ('There are no students registered');
      WHEN v_TotalStudent < 5 THEN
           INSERT INTO temp_table (char_col)
                  VALUES ('There are only a few students registered');
      WHEN v_TotalStudent < 10 THEN
           INSERT INTO temp_table (char_col)
                  VALUES ('There are a little more students registered');
      OTHER
           INSERT INTO temp_table (char_col)
                  VALUES ('There are many students registered');
   END;


5.3 Dynamic SQL

In Chapter 4., "Porting with MTK" on page 63, we show you a conversion example of the Oracle DBMS_SQL package, which MTK does not support. You can reference to DBMS_SQL with the dynamic SQL in DB2 UDB. In this section, we present additional examples that show how.

Example 1 - get_emp_name

Example 5-5 and Example 5-6 are two Oracle stored procedures use dynamic SQL. Example 5-5 uses the DBMS_SQL package.

Example 5-5: PL/SQL procedure with usage of DBMS_SQL
Start example
CREATE PROCEDURE get_emp_name_v1(emp_id NUMBER) AS
    cursor_name     INTEGER;
    rows_processed  INTEGER;
    sql_stmt        VARCHAR2(1000);
BEGIN
    cursor_name := dbms_sql.open_cursor;
    sql_stmt := 'SELECT last_name FROM employees WHERE emp_id = :x';
    DBMS_SQL.PARSE(cursor_name, sql_stmt, dbms_sql.native);
    DBMS_SQL.BIND_VARIABLE(cursor_name, ':x', emp_id);
    rows_processed := dbms_sql.execute(cursor_name);
    DBMS_SQL.close_cursor(cursor_name);
EXCEPTION
WHEN OTHERS THEN
    DBMS_SQL.CLOSE_CURSOR(cursor_name);
END;
End example
Example 5-6: PL/SQL procedure with usage of native dynamic SQL
Start example
CREATE OR REPLACE PROCEDURE get_emp_name_v2(emp_id IN NUMBER) AS
   sql_stmt   VARCHAR2(1000);
   v_result   VARCHAR2(20);
BEGIN
   sql_stmt := 'SELECT last_name FROM employees WHERE emp_id = :x';
   EXECUTE IMMEDIATE sql_stmt
      INTO v_result
      USING emp_id;
   dbms_output.put_line(v_result.last_name);
END;
End example

Example 5-6 shows a procedure with the same behavior, however, it is with dynamic SQL, which is available since Oracle version 8.

When using MTK to convert the procedure get_emp_name_v2(), MTK will report that the EXECUTE IMMEDIATE command cannot be converted because MTK cannot guarantee the correctness of converted dynamic SQL (only a true runtime test can determine correctness.). DB2 supports dynamic SQL in procedures using the same type of syntax supported in Oracle 8 (Example 5-6). If the dynamic SQL statement is an INSERT, UPDATE, or DELETE statement, conversion to DB2 is usually straight forward. If the dynamic statement is a SELECT, however, it needs to be converted to use a dynamic cursor in DB2 (as shown in Example 5-7).

Example 5-7: SQL PL procedure with native dynamic SQL
Start example
CREATE PROCEDURE get_emp_name_v2 ( IN emp_id FLOAT)
LANGUAGE SQL
BEGIN
    DECLARE v_dyn_sql   VARCHAR(1000);
    DECLARE v_sql_stmt  STATEMENT;
    DECLARE c_employees CURSOR FOR v_sql_stmt;
    SET v_dyn_sql = 'SELECT last_name FROM employees WHERE emp_id = '
                    || CHAR(emp_id);
    PREPARE v_sql_stmt FROM v_dyn_sql;
    OPEN c_employees;
    -- FETCH ...
    CLOSE c_employees;
END!
End example

Example 2: update_emp_office

Example 5-8 shows you a DB2 stored procedure with a dynamic UPDATE statement.

Example 5-8: Dynamic UPDATE with EXECUTE IMMEDIATE
Start example
CREATE PROCEDURE update_emp_office_v1 ( IN v_emp_id FLOAT
                                       ,IN v_office_id FLOAT
                                       ,OUT v_num_changes INTEGER)
LANGUAGE SQL
BEGIN
    DECLARE v_dyn_sql    VARCHAR(1000);

    SET v_dyn_sql = 'UPDATE employees' ||
                    ' SET office_id = ' || CHAR(v_office_id) ||
                    ' WHERE emp_id = ' || CHAR(v_emp_id);
    EXECUTE IMMEDIATE v_dyn_sql;

    GET DIAGNOSTICS v_num_changes = row_count;
END!
End example

In Example 5-5, the variable rows_processed contained the number of rows affected by the dynamic SQL statement. In DB2, the same can be done with GET DIAGNOSTICS. With the GET DIAGNOSTICS statement you get the number of row changed due to the last INSERT, UPDATE, or DELETE.

You use EXECUTE IMMEDIATE if the SQL statement only needs to be executed just once or infrequently. If the SQL statement needs to be executed repeatedly, you should use the PREPARE and EXECUTE statements. With the EXECUTE statement you can use parameter marker. Please note that the EXECUTE statement cannot be used with a SELECT or VALUES statement.

Example 5-9 demonstrates the use of a dynamic SQL statement using PREPARE and EXECUTE instead of EXECUTE IMMEDIATE.

Example 5-9: Dynamic UPDATE with EXECUTE and PREPARE
Start example
CREATE PROCEDURE update_emp_office_v2 ( IN v_emp_id FLOAT
                                       ,IN v_office_id FLOAT
                                       ,OUT v_num_changes INTEGER)
LANGUAGE SQL
BEGIN
    DECLARE v_dyn_sql    VARCHAR(1000);
    DECLARE v_stmt       STATEMENT;

    SET v_dyn_sql = 'UPDATE employees' ||
                    ' SET office_id = ?' ||
                    ' WHERE emp_id = ?';

    PREPARE v_stmt FROM v_dyn_sql;
    EXECUTE v_stmt USING v_office_id, v_emp_id;

    GET DIAGNOSTICS v_num_changes = row_count;
END!
End example

Example 3: get_max_band

The next example shows you a user defined function (UDF) with dynamic SQL written in Java. The function uses the invoker's database connection with all its authentications. The prepare is followed by the assignment of an input variable (called inOfficeID) to the value of the parameter marker. The SQL statement may contain a full-select.

Example 5-10: Java User Defined Function with dynamic SQL
Start example
import COM.ibm.db2.app.*;
import java.sql.*;

public class UDFemp extends UDF
{
  public void maxBand(int inOfficeID, String outBand)
    throws Exception
    {
      try
      {
        // Get caller's connection to the database
        Connection con =
          DriverManager.getConnection("jdbc:default:connection");

        String query = "SELECT max(band) " +
                       "FROM employees " +
                       "WHERE office_id = ?";

        PreparedStatement stmt = con.prepareStatement(query);
        stmt.setInt(1, inOfficeID);

        ResultSet rs = stmt.executeQuery();
       while(rs.next())
       {
         outBand = rs.getString(1);
       }

       set(2, outBand);

       rs.close();
       stmt.close();
       con.close();
     }

     catch (SQLException sqle)
     {
      setSQLstate("38999");
      setSQLmessage("SQLCODE = " + sqle.getSQLState());
      return;
     }
    }
}
End example

The corresponding CREATE FUNCTION statement for this Java UDF is as follows:

    CREATE FUNCTION get_max_band(INTEGER)
    RETURNS CHAR
    EXTERNAL NAME 'UDFemp!maxBand'
    FENCED
    CALLED ON NULL INPUT
    VARIANT
    READS SQL DATA
    PARAMETER STYLE DB2GENERAL
    LANGUAGE JAVA
    NO EXTERNAL ACTION!

A detailed description of external routines is in the DB2 UDB Application Development Guide: Programming Server Applications.


5.4 Cursor conversion

The MTK generally does a good job of converting cursors in stored procedures to DB2. Because DECLARE CURSOR syntax is not supported in inline SQL PL, some manual conversion of cursors is required for functions and triggers.

In this section, we discuss the cursors conversion in stored procedures. We show you how to convert the Oracle explicit cursor in function, and the methods of converting cursor attributes.

In general, Oracle PL/SQL and DB2 SQL PL are similar in their syntax and support for cursor operations. Table 5-2 shows the similarities/differences between the syntax.

Table 5-2: Mapping Oracle and DB2 Cursor operation

Operation

Oracle

DB2 UDB

Declaring a cursor

CURSOR cursor_name
[(cursor_parameter(s))]
IS select_statement;

DECLARE cursor_name
CURSOR [WITH HOLD] [WITH
RETURN] [TO CALLER | TO
CLIENT] FOR
select-statement

Opening a cursor

OPEN cursor_name
[(cursor_parameter(s))];

OPEN cursor_name [USING
host-variable]

Fetching from cursor

FETCH cursor_name INTO
variable(s)

FETCH [from] cursor_name
INTO variable(s)

Update fetched row

UPDATE table_name
SET statement(s)...
WHERE CURRENT OF
cursor_name;

UPDATE table_name
SET statement(s)...
WHERE CURRENT OF
cursor_name

Delete fetched row

DELETE FROM table_name
WHERE CURRENT OF
cursor_name;

DELETE FROM table_name
WHERE CURRENT OF
cursor_name

Closing cursor

CLOSE cursor_name;

CLOSE cursor_name

5.4.1 Converting explicit cursor in procedure

An Oracle SQL cursor is defined similar to a variable in a procedure. The definition is in the stored procedure specification. Example 5-11 is a sample Oracle procedure with an explicit cursor defined in the specification.

Example 5-11: Oracle procedure with explicit cursor
Start example
PROCEDURE get_sum_projects( v_office_id   IN  NUMBER
                           ,sum_projects  OUT NUMBER)
AS
   v_prj   NUMBER(3);
   CURSOR c1 IS
      SELECT current_projects
      FROM employees
      WHERE office_id = v_office_id;
BEGIN
   sum_projects := 0;
   OPEN c1;
   LOOP
      FETCH c1 INTO v_prj;
      EXIT WHEN c1%NOTFOUND;
      sum_projects := sum_projects + v_prj;
   END LOOP;
END;
End example

In DB2 UDB, you must define the SQL cursor in the procedure body. To use procedure parameters within the cursor you have to define and prepare the SQL statement for the cursor. Example 5-12 shows the cursor definition and PREPARE statement. This is also the conversion of Example 5-11.

Example 5-12: DB2 store procedure with cursor
Start example
CREATE PROCEDURE get_sum_projects ( IN  v_office_id  INTEGER
                                   ,OUT sum_projects INTEGER )
LANGUAGE SQL
BEGIN
    DECLARE v_no_data   SMALLINT DEFAULT 0;
    DECLARE v_prj       SMALLINT DEFAULT 0;
    DECLARE v_sql       VARCHAR(1000);
    DECLARE v_stmt      STATEMENT;
    DECLARE c1          CURSOR WITH RETURN FOR v_stmt;
    DECLARE CONTINUE HANDLER FOR NOT FOUND
       SET v_no_data = 1;

    SET sum_projects = 0;
    SET v_sql = 'SELECT current_projects ' ||
                'FROM employees ' ||
                'WHERE office_id = ' || CHAR(v_office_id);

    PREPARE v_stmt FROM v_sql;
    OPEN c1;
    FETCH c1 INTO v_prj;
    WHILE (v_no_data=0) DO
       SET sum_projects = sum_projects + v_prj;
       FETCH c1 INTO v_prj;
    END WHILE;
    CLOSE c1;
END!
End example

5.4.2 Converting explicit cursor in functions and triggers

It is important to understand that DB2 triggers and functions must use inline SQL PL. Oracle cursor operations in triggers and functions, such as explicit cursors, must be converted to the corresponding inline SQL PL syntax. Section 4.11.1, "Triggers" on page 136 provides an example of converting an explicit cursor in a trigger. In the following section, we show you how to convert an Oracle explicit cursor in a function using a FOR LOOP.

Example 5-13 shows the Oracle function source code.

Example 5-13: Function with an explicit cursor in Oracle
Start example
CREATE OR REPLACE FUNCTION CountProjects (
  /* Returns the number of projects in which the employee
     identified by p_emp_ID is currently engaged */
  p_empID IN employees.emp_ID%TYPE)
RETURN NUMBER AS

  v_TotalProjects NUMBER;

  -- Total number of projects
  v_AccountProjects NUMBER;

  -- projects for one account
  CURSOR c_DeptAccts IS
    SELECT dept_code, acct_id FROM employees
      WHERE emp_id = p_empID;
BEGIN

  FOR v_AccountRec IN c_DeptAccts LOOP
    -- Determine the projects for this account.

    SELECT num_projects INTO v_AccountProjects
      FROM accounts WHERE dept_code = v_AccountRec.dept_code
      AND acct_id = v_AccountRec.acct_id;

    -- Add it to the total so far.
    v_Totalprojects := v_Totalprojects + v_AccountProjects;

  END LOOP;

  RETURN v_Totalprojects;

END CountProjects;
End example

The converted DB2 code is shown in Example 5-14.

Listing 5-14: Conversion using a FOR LOOP in DB2
Start example
CREATE FUNCTION CountProjects(p_empID INTEGER)
RETURNS INTEGER
LANGUAGE SQL
BEGIN ATOMIC
   DECLARE v_TotalProjects INT DEFAULT 0;
   DECLARE v_AccountProjects INT;
   X: FOR v_DeptAccts as                      --[1]
      Select dept_code, acct_id
      FROM employees
      WHERE emp_id = p_empID
      DO
         SET v_AccountProjects = (
         SELECT num_projects                  --[2]
         FROM accounts
               WHERE dept_code = v_DeptAccts.dept_code
               AND acct_id = v_DeptAccts.acct_id);
         SET v_Totalprojects = v_Totalprojects + v_AccountProjects;
   END FOR X;
   RETURN v_Totalprojects;
END!
End example

Notes

[1] | The FOR LOOP "X" is declared and the values that will be used in the "where" clause in the "SET" statement are selected.
[2] | SELECT INTO is not supported in inline SQL. The equivalent can be achieved using the SET statement.

5.4.3 Converting cursor attributes

Oracle supports cursor attributes to get information about the current status of a cursor. SQLCODE/SQLSTATE can be used to obtain the analogous information in DB2. The following table shows how to match Oracle cursor attributes with DB2 SQLCODE/SQSTATE values.

Table 5-3: Mapping of cursor attributes

Oracle

DB2 UDB

%ISOPEN

Upon open a cursor, DB2 SQLCODE -502 is returned if
the cursor is already open. On FETCH, SQLCODE -501
is returned if the cursor is not open yet.

However, In DB2 procedure, you will not be able to
test for any negative sqlcodes (exceptions) unless
they are contained within an exception handler
because control will be returned to the calling
application or procedure.

If %isopen is used to test if a cursor is open
before closing it, it may not be needed in DB2. DB2
will close the cursor for you.
The SQLSTATE associated with SQLCODE -501 is 24501.
The SQLSTATE associated with SQLCODE -502 is 24502

%NOTFOUND

if (SQLCODE = 100) or if SQLSTATE = '02000'

%FOUND

if (SQLCODE = 0) or if SQLSTATE = '00000'

%ROWCOUNT

Use a counter variable to retrieve number of rows fetched from the cursor

The following examples demonstrate how to convert these Oracle attributes to DB2.

%ISOPEN

Let's consider the following Oracle code fragment that uses %ISOPEN:

   IF c1%ISOPEN THEN
        fetch c1 into var1;
   ELSE                            -- cursor is closed, so open it
      OPEN c1;
        fetch c1 into var1;
   END IF;

You can implement the same logic in DB2 using CONDITION HANDLER:

   DECLARE cursor_notopen CONDITION FOR SQLSTATE 24501;
   DECLARE CONTINUE HANDLER FOR cursor_notopen
   BEGIN
         open c1;
         FETCH c1 int var1;
   END;
     ...
   FETCH c1 into var1;

More detailed discussion of CONDITION HANDLERS is in 5.6, "Condition handling" on page 180.

%NOTFOUND

Here is an Oracle example that uses %NOTFOUND:

   OPEN cur1;
   LOOP
     FETCH cur1 INTO v_var1;
       EXIT WHEN cur1%NOTFOUND;
      ...
   END LOOP;

In DB2, this can be implemented using CONDITION HANDLERS or checking the SQLCODE value:

   DECLARE SQLCODE int DEFAULT 0;
   ……
   OPEN c1;
   L1: LOOP
         FETCH c1 INTO v_var1;
         IF SQLCODE = 100 THEN
                 LEAVE L1;
         END IF;
         ...
   END LOOP L1;

%ROWCOUNT

SQL %ROWCOUNT yields the number of rows affected by an INSERT, UPDATE, or DELETE statement, or returned by a SELECT INTO statement. %ROWCOUNT yields 0 if an INSERT, UPDATE, or DELETE statement affected no rows, or a SELECT INTO statement returned no rows.

The use of %ROWCOUNT can be demonstrated with following Oracle examples. First, let us consider the example that uses %ROWCOUNT to determine the condition for the loop:

   LOOP
      FETCH c1 INTO my_ename, my_deptno;
      IF c1%ROWCOUNT > 10 THEN
        EXIT;
      END IF;
      ...

   END LOOP;

This Oracle code will process only the first 10 rows for the given cursor. This logic can be implemented in DB2 using the FETCH FIRST N ROWS ONLY clause in the cursor declaration, and processing this cursor till NOT FOUND.

   DECLARE c1 CURSOR FOR
       SELECT ename, deptno
          FROM  emp_table
       FETCH FIRST 10 ROWS ONLY;

   DECLARE CONTINUE HANDLER FOR NOT FOUND
      BEGIN
               SET end-of-fetch = 1;
      END;

   L1: LOOP
         FETCH c1 INTO my_ename, my_deptno;
         IF end-of-fetch = 1 THEN
              LEAVE L1;
         END IF;
         …………
    END LOOP L1;

If %ROWCOUNT is used to determine how many rows from the cursor have been processed at any given time like the following Oracle code:

    LOOP
       FETCH c1 INTO my_ename, my_deptno;
       IF c1%ROWCOUNT > 10 THEN
          ...
       END IF;
       ...

    END LOOP;

In DB2, you would need to use local variable (counter) to store this information after each fetch from the cursor:

    DECLARE v_CURCOUNT INT DEFAULT 0;
        …….
        L1: LOOP
              FETCH c1 INTO my_ename, my_deptno;
              v_CURCOUNT = v_CURCOUNT + 1;
              IF vCURCOUNT > 10 THEN
              ……
              END IF;
              ……
          END LOOP L1;

In the following example, %ROWCOUNT is used to take action if more than ten rows have been deleted:

   DELETE FROM emp_table WHERE ...
   IF SQL%ROWCOUNT > 10 THEN      -- more than 10 rows were deleted
      ...

   END IF;

DB2 supports GET DIAGNOSTICS statement to return number of rows affected by INSERT, UPDATE, or DELETE statement:

   DECLARE rc INT DEFAULT 0;
   …….
   DELETE FROM emp_table WHERE ...
   GET DIAGNOSTICS rc = ROW_COUNT;
   IF rc > 10 THEN       -- more than 10 rows were deleted
      ...

   END IF;

Please note that the GET DIAGNOSTICS statement is not supported for the SELECT or SELECT INTO statement. SQLCODE will be 100 if no row is selected, SQLCODE will be 0 if one row is selected, and SQLCODE will be -811 (SQLSTATE 21000 - SQLERROR) if more then one row are selected.

%FOUND

Please note that for any SQL statement, Oracle treats it as an implicit cursor. Implicit cursor attributes return information about the execution of an INSERT, UPDATE, DELETE, or SELECT INTO statement. The values of the implicit cursor attributes always refer to the most recently executed SQL statement. Before Oracle opens the SQL cursor, the implicit cursor attributes yield NULL. In the following example, %FOUND is used to insert a row if a delete succeeds:

   DELETE FROM emp WHERE empno = my_empno;
   IF SQL%FOUND THEN    -- delete succeeded
      INSERT INTO emp_table VALUES (my_empno, my_ename);

This code can be converted to DB2 as follow:

   DELETE FROM emp WHERE empno = my_empno;
   IF SQLCODE = 0  THEN    -- delete succeeded
      INSERT INTO emp_table VALUES (my_empno, my_ename);


5.5 Collections

In Oracle, a collection is an ordered group of elements, all of the same type; for example, the bonuses for a employees. Each element has a unique subscript that determines its position in the collection. Oracle v8.1 PL/SQL offers two kinds of collections: nested tables and varrays (short for variable-size arrays).

Collections can have only one dimension, and must be indexed by integers. Collections can be passed as parameters. So, you can use them to move columns of data into and out of database tables, or between client-side applications and stored procedures.

5.5.1 Nested tables and varrays

To understand how nested tables and varrays can be converted to DB2, first let us address the difference between Oracle nested tables and varrays.

Items of type TABLE are called nested tables. Within the database, they can be viewed as one-column database tables. Oracle stores the rows of a nested table in no particular order. But, when you retrieve the nested table into a PL/SQL variable, the rows are given consecutive subscripts starting at 1. Nested table has no upper bound, while the size of variable arrays is fixed. The second important difference, the variable arrays must be dense (have consecutive subscripts). So, you cannot delete individual elements from an array. Initially, nested tables are dense, but they can be sparse (have nonconsecutive subscripts).

As DB2 does not support collections, the most generic way to convert a nested table is by using DB2 Declared Global Temporary Table (DGTT), where first column stores the value of the subscript, and the second column stores the value of Oracle nested table.

Note

DB2 temporary tables are not similar to Oracle temporary tables. DB2 temporary tables are memory bound (provided sufficient memory is available), visible only to the connection that declares it, and exist only for as long as a connection is maintained (or dropped). If you disconnect, the table is automatically cleaned up.
Tip

To use DGTTs, you must create a user temporary table space (none exists by default). In the simplest case, you can use:

create user temporary tablespace usertemp1 managed by system using
('usertemp1')

The size of the buffer pool associated with this tablespace will affect how memory-bound DGTTs are at runtime.

Let us clarify this with an example (Example 5-15) that filling nested table EmpList with names of the Employees for the given department from table emp_table.

Example 5-15: Oracle code using nested table
Start example
DECLARE
  TYPE EmpList IS TABLE OF emp_table.ename%TYPE ;
  CURSOR c1 IS
     SELECT emp_name
     FROM emp_table
     WHERE dept = v_dept;
  EmpName emp_table.ename%TYPE;
  empNum NUMBER;
BEGIN
  LOOP
    FETCH c1 INTO EmpName;
    WHEN c1%NOTFOUND EXIT;
    empNum := empNum + 1;
    EmpList(empNum):= EmpName;
  END LOOP;
  CLOSE c1;
END;
End example

The same can be implemented in DB2 using DGTT as shown in Example 5-16.

Example 5-16: DB2 UDB code using DGTT
Start example
DECLARE SQLCODE INT DEFAULT 0;
DECLARE v_empname varchar(30);
DECLARE v_num INT DEFAULT 0;
DECLARE c1 CURSOR FOR
        SELECT emp_name
        FROM emp_table
        WHERE dept = v_dept;
DECLARE GLOBAL TEMPORARY TABLE SESSION.temp_emp_list
        (num integer, EmpName varchar(30))
        WITH REPLACE
        ON COMMIT PRESERVE ROWS
        NOT LOGGED;

OPEN c1;
   WHILE (SQLCODE = 0) DO
      FETCH c1 INTO v_empname;
      SET v_num = v_num +1;
      INSERT INTO SESSION.temp_emp_list
         VALUES (v_num,v_empname);
   END WHILE;
CLOSE c1;
End example

Or better yet, the code is more efficient if converted as follows (Example 5-17).

Example 5-17: Efficient DB2 UDB code using DGTT
Start example
DECLARE GLOBAL TEMPORARY TABLE SESSION.temp_emp_list
         (num integer,EmpName varchar(30))
WITH REPLACE
ON COMMIT PRESERVE ROWS
NOT LOGGED;

INSERT INTO session.temp_emp_list
       SELECT row_number() over(), emp_name
       FROM emp_table
       WHERE dept = v_dept;
End example

To convert Oracle varrays, you can also use DGTT, or sometimes the redesign can help achieve the same functionality.

5.5.2 Bulk collect

In Oracle 8i and higher, you can fetch more then one row at a time into collection, using the BULK COLLECT clause. This clause is used as part of the SELECT INTO, FETCH INTO, or RETURNING INTO clause, and will retrieve rows from the query into indicated collections.

Example 5-15 on page 174 can be re-written using the BULK COLLECT clause as following:

   DECLARE
       TYPE EmpList IS TABLE OF emp_table.ename%TYPE ;
       CURSOR c1 IS
          SELECT emp_name
          FROM emp_table
          WHERE dept = v_dept;
   BEGIN
       OPEN c1;
       FETCH c1 BULK COLLECT INTO EmpList;
       CLOSE c1;
   END;

or

   DECLARE
      TYPE EmpList IS TABLE OF emp_table.ename%TYPE ;
   BEGIN
      SELECT emp_name BULK COLLECT INTO EmpList;
   END;

Oracle will treat SELECT INTO as implicit cursor. It will fetch the data starting at index 1, and successively overwrite elements in the output collection EmpList until it retrieved all requested rows.

To convert BULK COLLECT statement to DB2, you can use DB2 DGTT as shown in Example 5-16 on page 174, or in some cases you can use INSERT INTO (SELECT * FROM) statement, as it shows bellow (Example 5-18).

Example 5-18: DB2 UDB code using INSERT INTO
Start example
DECLARE v_empname varchar(30);
DECLARE v_num INT DEFAULT 0;
DECLARE GLOBAL TEMPORARY TABLE SESSION.temp_emp_list
        (num INTEGER, EmpName VARCHAR(30))
        WITH REPLACE
        ON COMMIT PRESERVE ROWS
        NOT LOGGED;
INSERT INTO SESSION.temp_emp_list (
   SELECT emp_name
   FROM emp_table
   WHERE detp = v_dept);
End example

For more information on the GLOBAL TEMPORARY TABLE refer to the DB2 UDB V8 manual SQL Reference Volume 2.

5.5.3 Passing result sets between procedures

In previous section, we discuss the general conversion principals for Oracle collection. This section demonstrates the special case of passing a multiple row result from one procedure to another.

It is often convenient to manipulate many variables at once as one unit. Oracle nested tables and varrays are frequently used to implement this kind of application.

For example, we need retrieve all employees from a specified department, who have an account code equal to 307, and pass the result to a PL/SQL block (it could as well be a client program). Here is a PL/SQL procedure that returns nested tables as the output parameter (Example 5-19).

Example 5-19: PL/SQL procedure returns nested table
Start example
CREATE PACKAGE BODY AccountPackage AS
  PROCEDURE AccountList(p_dept_code    IN     accounts.dept_code%TYPE,
                        p_acct_id      IN     accounts.acct_id%TYPE,
                        p_IDs          OUT    t_EmployeeIDTable,
                        p_NumEmployees IN OUT NUMBER) IS
      v_EmployeeID Employees.Emp_id%TYPE;

      -- Local cursor to fetch the registered Employees.
      CURSOR c_RegisteredEmployees IS
        SELECT Emp_id
          FROM Employees
          WHERE dept_code = p_dept_code
          AND acct_id = p_acct_id;
    BEGIN
      /* p_NumEmployees will be the table index. It will start at
         0, and be incremented each time through the fetch loop.
         At the end of the loop, it will have the number of rows
         fetched, and therefore the number of rows returned in
         p_IDs. */
      p_NumEmployees := 0;
      OPEN c_RegisteredEmployees;
      LOOP
        FETCH c_RegisteredEmployees INTO v_EmployeeID;
        EXIT WHEN c_RegisteredEmployees%NOTFOUND;

        p_NumEmployees := p_NumEmployees + 1;
        p_IDs(p_NumEmployees) := vEmployeeID;
      END LOOP;
    END AccountList;
END AccountPackage;
End example

Please note that type t_EmployeeIDTable should be declared within AccountPackage specification as follows:

   TYPE t_EmployeeIDTable IS TABLE OF Employees.Emp_id%TYPE;

The AccountList procedure can be called from the following PL/SQL block:

   DECLARE
     v_DeptEmployees   AccountPackage.t_EmployeeIDTable;
     v_NumEmployees   BINARY_INTEGER := 20;

   BEGIN
     -- Fill the PL/SQL table with employees from dept 'BA'
     AccountPackage.AccountList('BA', 307, v_DeptEmployees,v_NumEmployees);

     -- Insert these employee into temp_table

     FOR v_LoopCounter IN 1..v_NumEmployees
     LOOP
       INSERT INTO temp_table (num_col, char_col)
         VALUES (v_DeptEmployees(v_LoopCounter),
                  'In Department BA');
     END LOOP;
   END;

Using nested table t_EmployeeIDTable, the results from cursor c_RegisteredEmployees are passed to the calling block as one unit or as one output variable.

DB2 has a different mechanism for processing multiple rows results. SQL procedure uses the following to return the result set to a caller:

  • Specify DYNAMIC RESULT SETS clause in CREATE PROCEDURE statement.

  • Declare the cursor using WITH RETURN clause.

  • Keep the cursor open for the client application.

  • Unlike Oracle, no parameter is required for the result set to be passed out of this procedure.

Example 5-20 shows how a SQL procedure can pass results from the same cursor to the calling application. The name of the cursor has been changed to adhere to the DB2 18 character limit.

Example 5-20: SQL Procedure returns multiple rows using CURSOR WITH RETURN
Start example
CREATE PROCEDURE AccountPackage.AccountList ( IN p_dept_code CHAR(3),
                                              IN p_acct_id SMALLINT )
LANGUAGE SQL
RESULT SET 1

BEGIN

    DECLARE SQLCODE INTEGER DEFAULT 0;

    DECLARE c_RegisteredEmplo1 CURSOR WITH RETURN TO CALLER
     FOR SELECT "EMP_ID"
         FROM EMPLOYEES
       WHERE "DEPT_CODE" = p_dept_code
         AND "ACCT_ID" = p_acct_id;

      OPEN c_RegisteredEmplo1;

END
End example

There are two options for WITH RETURN clause:

  • WITH RETURN TO CALLER (default): Use this option to return the result set to the invoker, whether the invoker is an application or another procedure.

  • WITH RETURN TO CLIENT: Use this option to return the result set directly to the application, bypassing any intermediate nested routines.

To imitate Oracle example in full, let us convert a PL/SQL block that calls the AcountPackage.AccountList procedure to a DB2 SQL procedure as shown in Example 5-21.

Listing 5-21: DB2 Store procedure calls AccountPackage.AccountList
Start example
CREATE PROCEDURE AccountPackage.CALL_AccountList ( )
   LANGUAGE SQL
BEGIN
   DECLARE sqlcode  INT DEFAULT 0;
   DECLARE v_empId  INT DEFAULT 0;
   DECLARE v_empNum INT DEFAULT 0;
   DECLARE v_empCnt INT DEFAULT 0;
   DECLARE loc1     RESULT_SET_LOCATOR VARYING;            -- [1]

   SET v_empNum = 20;

   CALL AccountPackage.AccountList('BA',307);
   ASSOCIATE RESULT SET LOCATOR( loc1) WITH                -- [2]
           PROCEDURE  AccountPackage.AccountList;

   ALLOCATE c1 CURSOR FOR RESULT SET loc1;                 -- [3]

L1: LOOP
    FETCH FROM c1 INTO v_empID;
    IF (sqlcode = 100) or (v_empCnt > v_empNum)
      THEN LEAVE L1;
    ELSE
      SET v_empCnt = v_empCnt + 1;
      INSERT INTO temp_table (num_col, char_col)
           VALUES (v_empId, 'IN DEPARTMENT ');
    END IF;
  END LOOP L1;
END
End example

Note

To receive result sets in SQL procedures, it is necessary to:

[1] | DECLARE result set locators to the stored procedure expected to return these result sets.
[2] | ASSOCIATE result set locators to the stored procedure expected to return these result sets.
[3] | ALLOCATE each cursor expected to be returned to a result set locator.

Once this is done, rows can be fetched from the result sets. Please note that the cursor in this case plays the role of an Oracle nested table, and allows you to pass multiple variables (result set from cursor) as one unit.


5.6 Condition handling

This section discusses the various methods of implementing condition handling conversion.

5.6.1 Condition handling in stored procedure

Both PL/SQL and SQL PL support EXCEPTION HANDLERS to trap SQL errors and handle them. This mechanism permits separation of a procedure's error processing from its main logic.

PL/SQL uses the following syntax for EXCEPTION:

   EXCEPTION
      WHEN exception_name1 THEN <executable statements>
      WHEN exception_name2 THEN <executable statements>
      ...
      WHEN exception_nameN THEN <executable statements>
      WHEN OTHER <executable statements> ;

Where exception_name is one of the predefined exceptions (NO_DATA_FOUND, TOO_MANY_ROWS) or has been defined using the following syntax:

   exception_name EXCEPTION;
      PRAGMA EXCEPTION_INIT(exception_name, SQLCODE);

In DB2, SQL procedures exception handling is accomplished through the use of condition handlers.

A condition handler is an SQL statement that is executed when a specified condition is encountered during execution of a statement within the body of a procedure. The handler is declared within a compound statement, and the handler's scope is limited to that compound statement.

The following is the syntax for condition handler declaration:

   DECLARE {CONTINUE | EXIT | UNDO} HANDLER FOR <condition>
                SQL-procedure-statement;

where <condition> is one of the following:

  • SQLSTATE value

  • SQLEXEPTION (SQLCODE < 0)

  • SQLWARNING (SQLCODE > 0)

  • NOT FOUND

  • Condition name

    Warning

    In DB2, an INSERT, UPDATE or DELETE, which affects no rows also results in a NOT FOUND condition (+100). In absence of a NOT FOUND handler, the SQLWARNING handler will be invoked.

Based on this, to convert the following PL/SQL code to DB2:

   EXCEPTION
     WHEN NO_DATA_FOUND THEN v_status :=0;
     WHEN OTHER   THEN v_err_flag :=1;

Two condition handlers need to be declared:

   DECLARE CONTINUE HANDLER FOR NOT FOUND
     SET v_status   = 0;
   DECLARE CONTINUE HANDLER FOR SQLEXCEPTION
     SET v_err_flag = 1;

In the above example, Oracle exception name corresponds to a DB2 condition name, and the predefined NO_DATA_FOUND exception corresponds to the NOT FOUND condition. To match other Oracle predefined exceptions, the appropriate DB2 SQLSTATE values would have to be used, and the condition would be defined using the following syntax:

   DECLARE  condition_name CONDITION FOR SQLSTATE value;

For example, Oracle predefined exception TOO_MANY_ROWS can be converted using the following statement:

   DECLARE too_many_rows CONDITION FOR SQLSTATE '21000';

then a HANDLER for this CONDITION can be declared as follows:

   DECLARE EXIT HANDLER FOR too_many_rows
   BEGIN
   ...
   END;

The following procedure (Example 5-22) is to update title_desc column declared as char(50). If in_title_desc is longer then 50 characters, SQLEXCEPTION value is too long would occur and invoke the declared HANDLER. As a result, the table will not be updated and err_num = -433 will be returned as an output parameter.

Example 5-22: Condition handler - SQL EXCEPTION
Start example
CREATE PROCEDURE new_title ( IN in_title_desc varchar(100)
                            ,OUT err_num INT )
LANGUAGE SQL
P1: BEGIN
    DECLARE SQLCODE INTEGER DEFAULT 0;
    DECLARE SQLSTATE CHAR(5) DEFAULT ' ';

    DECLARE CONTINUE HANDLER FOR SQLEXCEPTION, SQLWARNING
      SET err_num = SQLCODE;

    UPDATE books
    SET title_desc = in_title_desc
    WHERE author = 'JACK LONDON';
END P1
End example

The example below demonstrates the usage of CONDITION HANDLERS in SQL procedures.

Note

This example uses a CONTINUE handler. That is, after the handler logic is complete, the flow of control continues from where the condition originally occurred. Without the continue handler, the procedure would have exited early, and returned an exception to the application.

Now, the above procedure can be changed to HANDLE a long value of title_desc and, should a value longer than 50 characters occur, update the books table with a truncated value. See Example 5-23.

Example 5-23: Condition handler - handle a long value
Start example
CREATE PROCEDURE new_title_1 ( IN in_title_desc VARCHAR(100)
                               ,OUT message_out CHAR(70) )
LANGUAGE SQL
P1: BEGIN
    DECLARE SQLCODE INTEGER  DEFAULT 0;
    DECLARE SQLSTATE CHAR(5) DEFAULT ' ';
    DECLARE v_trunc INT      DEFAULT 0;
    DECLARE value_error CONDITION FOR SQLSTATE '22001';

    DECLARE CONTINUE HANDLER FOR value_error
    BEGIN
       UPDATE books
       SET title_desc = substr(in_title_desc,1,50)
       WHERE author = 'JACK LONDON';
       SET v_trunc = 1;
    END;

    UPDATE books
    SET title_desc = in_title_desc
    WHERE author = 'JACK LONDON';

    IF v_trunc = 0 THEN
       SET message_out = 'TITLE UPDATED WITHOUT PROBLEM';
    ELSE
       SET message_out = 'TITLE UPDATED WITH TRUNCATION' ;
    END IF;
END P1
End example

5.6.2 Condition handling in triggers and functions

As discussed section 5.2, "Comparing SQL PL and inline SQL PL" on page 152, triggers and functions use a subset of the full SQL PL language called inline SQL PL. Unfortunately, condition handling is not supported in triggers or functions. However, there are often cases where condition handlers may not be required. Here we present some examples.

Consider the following Oracle function, which contains a condition handler:

   CREATE OR REPLACE FUNCTION func_with_handler1
   RETURN NUMBER
   AS
      v_id NUMBER;
   BEGIN
      BEGIN
         SELECT ObjID
         INTO v_id
         FROM T1;
         EXCEPTION WHEN OTHERS THEN
         v_Id := 0;
      END;
      RETURN v_id;
   END;

When converted through MTK, this function is converted as a stored procedure because a condition handler is not supported in DB2 functions. In some cases, this may be the appropriate conversion. If this function were used in an SQL statement however, we would need to make an effort to retain it as a function in DB2.

Upon closer examination of this function, you can see that the function can be rewritten without handlers provided that the column ObjID in table T1 is not nullable. It can be rewritten as follows:

   CREATE FUNCTION func_with_handler1()
   RETURNS INT
   BEGIN ATOMIC
       DECLARE v_id INT;
      SET (v_id) = (SELECT ObjID FROM T1);
      IF (v_id = NULL) THEN
          SET v_id = 0;
      END IF;
      RETURN v_id;
   END

The value of v_id is set to null if the SELECT statement returns no rows. Assuming the column ObjID is not nullable, if v_id is null after SELECT, it must be the case that no rows were returned. The same technique can be applied to triggers.

Of course, it could very well be that the logic is so complex that such a simple substitution is not possible. In that case, the other option is to change your application so that the function operates without handlers. If an error does occur, then the exception will be returned to the function caller (be it a stored procedure or the application itself) for handling.

5.6.3 Converting RAISE_APPLICATION_ERROR

Oracle PL/SQL permits issuance of user-defined error messages from stored procedures using RAISE_APPLICATION_ERROR. Thus, errors can be reported to the application. To call raise_application_error, the following syntax can be used:

   raise_application_error(error_number, message[, {TRUE | FALSE}]);

DB2 SQL procedures support SIGNAL SQLSTATE statements to provide a similar functionality.

Example 5-24 shows how to rewrite new_title procedure to report a detection of input value longer than 50 characters.

Example 5-24: Condition handler - SIGNAL SQLSTATE
Start example
   CREATE PROCEDURE new_title_2 (IN in_title_desc VARCHAR(100))
   LANGUAGE SQL
   P1: BEGIN
       DECLARE SQLCODE INTEGER   DEFAULT 0;
       DECLARE SQLSTATE CHAR(5)  DEFAULT ' ';

       IF (length(in_title_desc) > 50) THEN
          SIGNAL SQLSTATE '71001'
          SET MESSAGE_TEXT = 'Value for update is too long';
       ELSE
          UPDATE books
          SET title_desc = in_title_desc
          WHERE author = 'JACK LONDON';
       END IF;
   END P1
End example

In ORACLE PL/SQL exception handler, functions SQLCODE and SQLERRM can be used to determine which error occurred and to get the associated error message.

DB2 SQL PL supports the GET DIAGNOSTICS statement to obtain information related to the SQL statement just executed. This statement can be used within CONDITION HANDLER declaration to return message associated with the error:

   DECLARE EXIT HANDLER FOR SQLEXCEPTION
   GET DIAGNOSTICS EXCEPTION 1 out_err_msg = MESSAGE_TEXT;

Together with the error message, GET DIAGNOSTICS permits retrieval of the number of rows that were affected by the previous UPDATE, DELETE, or INSERT statement:

   GET DIAGNOSTICS v_rowcount = ROW_COUNT;

The RETURN value of a nested procedure can be retrieved by using:

   GET DIAGNOSTICS v_retcode = RETURN_STATUS;


5.7 Package initialization

With Oracle you can define initialization in PL/SQL packages, which is executed only one time when starting a new database session. Example 5-25 shows the initialization within an Oracle package.

Example 5-25: Oracle package with initialization
Start example
CREATE OR REPLACE PACKAGE BODY pkg_init_v1 AS

   -- function / procedure definition
   -- ...

-- Body initialization
BEGIN
   -- ...
END pkg_init_v1;
End example

In DB2 UDB, each SQL PL block is a function or procedure beginning with CREATE FUNCTION or CREATE PROCEDURE. MTK is able to convert the Example 5-25 if you define a procedure with the initialization commands.

Example 5-26 shows an alternative of Example 5-25 with the same behavior. In the initialization, part is now only the call of the procedure init, within init is the source of the initialization.

Example 5-26: Oracle package with initialization as procedure
Start example
CREATE OR REPLACE PACKAGE BODY pkg_init_v2 AS

   -- function / procedure definition
   -- ...

-- initialization procedure
PROCEDURE init IS
BEGIN
   -- ...
END;

-- Body initialization
BEGIN
   init;
END pkg_init_v2;
End example

Within your application, you have to add the call of the procedure init to perform the initialization every time you connect to the database.


5.8 Global variables

Global variables in Oracle are distinct for each connected user. The variables are global to the connection. The appropriate conversion is to use DB2 global temporary tables.

Example 5-27 shows you a simple Oracle package with the definition and initialization of two global variables.

Example 5-27: Definition of global variables in Oracle
Start example
CREATE OR REPLACE PACKAGE pkg_gv IS

   global_variable_1  VARCHAR2(128) := NULL;
   global_variable_2  INTEGER       := 1;

END pkg_gv;
End example
Definition and initialization

The following Example 5-28 is a DB2 stored procedure with the definition of a global temporary table. The table contains all the global variables you need within a session. Each column of the table corresponds to a global variable. The table needs only to have one row with the respective values.

Example 5-28: Temporary table with global variables
Start example
CREATE PROCEDURE init_global_variables
LANGUAGE SQL
BEGIN
   -- declare temporary table for global variables
   DECLARE GLOBAL TEMPORARY TABLE session.global_variables (
       global_variable_1    VARCHAR(128)
       ,global_variable_2   INTEGER )
   ON COMMIT PRESERVE ROWS;

   -- initialize global variables
   INSERT INTO session.global_variables (
       global_variable_1
      ,global_variable_2 )
   VALUES ( null
           ,0 );
END!
End example

The INSERT statement is necessary to initialize the global variables.

Note

ON COMMIT PRESERVE ROWS indicates that rows of the table will be preserved after ending a transaction with COMMIT.

Using a procedure to initialize the temporary table yields two key benefits:

  • The procedure developer does not have to hunt through application code (which may be maintained by another person) to find the DDL of the temporary table.

  • The definition of the table is centralized at one place. Should the global variables require changes, you do not have to search for all the declarations, just change the definition at one place.

As mentioned before, the values of the global variables are distinct for each connection. This means that you have to define the DB2 global temporary table at the beginning of each session. To do this with the definition of Example 5-28, you need to call the stored procedure init_global_variables after you connect to the DB2 database in your application.

When developing/converting other procedures, which rely on these global variables, you will have to first run the init_global_variables procedure first to define the temporary table in the current connection. Otherwise, DB2 will not be able to resolve references to the temporary table at build time.

Setting values of global variables

To set a new value to a global variable, use an UPDATE statement to the corresponding column in the temporary table GLOBAL_VARIABLES:

   UPDATE session.global_variables
      SET global_variable_1 = new_value;
Getting values of global variables

The get a value of a global variable use a SELECT statement to the corresponding column in the temporary table GLOBAL_VARIABLES:

   SELECT global_variable_1
      INTO gv_value
      FROM session.global_variables
      FETCH FIRST 1 ROWS ONLY;

Under normal circumstances you only have one row in the GLOBAL_VARIABLES table. To be sure to get not more than one row as result of the SELECT statement use the FETCH FIRST 1 ROWS ONLY clause.

To protect user from direct access to the global temporary table you may optionally encapsulate the statements to set/get values in stored procedures. In this case, you have to implement a procedure for each global variable. After that, you have to grant the user the appropriate authority.

Using INOUT parameters

When using only a few global variables shared by a few procedures, it might be more practical to simply convert the global variables as parameters. In this case, change the parameter definition of the procedures (which uses global variables) by adding an INOUT parameter for each of the global variables.


5.9 Hierarchical queries

With Oracle CONNECT BY ... START WITH ...clause can be used to select data that has a hierarchical relationship, usually some sort of parent - child relationships. In Example 5-29, the table EMPLOYEES consists of just these attributes: parent and child. We make sure (by means of a unique constraint) that the child is unique within the table.

Example 5-29: Oracle hierarchical query
Start example
SELECT  substr(lpad(' ', level * 2) || emp_id,1,20) AS emp_id
      , last_name
      , emp_mgr_id
      , level
FROM  employees
CONNECT BY PRIOR emp_id = emp_mgr_id
START WITH emp_mgr_id IS NULL;

EMP_ID               LAST_NAME            EMP_MGR_ID      LEVEL
-------------------- -------------------- ---------- ----------
  10000               Sands                                   1
  10001               Marcus                   10000          2
  10004               Polite                   10001          3
  10005               Tenor                    10001          3
  10002               January                  10000          2
  10008               Even                     10002          3
  10010               December                 10002          3
  10011               August                   10002          3
  10003               March                    10000          2
  10006               Blonde                   10003          3
  10007               Damon                    10003          3
  10009               Ration                   10003          3
End example

In the following we provide you a DB2 UDF to get the same result. The identity of each row is actually its encoded position in the hierarchy. This is arbitrary. The solution also assumes that the resulting sorting can be done based on the path. Here this works as long as not more than nine siblings exist on any given level. However, a simple formatting of the path to a specific number of digits per level can solve this problem.

The script uses SQL table functions. This capability however is only used for encapsulation and not required for function.

The function get_direct_childs() collects all immediate children of a node in the hierarchy and returns them together with their relative position to each other and in the tree; see Example 5-30.

Example 5-30: Computing of direct child data
Start example
CREATE FUNCTION get_direct_childs(code VARCHAR(30), parent INTEGER)
RETURNS TABLE(code VARCHAR(30), id INTEGER)
READS SQL DATA
DETERMINISTIC
NO EXTERNAL ACTION
RETURN
  SELECT code || '.' || RTRIM(CHAR(RANK() OVER (ORDER BY child_id))),
  child_id
    FROM (SELECT empno FROM emp
          WHERE emp.mgr
                = get_direct_childs.parent)
          AS T(child_id)!
End example

The function get_rec_childs() contains the recursive logic. It starts with the root, which is provided by the caller, and then collects children until no more new children can be found. See Example 5-31.

Example 5-31: Hierarchical query with entry point
Start example
CREATE FUNCTION get_rec_childs(root INTEGER)
RETURNS TABLE(code VARCHAR(30), id INTEGER)
READS SQL DATA
DETERMINISTIC
NO EXTERNAL ACTION
RETURN
  WITH rec(code, id)
    AS (VALUES(CAST('1' AS VARCHAR(30)), root)
        UNION ALL
        SELECT t.code, t.id
          FROM rec, TABLE(get_direct_childs(rec.code, rec.id)) AS T)
    SELECT code, id FROM rec !
End example

This function get_level() compute the hierarchy level of the current data; see Example 5-32.

Example 5-32: Compute hierarchy level
Start example
CREATE FUNCTION get_level(code VARCHAR(30))
RETURNS INTEGER
DETERMINISTIC
NO EXTERNAL ACTION
RETURN
  (length(code) - length(replace(code, '.', '')))!
End example

You get the hierarchy tree with the UDF get_rec_childs(). As a parameter, you have to specify the root.

In Example 5-33 you see the use of the hierarchy function and its output with an adequate format.

Example 5-33: Sample use of hierarchical query
Start example
SELECT  T.code
       ,T.id
       ,substr(  (space(2 * get_level(code)) || employees.last_name)
                , 1
                , 20) as last_name
       ,emp_mgr_id
FROM  TABLE(get_rec_childs(10000)) AS T
     ,employees
where T.id = employees.emp_id
ORDER BY code!

CODE        ID          LAST_NAME            EMP_MGR_ID
----------- ----------- -------------------- -----------
1                 10000  Sands                         -
1.1               10001  Marcus                    10000
1.1.1             10004  Polite                    10001
1.1.2             10005  Tenor                     10001
1.2               10002  January                   10000
1.2.1             10008  Even                      10002
1.2.2             10010  December                  10002
1.2.3             10011  August                    10002
1.3               10003  March                     10000
1.3.1             10006  Blonde                    10003
1.3.2             10007  Damon                     10003
1.3.3             10009  Ration                    10003
End example


5.10 Print output messages

When converting the call statement of Oracle function dbms_out.put.put_line(), MTK provides only a function skeleton for you. You still need to implement the function, which will best suit your application needs.

We offer you a user-defined function (UDF) solution called PUT_LINE() that will enable file output from pure SQL, such as an SQL stored procedure. You can use it as a tool for debugging stored procedures, but it also allows you to write to a specified file for other purposes as well.

You can find the sources of the function and a installation guide as additional material on the IBM Redbooks Internet site. See details on Appendix G, "Additional material" on page 415.


5.11 Implicit casting in SQL

In addition to syntax differences, we should highlight differences in how Oracle and DB2 handle data type casting. Whether you know it or not, Oracle performs implicit casting of data types (as required) while DB2 is strongly typed. Consider the following example:

   [1] create table t1 (c1 number);
   [2] insert into t1 ('1')
   [3] select * from t1 where c1='1'

In the first line, we create a table T1 which has a numeric column. In line two, however, the character value 1 can be inserted into T1 without error. The value was implicitly casted by Oracle from varchar2 to number. In line three, we have yet another example of implicit casting as the predicate c1 (numeric type) and 1 (character type) are allowed to be compared. Certainly there are many more cases than this. Implicit casting can happen in a variety of cases.

Because DB2 is strongly typed, SQL may have to be slightly rewritten to perform explicit casts. Implicit casting can be good and bad. It certainly makes SQL programming easier, but it can also be dangerous, and incurs some overhead, which is why purists will discourage its use.

Following the previous example, we can rewrite the series of SQL as follows:

   [1] create table t1 (c1 INT);
   [2] insert into t1 (1)
   [3] select * from t1 where c1=1

Of course, these are the easiest cases to solve because it is obvious where the problem lies. Another common place where implicit casting must be resolved is in functions and operators. For example:

   create procedure echo_input (v_num in numver(9,0), v_echo out varchar2)
   as
   begin
       v_echo := ' Input number is: ' || v_num;
   end;

In this case, the concatenation operator (||) in Oracle will automatically cast v_num to varchar2 so that the strings can be combined. In DB2, v_num will have to be explicitly cast to a character type. If you convert this code through MTK, it will help you identify all places where implicit casting is occurring by providing code to perform explicit casting. If you decide to perform a conversion without tools, it will take more time to find them.

Based on past experience, among the most time consuming porting activities will revolve around converting implicit casting to explicit casting in dynamic SQL. Because dynamic SQL, in general, cannot be fully resolved until runtime, MTK is not able to determine the proper casting functions to apply.

Consider the following example:

   create procedure dyn_cast
   as
       val varchar2(100) := '100';
   begin
       EXECUTE IMMEDIATE 'CREATE TABLE T1 (C1 number)';
       EXECUTE IMMEDIATE 'INSERT INTO T1 VALUES ( ''' || val || ''')';
   end;

Here we create a table T1 with a numeric column C1. When you convert to DB2, the procedure will build with very few changes. The final SQL statement as submitted to the database engine will look like this:

   INSERT INTO T1 VALUES ('100');

It will fail, however, at runtime because implicit casting is occurring in the INSERT statement.

Dealing with implicit casting will be quite troublesome at first, but as you troubleshoot these problems, you will learn to quickly identify these situations. The upside is that it will ultimately make your applications cleaner and in some cases, perform better (especially in high volume SQL statements).


5.12 Outer join

Both Oracle and DB2 support outer join. DB2 UDB supports the ANSI SQL syntax for three types of outer join: right, left, and full. Oracle supports the same syntax, starting in version 9i. Oracle also has proprietary left and right outer join syntax that DB2 does not support. Table 5-4 demonstrates how to map this old syntax to the DB2 equivalent for simple examples.

Table 5-4: Mapping of join definition

Oracle

DB2 UDB

SELECT A.last_name, A.id,B.name
FROM emp A, Customer B
WHERE A.id (+) = B.sales_rep_id;

SELECT A.last_name,A.id,B.name
FROM emp A
RIGHT OUTER JOIN customer B
ON A.id = B.sales_rep_id;

SELECT A.last_name, A.id,B.name
FROM emp A, Customer B
WHERE A.id = B.sales_rep_id (+);

SELECT A.last_name,A.id,B.name
FROM emp A
LEFT OUTER JOIN customer B
ON A.id = B.sales_rep_id;

SELECT A.last_name, A.id,B.name
FROM emp A, Customer B
WHERE A.id (+) = B.sales_rep_id (+);

SELECT A.last_name,A.id,B.name
FROM emp A
FULL OUTER JOIN customer B
ON A.id = B.sales_rep_id;

The MTK provides basic support for Oracle outer joins, with the following restrictions:

  • Only the equality (=) operator is supported.

  • The (+) operator cannot follow a complex expression; it can follow a column reference only.

In some cases, the MTK will not be able to convert complex outer join syntax. The following example shows how a complex SQL statement involving multiple outer joins can be mapped from Oracle to DB2 syntax.

It is important to realize that in Oracle, outer joins are defined in the WHERE clause, whereas in DB2 they are defined in the FROM clause. Further, the outer join condition of the two tables must be specified in the ON clause, not in the WHERE clause.

Example 5-34 shows the Oracle outer join syntax:

Example 5-34: Oracle outer joins
Start example
SELECT
   t1.surname
FROM
   EXAMPLE_TABLE1 t1,
   EXAMPLE_TABLE2 t2,
   EXAMPLE_TABLE3 t3,
   EXAMPLE_TABLE4 t4
WHERE
      ((t1.emptype = 1) OR (t1.position = 'Manager'))
   AND (t1.empid = t2.empid(+))
   AND (t2.empid = t3.empid(+))
   AND (t2.sin = t3.sin(+))
   AND (t3.jobtype(+) = 'Full-Time')
   AND (t2.empid = t4.empid(+))
   AND (t2.sin = t4.sin(+))
ORDER BY
   t1.emptype, t2.other
End example

Example 5-35 shows the DB2 conversion:

Example 5-35: DB2 outer join conversion
Start example
SELECT
   t1.surname,
FROM
      EXAMPLE_TABLE1 t1 LEFT OUTER JOIN
        EXAMPLE_TABLE2 t2 ON (t2.empid = t1.empid) LEFT OUTER JOIN
          EXAMPLE_TABLE3 t3 ON (t3.sin = t2.sin)
                                  AND (t3.empid = t2.empid)
                                  AND (t3.jobtype = 'Full-Time')
                               LEFT OUTER JOIN
            EXAMPLE_TABLE4 t4 ON (t4.sin = t2.sin)
                                  AND (t4.empid = t2.empid)
WHERE
   ((t1.emptype = 1) OR (t1.position = 'Manager'))
ORDER BY
   t1.emptype, t2.other
End example


5.13 Decode statement

Oracle DECODE statement can be converted to DB2 CASE statement in two ways:

   DECODE (condition, case1, assign1, case2, assign 2....,default)

This can be converted to the simple CASE statement:

   CASE condition
      WHEN case1 THEN assign 1
      WHEN case2 THEN assign 2
      ....
      ELSE default
   END

Or, to the searched CASE statement:

   CASE
      WHEN condition THEN assign 1
      WHEN condition THEN assign 2
      ....
      ELSE default
   END

For example, the Oracle code:

   SELECT AVG(DECODE(Grade, 'A', 1,
                            'B', 2,
                            'C', 3,
                            'D', 4,
                            'E', 5))
   INTO v_Grade FROM Students
   WHERE DEPARTMENT = p_Department AND Course_ID = p_Course_ID;

This can be converted to DB2 code:

   SELECT AVG(CASE GRADE WHEN 'A' THEN 1
                         WHEN 'B' THEN 2
                         WHEN 'C' THEN 3
                         WHEN 'D' THEN 4
                         WHEN 'E' THEN 5
                         END) INTO v_Grade
   FROM Students
   WHERE DEPARTMENT = p_Department
     AND Course_ID = p_Course_ID;


5.14 Rownum

Oracle uses ROWNUM pseudo-column to control the number of rows returned from an SQL statement. In DB2 you determine the number of rows to read with the FETCH FIRST n ROWS ONLY statement.

Table 5-5 bellow shows how different statements can be converted.

Table 5-5: Mapping of ROWNUM function

Oracle

DB2 UDB

SELECT

select * from tab1 where
ROWNUM < 2

select * from tab1
FETCH FIRST 1 ROW ONLY;

UPDATE

update tab1
set c1 = v1
where c2 = v2
and ROWNUM <= 10

FOR lv as temp_cur CURSOR FOR
  SELECT *
    FROM tab1
    WHERE c2 = v2
    FETCH FIRST 10 ROWS ONLY
  FOR UPDATE DO
    UPDATE tab1
    SET c1 = v1
    WHERE CURRENT OF temp_cur;
END FOR;

With FixPak 4 or above:
UPDATE (select c1 from tab1where
c2=v2 fetch first 10 rows only)
set c1=v1

DELETE

delete from tab1
where ROWNUM <= 100

FOR lv as temp_cur CURSOR FOR
  SELECT * FROM tab1
  FETCH FIRST 100 ROWS ONLY
  FOR UPDATE DO
    DELETE FROM tab1
    WHERE CURRENT OF temp_cur;
END FOR;

With FixPak 4 or above:
DELETE FROM (SELECT 1 FROM tab1
FETCH FIRST 100 ROWS ONLY)


5.15 INSERT, UPDATE, DELETE returning values

DB2 UDB has introduced several new features in FixPak 4. With FixPak 4, you can use SELECT and SELECT INTO statements to retrieve result sets from SQL data-change operations (INSERT, UPDATE, and DELETE) embedded in the FROM clause. This new feature can be used to migration Oracle code using the similar feature. Example 5-36 is a sample Oracle code using RETURNING INTO statement to retrieve value after updating a table. Example 5-37 and Example 5-38 shows two ways to convert this Oracle code into DB2 code.

Example 5-36: Oracle code using RETURNING INTO
Start example
Update staff
Set salary =10000.0
where id =p_id
returning name into p_name;
End example
Example 5-37: DB2 code using SELECT INTO
Start example
SELECT name INTO p_name
FROM NEW TABLE (
      UPDATE staff
      SET salary = 10000.0
      WHERE id = p_id);
End example
Example 5-38: DB2 CODE using SELECT
Start example
set p_name = (SELECT name
FROM NEW TABLE (
       UPDATE staff
       SET salary = 10000.0
       WHERE id = p_id));
End example


5.16 Select from DUAL

Oracle provides a dummy table called DUAL, which is frequently used to retrieve system information. When converting references to DUAL, you have several options:

  • Change the SELECT statement to a VALUES statement.

  • Directly assign special registers to variables (in SQL PL).

  • Create a table/view called DUAL to mimic the Oracle DUAL table (DUAL would need to be created/aliased under all schemas).

  • Use the DB2 dummy table SYSIBM.SYSDUMMY1, which has a single row and one column, IBMREQD, with a value of Y.

  • Create a synonym of SYSIBM.SYSDUMMY1 called DUAL.

Table 5-6: Use of dummy table for system information

Oracle

DB2 UDB

select SYSDATE from DUAL

VALUES(CURRENT TIMESTAMP) INTO <variable>

or

select CURRENT TIMESTAMP from
SYSIBM.SYSDUMMY1

In some circumstances it may be too costly to comb through all source code to convert references to DUAL and Oracle system variables to use DB2 syntax. As an alternative, you can preserve your existing SQL by defining a view named DUAL with the (column) value(s) you need. Example 5-39 illustrates.

Example 5-39: DB2 dummy view for system information
Start example
create view dual (sysdate)
as select CURRENT TIMESTAMP from SYSIBM.SYSDUMMY1
!
End example

The result looks like

   db2 => select sysdate from dual

   SYSDATE
   --------------------------
   2003-10-15-18.03.59.399071

     1 record(s) selected.


5.17 Manipulating date and time

Both Oracle and DB2 UDB have date and time data types and functions to get the date and time from system or convert the date and time into different formats, and perform arithmetic on dates. Oracle has DATE, which can be mapped to DB2 TIMESTAMP. DB2 has two other date and time functions called DATE and TIME.

If your applications only use the date portion of Oracle's date data type, it will be more efficient to convert these types to DB2's DATE type (rather than TIMESTAMP). Here we show you some examples on date manipulation.

  • Getting dates

    In Oracle, you use SELECT to get the date as following:

       SELECT sysdate from dual;

    In DB2, you use VALUES to get the date:

       SELECT current timestamp FROM sysibm.sysdummy1;
   SELECT current date FROM sysibm.sysdummy1;
   SELECT current time FROM sysibm.sysdummy1;

  • Converting dates

    To convert the date in Oracle, TO_CHAR is used:

       to_char(sysdate,'YYYY-MM-DD')
   to_char(sysdate,'MM/DD/YYYY')

    DB2 UDB V8.1 supports functions TO_CHAR and TO_DATE but for only one format, as illustrated here:

       TO_CHAR (timestamp_expression,'YYY-MM-DD HH24:MI:SS')
   TO_DATE (string_expression, 'YYY-MM-DD HH24:MI:SS')

    In addition, you can use the CHAR function to convert the date and specify the localized format such as:

       CHAR(current date,ISO);
   CHAR(current date,USA);

    The following are more examples demonstrate how DB2 dates can be converted to different formats:

       char(current date) = '10/01/2003'
   char(current date + 3 days) = '10/04/2003'
   char(current date,ISO) = '2003-10-01'
   char(current date,EUR) = '01.10.2003'
   char(current date,JIS) = '2003-10-01'
   char(current time,USA) = '02:21 PM'
   char(current time + 2 hours,EUR) ='16.21.23'
    Note

    For more information on using CHAR function for date/time conversion, refer to DB2 UDB SQL Reference.

  • Dates arithmetic

    Dates arithmetic is frequently used. The following is an Oracle example:

       add_months(sysdate,16)

    In DB2, the similar function can be implemented as following:

       current date + 16 months

    Here are other examples of how arithmetic manipulation can be done with DB2 dates:

       current date = 10/02/2003
   current date + 3 days = 10/05/2003
   current timestamp + 2 years = 2005-10-02-12.33.27.667000
   current timestamp - 2 months = 2003-08-02-12.33.27.667002
   current time + 5 minutes = 12:38:27

    DB2 also provides some more functions to manipulate with dates, such as days, dayname, monthname, and much more.

  • Using UDF

    Certain Oracle functions not supported by DB2 can be easily duplicated by writing UDF. For example, the following UDF can be used to convert the Oracle built-in function last_day:

       CREATE FUNCTION last_day(v_date date)
   RETURNS DATE
   SPECIFIC lastday
   LANGUAGE SQL
   CONTAINS SQL
   NO EXTERNAL ACTION
   DETERMINISTIC
   RETURN (v_date + 1 MONTHS) - DAY(v_date + 1 MONTHS) DAYS;

    You can find the UDF samples to convert Oracle DUMP(date), NEW_TIME, NEXT_DAY(), TRUNC() and other sample UDFs for migration at IBM Web site:

    http://www7b.software.ibm.com/dmdd/library/samples/db2/0205udfs/

    Another example of using DB2 UDF in dates arithmetic is converting the Oracle months_between function:

       months_between(sysdate,v_date)

    If you use MTK to automate your conversion, MTK will implement months_between as a User Defined Function and automatically deploy it into the database. The following is the source code for this function:

       CREATE FUNCTION months_between(d1 TIMESTAMP, d2 TIMESTAMP)
    RETURNS FLOAT
    LANGUAGE SQL
    DETERMINISTIC
    NO EXTERNAL ACTION
    CONTAINS SQL
    RETURN 12*(year(d1) - year(d2)) + month(d1) - month(d2)
           + (TIMESTAMPDIFF(2,CHAR(d1 - (d2 + (12*(year(d1) - year(d2))
              + month(d1) - month(d2)) MONTHS))) / 2678400.0)

    This function employs the DB2 built-in function TIMESTAMPDIFF. Details for TIMESTAMPDIFF can be found in the DB2 UDB manual SQL Reference.

For more information on manipulation with dates, refer to the article on the DB2 developer domain:

http://www7b.software.ibm.com/dmdd/library/techarticle/0211yip/0211yip3.html


5.18 Set operations

Set operators can be used to combine result sets in both Oracle and DB2 UDB. Table 5-7 shows the differences between the products.

Table 5-7: Mapping of set operations
Oracle | DB2 UDB
UNION | UNION
UNION ALL | UNION ALL
MINUS | EXCEPT
INTERSECT | INTERSECT

DB2 UDB supports the ALL option on each operator, allowing duplicates to be preserved. Oracle allows ALL only on UNION.

Null values conversion

In Oracle, function NVL provides a conversion of NULL values to non-null values:

   NVL(TO_CHAR(MANAGER_ID),'No Manager')

converts all of the NULL values in the manager_id column to the string: "No Manager"

In DB2, use the COALESCE function to convert nulls, as in:

   COALESCE(MANAGER_ID,'No Manager')


5.19 Function which returns rowtype

Oracle allows result sets to be returned from functions if its return type is a REF Cursor, as illustrated in Example 5-40. You will likely convert such functions as procedures in DB2 as this minimizes the amount of application changes required (you would simply add the word CALL in front of the function call). The (less desirable) alternative is to convert this as a table function, but table functions in DB2 have limited functionality, and the application must convert the function call into a select statement.

Example 5-40: Oracle function with a REF cursor
Start example
CREATE OR REPLACE PACKAGE ReturnRtype AS
  TYPE t_RefCur IS REF CURSOR;

  -- Selects from employees based on the supplied department,
  -- and returns the opened cursor variable.
  FUNCTION EmployeesQuery(p_Department IN VARCHAR2)
    RETURN t_RefCur;
END ReturnRtype;

CREATE OR REPLACE PACKAGE BODY ReturnRtype AS

  -- Selects from employees based on the supplied department,
  -- and returns the opened cursor variable.
  FUNCTION EmployeesQuery(p_Department IN VARCHAR2)
    RETURN t_RefCur IS
    v_ReturnCursor t_RefCur;
    v_SQLStatement VARCHAR2(500);
  BEGIN
    v_SQLStatement := 'SELECT * FROM employees WHERE department = :m';

    -- Open the cursor variable, and return it.
    OPEN v_ReturnCursor FOR v_SQLStatement USING p_Department;
    RETURN v_ReturnCursor;
  END EmployeesQuery;
END ReturnRtype;
End example

The converted DB2 code is shown in Example 5-41.

Example 5-41: Conversion to a procedure with a Result Set in DB2
Start example
Create Procedure EmployeesQuery (IN p_Department varchar(30))
LANGUAGE SQL
DYNAMIC RESULT SETS 1
BEGIN
   DECLARE C1 cursor with return to client for
   Select * from employees where department = p_Department;
   OPEN C1;
END!
End example


5.20 Local functions

Oracle allows procedures or functions - called Local Procedures or Local Functions - to be created and referenced within the body of a Stored Procedure. When converting this to DB2, the Local Procedure or Local Function must be created outside of the Stored Procedure that references it, before it can be used. The example below shows how a Local Function created and referenced in an Oracle Stored procedure would be converted to DB2.

Example 5-42 shows the Oracle source code of the function.

Example 5-42: Oracle procedure with Local function
Start example
CREATE OR REPLACE PROCEDURE callLocalFunc AS
  /* Local declarations, which include a cursor, variable, and a
     function. */
  CURSOR c_AllEmployees IS
    SELECT first_name, last_name
      FROM employees;

  v_FormattedName VARCHAR2(50);

  /* Function which will return the first and last name
     concatenated together, separated by a space. */
  FUNCTION FormatName(p_FirstName IN VARCHAR2,
                      p_LastName IN VARCHAR2)
    RETURN VARCHAR2 IS
  BEGIN
    RETURN p_FirstName || ' ' || p_LastName;
  END FormatName;

-- Begin main block.
BEGIN
  FOR v_EmployeeRecord IN c_AllEmployees LOOP
    v_FormattedName :=
      FormatName(v_ EmployeeRecord.first_name,
                 v_ EmployeeRecord.last_name);
    DBMS_OUTPUT.PUT_LINE(v_FormattedName);
  END LOOP;
END callLocalFunc;
End example

Example 5-43 shows the DB2 conversion of the function.

Listing 5-43: DB2 Conversion of Oracle Procedure with Local Function
Start example
CREATE FUNCTION FormatName(p_FirstName VARCHAR(20),        --[1]
                           p_LastName VARCHAR(20))
    RETURNS VARCHAR(41)
LANGUAGE SQL
BEGIN ATOMIC
   RETURN p_FirstName || '' || p_LastName;
END!

CREATE PROCEDURE callFunc ()
LANGUAGE SQL

BEGIN
 DECLARE c_AllEmployees CURSOR WITH RETURN FOR
   SELECT FormatName(first_name, last_name) FROM employees;

 OPEN c_AllEmployees;
END!
End example

Notes

[1]

The function must be created before the procedure that references it.


5.21 Additional considerations

External procedures and functions are also frequently seen in Oracle and DB2 UDB application. The complete information on building and running external procedures and functions is beyond the scope of this redbook. We provide here two examples of building routines using C and Java. For complete information on building and running external procedures and functions, please consult the following IBM DB2 UDB v8.1 documents:

  • Application Development Guide: Building and Running Applications, SC09-4825

  • Application Development Guide: Programming Client Applications, SC09-4826

  • Application Development Guide: Programming Server Applications, SC09-4827

5.21.1 Building C/C++ routines

We now show an example of creating a stored procedure written in C. First, here are some basic steps that must be followed when creating any C procedure (or function):

  • Create and save the external procedure/function and save it on your file system. If the procedure/function contains embedded SQL then it should be saved with the extension .sqc, if not save it with the extension .c

  • Create the export file (AIX ONLY)

    AIX requires you to provide an export file that specifies which global functions in the library are callable from outside it. This file must include the names of all routines in the library. Other UNIX platforms simply export all global functions in the library. This is an example of an AIX export file for the procedure outlanguage that exists within the file spserver.sqc:

    #! spserver export file
outlanguage

    The export file spserver.exp lists the stored procedure outlanguage. The linker uses spserver.exp to create the shared library spserver that contains the outlanguage stored procedure.

  • On Windows, a DEF file is required which has a similar purpose. See sqllib/samples/c/spserver.def for an example.

  • Run the bldrtn script which creates the shared library:

    bldrtn my_routine my_database_name

    The script copies the shared library to the server in the path sqllib/function.

  • Catalog the routines by running the catalog_my_routine script on the server.

Notes

  • After a shared library is built, it is typically copied into a directory from which DB2 will access it. When attempting to replace a routine shared library, you should either run /usr/sbin/slibclean to flush the AIX shared library cache, or remove the library from the target directory, and then copy the library from the source directory to the target directory. Otherwise, the copy operation may fail because AIX keeps a cache of referenced libraries and does not allow the library to be overwritten.

  • DB2 provides build scripts for precompiling, compiling, and linking C stored procedures. These are located in the sqllib/samples/c directory, along with sample programs that can be built with these files. This directory also contains the embprep script used within the build script to precompile a *.sqc file. The build scripts have the .bat (batch) extension on Windows, and have no extension on UNIX platforms. For example, bldrtn.bat is a script to build C/C++ stored procedure on Windows platform; bldrtn is the equivalent on UNIX.

Example

Here is a simple example of creating and cataloging a stored procedure that is written in C. This procedure queries the sysprocedures table from the DB2 system catalog to find in which language (JAVA, C, etc.) that a procedure TWO_RESULT_SETS is written.

  • The C source file (Example 5-44), with embedded SQL is created and saved as outlanguage.sqc.

    Example 5-44: Stored Procedure in C

    Start example

       #include <stdio.h>
   #include <string.h>
   #include <stdlib.h>
   #include <sqlda.h>
   #include <sqlca.h>
   #include <sqludf.h>
   #include <sql.h>
   #include <memory.h>
   SQL_API_RC SQL_API_FN outlanguage(char language[9]){
     struct sqlca sqlca;
     EXEC SQL BEGIN DECLARE SECTION;
       char out_lang[9];
     EXEC SQL END DECLARE SECTION;
     /* Initialize strings used for output parameters to NULL */
     memset(language, '\0', 9);
     EXEC SQL SELECT language INTO :out_lang
       FROM sysibm.sysprocedures
       WHERE procname = 'TWO_RESULT_SETS';
     strcpy(language, out_lang);
     return 0;
   } /* outlanguage function */
    End example

  • The .exp file is created and saved as outlanguage.exp. Here are the contents of that file:

       outlanguage

  • The file outlanguage_crt.db2, which catalogs the procedure is created and saved. Here is the contents of that file:

       CREATE PROCEDURE outlanguage (OUT language CHAR(8))
   DYNAMIC RESULT SETS 0
   LANGUAGE C
   PARAMETER STYLE SQL
   NO DBINFO
   FENCED NOT THREADSAFE
   MODIFIES SQL DATA
   PROGRAM TYPE SUB
   EXTERNAL NAME 'outlanguage!outlanguage'!

  • The build script bldrtn for the outlanguage.sqc file is executed using the db2_emp database:

    bldrtn outlanguage db2_emp

  • A connection is made to the database:

    db2 connect to db2_emp

  • The script to Catalog the procedure is executed:

    db2 –td! –vf outlanguage_crt.db2 > message.out

  • DB2 responds with the message:

    DB20000I The SQL command completed successfully.

    The message.out file should be viewed for messages, especially if any other message than The SQL command completed successfully is returned.

  • The procedure is tested:

    db2 "call outlanguage(?)"

    Results:

       Value of output parameters
     --------------------------
     Parameter Name  : LANGUAGE
     Parameter Value : JAVA
     Return Status = 0

5.21.2 Building JAVA routines

Here are the basic steps to create an external Java User-Defined Function (UDF) from the DB2 Command Window:

  • Compile your_javaFileName.java to produce the file your_javaFileName.class with this command:

    javac your_javaFileName.java

  • Copy your_javaFileName.class to the sqllib\function directory on Windows operating systems, or to the sqllib/function directory on UNIX.

  • Connect to the database:

    db2 connect to your_database_name

  • Register the your_javaFileName library in the database using the CREATE FUNCTION SQL statement.

    db2 –td! –vf <your_create_function_statement.db2>

Example

Here is an example of a Java UDF that will retrieve the system name from the DB2 Registry variable DB2SYSTEM.

  • The Java source file as shown in Example 5-45 is saved as db2system_nameUDF.java.

    Example 5-45: UDF Java source

    Start example

    import java.io.*;
public class db2system_nameUDF {
  public static String db2system_name() {
    Runtime rt = Runtime.getRuntime();
    Process p=null;
    String s = null;
    String returnString = "";
    try {
       // WINDOWS: **** uncomment and compile the following for Windows
       // p = rt.exec("cmd /C db2set DB2SYSTEM");
       // UNIX: **** uncomment and compile the following for UNIX
       p = rt.exec("db2set DB2SYSTEM");
       BufferedInputStream buffer =
          new BufferedInputStream(p.getInputStream());
       BufferedReader commandResult =
          new BufferedReader(new InputStreamReader(buffer));
       try {
           while ((s = commandResult.readLine()) != null)
               returnString = returnString.trim() + s.trim() ;
           // MAX number of chars for the DB2SYSTEM variable is 209 characters
           commandResult.close();
           // Ignore read errors; they mean process is done
       } catch (Exception e) {
       }
    } catch (IOException e) {
        returnString = "failure!";
    }
    return(returnString);
  }
}
    End example

  • Compile the Java source. The compile command is:

    javac db2system_nameUDF.java

  • Copy the .class file to /sqllib/function directory

    $ cp db2system_nameUDF.java /home/db2inst1/sqllib/function

  • Construct the Create Function file and save it as db2system_name.db2:

       DROP FUNCTION DB2SYSTEM_NAME !
   CREATE FUNCTION DB2SYSTEM_NAME ()
   RETURNS VARCHAR(209)
   EXTERNAL NAME 'db2system_nameUDF!db2system_name'
   LANGUAGE JAVA
   PARAMETER STYLE JAVA
   NOT DETERMINISTIC
   NO SQL
   EXTERNAL ACTION!

  • Connect to the database:

    db2 connect to db2_emp

  • Execute the script to register the UDF with the database:

    db -td! -vf db2system_name.db2

  • Test the UDF:

    db2 "values db2system_name()"

    Result:

    -------------------------------------------------
smpoaix
1 record(s) selected.


Chapter 6: Data Conversion

Overview

The data conversion is a sensitive task within the porting project. You have to ensure that all data will be moved to the target database both correctly and in time.

In this chapter, we discuss the data conversion methods for deploying the data from Oracle to the DB2 database. The data can be transformed through the following methods:

  • Using the Migration Tool Kit generated scripts and data file

  • Using MTK to move data on-line

  • Exporting the data manually from Oracle to flat file and importing or loading to DB2 UDB

  • Through pipes

  • Using alternative data conversion products

Furthermore, we give you some hints for the time planning for the data movement process.


6.1 Data conversion process

The data conversion process is quite complex. Before you define a porting method, you should do some tests only with a portion of the data to verify the chosen method. But the tests should cover all potential cases. We recommend that you start early with the testing.

The tasks of the test phase are:

  • Calculate the source data size and calculate the needed space for the files on disk.

  • Select the tools and the conversion method.

  • Test the conversion using the chosen method with small amount of data.

With the result of the test, you should be able to:

  • Estimate the time for the complete data conversion process.

  • Create a plan for development environment conversion. Use the information about to derive a complete plan.

  • Create a plan for production environment conversion. Use the information from development environment conversion.

  • Schedule the time.

The following objects influence the time and complexity of the process:

  • Amount of data and data changes

    The more data you have to move to more time you need. Consider the data changes as well as the timestamp conversions.

  • System availability

    You can run the data movement either during the production system is down or during the business process is running by synchronizing source and target database. Depending on the strategy you choose, you need less or more time.

  • Hardware resources

    Be aware that you need up to three times the disk space during the data movement for:

    • The source data in Oracle

    • The unloaded data stored in the filesystem

    • The loaded data in the target DB2 UDB


6.2 Time planning

After testing the data movement and choosing the proper tool and strategy, you have to create a detailed time plan with following tasks:

  • Depending on the data movement method:

    • Implementing or modifying scripts for data unload and load

    • Learning the use of the chosen data movement tools

  • Data unload from Oracle

  • Data load to DB2 UDB

  • Backup target database

  • Test loaded data on completeness and consistency

  • Switch of applications including database interfaces

  • Fallback process in case of incidents

The most sensitive environment is a production system with a 7x24 hours availability requirement. Figure 6-1 shows you the way how to move the data to the target database in a high availability environment. The dark color represents the new data, the light color represents the converted and moved data. If possible, export the data from a standby database or mirror database to minimize the impact on the production environment. You have to do following tasks:

  1. Create scripts that export all data up to a defined timestamp.

  2. Create scripts that export changed data since the last export. This includes new data as well as deleted data.

  3. Repeat step 2 as often as when all data is moved to the target database.

  4. Define fallback strategy and prepare fallback scripts.

Click To expand
Figure 6-1: Data movement strategy in a high availability environment

When the data is completely moved to the target database, you can switch the application and database. Prepare a well defined rollout process for the applications, and the belonging interfaces to DB2 UDB. Allow time for unplanned incidents.


6.3 Data movement through flat files

The main principle of data movement is to export the Oracle data to flat files in a well defined format, and to load or import the data to DB2 UDB. We can use any tool or write any application to achieve this. This section discusses the data movement through flat files.

The script examples included in this section can be download from IBM Redbook Web site. Please see Appendix G, "Additional material" on page 415 for details.

Before writing data into flat file, ensure that the maximum file size of your operating system is big enough. On AIX you get the actual file size limit in blocks with the command:

   ulimit -a

To set the file size limit to unlimited on AIX, enter as root:

   ulimit -f -1

6.3.1 Moving data using MTK

In 4.6, "The Generate Data Transfer Scripts task" on page 108, we explain how to use MTK to generate scripts for data unload and data load; the correlation of scripts and table definitions of the source and target defined within MTK. MTK allows you to move data through its GUI on-line without generated scripts as well. When moving data on-line, MTK does not use the generated scripts when deploying the load/import from the GUI.

6.3.2 Using shell scripts

We use UNIX shell scripts in our example, which uses the Oracle SQL*Plus utility to download the data from Oracle tables to flat files. These scripts can be run only in UNIX platforms, and should be run under a user that has the Oracle environment set. These scripts can only be run for Oracle tables containing CHAR, VARCHAR2, NUMBER data types. For exporting LOB columns, special programs has to be written with Oracle APIs. Example 6-1 shows the main data_unload.sh script. This script reads the table name from table_list_file parameter specified when invoking the script and constructs the dynamic query and estimates the line size using two other awk scripts. Once the query is constructed, the query is fed to the SQL*Plus utility, the output is spooled, and stored in the output file with delimited ASCII (DEL) format table_name.DAT.

Example 6-1: The data_unload.sh script
Start example
#!/bin/ksh
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# Shell script:  data_unload.sh
#
# Syntax:        data_unload.sh <table_list_file>
#
# Starting from an flat file containing a list of all the table,
# extracts data from Oracle for each table and writes data into
# a file named table_name.DAT, formatted in columns
#
# This script uses the awk command with the following awk command files:
# desc.awk   formats the query command files using RTRIM and DECODE
#            to obtain a column-formatted output
# count.awk  computes the total length of a record
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

#
# Define the environment variables for the oracle user and password
ORACLE_USR=user1
ORACLE_PWD=user1
#
# Start of main program

# Loop on all the tables listed in the input file
for i in `cat $1`
do
  # Define some environment variables for temporary files
  export OUTFILE=$i.DAT
  DSCFILE=$i.dsc
  SQLFILE=$i.sql
  VARFILE=$i.var
  ALLFILE=$i.all
  POSFILE=$i.pos
  rm -f $OUTFILE
  rm -f $DSCFILE
  rm -f $SQLFILE

  # Extract the table description from Oracle catalog
  sqlplus -s $ORACLE_USR/$ORACLE_PWD <<EOF >/dev/null 2>&1
  clear columns
  clear breaks
  set pagesize 100
  set newpage 1
  set feedback off
  spool $DSCFILE
  desc $i
  EOF

  # Cut head and tail from the file containing the descriptions of the tables
  # Change also the NOT NULL clause in a blank string
  # and cut the blanks in the first column
  tail +3 $DSCFILE | sed 's/NOT NULL/ /; s/^ //' > $DSCFILE.tmp1
  NL=`wc -l < $DSCFILE.tmp1`
  NLM1=`expr $NL - 1`
  head -$NLM1 $DSCFILE.tmp1 > $DSCFILE.tmp2
  cp $DSCFILE.tmp2 $VARFILE

  # Change the data types, leaving in the file the respective lengths
  # It is assumed that 41 bytes are enough to contain the significative
  # part of the NUMBER fields
  sed -e 's/ VARCHAR2(/ /' \
  -e 's/ NUMBER(/ /' \
  -e 's/ NUMBER/ 41/' \
  -e 's/ INTEGER(/ /' \
  -e 's/ INTEGER/ 41/' \
  -e 's/ CHAR(/ /' \
  -e 's/ CHAR/ 1/' \
  -e 's/ RAW(/ /' \
  -e 's/ VARCHAR(/ /' \
  -e 's/)//' \
  -e 's/\([0-9]*\)\,\([0-9 ]\)*/\1/' \
  $DSCFILE.tmp2 > $DSCFILE.tmp3
  mv $DSCFILE.tmp3 $DSCFILE
  rm -f $DSCFILE.tmp*

  # Compute the record length of the table
  # using the count.awk awk script
  LS=`awk -f count.awk $DSCFILE`

  # Prepare the heading of the query statement on the table
  # by echoing the statements into the sql file
  echo "clear columns" > $SQLFILE
  echo "clear breaks" >> $SQLFILE
  echo "set pagesize 50000" >> $SQLFILE
  echo "set linesize $LS" >> $SQLFILE
  echo "set feedback off" >> $SQLFILE
  echo "set heading off" >> $SQLFILE
  echo "set space 0" >> $SQLFILE
  echo "set newpage 1" >> $SQLFILE
  echo "spool $OUTFILE" >> $SQLFILE
  echo "select '' " >> $SQLFILE

  # Append to the query statement file the list of the table fields
  # to obtain the column layout, using the desc.awk awk script
  awk -f desc.awk $VARFILE >> $SQLFILE

  # Append to the query statement file the "from" clause
  # and the closing instructions
  echo "from $i;" >> $SQLFILE
  echo "spool off" >> $SQLFILE
  echo "quit" >> $SQLFILE

  # Execute the query statement
  sqlplus -s $ORACLE_USR/$ORACLE_PWD @$SQLFILE >/dev/null 2>&1

  # Cut the first line from the output file
  tail +2 $OUTFILE > $OUTFILE.tmp
  mv $OUTFILE.tmp $OUTFILE

  # Change the DATE data type into its DB2 external length, 26 bytes
  sed 's/ DATE/ 26/' $DSCFILE > $DSCFILE.tmp1
  mv $DSCFILE.tmp1 $DSCFILE
done
End example

The table name is read from table_list_file and described using the DESCRIBE TABLE command, and output is directed to a describe file TABLE_NAME.dsc. From the describe file, the SELECT query is constructed using the awk script file desc.awk, which produces the TABLE_NAME.sql file. Example 6-2 shows the desc.awk script. The TABLE_NAME.sql file contains the SELECT statement on which executed produces the result that can be exported to a delimited ASCII file type, which can be used for the LOAD or IMPORT utilities. The character data types are enclosed by the ~ character and the DATE data types are converted to equivalent DB2 TIMESTAMP data type. The query uses concatenation string || to concatenate the column values to single line.

Example 6-2: The desc.awk script
Start example
BEGIN {}
{
  if ($2 == "DATE")
    print " || rtrim(DECODE("$1",NULL,' ',TO_CHAR("$1",'YYYY-MM-DD-HH24.MI.SS')
|| '.000000'),26)"
  if (substr($2,1,4) == "CHAR")
    print " ||'~'||rtrim("$1")||'~,' "
  if (substr($2,1,8) == "VARCHAR2")
    print " ||'~'||rtrim("$1")||'~,' "
  if (substr($2,1,6) == "NUMBER")
    print " ||rtrim("$1")||','"
}
End example

The data_unload.sh script also uses another awk script count.awk to count the length of each column to estimate the output line size for SQL*Plus utility. Example 6-3 shows the count.awk script. Once the SELECT statement and the line size is ready, the SQL*Plus environment is set using SET PAGESIZE, SET LINESIZE commands. The command SET PAGESIZE, SET LINESIZE, SET FEEDBACK manipulates the output. The SET LINESIZE is set with the output produced by the count.awk script. Then the SQL*Plus runs the TABLE_NAME.sql file and spools the output to TABLE_NAME.dat output flat file. This file is in delimited ASCII (DEL) format and can be used by the LOAD or IMPORT utility. For example to export the ACCOUNTS table enter the table name into a file say table.lst, edit the data_unload.sh script enter the Oracle user name ORACLE_USR and password ORACLE_PWD and invoke using the command:

sh data_unload.sh table.lst
Example 6-3: The count.awk script
Start example
BEGIN { total=0 }
{
  if ($2 == "DATE")
    total +=26
  else
    total += $2+4
}
END { print total }
End example

This produces the accounts.dsc, accounts.sql, accounts.var, and accounts.DAT file. To load the data using LOAD utility, use the command:

DB2 LOAD FROM accounts.DAT OF DEL MODIFIED BY CHARDEL~ INSERT INTO
ACCOUNTS

To load the data using IMPORT utility use the command:

DB2 IMPORT FROM accounts.DAT OF DEL MODIFIED BY CHARDEL~ INSERT INTO
ACCOUNTS

6.3.3 Using Oracle's stored procedures

In this example we explain an Oracle stored procedure export_table, written by this redbook team to demonstrate how to unload the data from Oracle using this stored procedure, and to load the data to DB2. As in our previous example, this stored procedure can only be used for CHAR, VARCHAR2, NUMBER, and DATE data types. As in the shell script, this stored procedure gets the table name as the input parameter, constructs the SELECT query for output, and exports the table data to a output flat file. This output file format is also delimited in a ASCII file format.

The advantage of using this stored procedure is it can be used in Windows and NIX platforms. The output file is placed under the directory specified by the UTL_FILE_DIR initialization parameter. The UTL_FILE_DIR initialization parameter specifies the directory for PL/SQL file I/O. So, it is a must that this initialization parameter be specified in the Oracle instance before using this stored procedure. Example 6-4 shows the export_table stored procedure script.

Example 6-4: Procedure to export_ table data
Start example
/*************************************************************/
/* This stored procedure accept the table name as input      */
/* and exports the data into flat file identified by the     */
/* UTL_FILE_DIR with the format acceptable by the DB2        */
/* IMPORT utility or LOAD utility as Delimited ASCII file    */
/* Note : this procedure can be used for the table with data */
/* types CHAR,VARCHAR2 and NUMBER.                           */
/*************************************************************/
CREATE OR REPLACE PROCEDURE export_table(
   i_table_name IN VARCHAR2                       -- table name to be exported
)
IS
  stmt_1      VARCHAR2(4000) := 'select ';        -- first part of select
  stmt_2      VARCHAR(50) := ' as linecol from '; -- second part of the select
  stmt_cursor INTEGER;                            -- statement handle
  linecol     VARCHAR2(4000);                     -- output buffer for utl_file
  ret         INTEGER;                            -- dbms_sql handle
  filepath    VARCHAR(40):='c:\oracle';           -- path for output file
  filename    VARCHAR(40);                        -- output filename
  filemode    CHAR(1):='w';                       -- output file mode for write
  filelnsz    INTEGER := 4000;                    -- max file line size
  dtype_excp  EXCEPTION;
  fhandle     utl_file.file_type;                 -- file handle for utl_file
  CURSOR col_crsr(tab_col_name IN VARCHAR2) IS
     SELECT column_name, data_type
     FROM user_tab_columns
     WHERE table_name = tab_col_name;

BEGIN
   stmt_1 := stmt_1||'/*parallel('||i_table_name||',4)*/'||''''||'''';

   /*********************************************************/
   /* Build the select statement                            */
   /*********************************************************/
   FOR my_rec IN col_crsr(i_table_name) LOOP
     IF my_rec.data_type = 'DATE' THEN
       stmt_1 := stmt_1 || '|| rtrim(DECODE('|| my_rec.column_name
                        || ',NULL,'|| ''' '''|| ',TO_CHAR('
                        || my_rec.column_name ||','''
                        || 'YYYY-MM-DD-HH24.MI.SS'||''')))';
     ELSIF my_rec.data_type = 'CHAR' THEN
       stmt_1 := stmt_1 || '||'''||'~'||''''||'||rtrim('
                        || my_rec.column_name||')||'''||'~,'||'''';
     ELSIF my_rec.data_type = 'VARCHAR2' THEN
       stmt_1 := stmt_1 || '||'''||'~'||''''||'||rtrim('
                        || my_rec.column_name||')||'''||'~,'||'''';
     ELSIF my_rec.data_type = 'NUMBER' THEN
       stmt_1 := stmt_1 || '||rtrim('||my_rec.column_name
                        || ')||'''||','||'''';
     ELSE RAISE dtype_excp;
     END IF;
   END LOOP;
   stmt_2 := stmt_2 || i_table_name;
   stmt_1 := stmt_1 || stmt_2;

   /*********************************************************/
   /* Execute the statement and open the cursor             */
   /*********************************************************/
   stmt_cursor := dbms_sql.open_cursor;
   dbms_sql.parse(stmt_cursor,stmt_1,dbms_sql.native);
   dbms_sql.define_column(stmt_cursor,1,linecol,4000);
   ret := dbms_sql.execute(stmt_cursor);
   filename:=i_table_name||'.DAT';
   fhandle:= utl_file.fopen(filepath,filename,filemode,filelnsz);

   /*********************************************************/
   /* Fetch the rows and write it to output file            */
   /*********************************************************/
   WHILE dbms_sql.fetch_rows(stmt_cursor)>0 LOOP
     dbms_sql.column_value(stmt_cursor,1,linecol);
     utl_file.put_line(fhandle,linecol);
   END LOOP;

   /********************************************************/
   /* Close the cursor and file                            */
   /********************************************************/
   dbms_sql.close_cursor(stmt_cursor);
   utl_file.fclose(fhandle);

   EXCEPTION
   WHEN dtype_excp THEN dbms_output.put_line('Invalid Data type');
END;
End example

This stored procedure use the Oracle DBMS_SQL package to construct the select statement and retrieve the result set. It uses UTL_FILE Oracle package to create the output file, open it, and write the output data to the output file. The UTL_FILE can only write to output file created under UTL_FILE_DIR identified directory. The filepath variable in the stored procedure has to be edited and specified the value given for UTL_FILE_DIR initialization parameter. In our example, it points to C:\Oracle as the UTL_FILE_DIR parameter. The output file created will be named as TABLE_NAME.DAT file. For example, to export the data in the ACCOUNTS table, the stored procedure is called using the command:

CALL EXPORT_TABLE('ACCOUNTS')

Note that the table name should be entered in uppercase. When the stored procedure is called successfully, it produces the output file ACCOUNTS.DAT file. To load the data using LOAD utility, use the command:

DB2 LOAD FROM ACCOUNTS.DAT OF DEL MODIFIED BY CHARDEL~ INSERT INTO
ACCOUNTS

To load the data using IMPORT utility use the command:

DB2 IMPORT FROM ACCOUNTS.DAT OF DEL MODIFIED BY CHARDEL~ INSERT INTO
ACCOUNTS


6.4 Alternative ways for data movement

Beside the MTK, there are many other tools and products for data movement. Here we show you some of them. You should chose the tool according to your environment and the amount of data.

6.4.1 Data movement through named pipes

As described in 6.1, "Data conversion process" on page 212, you need additional disk space during the data movement process. To avoid the space for the flat files, you can use named pipes on UNIX-based systems. To use this function, the writer and reader of the named pipe must be on the same machine. You must create the named pipe on a local file system before exporting data from the Oracle database.

Because the named pipe is treated as a local device, there is no need to specify that the target is a named pipe. In the following is an AIX example:

  1. Create a named pipe:

    mkfifo /u/dbuser/mypipe

  2. Use this pipe as the target for data unload operation:

    <data unload routine> > /u/dbuser/mypipe

  3. Load data into DB2 UDB from the pipe:

    <data load routine> < /u/dbuser/mypipe

The commands in step 2 and 3 show you only the principle of using the pipes. To unload and load the data, use the routines discussed in this chapter.

Note

It is important to start the pipe reader after starting the pipe writer. Otherwise, the reader will find an empty pipe and exit immediately.

6.4.2 DB2 Information Integrator

In a high availability environment, you have to move the data during production activity. A practical solution is the replication facility of the DB2 Information Integrator.

IBM DB2 Information Integrator provides integrated, real-time access to diverse data as if it were a single database, regardless of where it resides. You are able to hold the same data both in Oracle and in DB2 UDB. You are free to switch to the new DB2 database when the functionality of the ported database and application is guaranteed.

The replication server, former known as DB2 Data Propagator, lets users manage data movement strategies between mixed relational data sources including distribution and consolidation models.

Data movement can be managed table-at-a-time such as for warehouse loading during batch windows, or with transaction consistency for data that is never off-line. It can be automated to occur on a specific schedule, at designated intervals, continuously, or as triggered by events. Transformation can be applied in-line with the data movement through standard SQL expressions and stored procedure execution.

For porting data, you can use the replication server to support data consolidation, moving data from Oracle to DB2 UDB.

You can get more information about replication in the redbook A Practical Guide to DB2 UDB Data Replication V8, SG24-6828-00, and in the DB2 Information Integrator Guide.

6.4.3 Third party tools

In 2.1.2, "Understanding and choosing migration tools" on page 30, we introduce some third party tools. The products are:

  • SQLWays (Ispirer Systems)

  • DataStage (Ascential)

  • DataJunction

These products are good for moving data between different databases.


Chapter 7: Application Conversion

Overview

In this chapter, we discuss the application conversion from an Oracle environment to a DB2 UDB environment. We cover the following topics:

  • Planing

  • Conversion of self-build applications

    • written with Oracle Pro*C

    • written in Java

    • based on Oracle OCI

    • based on ODBC

  • Package application migration

    • SAP

    • PeopleSoft

    • Siebel


7.1 Application migration planning

Application migration is another major step in the entire migration project. The application migration process includes:

  • Check of software and hardware availability and compatibility

  • Education of developer and administrators

  • Analysis of application logic and source code

  • Setting up of the target environment

  • Change of database specific items

  • Application test

  • Application tuning

  • Roll-out

  • User education

The planning includes the creation of a project plan. Plan enough time and resources for each task. IBM and our business partners can help you with questions in order to define a well prepared project.

For the in-house developed applications, the migration effort is on the shoulder of the migration team. For package applications, you can contact the vendor for a recommended migration process. In 7.3, "Package applications migration planning" on page 250, we explain the recommended migration process of some packages.

Check software and hardware availability and compatibility

The architecture profile is one of the outputs of the first task of migration planning assessment. While preparing the architecture profile, you need to check the availability and compatibility of all involved software and hardware in the new environment.

Education of developer and administrators

Ensure that the staff has the skills for all products and the system environment you will use for the migration project. Understanding the new product is essential for analyzing the source system.

Analyze of application logic and source code

In this analysis phase you should identify all the Oracle proprietary features and the affected sources. Examples of Oracle proprietary features are direct SQL queries to the Oracle Data Dictionary, Optimizer hints and Oracle joins, which are not supported by DB2 UDB. You also need to analyze the database calls within the application for the usage of database API.

Setting up the target environment

The target system, either the same or a different one, has to be set up for application development. The environment can includes:

  • The Integrated Development Environment (IDE)

  • Database framework

  • Repository

  • Source code generator

  • Configuration management tool

  • Documentation tool

A complex system environment consists usually of products from different vendors. Please check the availability and compatibility before starting the project.

Change of database specific items

Regarding the use of the database API, you need to change the database calls in the applications. The changes include:

  • language syntax changes

    The syntax of database calls varied in the different programming languages. In 7.2, "Self-build application" on page 228, we discuss the varieties of C/C++ and Java applications. For information regarding other languages, please contact IBM Technical Sales.

  • SQL query changes

    Oracle support partly non-standard SQL query like including of optimizer hints or table joins with a (+) syntax. To convert such queries to standard SQL, you can use the MTL SQL Translator.

    You need to modify the SQL queries to the Oracle Data Dictionary as well, and change them to select the data from the DB2 UDB Catalog.

  • Changes in calling procedures and functions

    Sometimes there is a need to change procedures to functions and vice versa. In such cases, you have to change all the calling commands and the logic belonging to the calls in other parts of the database and of the applications.

  • Logical changes

    Because of architectural differences between Oracle and DB2 UDB, changes in the program flow might be necessary. Most of the changes are related to the different concurrency model.

Application test

A complete application test is necessary after the database conversion and application modification to ensure that the database conversion is completed, and all the application functions work properly.

It is prudent to run the migration several times in a development system to guarantee the process, then run the same migration in test system with existing test data, then a copy or subset of productions data, before eventually running the process in production. Chapter 9, "Testing" on page 275 discusses the testing steps in detail.

Application tuning

Tuning is a continuous activity for the database since data volume, number of users, and applications change from time to time. After the migration, the application tuning should be concerned with the architectural differences between Oracle and DB2 UDB. For the details, please see Chapter 9, "Testing" on page 275, in the DB2 UDB Performance-tuning Guidelines, and the redbook DB2 UDB V7.1 Performance Tuning Guide, SG24-6012.

Roll-out

The roll-out procedure varies and depends on the type of application and the kind of database connection you have. Prepare the workstations with the proper driver (e.g. DB2 UDB Runtime Client, ODBC, JDBC) and the server according to the DB2 UDB version.

User education

In case of changes in the user interface, the business logic, or the application behavior because of system improvements, user education is required. Be sure to provide enough user education since the acceptance of the target system is corresponding to the skills and satisfaction of the users.


7.2 Self-build application

Self-build (in-house developed) application is unique in every case. There are variety of languages used in applications and each one can have its unique way of using APIs. In this section we explain the necessary steps in converting self-build applications from Oracle to DB2 UDB, and we provide some examples in C/C++ and Java, which show you how to convert the database calls.

Please note that the examples included in this chapter are excerpts from the actual programs, and cannot be compiled and executed by themselves.

7.2.1 Converting Oracle Pro*C applications to DB2 UDB

While many aspects of DB2 UDB application development underwent changes in recent years (stored procedures from C/COBOL/Java to SQL procedure language, support for PL/SQL in user-defined functions, triggers, and in-line SQL, and an enriched set of (built-in functions, etc.), support for embedding SQL into other host languages (C/C++) practically has not changed. This has resulted in many difficulties during migrations of applications from Oracle to DB2 UDB.

This chapter explains the steps necessary during application conversion to programs with embedded DB2 SQL calls.

Connecting to database

There is a difference in how C programs connect to the database. In Oracle each instance (service name) can manage only one database. DB2 instances can be used to manage multiple databases, thus the database name should be implicitly provided by connection statement.

In order to connect to the Oracle database, you need to specify Oracle user and password for that user:

   EXEC SQL CONNECT :user_name IDENTIFIED BY :password;

In DB2 UDB, you need to specify the database name, user ID, and password for that user ID. So, the above statement will be converted as:

   EXEC SQL CONNECT TO :dbname USERID :userid PASSWORD :password;

Please note that dbname, userid and password need to be declared as host variables.

Host variable declaration

Host variables are C or C++ language variables that are referenced within SQL statements. They allow an application to pass input data to and receive output data from the database manager. After the application is precompiled, host variables are used by the compiler as any other C/C++ variable.

Host variables should not only be compatible with DB2 data types (accepted by DB2 precompiler), but also must be acceptable for the programming language compiler.

As the C program manipulates the values from the tables using host variables, the first step is to convert Oracle table definition to DB2 data types; see Appendix B, "Data types" on page 365 for details. Please note that this mapping is one to many as it depends on the actual usage of data. For example, Oracle DATE data can be converted to DB2 DATE, if it only stores the actual date, but it needs to be converted to DB2 TIMESTAMP if it stores DATE and TIME.

The next step is to match DB2 data types with C data types. The table in Appendix B, "Data types" shows mapping between data types.

All host variables in a C program need to be declared in a special declaration section, so that the DB2 precompiler can identify the host variables and the data types:

   EXEC SQL BEGIN
   DECLARE SECTION;
      char emp_name[31] = {'\0'};
      sqlint32  ret_code = 0;
   EXEC SQL END DECLARE SECTION;

Within this declaration section, there are rules for host variable data types that are different from Oracle precompiler rules. Oracle precompiler permits host variables to be declared as VARCHAR. VARCHAR[n] is a pseudo-type recognized by the Pro*C precompiler. It is used to represent blank-padded, variable-length strings. Pro*C precompiler will convert it into a structure with a 2-byte length field followed by a n-byte character array. DB2 requires usage of standard C constructs. So, the declaration for the variable emp_name VARCHAR[25] needs to be converted as follows:

   struct emp_name {
      short  var_len;
      char   var_data[25] };

Or, as mentioned above, the use of a char emp_name[n] is also permitted for VARCHAR data. Variables of user-defined types (using typedef) in PRO*C need to be converted to the source data type. For example, type theUser_t has been declared to host values from Oracle object type:

   typedef struct user_s
         {short int userNum;
           char userName[25];
           char userAddress[40];
         } theUser_t;

In Pro*C program, you can have host variables declared as theUser_t:

   EXEC SQL BEGIN DECLARE;
             theUser_t *myUser;
        EXEC SQL END DECLARE SECTION;

To use this host variable for DB2, you would need to take this out of the EXEC SQL DECLARE SECTION and define the host variable MyUser as a structure.

DB2 allows for the host variable to be declared as a pointer with the following restriction:

  • If a host variable is declared as a pointer, no other host variable may be declared with that same name within the same source file.

The host variable declaration char *ptr is accepted, but it does not mean a null-terminated character string of an undetermined length. Instead, it means a pointer to a fixed-length, single-character host variable. This may not be what was intended for the Oracle host variable declaration.

It is recommended that sqlint32 and sqlint64 are used for INTEGER and BIGINT host variables, respectively. By default, the use of long host variables results in the precompiler error SQL0402 on platforms where long is a 64-bit quantity such as 64 BIT UNIX. Use the PREP option LONGERROR NO to force DB2 to accept long variables as acceptable host variable types and treat them as BIGINT variables.

Oracle host tables

In Pro*C programs, you can declare host variables using arrays, then declare a cursor you want to get results from. You can then issue a fetch statement that will get all rows from the cursor into that host array.

Here is a fragment of PRO*C that demonstrates this method:

   EXEC SQL BEGIN DECLARE SECTION;

   long int     dept_numb[10];
   char         dept_name[10][14];
   char         v_location[12];

   EXEC SQL END DECLARE SECTION;
   /* …… */

   EXEC SQL DECLARE CUR1 CURSOR FOR
        SELECT DEPTNUMB, DEPTNAME
         FROM org_table
        WHERE LOCATION = :v_location;
   /*……. */

   EXEC SQL FETCH CUR1 INTO :dept_num, :dept_name;

The last statement will get all 10 rows from the cursor into arrays.

As DB2 does not support arrays for the host variable declaration, the above code needs to be converted as follows:

   EXEC SQL BEGIN DECLARE SECTION;

   sqlint32     h_dept_numb = 0;
   char         h_dept_name[14] = {'\0'};
   char         v_location[12] = {'\0'};

   EXEC SQL END DECLARE SECTION;
   /* move array out of DECLARE section - just C variables */
   long int     dept_numb[10];
   char         dept_name[10][14];
   short int    i = 0;

   /* …… */

   EXEC SQL DECLARE CUR1 CURSOR FOR
        SELECT DEPTNUMB, DEPTNAME
         FROM org_table
        WHERE LOCATION = :v_location;

   /*we need Fetch one row at the time and move to corresponding
         member of array */

   for (i=0;i<11;i++){
       EXEC SQL FETCH CUR1 INTO :h_dept_num, :h_dept_name;
       if (SQLCODE == 100) {
         break;
       }
       dept_numb[i] = h_dept_numb;
       strcpy(dept_name[i], h_dept_name);
   }

Exception handling

The mechanisms for trapping errors are quite similar between Oracle and DB2 UDB, using the same concept of separating error routines from the mainline logic. There are three different WHENEVER statements that could be used to define program behavior in case of an error in DB2:

EXEC SQL WHENEVER SQLERROR GOTO error_routine;
EXEC SQL WHENEVER SQLWARNING CONTINUE;
EXEC SQL WHENEVER NOT FOUND not_found_routine;

Although the WHENEVER statement is prefixed by EXEC SQL like other SQL statements, it is not an executable statement. Instead, a WHENEVER statement causes the precompiler to generate code in a program to check the SQLCODE attribute from the SQLCA after each SQL statement, and to perform the action specified in the WHENEVER statement. SQLERROR means that an SQL statement returns a non-positive SQLCODE indicating an error condition. SQLWARNING indicates a non-negative SQLCODE (except +100), while NOT FOUND specifies SQLCODE = +100, indicating that no data rows were found to satisfy a request.

A compilation unit can contain as many WHENEVER statements as necessary, and they can be placed anywhere in the program. The scope of one WHENEVER statement reaches from the placement of the statement in the file onward in the character stream of the file until the next suitable WHENEVER statement is found or end-of-file is reached. No functions or programming blocks are considered in that analysis. For example, you may have two different SELECT statements, one must return at least one row, and the other may not return any. You will need two different WHENEVER statements:

   EXEC SQL WHENEVER NOT FOUND GOTO no_row_error;
        EXEC SQL SELECT  address
                           INTO  :address
                           FROM   test_table
                          WHERE phone = :pnone_num;
        ……..
        EXEC SQL WHENEVER NOT FOUND CONTINUE;
        EXEC SQL SELECT  commis_rate
                          INTO :rate :rateind
                           WHERE prod_id = :prodId;
         if (rateind == -1) rate = 0.15;
         ……

Oracle precompiler also supports DO and STOP statements as actions in a WHENEVER statement; those are not supported by DB2 precompiler and need to be converted to GOTO.

Another alternative is to check explicitly the SQLCODE after each EXEC SQL statement because that allows more context-sensitive error handling.

Error messages and warnings

The SQL Communication Area (SQLCA) data structure in DB2 is similar to the same structure of Oracle. SQLCA provides information for diagnostic checking and event handling.

To get the full text of longer (or nested) error messages, you need the sqlglm() function:

   sqlglm(message_buffer, &buffer_size, &message_length);

where message_buffer is the character buffer in which you want Oracle to store the error message; buffer_size specifies the size of message_buffer in bytes; Oracle stores the actual length of the error message in *message_length. The maximum length of an Oracle error message is 512 bytes.

DB2 UDB provides its user with a special run-time API function to return an error message based on SQLCODE:

   rc=sqlaintp(msg_buffer, 1024, 80, sqlca.sqlcode);

Where 80 stands for the number of characters after which a line break will be inserted in the message. DB2 will search for work-boundaries to place such a line break. 1024 specifies the length of the message buffer, e.g. char msg_buffer[1024]. As a result of invoking this function, the allocated buffer will contain the descriptive error message, e.g.:

   SQL0433N Value "TEST VALUES" is too long. SQLSTATE=22001.

If you need more information about a particular error, DB2 UDB provides an API function that returns an extended message associated with the specific SQLSTATE:

   rc=sqlogstt(msg_sqlstate_buffer, 1024, 80, sqlca.sqlcode);

As a result of invoking this function, char msg_sqlstate_buffer[1024] will contain, for example, the following message:

   SQLSTATE 22001: Character data, right truncation occurred; for example, an
   update or insert value is a string that is too long for the column, or
   datetime value cannot be assigned to a host variable, because it is too
   small.

Passing data to a stored procedure from a C program

In Oracle, in order to invoke a remote database procedure, the following statements are used:

   EXEC SQL EXECUTE
          BEGIN
            Package_name.SP_name(:arg_in1,:arg_in2, :status_out);
          END;
   END-EXEC;

The value transfer between the calling environment and the stored procedure may be achieved through arguments. You can choose one of three modes for each argument: IN, OUT or INOUT. For example, the above stored procedure may be declared as:

   CREATE PACKAGE package_name IS
        PROCEDURE  SP_name(
                agr_in1 IN NUMBER ,
                arg_in2 IN CHAR(30),
                status_out OUT NUMBER);

When this stored procedure is invoked, values passed from the calling program will be accepted by the stored procedure correspondingly.

DB2 client application invokes stored procedure by using the CALL statement. The CALL statement can pass parameters to the stored procedure and receive parameters returned from the stored procedure. It has the following syntax:

   CALL procedure_name (:parm1, …:parmN);

As with all SQL statements you prepare CALL statement with parameters markers an then supply values for the markers using SQLDA:

   CALL procedure_name USING DESCRIPTOR host_var;

The SQLDA is very helpful if you have an unknown number of host variables or very many variables - like 100 or more. Managing single variables in those cases can be very troublesome.

In order to invoke stored procedure from C client the following need to be in place

  • a stored procedure need to be created and registered with database

  • a host variable or parameter marker to each IN and INOUT parameter of the stored procedure should be declared and initialized

Consider an example. The program must give a raise to each employee whose current salary is less than some value. The program will pass that value to a stored procedure, perform an update and return back the status. Client code in C will look as shown in Example 7-1.

Example 7-1: Passing data to store procedure
Start example
#include <sqlenv.h>

main()
{
    EXEC SQL BEGIN DECLARE SECTION;
         Sqlint32  salary_val=0;
         Sqlint16 salind=1;
         Sqlint16  status=0;
         Sqlint16  statind=0;
    EXEC SQL END DECLARE SECTION;

    EXEC SQL INCLUDE SQLCA;
    EXEC SQL CONNECT TO sample;
    EXEC SQL WHENEVER SQLERROR GOTO err_routine;

    salary_val = getSalaryForRaise();
    statind = -1;   /* set indicator variable to -1 */
                    /* for status as output-only variable */

     EXEC SQL CALL raiseSal(:salary_val :salind, :status :statind);
      if (status == 0){
          printf  (" The raises has been successfully given \n ");
          EXEC SQL COMMIT;
       }
       else
          if (status ==1)
              printf  (" NO input values has been provided.\n ");
          else
              if (status == 2)
                  printf("Stored procedure failed.\n");

    err_routine:
        printf  (" SQL Error, SQLCODE = \n ", SQLCODE);
        EXEC SQL ROLLBACK;
}
End example

Note that all host variables that are used as parameters in the statement are declared and initialized in EXEC SQL DECLARE SECTION.

Building C/C++ DB2 application.

DB2 UDB provides sample build scripts for precompiling, compiling, and linking C-embedded SQL programs. These are located in the sqllib/samples/c directory, along with sample programs that can be built with these files. This directory also contains the embprep script used within the build script to precompile a *.sqc file.

Build files are provided by DB2 UDB for each language on supported platforms where the types of programs they build are available in the same directory as the sample programs for each language. These build files, unless otherwise indicated, are for supported languages on all supported platforms. The build files have the .bat (batch) extension on Windows, and have no extension on UNIX platforms. For example, bldmapp.bat is a script to build C/C++ application on Windows.

DB2 UDB also provides utilemb.sqc and utilemb.h files, containing functions for error handling. In order to use utility functions, the utility file must first be compiled, and then its object file linked in during the creation of the target program's executable. Both the makefile and build files in the samples directories do this for the programs that require error-checking utilities.

For more information on building C applications, see IBM DB2 UDB Application Development Guide: Building and Running Applications.

7.2.2 Converting Oracle Java applications to DB2 UDB

For Java programmers, DB2 UDB offers two application programming interfaces (APIs), JDBC and SQLj.

JDBC is a mandatory component of the Java programming language as defined in the Java 2, Standard Edition (J2SE) specification. To enable JDBC applications for DB2 UDB, an implementation of the various Java classes and interfaces, as defined in the standard, is required. This implementation is known as a JDBC driver. DB2 UDB offers a complete set of JDBC drivers for this purpose. The JDBC drivers are categorized as the legacy CLI drivers or the new Universal JDBC Drivers.

SQLJ is a standard development model for data access from Java applications. The SQLJ API is defined within the SQL 1999 specification. The new Universal JDBC Driver provides support for both JDBC and SQLJ APIs in a single implementation. JDBC and SQLJ can interoperate in the same application. SQLJ provides the unique ability to develop using static SQL statements and control access at the DB2 UDB package level.

The Java code conversion is rather easy. The API itself is well defined and database independent. For instance, the database connection logic is encapsulated in standard J2EE DataSource objects. The Oracle or DB2 UDB specific things like user name, database name, etc. are then configured declaratively within the application.

However, there is the need to change your Java source code regarding:

  • The API driver (JDBC or SQLJ)

  • The database connect string

  • Oracle proprietary SQLs like CONNECT BY for recursive SQL, the usage of DECODE() or SQL syntax like the (+) operator instead of LEFT/RIGHT OUTER JOIN. MTK provide support here with the SQL Translator.

  • Remove or simulate proprietary optimizer hints in SQL queries.

Java access methods to DB2

DB2 UDB has rich support for the Java programming environment. You can access DB2 data by putting the Java class into a module in one of the following ways:

  • DB2 Server

    • Stored procedures (JDBC or SQLJ)

    • SQL functions or user-defined functions (JDBC or SQLJ)

  • Browser

    • Applets based on JDBC (JDBC)

  • J2EE Application Servers (such as WebSphere® Application Server)

    • Java ServerPages (JSPs) (JDBC)

    • Servlets (SQLJ or JDBC)

    • Enterprise JavaBeans (EJBs) (SQLJ or JDBC)

Available JDBC driver for DB2 UDB

DB2 UDB V8.1 supports the JDBC 2.1 and JDBC 3.0. Table 7-1 shows you the JDBC drivers delivered by IBM. An overview of all available JDBC drivers can be found at:

Table 7-1: JDBC driver
Type | Driver URL
type 2 | COM.ibm.db2.jdbc.app.DB2Driver (only for applications)
type 3 | COM.ibm.db2.jdbc.net.DB2Driver (only for applets)
type 4 | com.ibm.db2.jcc.DB2Driver (for applications and applets)

http://servlet.java.sun.com/products/jdbc/drivers

The type 3 and 4 drivers require you to provide the user ID, password, host name and a port number. For the type 3 driver, the port number is the applet server port number. For the type 4 driver the port number is the DB2 UDB server port number. The type 2 driver implicitly uses the default value for user ID and password from the DB2 client catalog, unless you explicitly specify alternative values. The JDBC Type 1 driver is based on a JDBC-ODBC bridge. Therefore, an ODBC driver can be used in combination with this JDBC driver (provided by Sun). IBM does not provide a Type 1 driver, and it is not a recommended environment.

After coding your program, compile it as you would with any other Java program. You do not need to perform any special precompile or bind steps.

JDBC driver declaration

In order to connect from a Java application to an Oracle database using the OCI driver, you have to import the Oracle driver calls, register the driver manager, and connect with your user ID, the password, and the database name.

In DB2 UDB, it is not necessary to import a DB2 JDBC library. The registration and connection to DB2 UDB is similar to Example 7-2. Use the proper JDBC driver URL and connection string you need as explained in Table 7-1.

Example 7-2: Oracle JDBC connection
Start example
import java.sql.*;
import java.io.*;
import oracle.jdbc.driver.*;

class rsetClient
{
  public static void main (String args []) throws SQLException
  {
    // Load the driver
    DriverManager.registerDriver(new oracle.jdbc.driver.OracleDriver());

    // Connect to the database
    Connection conn =
      DriverManager.getConnection ("jdbc:oracle:oci8:@oracle","uid","pwd");

    // ...
  }
}
End example
Example 7-3: DB2 JDBC connection
Start example
import java.sql.*;

class rsetClient
{
  public static void main (String args []) throws SQLException {

   // Load DB2 JDBC application driver
   try
    {
       Class.forName("COM.ibm.db2.jdbc.app.DB2Driver");
    }
    catch (Exception e)
    {
         e.printStackTrace();
    }
    // Connect to the database
    Connection conn =
      DriverManager.getConnection("jdbc:db2:dbname","uid","pwd");
    // ...
  }
}
End example

Stored procedure call

The calls of stored procedure differ in the handling of input parameters and output parameters between Oracle and DB2 UDB. The following examples explain the different kinds of procedure calls, and the usage of parameters and result sets.

Stored procedure with input parameter

We assume a stored procedure defined in Oracle as:

   CREATE OR REPLACE PROCEDURE sp_testcall_1( parm1 IN INTEGER
                                             ,parm2 IN INTEGER)

and in DB2 UDB as:

   CREATE PROCEDURE sp_testcall_1( IN parm1 INTEGER
                                  ,IN parm2 INTEGER )

The procedures have two input parameters and no output parameter. There is no difference in the call between Oracle and DB2. In both cases you have to set the parameter values before you call and execute the procedure.

Example 7-4: Java call of Oracle or DB2 UDB procedure with input parameter
Start example
String SP_CALL = "{call sp_testcall_1(?,?)}";

// Connect to the database
Connection conn =
  DriverManager.getConnection (url, userName, password);

CallableStatement stmt;
try {
    stmt = conn.prepareCall(SP_CALL);
    stmt.setInt(1,10);
    stmt.setInt(2,15);
    stmt.execute();
    // ...
}
End example
Stored procedure with result set

The next example shows a procedure without input parameter, but a result set as output parameter. The result set is an opened cursor defined within the procedure. The rows are fetched in the Java application with a loop.

The Oracle stored procedure is defined as:

   TYPE CursorType IS REF CURSOR;
   CREATE PROCEDURE sp_testcall_3(oCursor OUT CursorType) AS
   BEGIN
    open oCursor for select last_name from employees;
   END;

The output parameter type is registered as CURSOR before the procedure is called.

The corresponding DB2 procedure looks like:

   CREATE PROCEDURE db2_spcall_v3
   RESULT SETS 1
   LANGUAGE SQL
   BEGIN
      DECLARE c1 CURSOR WITH RETURN FOR
        SELECT last_name
        FROM employees;

      OPEN c1;
   END!

The result set definition in SQL PL is different than Oracle's PL/SQL. You have to specify the amount of expected result sets.

With DB2 UDB, you do not need to register the result set with the method registerOutParameter() in the Java application. To get the result set you call the method getResultSet() instead of getObject() as in Example 7-5.

Example 7-5: Java call of Oracle procedure with result set
Start example
String SP_CALL = "{call sp_testcall_3}";

// Connect to the database
Connection conn =
  DriverManager.getConnection (url, userName, password);

try {
    CallableStatement stmt = conn.prepareCall(SP_CALL);
    stmt.registerOutParameter (1, OracleTypes.CURSOR);
    stmt.executeUpdate();
    ResultSet rs = (ResultSet) stmt.getObject(1);
    while(rs.next())
    {
        // ...
    }
}
End example
Example 7-6: Java call of DB2 UDB procedure with result set
Start example
String SP_CALL = "{call db2_spcall_v3}";

// Connect to the database
Connection conn =
      DriverManager.getConnection (url, userName, password);

try {
        CallableStatement stmt = conn.prepareCall(SP_CALL);
        ResultSet rs = null;
        stmt.execute();
        rs = stmt.getResultSet();
        while(rs.next())
        {
            // ...
        }
}
End example
Stored procedure with input parameter and result set

Example 7-7 is a combination of Example 7-4 and Example 7-5. Note the numbering of the parameters. The first input parameter value2 is numbered with 2, the result set rs is numbered with 1.

Example 7-7: Java call of Oracle procedure with input parameter and result set
Start example
private static final String SP_CALL = "{call sp_testcall4 (?) }";

CallableStatement stmt1 = conn.prepareCall(SP_CALL);

Stmt1.registerOutParameter(1, OracleTypes.CURSOR);
Stmt1.execute();
ResultSet rs = (ResultSet) stmt1.getObject(1);

while(rs.next()) {
    int value1 = rs.getInt(1);
    stmt2.setInt(2, value2);
    stmt2.execute();
    ResultSet rs = (ResultSet) stmt1.getObject(1);
    // ...
}
End example

You define with DB2 UDB the input parameter and the result set as we show in Example 7-4 and Example 7-6. The numbering of the input parameter begins with 1, independent from an expected result set.

Example 7-8: Java call of DB2 UDB procedure with input parameter and result set
Start example
String SP_CALL = "{call db2_spcall_v4(?)}";

Connect to the database
    Connection conn =
      DriverManager.getConnection (url, userName, password);

try {
        CallableStatement stmt = conn.prepareCall(SP_CALL);
        stmt.setInt(1, emp_id);
        ResultSet rs = null;
        stmt.execute();
        rs = stmt.getResultSet();
        while(rs.next())
        {
            System.out.println (rs.getString (1));
            // ...
        }
}
End example
Stored procedure converted from a function

The call of an Oracle function is similar to the call of a procedure with input parameter and a result set. The function is defined as:

   CREATE TYPE CursorType IS REF CURSOR;
   CREATE FUNCTION sp_testcall_4(v_num IN INTEGER)
                   RETURN CursorType

As described in Chapter 5, "Conversion reference" on page 149, you have to convert the Oracle function to a DB2 procedure. The migrated DB2 procedure may look like the previous Example 7-9 with an input parameter and a result set as an output parameter.

Example 7-9: Java of Oracle function with input parameter and result set
Start example
String SP_CALL = "{? = call sp_testcall_4(?)}";

// Connect to the database
Connection conn =
  DriverManager.getConnection (url, userName, password);

try {
    CallableStatement stmt = conn.prepareCall(SP_CALL);
    stmt.registerOutParameter (1, OracleTypes.CURSOR);
    stmt.setInt(2, 6);
    stmt.execute();
    ResultSet rs = (ResultSet) stmt.getObject(1);
    while(rs.next())
    {
        // ...
    }
}
End example

7.2.3 Converting Oracle Call Interface applications

For applications using the Oracle Call Interface (OCI) you may want to consider rewriting them by using CLI or ODBC. The OCI is specific to the Oracle database and cannot be used with any other databases.

In most cases, you can replace OCI functions with the appropriate CLI/ODBC functions, followed by relevant changes to the supporting program code. The remaining non-OCI program code should require minimal modification. The examples in this chapter show a comparison of the OCI and CLI/ODBC statements required for establishing a connection to an Oracle and DB2 UDB database.

Introduction to CLI

DB2 Call Level Interface (DB2 CLI) is IBM's callable SQL interface to the DB2 family of database servers. It is a C and C++ application programming interface for relational database access that uses function calls to pass dynamic SQL statements as function arguments. It is an alternative to embedded dynamic SQL, but unlike embedded SQL, DB2 CLI does not require host variables or a precompiler.

DB2 CLI is based on the Microsoft Open Database Connectivity (ODBC) specification, and the International Standard for SQL/CLI. These specifications were chosen as the basis for the DB2 Call Level Interface in an effort to follow industry standards, and to provide a shorter learning curve for those application programmers already familiar with either of these database interfaces. In addition, some DB2 specific extensions have been added to help the application programmer specifically exploit DB2 features.

The DB2 CLI driver also acts as an ODBC driver when loaded by an ODBC driver manager. It conforms to ODBC 3.51.

Comparison of DB2 CLI and Microsoft ODBC

Figure 7-1 compares DB2 CLI and the DB2 ODBC driver. The left side shows an ODBC driver under the ODBC Driver Manager, and the right side illustrates DB2 CLI, the callable interface designed for DB2 UDB specific applications.

Click To expand
Figure 7-1: DB2 CLI and ODBC

In an ODBC environment, the Driver Manager provides the interface to the application. It also dynamically loads the necessary driver for the database server that the application connects to. It is the driver that implements the ODBC function set, with the exception of some extended functions implemented by the Driver Manager. In this environment, DB2 CLI conforms to ODBC 3.51.

For ODBC application development, you must obtain an ODBC Software Development Kit. For the Windows platform, the ODBC SDK is available as part of the Microsoft Data Access Components (MDAC) SDK, available for download from http://www.microsoft.com/data/ For non-Windows platforms, the ODBC SDK is provided by other vendors.

In environments without an ODBC driver manager, DB2 CLI is a self-sufficient driver, which supports a subset of the functions provided by the ODBC driver. Appendix C, "Oracle Call Interface (OCI) mapping" on page 377 summarizes the two levels of support. The CLI and ODBC function summary provides a complete list of ODBC functions and indicates if they are supported.

Setting up the CLI environment

Runtime support for DB2 CLI applications is contained in all DB2 UDB clients. Support for building and running DB2 CLI applications is contained in the DB2 Application Development (DB2 AD) Client.

The CLI/ODBC driver will auto bind on the first connection to the database, provided the user has the appropriate privilege or authorization. The administrator may want to perform the first connect or explicitly bind the required files.

Procedure

In order for a DB2 CLI application to successfully access a DB2 database:

  1. Ensure the DB2 CLI/ODBC driver was installed during the DB2 client install.

  2. Catalog the DB2 database and node if the database is being accessed from a remote client. On the Windows platform, you can use the CLI/ODBC settings GUI to catalog the DB2 database.

  3. Optional: Explicitly bind the DB2 CLI/ODBC bind files to the database with the command:

       db2 bind ~/sqllib/bnd/@db2cli.lst blocking all messages cli.msg\
              grant public

    On the Windows platform, you can use the CLI/ODBC settings GUI to bind the DB2 CLI/ODBC bind files to the database.

  4. Optional: Change the DB2 CLI/ODBC configuration keywords by editing the db2cli.ini file, located in the sqllib directory on Windows, and in the sqllib/cfg directory on UNIX platforms.

    On the Windows platform, you can use the CLI/ODBC settings GUI to set the DB2 CLI/ODBC configuration keywords.

Change of OCI database calls

All Oracle Call Interface (OCI) calls in your application need to be changed to CLI calls. The program flow is retaining, but you need to modify the definition and processing of database handles. There may not be an exact match in the conversion process. Your program code might require additional revisions to obtain similar functionality.

The following examples show you the different SQL statements in order to connect to a database. In Oracle you need to define variables for the environment handles as well as the database name, username, and password:

   ociRC = OCILogon( env_hp,                    // environment handle
                     err_hp,                    // error handle
                     &svc_hp,                   // service context
                     user_name,                 // username
                     strlen (user_name),        // length of username
                     password,                  // password
                     strlen (password),         // length of password
                     db_name                    // database name
                     strlen (db_name));         // length of database name

In DB2 UDB you also need to specify the connection handle, database name, username, and password. So, the OCI statement will be converted as:

   cliRC = SQLConnect( *pHdbc,                  // connection handle
                       db_name,                 // database name
                       strlen (db_name),        // length of database name
                       user_name,               // username
                       strlen (user_name),      // length of username
                       password,                // password
                       strlen (password));      // length of password

Appendix C, "Oracle Call Interface (OCI) mapping" on page 377 gives you a mapping of the most important Oracle8 OCI calls to the closest DB2 CLI equivalents. Refer to the Oracle8i Server Application Development guide and to the DB2 UDB Call Level Interface Guide and Reference for details on the OCI and CLI functions.

The following classes of OCI functions have no equivalents in DB2 CLI. The functionality must be implemented either in SQL or in C (or C++) directly:

  • Navigational functions

    OCIObject__()
OCICache__()

  • Datatype mapping and manipulation functions

    OCIColl__()
OCIDate__()
OCINumber__()
OCIString__

    etc.

    However, CLI performs conversion of data between data types wherever possible.

  • External procedure functions

    OCIExtProc__()

Error handling and diagnostics

Diagnostics refers to dealing with warning or error conditions generated within an application. There are two levels of diagnostics returned when calling DB2 CLI functions:

  • Return codes

  • Detailed diagnostics consist of SQLSTATEs, messages, and SQLCA

Each CLI function returns the function return code for a basic diagnosis. The functions SQLGetDiagRec() and SQLGetDiagField() provide more detailed diagnostic information. If the diagnostic originates at the DBMS, the SQLGetSQLCA() function provides access to the SQLCA. This arrangement lets applications handle the basic flow control based on return codes, and uses the SQLSTATES along with the SQLCA to determine the specific causes of failure, and to perform specific error handling.

Table 7-2 lists the mapping of all possible return codes of Oracle OCI functions and DB2 CLI functions.

Table 7-2: Return code mapping from OCI to CLI functions
OCI return code | CLI return code | Explanation
OCI_SUCCESS | SQL_SUCCESS | The function completed successfully, no additional SQLSTATE information is available.
OCI_SUCCESS_WITH_INFO | SQL_SUCCESS_WITH_INFO | The function completed successfully with a warning or other information. Call SQLGetDiagRec() or SQLGetDiagField() to receive the SQLSTATE and any other informational messages or warnings. The SQLSTATE will have a class of '01'.
OCI_NO_DATA | SQL_NO_DATA_FOUND | The function returned successfully, but no relevant data was found. When this is returned after the execution of an SQL statement, additional information may be available and can be obtained by calling SQLGetDiagRec() or SQLGetDiagField().
OCI_ERROR | SQL_ERROR | The function failed. Call SQLGetDiagRec() or SQLGetDiagField() to receive the SQLSTATE and any other error information.
OCI_INVALID_HANDLE | SQL_INVALID_HANDLE | The function failed due to an invalid input handle (environment, connection or statement handle). This is a programming error. No further information is available.
OCI_NEED_DATA | SQL_NEED_DATA | The application tried to execute an SQL statement but DB2 CLI lacks parameter data that the application had indicated would be passed at execute time.
OCI_STILL_EXECUTING | SQL_STILL_EXECUTING | The function is running asynchronously and has not yet completed. The DB2 CLI driver has returned control to the application after calling the function, but the function has not yet finished executing.
OCI_CONTINUE | no equivalent |

The OCI function OCIErrorGet() returns the diagnostic record according to the SQLSTATE. Within a CLI application, the functions SQLGetDiagRec() and SQLGetDiagField() return three pieces of information:

  • SQLSTATE

  • Native error

    If the diagnostic is detected by the data source, this is the SQLCODE; otherwise, this is set to -99999.

  • Message text

    This is the message text associated with the SQLSTATE.

SQLGetSQLCA() returns the SQLCA for access to specific fields, but should only be used when SQLGetDiagRec() or SQLGetDiagField() cannot provide the desired information.

Further information

You can find more information about CLI applications and development in:

  • DB2 UDB Call Level Interface Guide and Reference, volumn1, SC09-4849; volumn2, SC09-4850

  • DB2 UDB Application Development Guide: Building and Running Applications, SC09-4825

  • DB2 UDB Application Development Guide: Programming Client Applications, SC09-4826

  • Web site http://www.ibm.com/software/data/db2/udb/ad

7.2.4 Converting ODBC applications

The Open Database Connectivity (ODBC) is similar to the CLI standard. Applications based on ODBC are able to connect to the most popular databases. Thus, the application conversion is pretty easy. You have to perform the conversion of database specific items in your application such as:

  • Proprietary SQL query changes

  • Possible changes in calling stored procedures and functions

  • Possible logical changes

And, the proceed to the test, roll-out, and education tasks as well. Your current development environment will be the same. For a more detailed description of the necessary steps, please reference 7.1, "Application migration planning" on page 226.


7.3 Package applications migration planning

For package applications, the according vendor delivers the application and database based on DB2 UDB. The migration limits to:

  • Check software and hardware availability and compatibility

  • Education of developer and administrators

  • Analyze of customized changes in application and database

  • Setting up the target environment

  • Change of customized items

  • Test of data migration and customized items

  • Roll-out

To keep the support from the vendor, you have to meet the prescribed migration plan and process. We show you in this chapter the migration approach for SAP, Siebel, and PeopleSoft environments.

7.3.1 SAP

An SAP system is divided in different layers. The application and business logic is independent of the database. SAP uses only common database types and functionality. However, in planning of the migration efforts, you have to take into account your self-made customizations.

Migration requirements

For database migration, SAP requires the customer to use the SAP Migration Service in order for the system to be supported after the migration is complete. The SAP Migration Service is fee-based and will provide you with the following:

  • Cross check of the database migration project plan

  • Migration tools

  • Migration keys

  • Remote Going Live Migration check

  • Support in case of migration tool problems

The SAP R/3 software for your new IBM DB2 system will be delivered by SAP after the necessary contractual/licensing changes.

Migrating a SAP R/3 system to a different operating system or database needs to be planned and approved by SAP, and therefore SAP requires that you use their migration tools.

To perform a migration you need a migration key. This key will be provided to you by SAP. The key is mandatory for the data export step and data import using SAP's tools.

The migration project plan

To successfully perform a migration, you need to follow a well-defined process using the steps shown in Figure 7-2. Therefore, SAP demands a project plan for your migration project. This plan is made by the customer and the migration partner. SAP Migration Service will check this plan to ensure that your migration will be successful. Sample project plans can be found at Web site: http://service.sap.com/osdbmigration

Click To expand
Figure 7-2: SAP R/3 database migration project

The migration project

Figure 7-2 gives you an overview of a SAP R/3 database migration project:

As database migration comprises several tasks, we recommend that you begin planning three to four months in advance.

Figure 7-3 provides a typical time line for planning a migration.

Click To expand
Figure 7-3: SAP R/3 database migration timeline

Migration test and check

Before the final migration, SAP requires at least one migration test run. This will assure that all your SAP R/3 data and functionality are moved correctly to the target system.

After the first functional test of the migrated system, end users should be involved in the test process as well. This ensures that the target system is tested comprehensively.

The Going live migration check is a part of the migration services from SAP. It should be scheduled after the test migration, and three to four weeks before the final migration.

Final migration and verification

This step is performed after a successful test of the target system and SAP's Going live migration check.

The final migration is usually scheduled for a weekend as downtime is required while the switch to a new platform occurs. The steps are the same as with the test run, but in addition, you should do a full backup afterwards.

The Going live migration verification is again a part of the migration services from SAP. The migration verification step is done twice. The first time should be scheduled one to two weeks after the final migration; the second time it should be scheduled six to eight weeks after the final migration. This should ensure that all daily, monthly, and other reports and functions are operating correctly.

7.3.2 PeopleSoft

PeopleSoft migration limits to the conversion of the database objects and data from the source to the target as well as the adoption of the administration tasks to the target. The application for the proper database is delivered by PeopleSoft. Most PeopleSoft installations have done some degree of customization of their databases. The customization can be of the following types:

  • Modifications to DDL

  • Use of stored procedures and triggers

  • Use of non-ANSI SQL

  • Use of non-ANSI data types

PeopleSoft offers the tool DataMover to generate script files, which you can use to build the database objects in the target DB2 UDB.

To migrate the customizations, please follow our recommendations in Chapter 4, "Porting with MTK" on page 63, and Chapter 5, "Conversion reference" on page 149.

Migration project

The migration project includes the following key steps:

  1. Selection of migration service provider

  2. Project planning and analysis

  3. Migration of development, test and production

  4. Education and training of administrators and end-user

  5. Acceptance test

Regarding education and acceptance test, see the information in 7.1, "Application migration planning" on page 226.

Selection of migration service provider

Select a service provider of your choice, which helps you to run the migration process. Your PeopleSoft provider or IBM supports you in your project. For contacts, please have a look to the IBM migration Internet site: http://www.ibm.com/software/data/db2/migration/

Project planning and analysis

Analyze the number and type of your database environment. Determine the number and identity of customized tables, indexes, and views. Create a migration plan as we recommend in Chapter 2, "Oracle migration project planning" on page 29 together with your vendor and service provider.

Migration process

PeopleSoft recommends that you migrate first the development, and if available, the test environment before migrating the production environment. In a typical PeopleSoft installation, there is the time required in each of the following phases:

  • Development: one to three weeks

  • Test: one to two weeks

  • Production: one to two weeks

The migration steps are:

  1. Load RDBMS onto system.

  2. Load Peoplesoft software onto system.

  3. Select data unload/load tool (provided by PeopleSoft or RDBMS vendor provider).

  4. Create database.

  5. Include extensions/customizations.

  6. Define tablespaces/physical layout.

  7. Unload source database.

  8. Load destination database.

  9. Test load and repeat steps if necessary.

Data migration

For moving data from Oracle to DB2 UDB in a PeopleSoft environment, you have to export the Oracle data and import it into DB2 UDB. Therefore, you have these options:

  • DataMover utility

    A graphical utility to move PeopleSoft databases across operating systems and database platforms

  • Creating a flat file by exporting data from tables. Once the flat file has been created in one of the three acceptable formats which are:

    • ASCII

    • ASCII delimited file

    • Integrated Xchange Format (IXF)

  • IBM DB2 Information Integrator

    View popular relational data sources and non-relational data sources as if they were local DB2 UDB data sources.

DataMover Tool

DataMover is a PeopleSoft Tool that provides a convenient way to perform the following tasks:

  • Transfer application data between PeopleSoft databases

  • Move PeopleSoft databases across operating systems and database platforms

  • Execute SQL statements against any PeopleSoft database, regardless of the underlying operating system or database platform

  • Control database security and access

DataMover is used to create, edit, and run scripts. These scripts may include any combination of SQL commands and DataMover commands for exporting and importing database contents, among other things. The default file extension for scripts is .DMS (for DataMover Script).

DataMover commands are platform-independent and are unique to DataMover. You can use DataMover commands for importing, exporting, and other tasks, such as controlling the run environment, renaming fields and records, database security administration, and denoting comments.

If you plan to create or edit DataMover scripts, you will need to keep the syntax rules in mind to make sure your commands run successfully.

Further information

For more information about PeopleSoft:

  • Redbook:

    • Planning for a Migration of PeopleSoft 7.5 from Oracle/UNIX to DB2 for OS/390, SG24-5648

    • Planning to Install PeopleSoft with DB2 for OS/390, SG24-5156-01

  • PeopleSoft Web site: http://www.peoplesoft.com

7.3.3 Siebel

Siebel solutions are implemented in a layered architecture with database independence. Thus, the Siebel application layer and business logic layer is not affected from the database migration. Figure 7-4 shows the typical migration process of a Siebel System.

Click To expand
Figure 7-4: Siebel migration process

We recommend that you involve Siebel or a certified partner in the migration planning for a successful realization.

For detailed information about Siebel migration, see the redbook Migrating Siebel Database from DB2/Oracle for NT to DB2 for OS/390, SG24-6236.

Planning tasks

Before performing a migration, there are a few planning tasks that need to be carried out. It is important to migrate a version of Siebel on a source system to the same level of Siebel on a target system. Whichever database migration process you use, it will be sensitive to Siebel versions, as each version of Siebel may have different database tables and columns.

If you need to migrate to a later version of Siebel, you need to upgrade your existing implementation to that level before migrating.

You need to make sure that your installation has all the required FixPacks applied for the version of Siebel you are trying to install. These can be found in Siebel's Product Availability Matrix.

Estimate the size of the target database server and the size needed for a data migration.

Identify personnel with database and Siebel customization skills. Analyze the amount of customization, and plan workarounds especially when Oracle specific features are used.

Once these tasks have been carried out, it will be possible to plan the data migration in more detail.

Setting up the target system

To set up the environment, consider the recommendations from Siebel.

Data migration

You have more options to migrate data from the source database to the target. Siebel delivers two utilities called Dataexp and Dataimp, which are often used by Siebel services personnel to move data.

You can pass each utility the name of the database and a list of tables to process. The Dataexp utility will export the data from the tables and stores the results in a data file, which is independent of the database implementation. Dataimp takes this file and inserts the contents into a target database.

Having a database independent data file means that we can use Dataimp to insert the data to a different target. This is exactly how Siebel handles distributing the seed and base repository data for different operating systems.

Dataexp and Dataimp is the ideal method for migrating any Siebel data with the minimum of coding and administration. Running Dataimp for very large volumes is not advisable due to the insert process. Alternatively, you can use the tools mentioned in Chapter 6, "Data conversion" on page 211, which may help you get around the potential long run times.

Migrating additional programs

In a typical Siebel installation there are additional programs such as batch jobs, which are not delivered by Siebel. You have to migrate these programs using the custom-build databases and application migration process we provide in this book.

Test

Once the data migration process has been completed, you should run various tests against the old system and the new system to make sure that they operate the same way, and return the same data with the same search criteria.

Further information

More information about Siebel application and database migration is available in:

  • Redbooks:

    • Siebel 2000 Database Implementation on OS/390 Using NT Siebel Servers, SG24-5953

    • Migrating Siebel Database from DB2 NT to DB2 S/390®, SG24-6236

  • Web site: http://www-3.ibm.com/software/data/partners/ae1partners/siebel/


Chapter 8: Script Conversion

Overview

In this chapter, we discuss the administration script conversion from an Oracle environment to a DB2 UDB environment. The chapter covers:

  • Data load script conversion

  • Administration script conversion

  • Report tools available to DB2


8.1 Data Load scripts

Data from other systems with no direct connection are mostly loaded into the database with a load utility. Oracle uses the SQL*Loader in combination with a control file. With DB2 UDB you can use:

  • DB2 UDB Load utility

    The load utility is capable of efficiently moving large quantities of data into newly created tables, or into tables that already contain data. The load process contain the four phases:

    • Load data

    • Build indexes

    • Delete rows with a unique key violation or a DATALINK violation

    • Copy index data from a system temporary table space to the original table space

  • DB2 UDB Import utility

    The import utility inserts data from an input file into a table or updatable view. If the table or view receiving the imported data already contains data, you can either replace or append to the existing data.

The load utility is faster than the import utility, because it writes formatted pages directly into the database, while the import utility performs SQL INSERTs. The load utility does not fire triggers, and does not perform referential or table constraints checking (other than validating the uniqueness of the indexes).

Oracle loader utility has two modes: direct path and conventional path. Oracle's direct path more closely resembles the DB2 load utility while the conventional path more closely resembles the DB2 import utility.

Oracle define its own Data Definition Language (DDL) to load data from a file into the database. The DDL is different to the DB2 UDB syntax.

For the most frequently used commands in an Oracle control file, in this chapter are scripts to convert the controls files to DB2 load or DB2 import files.

We recommend to migrate the more complex Oracle control file manually and implement workarounds for the functionality not available within the DB2 UDB load command. For detailed information about the DB2 load command and DB2 import command, see Chapter 6, "Data conversion" on page 211.

8.1.1 Migration approach

We propose the following approach in converting Oracle load commands:

  1. Examine the Oracle control file, the datafile format, and the target table.

  2. Check for alternatives, such as the use of database links, DB2 Information Integrator, etc. to improve the data import.

  3. Convert the Oracle control file to the proper DB2 command. In the next section we show you an easy way to convert the scripts automatically. Please note the variety of DB2 load options.

8.1.2 Loading fixed-format fields

In Example 8-1 is a simple control file to load data into the table accounts of the ORA_EMP database. The file contains a reference to the datafile accounts.dat, the target table, the fixed data positions, and its data types.

Example 8-1: SQL*Loader control file with fixed-format fields
Start example
LOAD DATA
INFILE '/home/ora_usr/accounts.dat'
INTO TABLE accounts
(  acct_id             POSITION(0001:0003) NUMBER
   ,dept_code          POSITION(0004:0006) CHAR
   ,acct_desc          POSITION(0009:0100) VARCHAR2
   ,max_employees      POSITION(0101:0103) NUMBER
   ,current_employees  POSITION(0104:0106) NUMBER
   ,num_projects       POSITION(0107:0107) NUMBER )
End example

Example 8-2 shows the corresponding DB2 load command. The details of the load command are nearly the same. The most sensitive part during the migration is the correct conversion of the POSITION() specification. To avoid errors, we recommend to migrate at least this part of the control file automatically. In Appendix D, "Converter for SQL*Loader" on page 383 is the Perl script conv_ctl.pl to convert simple SQL*Loader files to DB2 load files.

Example 8-2: DB2 UDB Load file for table ACCOUNTS
Start example
LOAD FROM '/home/ora_usr/accounts.dat' of ASC
METHOD L
        ( 0001 0003
         ,0004 0006
         ,0009 0100
         ,0101 0103
         ,0104 0106 )
INSERT INTO accounts
        ( acct_id
         ,dept_code
         ,acct_desc
         ,max_employees
         ,current_employees );
End example

8.1.3 Loading variable-length data

Example 8-3 is a simple Oracle control file to load data with a variable length into the table ACCOUNTS. The delimiter in this sample is a comma, the fields may be enclosed in double quotes. The datafile accounts.dat looks like:

   101,"ACT","Major Bank Co.",30,11,4
   301,"ACT","Large Telco Inc.",30,0,4
   101,"IT","Huge Software Co.",50,0,4
   203,"MKT","Basic Insurance Co.",15,0,3
Example 8-3: SQL*Loader control file with variable-length fields
Start example
LOAD DATA
INFILE '/home/ora_usr/accounts.dat'
INTO TABLE accounts
FIELDS TERMINATED BY "," OPTIONALLY ENCLOSED BY '"'
( acct_id
 ,dept_code
 ,acct_desc
 ,max_employees
 ,current_employees
 ,num_projects )
End example

The Perl script conv_ctl.pl in Appendix D, "Converter for SQL*Loader" on page 383 converts the control file to a proper DB2 Load file. Modify the generated DB2 load command if you need additional features.

Example 8-4: DB2 load commend with variable-length fields
Start example
LOAD FROM '/home/ora_usr/accounts.dat' of ASC
MODIFIED BY COLDEL,
METHOD P (1, 2, 3, 4, 5 )
INSERT INTO accounts
        ( acct_id
         ,dept_code
         ,acct_desc
         ,max_employees
         ,current_employees )!
End example

8.1.4 Initializations in Oracle SQL*Loader control file

In the Oracle SQL*Loader file you are able to specify initialization values for defined data.

Example 8-5 shows the same sample as above, but with conditions for the columns dept_code and current_employees.

Example 8-5: SQL*Loader control file with conditions for table ACCOUNTS
Start example
LOAD DATA
CHARACTERSET we8pc850
INFILE '/home/ora_usr/accounts.dat'
INTO TABLE accounts
( acct_id            POSITION(0001:0003) NUMBER
  ,dept_code          POSITION(0004:0006) CHAR DEFAULTIF dept_code=" "
  ,acct_desc          POSITION(0009:0100) VARCHAR2
  ,max_employees      POSITION(0101:0103) NUMBER
  ,current_employees  POSITION(0104:0106) NUMBER NULLIF current_employees="0"
  ,num_projects       POSITION(0107:0107) NUMBER )
End example

The column dept_code is set to its default value if the loaded data is blank and the variable current_employees is set to null if the loaded data is 0. Such data manipulations are not allowed with DB2 load. To achieve the data manipulation, run a separate UPDATE command after the data is loaded:

   UPDATE accounts
   SET dept_code=DEFAULT
   WHERE dept_code=" ");

   UPDATE accounts
   SET current_employees=NULL
   WHERE current_employees="0");

In Appendix D, "Converter for SQL*Loader" on page 383 is the Perl script gen_load_update.pl used to generate DB2 UDB UPDATE commands from Oracle control files.

8.1.5 Loading data into multiple tables

To achieve data loads into multiple tables, migrate the Oracle commands in this sequence:

  1. Separate the load commands to single commands per script and file.

  2. Convert the separated load command. Consider the suggestions we make in the previous chapters.

  3. Control the DB2 commands with scripts (sh, batch, etc.) regarding the needs of your system.


8.2 Administration scripts

Database administrators use many administration scripts to schedule and run their day-to-day activities. Conversion of these administration scripts from Oracle to DB2 also plays an important role in migration. This section discusses how certain administration commands and DDLs can be converted to DB2 commands and DDLs.

8.2.1 Dynamic performance views and table function

Oracle provides dynamic performance views that are updated dynamically by the Oracle instance. Dynamic performance views are prefixed by V_$ and have public synonyms created with the V$ prefix. Dynamic performance views are accessed by the database administrators, and are listed in V$FIXED_TABLE. These views are used by the database administrators to monitor the database. The information provided by these views are not static, and are dynamically updated by the database and instance. Examples of such views are V$INSTANCE, V$DATABASE, V$TABLESPACE, V$DATAFILE, etc.

DB2 UDB provides snapshot monitor to give the performance details of the database and instance. DB2 snapshot monitor gives a point-in-time view of how the database is performing. Section 9.4.4, "Problem determination tools" on page 301 gives a detailed look on these snapshot monitors. DB2 UDB Version 8.1 provides a list of built-in table functions to query the snapshot monitor output and to get the result sets in a table form. This can be thought of as equivalent to V$ views in Oracle. Though the information we get from the V$ views and table functions cannot be exactly same, some information is common, and both return dynamic data. Some of these table functions are SNAPSHOT_DBM, SNAPSHOT_DATABASE, SNAPSHOT_STATEMENT, SNAPSHOT_TABLE, etc. For example, to get the information about applications connected to the database, a table function call is made using:

SELECT * FROM TABLE( SNAPSHOT_APPL( cast (NULL as VARCHAR), -1)) as
SNAPSHOT_APPL

An equivalent query to execute in Oracle for connected application is:

SELECT * FROM V$SESSION

Table 8-1 shows some of the V$ views and its equivalent table functions.

Table 8-1: V$ views and table functions
Dynamic performance views | Snapshot table functions
V$INSTANCE | SNAPSHOT_DBM
V$DATABASE | SNAPSHOT_DATABASE
V$TABLESPACE | SNAPSHOT_TBS
V$DATAFILE | SNAPSHOT_CONTAINER
V$SESSION | SNAPSHOT_APPL
V$SQLTEXT | SNAPSHOT_STATEMENT
V$LOCK | SNAPSHOT_LOCK
V$BUFFERPOOL | SNAPSHOT_BP
Note

For more information on table functions, refer to Part 3," Using snapshot monitor" in System Monitor Guide and Reference, SC09-4847-00.

8.2.2 Frequently used commands and DDLs by DBA

It is useful for DBAs to know how certain important administrative commands and DDLs used in Oracle can be converted to DB2. This is helpful for the DBAs to create certain maintenance scripts in the DB2 environment. Table 8-2 lists out some of the sample commands and the DDL converted to DB2 equivalents.

Table 8-2: Commands and DDL conversion

Oracle

DB2 UDB

CREATE DATABASE ORA_EMP
MAXLOGFILES 2 MAXLOGMEMBERS 3
LOGFILE GROUP 1
('/disk1/log1a.log','/disk1/log1b.log','/disk1
/log1c.log') SIZE 1M,
GROUP 2
('/disk2/log2a.log','/disk2/log2b.log','/disk2
/log2c.log') SIZE 1M
DATAFILE '/disk1/system01.dbf' SIZE
100M;

CREATE DATABASE DB2_EMP
CATALOG TABLESPACE MANAGED BY
DATABASE USING (FILE
'/disk1/syscatspace.dbf' 25600);
UPDATE DB CFG FOR DB2_EMP USING
LOGPRIMARY 2;
UPDATE DB CFG FOR DB2_EMP USING
NEWLOGPATH '/disk1';
UPDATE DB CFG FOR DB2_EMP USING
MIRRORLOGPATH '/disk2';
UPDATE DB CFG FOR DB2_EMP USING
LOGFILSIZ 256;

CREATE TABLESPACE
USER_DATA_TBS
DATAFILE '/disk1/user_data_tbs_01.dbf'
SIZE 50M MINIMUM EXTENT 1M
PERMANENT

CREATE REGULAR TABLESPACE
USER_DATA_TBS MANAGED BY
DATABASE USING (FILE
'/disk1/user_data_tbs_01.dbf' 12800)
EXTENTSIZE 1M

CREATE TABLESPACE
USER_TEMP_TBS
DATAFILE '/disk1/user_temp_tbs_01.dbf'
SIZE 50M MINIMUM EXTENT 1M
TEMPORARY

CREATE USER TEMPORARY
TABLESPACE USER_TEMP_TBS
MANAGED BY DATABASE USING (FILE
'/disk1/user_data_tbs_01.dbf' 12800)
EXTENTSIZE 1M

CREATE TABLESPACE
USER_LOB_TBS
DATAFILE '/disk1/user_lob_tbs_01.dbf'
SIZE 100M MINIMUM EXTENT 1M
PERMANENT

CREATE LARGE TABLESPACE
USER_TEMP_TBS MANAGED BY
DATABASE USING (FILE
'/disk1/user_data_tbs_01.dbf' 25600)
EXTENTSIZE 1M

CREATE USER ORA_USR IDENTIFIED
BY EXTERNALLY

CREATE SCHEMA DB2_USR
AUTHORIZATION DB2_USR
-- identifies o/s user db2_usr

GRANT CREATE SESSION, CREATE
TABLE TO ORA_USR;

GRANT CONNECT, CREATETAB ON
DATABASE TO USER DB2_USR;

ALTER SYSTEM KILL SESSION
('sid','serial') IMMEDIATE

FORCE APPLICATION (appl handle)
MODE ASYNC

ALTER SYSTEM SUSPEND

SET WRITE SUSPEND FOR DB

ALTER SYSTEM QUIESCE
RESTRICTED
-- Only allowed in Oracle 9i

QUIESCE DB database name

ALTER SYSTEM ARCHIVE LOG

ARCHIVE LOG FOR DB database name

ALTER SYSTEM FLUSH
SHARED_POOL

FLUSH PACKAGE CACHE DYNAMIC

DBMS_SPACE_ADMIN package

INSPECT database command

SET TRANSACTION ISOLATION LEVEL

CHANGE ISOLATION LEVEL

ANALYZE TABLE command

RUNSTATS ON TABLE

8.2.3 Backup scripts conversion

Oracle uses two level of backups: datafile backup and logical backup using the export utility. DB2 uses the BACKUP database command to backup the database. This can be thought of as an equivalent to the Oracle export utility. So, the logical backup scripts using export utility in Oracle can be converted to DB2 backup scripts. Example 8-6 shows a sample shell script used to export the database.

Example 8-6: Export script in Oracle
Start example
#!/usr/bin/ksh
##### -- Oracle daily logical backup script --
today=`date +%C%y%m%d`
dumpfile=/oracle/backup/exp_$today.dmp
logfile=/oracle/backup/exp_$today

ORACLE_SID=ORA_EMP
export ORACLE_SID

exp system/manager file=$dumpfile log=$logfile buffer=10485760 full=y;
End example

Example 8-7 shows the equivalent shell script used in the DB2 environment to back up the database.

Example 8-7: BACKUP database script in DB2
Start example
#!/usr/bin/ksh
###### DB2 daily backup script ##########
today=`date +%C%y%m%d`
logfile=/db2/backup/db2bkup_log$today.log
BACKUPDIR=/db2/backup
db1=DB2_EMP

DB2INSTANCE=db2inst1
export DB2INSTANCE

db2 backup db $db1 online to $BACKUPDIR with 4 buffers buffer 512>> $logfile;
End example

The examples show how to back up the database into the disk. Like Oracle, DB2 also supports backing up the database directly into the tape. For more information, refer Data Recovery and High Availability Guide and Reference, SC09-4831-00.


8.3 Tools and wizards

DB2 UDB ships with many tools and wizards that help the database administrators to maintain and administrate the database. These wizards and tools are also used to generate the scripts for database administration. Examples of such wizards are Backup Wizard, Create Database Wizard, Create Tablespace Wizard, Design Advisor, Load Wizard, etc. These wizards and tools can be accessed from DB2 Control Center. Figure 8-1 shows how Backup Wizard is used to generate the backup script. The generated script can be exported to output file using Export Scripts option.

Click To expand
Figure 8-1: Backup Wizard

The scripts or job generated by the wizards can be scheduled to run and maintained in the Task Center. Figure 8-2 shows the Task Center. Task Center is also used to notify administrators on the status of a completed job. For more information on these wizards and tools, refer Guide to GUI Tools for Administration and Development, SC09-4851-00.

Click To expand
Figure 8-2: Task Center


8.4 Report tools

Reporting in DB2 is based on self prepared applications or external tools. One of the tools is IBM Query Management Facility for Windows (QMF™ for Microsoft Windows). QMF is an integrated query and reporting tool set, which allows one to generate queries and reports, and gives the availability to store them in multiple DB2 database servers. The prepared queries or reports can be viewed in various formats, such as Microsoft Excel, IBM Lotus® 1-2-3®, or text files. For more information about QMF visit the Web site:

http://www.ibm.com/software/data/qmf/

Because DB2 relies on open standards, many reporting tools from other vendors (including Brio Software Inc., Crystal Decisions Inc., Cognos Inc., MicroStrategy Inc. and Business Objects S.A.) can be used with DB2.

For OLAP (OnLine Analytical Processing) the report DB2 Cube Views product can be used. Cube Views automate the creation of OLAP metadata at the database level so that metadata can be shared among applications that access the database. A number of third party tools support the metadata format, so there is no need to create the metadata for each product. Cube Views aggregates the data into cube-like dimensional charts, allowing users to access the data from different perspectives. DB2 Cube views provides a SQL-based and XML-based application programming interface (API) for OLAP tools and application developers. Through CLI, ODBC, or JDBC connections or by using embedded SQL to DB2, applications and tools can use a single stored procedure to create, modify, and retrieve metadata objects. DB2 Cube Views also provide a functionality to query and explore the data in a Microsoft Excel spreadsheet. For more information about Cube Views refer to:

http://www.ibm.com/software/data/db2/db2md/


Chapter 9: Testing

All stages of the migration process should be validated by running a series of carefully designed tests. The purpose of the tests is to determine the differences between the expected results (the source environment) and the observed results (the migrated application). The detected changes should be synchronized with the development stages of the project. This chapter describes the test objectives and a generic testing methodology, which can be employed to test migrated applications.

9.1 Planning

The test planning details the activities, dependencies, and effort required to conduct the test of the converted solution.

9.1.1 Principles of software tests

Keep in mind the principles of software tests in general:

  • It is not possible to test a nontrivial system completely.

  • Tests are optimizing processes regarding completeness.

  • Always test against expectations.

  • Each test must have reachable goals.

  • Test cases have to contain reachable and non-reachable data.

  • Test cases must be repeatable.

  • Test cases have to be archived in the configuration management system as well as source code and documentation.

9.1.2 Test documentation

The test documentation is the most important part of the project. The ANSI/IEEE Standard for Software Test Documentation, ANSI/IEEE Std 829-1983, describes its content exactly. We give you here a high level overview.

Scope

State the purpose of the plan, possibly identifying the level of the plan (master etc.). This is essentially the executive summary part of the plan.

You may want to include any references to other plans, documents, or items that contain information relevant to this project and process. If preferable, you can create a references section to contain all reference documents.

Identify the Scope of the plan in relation to the Software Project plan that it relates to. Other items may include, resource and budget constraints, scope of the testing effort, how testing relates to other evaluation activities (Analysis & Reviews), and possible the process to be used for change control and communication, and coordination of key activities.

As this is the Executive Summary, keep information brief and to the point.

Definition of test items

Define the test items you intend to test within the scope of this test plan. Essentially, something you will test is a list of what is to be tested. This can be developed from the software application inventories as well as other sources of documentation and information.

This section is a technical description of the software, and can be oriented to the level of the test plan. For higher levels, it may be by application or functional area, for lower levels it may be by program, unit, module, or build.

Features to be tested

This is a listing of what is to be tested from the users viewpoint of what the system does. This is not a technical description of the software, but a users view of the functions. Users do not understand technical software terminology. They understand functions and processes as they relate to their jobs.

Set the level of risk for each feature. Use a simple rating scale such as high, medium and low (H, M, L). These types of levels are understandable to a user. You should be prepared to discuss why a particular level was chosen.

Features not to be tested

This is a listing of what is not to be tested from both the users viewpoint of what the system does and a configuration management view. This is not a technical description of the software, but a users view of the functions.

Identify why the feature is not to be tested; there can be any number of reasons.

Approach®

This is your overall test strategy for this test plan. It should be appropriate to the the plan and should be in agreement with plans affecting application and database parts. Overall rules and processes should be identified:

  • Are any special tools to be used and what are they?

  • Will the tool require special training?

  • What metrics will be collected?

  • Which level is each metric to be collected at?

  • How is Configuration Management to be handled?

  • How many different configurations will be tested?

  • Combinations of hardware, software, and other vendor packages.

  • What levels of regression testing will be done and how much at each test level?

  • Will regression testing be based on severity of defects detected?

  • How will elements in the requirements and design that do not make sense or are un-testable be processed?

Item pass and fail criteria

What is the completion criteria for this plan? What is the number and severity of defects located? This is a critical aspect of any test plan and should be appropriate to the level of the plan.

Suspension criteria and resumption requirements

Know when to pause in a series of tests. If the number or type of defects reaches a point where the follow on testing has no value, it makes no sense to continue the test; you are just wasting resources.

Specify what constitutes stoppage for a test or series of tests, and what is the acceptable level of defects that will allow the testing to proceed past the defects.

Testing after a truly fatal error will generate conditions that may be identified as defects, but are in fact ghost errors caused by the earlier defects that were ignored.

Test deliverables

What is to be delivered as part of this plan?

  • Test plan document

  • Test cases

  • Test design specification

  • Tools and their outputs

  • Error logs and execution logs

  • Problem reports and corrective actions

One thing that is not a test deliverable is the software itself, which is listed under test items, and is delivered by development.

Environmental needs

Are there any special requirements for this test plan, such as:

  • Special hardware such as simulators, static generators, etc.

  • How will test data be provided? Are there special collection requirements or specific ranges of data that must be provided?

  • How much testing will be done on each component of a multi-part feature?

  • Special power requirements

  • Specific versions of other supporting software

  • Restricted use of the system during testing

Staffing and skills

The staffing depends on the kind of test defined in Chapter 9.1.3, "Test phases" on page 279. In this section you should define the persons and the education and training needed for executing the test case.

Responsibilities

Who is in charge? This issue includes all areas of the plan. Here are some examples:

  • Setting risks

  • Selecting features to be tested and not tested

  • Setting overall strategy for this level of plan

  • Ensuring all required elements are in place for testing

  • Providing for resolution of scheduling conflicts, especially if testing is done on the production system

  • Who provides the required training?

  • Who makes the critical "go/no" decisions for items not covered in the test plans?

9.1.3 Test phases

Series of well designed tests should validate all stages of the migration process. Detailed test plan should describe all the test phases, scope of the tests, validation criteria, and specify the time frame. To ensure that the applications operate in the same manner as they did in the source database, the tests plan should include data migration, functional, and performance tests, as well as other post migration assessments.

Data migration testing

Extracting and loading process entails conversion between source and target data types. The migrated database should be verified to ensure that all data is accessible, and was imported without any failure or modification that could cause applications to function improperly.

Functional testing

Functional testing is a set of tests in which new and existing functionality of the system are tested after migration. Functional testing includes all components of the RDBMS system (stored procedures, triggers), networking, and application components. The objective of functional testing is to verify that each component of the system functions as it did before migrating, and to verify that new functions are working properly.

Integration testing

Integration testing examines the interaction of each component of the system. All modules of the system and any additional applications (WEB, supportive modules, Java programs, etc.) running against the target database instance should be verified to ensure that there are no problems with the new environment. The tests should also include GUI and text-based interfaces with local and remote connections.

Performance testing

Performance testing of a target database compares the performance of various SQL statements in the target database with the statements' performance in the source database. Before migrating, you should understand the performance profile of the application under the source database. Specifically, you should understand the calls the application makes to the database engine.

Volume/Load stress testing

Volume and load stress testing tests the entire migrated database under high volume and loads. The objective of volume and load testing is to emulate how the migrated system might behave in a production environment. These tests should determine whether any database or application tuning is necessary.

Acceptance testing

Acceptance tests are carried out by the end users of the migrated system. Users are asked to simply explore the system, test usability, and system features, and give direct feedback. After acceptance, tests are usually the last step before going into production with the new system.

Post migration tests

Because a migrated database can be completely new environment for the IT staff, the test plan should also encompass examination of new administration procedures like database backup/restore, daily maintenance operation, or software updates.

9.1.4 Time planning and time exposure

The time planning should be based on realistic and validated estimates. If the estimates for the migration of the application and database are inaccurate, the entire project plan will slip, and the testing is part of the overall project plan.

It is always best to tie all test dates directly to their related migration activity dates. This prevents the test team from being perceived as the cause of a delay. For example, if system testing is to begin after delivery of the final build, then system testing begins the day after delivery. If the delivery is late, system testing starts from the day of delivery, not on a specific date. This is called dependent or relative dating.

Figure 9-1 shows the phases during a typical migration project. The definition of the test plans happen in a very early moment. The test cases, and all its following tasks, must be done for all test phases as described in Chapter 9.1.3, "Test phases" on page 279.

Click To expand
Figure 9-1: Phases during a migration project

The time exposure of tests depends on the availability of an exiting test plan and already prepared test items. The efforts depend also on the degree of changes during the application and database migration.

Note

The test efforts can be between 50% and 70% of the total migration effort.


9.2 Data checking technique

Data movement is the first thing any migration should focus on. Without having all your tables and data properly moved over, all other migration testing is in vain. The test process should detect, if all rows were imported into the target database, verify that data type conversions were successful, and check random data byte-by-byte. The data checking process should be automated by appropriate scripts. When testing data migration you should:

  • Check IMPORT/LOAD messages for errors and warnings.

  • Count the number of rows in source and target databases and compare them.

  • Prepare scripts that perform data checks

  • Involve data administration staff familiar with the application and its data to perform random checks.

9.2.1 IMPORT/LOAD messages

You should always check the messages generated by IMPORT or LOAD commands. Example 9-1 presents messages generated by the sample import command. You should read not only the summary at the end of the listing, but also pay attention to the warning messages.

Example 9-1: Sample IMPORT messages
Start example
db2 import from table01.unl of del replace into table01

SQL3109N  The utility is beginning to load data from file "table01.unl".

SQL3148W  A row from the input file was not inserted into the table.  SQLCODE
"-545" was returned.

SQL0545N  The requested operation is not allowed because a row does not satisfy
the check constraint "ARTURW.TABLE01.SQL030812222227680".  SQLSTATE=23513

SQL3185W  The previous error occurred while processing data from row "2" of the
input file.

SQL3117W  The field value in row "3" and column "1" cannot be converted to a
SMALLINT value.  A null was loaded.

SQL3125W  The character data in row "4" and column "2" was truncated because
the data is longer than the target database column.

SQL3110N  The utility has completed processing. "4" rows were read from the
input file.
SQL3221W  ...Begin COMMIT WORK. Input Record Count = "4".

SQL3222W  ...COMMIT of any database changes was successful.

SQL3149N  "4" rows were processed from the input file.  "3" rows were
successfully inserted into the table.  "1" rows were rejected.

Number of rows read         = 4
Number of rows skipped      = 0
Number of rows inserted     = 3
Number of rows updated      = 0
Number of rows rejected     = 1
Number of rows committed    = 4
End example

As shown in the summary, during the import process one record from the input file was rejected, and three were inserted into the database. To understand the nature of the warnings, you should look into the data source file and the table definition (db2look command). For Example 9-1, the table definition is presented in Figure 9-2 and the data file in Figure 9-3.

Start Figure
CREATE TABLE TABLE01 (
  C1 SMALLINT,
  C2 CHAR(3),
  C3 SMALLINT CHECK( C3 IN (1,2,3)))
End Figure

Figure 9-2: Table "table01" definition for Example 9-1
Start Figure
1,"abc",1
2,"abc",4
32768,"abc",2
4,"abcd",3
End Figure

Figure 9-3: Data file "table01.unl" for Example 9-1

The first row from the input file (Figure 9-3) was inserted without any warnings. The second row was rejected because it violated check constraint (warnings SQL3148W, SQL0545N, SQL3185W). A value of 32768 from the third row was changed to null because it was out of SMALLINT data type range (warning SQL3117W) and string abcd from the last row was truncated to abc because it was longer than the relevant column definition (warning SQL3125W).

The LOAD utility generates messages in similar format, but because it is designed for speed, it bypasses the SQL engine, and inserts data directly into table spaces without constraint checking. Inserting the same table01.unl file (Figure 9-3) into table01 (Figure 9-2) with load utility generates messages without SQL3148W, SQL0545N, SQL3185W warnings as shown in Figure 9-2.

Example 9-2: LOAD messages
Start example
db2 load from table01.unl of del replace into table01

[..]
SQL3117W  The field value in row "3" and column "1" cannot be converted to a
SMALLINT value.  A null was loaded.

SQL3125W  The character data in row "4" and column "2" was truncated because
the data is longer than the target database column.

[..]
Number of rows read         = 4
Number of rows skipped      = 0
Number of rows loaded       = 4
Number of rows rejected     = 0
Number of rows deleted      = 0
Number of rows committed    = 4
End example

A table that has been created with constraints is left by the LOAD command in check pending state. Accessing the table with SQL queries generates warning SQL0668N Operation not allowed for reason code "1" on table "<TABLE_NAME>". SQLSTATE=57016. The SET INTEGRITY SQL statement should be used to move loaded table into a usable state. Example 9-3 shows a way to validate constraints. All rows that violated constraints will be moved to exception table table01_e.

Example 9-3: Turning integrity checking back on.
Start example
db2 create table table01_e like table01
db2 set integrity for table01 immediate checked for exception in table01 use
table01_e

SQL3602W  Check data processing found constraint violations and moved them to
exception tables.  SQLSTATE=01603
End example

The set integrity statement has many options, like turning integrity on only for new data, turning integrity off, or specifying exception tables with additional diagnostic information. To read more about SET INTEGRITY command refer to:

  • DB2 UDB SQL Reference Volume 2

  • DB2 UDB SQL Reference Volume 1 for exception tables.

9.2.2 Data checking scripts

Scripts performing logical data integrity checks automate the data verification process and save administrator effort. For small tables (with less that 50,000 rows) you can write a program that compares data byte-by-byte. The program (preferably ODBC, JDBC, or SQL script) can extract sorted rows from Oracle and DB2 to files in the same ASCII format. The files should be then binary compared (on UNIX use DIFF command) and checked to determine if they are the same. For larger tables, comparing all rows byte by bytes can be very inefficient. The data migration should be evaluated by comparing aggregate values, like the number of rows. To do this you can create a special table for storing the information about the number of rows in the source Oracle database. Table CK_ROW_COUNT presented in Example 9-4 can be used for that purpose.

Example 9-4: Table for storing number of rows (Oracle)
Start example
CREATE TABLE CK_ROW_COUNT (
   TAB_NAME VARCHAR2(30), -- table name
   ROW_COUNT INT, -- number of rows
   SYS_NAME CHAR(3), -- code to distinguish the system: ORA or DB2
   TIME_INS DATE -- time when the count was performed
End example

For each table you should count the number of rows and store the information in the CK_ROW_COUNT table. The following insert statement can be used for that purpose:

   insert into ck_row_count select 'TAB_NAME', count(*), 'ORA',  sysdate from
   TAB_NAME

The table CK_ROW_COUNTS and its data can be manually migrated to the target DB2 database. Example 9-5 presents DB2 versions of the table.

Example 9-5: Table for storing number of rows (DB2)
Start example
CREATE TABLE CK_ROW_COUNT (
   TAB_NAME VARCHAR(30),
   ROW_COUNT INT,
   SYS_NAME CHAR(3),
   TIME_INS TIMESTAMP
)
End example

On the DB2 system, you should repeat the counting process with the equivalent insert statement:

   insert into ck_row_count select 'TAB_NAME', count(*), 'DB2',  CURRENT
   TIMESTAMP from  TAB_NAME

After performing the described steps DB2 table CK_ROW_COUNT should contain information about the number of rows counted on Oracle and DB2 databases. The records in the table should look like Example 9-6.

Example 9-6: Sample table CK_ROW_COUNTS contents
Start example
select TAB_NAME, ROW_COUNT, SYS_NAME, TIME_INS from CK_ROW_COUNT
[...]
TABLE_A 39001 ORA 2003-08-13-10.13.39
TABLE_A 39001 DB2 2003-08-13-10.32.13
TABLE_B 60003 ORA 2003-08-13-10.15.29
TABLE_B 60002 DB2 2003-08-13-10.33.49
[...]
End example

Having the information about number of rows in a SQL table is very convenient, because with single query you can get the table names that contain the different number of rows in source and target databases:

   select tab_name from (select distinct tab_name, num_rows from CK_ROW_COUNT)
   as t_temp group by t_temp.tab_name having(count(*) > 1)

To manually migrate the data from the Oracle ck_row_count table, you can save the results of the following query to a file (ck_row_count.unl):

   select tab_name || ',' || row_count || ',' || sys_name || ',' || to_char(
   time_ins, 'yyyy-mm-dd-hh24.mi.ss".000000"') from  ck_row_count

and import the file into DB2 using DB2 import command:

   db2 import from ck_row_count.unl of del insert into ck_row_count

The process of creating the statements that count the number of rows is automated by a PL/SQL script presented in Example 9-7. The script retrieves information about the user tables from the Oracle data dictionary, and generates two files count_rows_ora.sql (Oracle version) and count_rows_db2.sql (DB2 version) with insert statements that can used for calculating rows for all user tables.

Example 9-7: PL/SQL program that generates scripts for counting rows
Start example
set heading off;
set echo off;
set feedback off;
set serveroutput on size 100000

---- Generating script for Oracle database
spool count_rows_ora.sql;

BEGIN
  dbms_output.put_line( 'CREATE TABLE CK_ROW_COUNT ( TAB_NAME VARCHAR2(30),
ROW_COUNT INT, SYS_NAME CHAR(3), TIME_INS DATE);');

  FOR tab_rec IN (SELECT TABLE_NAME from TABS ) LOOP
   dbms_output.put_line( 'INSERT INTO CK_ROW_COUNT SELECT
'''||tab_rec.table_name||''', COUNT(*), ''ORA'',  SYSDATE FROM '||
tab_rec.table_name ||';');
  END LOOP;
  dbms_output.put_line( 'COMMIT; ');
END;
/
spool off;

---- Generating script for DB2 database
spool count_rows_db2.sql;
BEGIN

  dbms_output.put_line( 'CREATE TABLE CK_ROW_COUNT ( TAB_NAME VARCHAR(30),
ROW_COUNT INT, SYS_NAME CHAR(3), TIME_INS TIMESTAMP);');

  FOR tab_rec IN (SELECT TABLE_NAME from TABS ) LOOP
   dbms_output.put_line( 'INSERT INTO CK_ROW_COUNT SELECT
'''||tab_rec.table_name||''', COUNT(*), ''DB2'',  CURRENT TIMESTAMP FROM '||
tab_rec.table_name ||';');
  END LOOP;
  dbms_output.put_line( 'COMMIT; ');
END;
/
spool off;
rollback;
End example

The presented approach for comparing the number of rows can be extended for additional checking, like comparing sum of numeric columns. Here are the steps that summarize the technique:

  1. Define check sum tables on the source database and characterize scope of the computation.

  2. Perform the computation and store the results in the appropriate check sum tables. Use Oracle data dictionary (TABS and COLS) to generate the aggregate queries, or write SPL procedures.

  3. Migrate the check sum tables as other user tables.

  4. Perform equivalent computations on the target system, and store the information in the migrated check sum tables.

  5. Compare the computed values.

Table 9-4 provides computations for selected database types. The argument for the DB2 sum() function is converted to DECIMAL type, because in most cases the sum() function returns the same data type as its argument, which can cause arithmetic overflow. For example, when calculating the sum on an integer column, if the result exceeds the integer data type range, error SQL0802N is generated Arithmetic overflow or other arithmetic exception occurred. Converting the argument to DECIMAL eliminates the error.

Table 9-1: Aggregations for data migration verification
Data type | Oracle operation | DB2 operation
numeric(<precison>,<scale>) | sum( val) | sum( cast(val as decimal(31,<scale>)))
date | sum( trunc( val - to_date('0001/01/02', 'yyyy/mm/dd'))) | sum( cast(days(val) as decimal(31,1)))
variable length character | sum( length(val)) | sum( cast( length(val) as decimal(31,0)))
fixed length character | sum( length(rtrim(val))) | sum( cast( length(rtrim(val)) as decimal(31,0)))


9.3 Code and application testing

The most important part of the testing process is to verify that each component of the system functions as it did before migrating. All components of RDBMS system including views, stored procedures, triggers, application components, and security systems should be verified whether they are working properly.

9.3.1 View sanity check

The next step after data migration testing is to check all migrated views. Once data is moved over, the views can be tested to make sure they are working in the same way as in the source database. Depending upon the view, different checking scenarios can be created. Basic views can be easily checked, by counting rows the views return, or comparing calculated values similarly to the tests done on regular tables. More complicated views need a little more thought on how they should be checked, however, all view should be at a minimum reviewed by executing queries against them. The views created with intention to modify data should also be tested for inserting, updating, and deleting.

9.3.2 PL/SQL to SQL PL object check

All stored procedures, user defined functions, and triggers should be unit tested individually before they are promoted for further testing. This means that after objects are migrated (either manually, with MTK, or some combination of that) they need to be checked to make sure they function properly. Basic problems can be discovered by running stored procedures through the Development Center. The Development Center is a powerful tool used to develop stored procedures, user defined functions, or structured types. Within the Development Center there are options to run selected procedures in debug mode (Figure 9-4).

Click To expand
Figure 9-4: Development Center debug window.

The Development Center can be run from the command line by entering db2dc or starting from the Tools menu of any graphical administration tool provided with DB2. For more information about the Development Center, refer to IBM DB2 UDB Guide to GUI Tools for Administration and Development, SC09-4851.

9.3.3 Application code check

The scope of application testing depends on the migrated application. For systems that were designed to support many versions of databases, like SAP, Siebel, or PeopleSoft, the testing process is usually well defined by the vendors, and offered a as a paid service.

For self build applications, the testing process should be started with the application queries. All queries should be independently tested to ensure that they return the expected results. With the application queries successfully migrated, the surrounding client programs should be rebuilt, and then the application should be tested against the target database. Each module of the application and possibly each screen form should be run and checked for errors or improper functionality. All the supported by application connectivity interfaced should also be checked.

The very important issue is to document all the tests conditions, like what operations were performed, which application screens were opened, what input data was used for testing, and what was the result. For larger projects, the documenting part can become overwhelming, so usually specialized software is used for those cases. As mentioned earlier, by definition, the new application cannot be fully tested. In the migration project, the application testing is an iterative process of planning, designing the test cases, executing the test cases, and finally evaluating and analyzing the results.

Together with various functional testing, the application should be checked also against performance. Since there are many architectural differences between Oracle and DB2, some SQL operations might require further optimization. Observing the performance differences on early testing stages increases the chance to prepare more optimal code for the new environment.

Before going into production, the migrated database should be verified under high volume and loads. These tests should emulate the production environment, and can determine if further application or database tuning is necessary. The stress load can also reveal other hidden problems, like locking issues, which can be observed only in a production environment.

9.3.4 Security

Before going into production, security must be checked in detail. Oracle handles security quite differently than DB2, so it is not trivial to compare the user rights between the two systems. Oracle's grants to roles are resolved in DB2 with operating system groups or secondary authorization identifications. A list of Oracle user should be compared to equivalent DB2 operating system users. All of DB2's authorities should be verified to allow proper persons to connect to the database. Privileges for all database objects also should be verified. Another important issue is to check the identifications of the user who was used for binding stored procedures, because executor of the procedures inherit the binder privileges.

9.3.5 Tools for testing and problem trucking

The software testing process can be a very complex task. All the tests should be synchronized with the development life cycle, and be well documented. For large projects, it might be necessary to use supportive software to improve testing productivity. IBM Rational Suite® TestStudio® can be used for that purpose.

IBM Rational Suite TestStudio is a set of tools for testers and developers. It automates regression, functionality, and performance testing, and provides background runtime analysis for increased product reliability. Rational Suite TestStudio also includes tools for control, management, and reporting of all test activities, defect, and change tracking, software configuration management, and requirements management. Rational Suite TestStudio addresses everything from test process standardization to results analysis, requirement determination to impact analysis, and test automation to defect tracking and reporting.

For more information about testing products, go to the IBM Rational Web site:

http://www.ibm.com/software/rational


9.4 Troubleshooting

The first step of problem determination is to know what information is available to you. Whenever DB2 UDB performs an operation, there is a return code associated with that operation. The return code is displayed to the user in the form of an informational or error message. These messages are logged into diagnostic files depending on the diagnostic level set in the DB2 Manager Configuration. In this section, we discuss the DB2 diagnostic logs, error message interpretation, tips that may help with problem determination, troubleshooting, as well as the resolutions to some specific problems.

The following actions should be taken when experiencing a DB2 related problem:

  • Check related messages

  • Explain error codes

  • Check documentation

  • Search through available Internet resources

  • Review APARs for current FixPak level

  • Use available tools to narrow the problem

  • Ask IBM for support

9.4.1 Interpreting DB2 informational messages

Start your investigation from the return code. DB2 UDB provides a return code for every operation performed in the form of CCCnnnnnS. The prefix CCC identifies the DB2 UDB component that is returning the message; the nnnnn is a four or five digit number which is also referred to as SQLCODE; and the S is a severity indicator. For example, SQL0289N the SQL component identifier, represents a message from the Database Manager, the SQLCODE is 0289, which is an error message.

Here is the complete list for DB2 UDB error messages to prefix your reference:

  • SQL Database Manager messages

  • DB2 Command Line Processor messages

  • ASN Replication messages

  • CLI Call Level Interface messages

  • SQJ Embedded SQLJ in Java messages

  • SPM Synch Point Manager messages

  • DBI Installation or configuration messages

  • DBA Control Center and Database Administration Utility messages

  • CCA Client Configuration Assistant messages

  • DWC Data Warehouse Center messages

  • FLG Information Catalog Manager messages

  • SAT Satellite messages

The three severity indicators are:

  • W: Indicates warning or informational messages

  • N: Indicates error messages

  • C: Indicates critical system errors

DB2 UDB also provides detailed information for each message. The full error message describes the nature of the problem in detail and potential user responses. To display the DB2 UDB return code full message, you can use the DB2 command db2 ? error-code. In AIX or Linux, since ? (question mark) is a special character, you need to separate the DB2 command and the error code with a double quote ("). See Example 9-8.

Example 9-8: Explaining error codes
Start example
db2 "? sql0289"
SQL0289N Unable to allocate new pages in table space
          "<tablespace-name>".

Explanation:

One of the following conditions is true:

1. One of the containers assigned to this SMS table space has
   reached the maximum file size. This is the likely cause of
   the error.
2. All the containers assigned to this DMS table space are
   full.  This is the likely cause of the error.

[...]
End example

You can find full information about the DB2 message format, and a listing of all the messages in DB2 UDB Messages Reference, Volumes 1 and 2.

9.4.2 DB2 diagnostic logs

DB2 UDB logs every return code in diagnostic logs based on the diagnostic level set in the database manager configuration. When investigating DB2 problems, the essential information can be found in diagnostic log files generated by DB2. These logs are:

  • db2diag.log

  • Notify files

  • Trap files

  • Dump files

  • Messages files

db2diag.log

The db2diag.log is the most often used file for DB2 problem investigation. You can find this file in the DB2 UDB diagnostic directory, defined by the DIAGPATH variable in the Database Manager Configuration. If the DIAGPATH parameter is not set, by default the directory is located at:

UNIX:

$HOME/sqllib/db2dump

where $HOME is the DB2 instance owner's home directory.

Windows:

<INSTALL PATH>\<DB2INSTANCE>

where <INSTALL PATH> is the directory where DB2 is installed, and <DB2INSTANCE> is the name of DB2 instance.

The database manager configuration parameter DIAGLEVEL controls how much information is logged to the db2diag.log.Valid values can range from 0 to 4:

  • 0 - No diagnostic data captured

  • 1 - Severe errors only

  • 2 - All errors

  • 3 - All errors and warnings (default)

  • 4 - All errors, warnings and informational messages

Most of the time, the default value is sufficient for problem determination. In some cases, especially on development or test systems you can set the parameter to 4, and collect all informational messages. However, be aware that depending on the activity, this may cause performance issues due to the large amount of data recorded into the file. Setting DIAGLEVEL to 4 may also make the file very large and harder to read.

The information in the db2diag.log includes:

  • A diagnostic message (beginning with DIA) explaining the reason for the error.

  • Application identifiers, which allow matching up error entries with corresponding application or db2 server processes

  • Any available supporting data, such as SQLCA data structures, and pointers to the location of any extra dump or trap files.

  • Administrative events, i.e. backup/restore start and finish

Example 9-9 contains extract of db2diag.log taken at DIAGLEVEL 3.

Listing 9-9: Example of db2diag.log file
Start example
[1] 2003-07-29-02.26.33.004000   [2] Instance:DB2INST1   [3] Node:000
[4] PID:1012(db2syscs.exe)   [5] TID:1996   [6] Appid:*LOCAL.DB2.00E049090924
[7] data management  [8] sqldEscalateLocks  [9] Probe:3  [10] Database:DB2_EMP2

[11] ADM5502W  The escalation of "1251" locks on table "DB2INST1  .TABLE01" to
lock intent "X" was successful.
End example

Explanation of db2diag.log entries are included below. The number in parenthesis corresponds to the following numbers:

[1] | The date and timestamp of the entry made into the log.
[2] | The name of the instance. In this example DB2INST1.
[3] | The node or partition number. This number is always 0 in a single partition configuration
[4] | The process ID of the application or agent
[5] | The thread ID of the application or agent. This is only used on the Windows platform.
[6] | The application ID. This corresponds to the LIST APPLICATIONS command output. Each application has a unique application ID.
[7] | Component name
[8] | The name of the function in the component that is reporting an error or information.
[9] | The probe point in the function. This corresponds to a location in the source code of the function that has returned an error or information.
[10] | Name of the accessed database that generated the message.
[11] | Diagnostic information. In this example this is a administration warning, telling about lock escalation (1251 row locks where successfully replaced by one table lock) on table DB2INST1.TABLE01.

Notify files

DB2 UDB also provides diagnosis information at the point failure to the administration notification log. On UNIX platforms, the administration notification log is a text file called <instance>.nfy, where <instance> is the name of the instance. On Windows, all administration notification messages are written to the Event Log.

The DBM configuration parameter NOTIFYLEVEL specifies the level of information to be recorded:

  • 0 - No administration notification messages captured (not recommended)

  • 1 - Fatal or unrecoverable errors

  • 2 - Immediate action required

  • 3 - Important information, no immediate action required (default)

  • 4 - Informational messages

Not only can DB2 UDB write to the notify logs, but also the Health Monitor, the Capture and Apply programs, and user applications using the db2AdminMsgWrite API.

Trap files

Whenever a DB2 UDB process receives a signal or exception (raised by the operating system as a result of a system event) that is recognized by the DB2 signal handler, a trap file is generated in the DB2 diagnostic directory. The files are created using the following naming convention:

UNIX:

  • tpppppp.nnn

    • pppppp: the process ID (PID)

    • nnn: the node where the trap occurred

    • Example: t123456.000

Windows:

  • DBpppttt.TRP

    • ppp : the process ID (PID)

    • ttt : the thread ID (TID)

    • Example: DB123654.TRP

Depending on the signal received or the exception raised, the existence of these files can indicate different extremes of consequences. These consequences can range from the generation of a simple stack trace back for additional diagnostics, to a complete DB2 instance shutdown due to a serious internal or external problem. A list of all available signals for selected operating systems can be obtained from the following files:

  • UNIX: /usr/include/sys/signal.h

  • Windows (requires the software development kit): Winnt.h

Dump files

When DB2 determines that internal information needs to be collected, it will often create binary dump files in the diagnostic path. These files are generated with the following format:

UNIX:

  • pppppp.nnn or lpppppp.nnn (for lock list dump)

    • pppppp: the process ID (PID)

    • nnn: the node where the problem occurred

    • Example: 123456.000

Windows:

  • pppttt.nnn or lpppttt.nnn (for lock list dump)

    • ppp: the process ID (PID)

    • ttt: the thread ID (TID)

    • nnn: the node where the problem occurred

    • Example: 123654.000

Messages files

Some DB2 UDB utilities like BIND, LOAD, EXPORT, and IMPORT provide an option to dump out a messages file to a user-defined location. These files contain useful information to report the progress, success, or failure of the utility that was run.

9.4.3 DB2 support information

Identifying what information is typically required to resolve problems is a very important step. All the conditions that define the problem are essential when reviewing documentation, searching through available Internet resources, or contacting DB2 support.

Maintenance version

The Db2level utility can be used to check current versions of DB2 UDB. As presented in Figure 9-5, the utility returns information about the installed maintenance updates (FixPaks); length of word used by instance (32 bit or 64 bit); build date; and other code identifiers. It is a good habit to check periodically if here are the newest available FixPaks. DB2 maintenance updates are freely available at:

Click To expand
Figure 9-5: Sample db2level output

ftp://ftp.software.ibm.com/ps/products/db2/fixes

db2support utility

The db2support utility is designed to automatically collect all DB2 and system diagnostic data. This program generates information about a DB2 server, including information about its configuration and system environment. The output of this program is stored in one compressed file named db2support.zip, located in the directory specified as part of the command invoked under command line. In one simple step, the tool can gather database manager snapshots, configuration files, and operating system parameters, which should make the problem determination quicker. Below there is a sample call of the utility:

db2support . -d db2_emp -c

The dot represents the current directory where the output file is stored. The rest of the command is optional. -d and -c instructs the utility to connect to the db2_emp database, and also gather information about database objects such as table spaces, tables, or packages.

DB2 Technical Support site

An invaluable place to look if experiencing a problem is the DB2 Technical Support site for Linux, OS/2®, Windows, and UNIX located on the Web at:

http://www.ibm.com/software/data/db2/udb/winos2unix/support

The site has the most recent copies of the documentation, the knowledge base to search for technical recommendations or DB2 UDB defects, links for product updates, the latest support news, and many useful DB2 UDB related links.

To find related problems, prepare words that describe the issue like the commands that were run, the symptoms, and tokens from the diagnostics messages, and use them as a search terms in DB2 Knowledge Base. The Knowledge Base offers an option to search through DB2 UDB documentation, TechNotes, and DB2 UDB defects (APARs).

TechNotes is a set of recommendations and solutions for specific problems. For example, to check which operating system patches are needed for DB2 UDB installation on the Solaris operating system, click the Advanced Search selection on navigation menu, and type the solaris patch keywords as presented in Figure 9-6, and click Search DB2 V8 Information Center at the bottom of the screen.

Click To expand
Figure 9-6: Searching for problem resolutions using TechNotes

The search returned one document in the Installation and Configuration category for TechNotes as presented in Figure 9-7.

Click To expand
Figure 9-7: Sample TechNotes search results

The following the link leads to the desired document describing Sun Solaris versions supported by DB2 UDB (Figure 9-8).

Click To expand
Figure 9-8: Sample TechNotes document link

Authorized Program Analysis Reports (APARs) are defects in DB2's code discovered by customers that require a fix. APARs have unique identifiers and are always specific to a particular version, but may affect multiple products in the DB2 family running on multiple platforms. Fixes for APARs are provided through DB2 UDB FixPaks.

On the DB2 support site there is a possibility to search for closed, open, and HIPER APARs. A status of closed APAR indicates the resolution for the problem has been verified and included in the FixPaks. Open APARs represent DB2 UDB defects that are currently being worked upon or waiting to be included in the next available FixPak. HIPER APARs (High-Impact or PERvasive) are critical problems that should be reviewed to assess the potential impact of staying at a particular FixPak level.

DB2 Technical Support site offers e-mail notification of critical or pervasive DB2 UDB customer support issues, including HIPER APARs and FixPak alerts. To subscribe it, follow the DB2 Alert link on the Technical Support main page, and provide your e-mail as shown on Figure 9-9.

Click To expand
Figure 9-9: Subscribing DB2 alert

Calling IBM support

If the problem seems to be too complex to solve on your own, you can contact the IBM Software Support Center. In order to understand and resolve your support service request in the most expedient way possible, it is important that you gather information about the problem and have it on hand when talking to the software specialist.

The guidelines and reference materials (which you may need when require IBM support) as well the telephone numbers are available on IBM Software Support Guide:

http://techsupport.services.ibm.com/guides/handbook.html

9.4.4 Problem determination tools

Tuning and troubleshooting a database can be a complex process. DB2 UDB comes with a great number of tools, functions, and applications that make this task much simpler.

Monitoring tools

DB2 UDB monitoring utilities can collect information on many different system activities, like usage of buffer pools, locks held by applications, sorts preformed by system, activities on tables, connections, transactions statistics, or statements run on the system. There are two main methods of monitoring:

  • Snapshot monitoring

  • Event monitoring

Snapshot monitoring

Snapshot monitoring describes the state of database activity at the particular point in time the snapshot is taken. Snapshot monitoring is useful in determining the current state of the database and its applications. Because snapshots provide the point in time data, usually they are executed in scripts on regular intervals.

Snapshots can be taken from the command line, using custom API program or through SQL using table functions. Example 9-10 shows extract from sample snapshot invoked form the command line.

Example 9-10: Example snapshot
Start example
db2 get snapshot for database on db2_emp

              Database Snapshot

Database name                              = DB2_EMP
Database path                              =
/db2/home/db2inst1/db2inst1/NODE0000/SQL00001/
Input database alias                       = DB2_EMP
Database status                            = Active
[...]

High water mark for connections            = 3
Application connects                       = 7
Secondary connects total                   = 0
Applications connected currently           = 1
Appls. executing in db manager currently   = 0
Agents associated with applications        = 1
Maximum agents associated with applications= 1
Maximum coordinating agents                = 1
[...]

Buffer pool data logical reads             = Not Collected
Buffer pool data physical reads            = Not Collected
Asynchronous pool data page reads          = Not Collected
[...]
End example

The snapshot collects database level information for database DB2_EMP. Some of the returned parameters display point in time values such as the number of currently connected applications:

   Applications connected currently           = 1

Some parameters represent cumulative values like the number of connect statements issued against the database:

   Application connects                       = 7

Some parameters can contain historical values like the maximum number of concurrent connections that have been observed on the database:

   High water mark for connections            = 3

The cumulative or historical values relate to the point in time, since the last counter's initialization. The counters can be reset to zero by the RESET MONITOR command, or by the appropriate DB2 event. With the mentioned Example 9-10 database deactivation and activation will reset all the database level counters. Example 9-11 shows how to reset monitors for entire instance and for the specific database.

Example 9-11: Resetting snapshot monitor counters
Start example
db2 reset monitor all
db2 reset monitor for database db2_emp
End example

To optimize database performance in a default DB2 configuration, most of the snapshot monitor elements are not collected. Because of that reason, in Example 9-10 the value Not Collected was displayed for the buffer pool statistics. DB2 UDB contains monitor switches to provide database administrators with the option of constraining the collection of monitor elements. Current monitor switches set for the session can be displayed from the command line by GET MONITOR SWITCHES, as shown in Example 9-12.

Example 9-12: Displaying monitor switches
Start example
db2 get monitor switches

            Monitor Recording Switches

Switch list for db partition number 0
Buffer Pool Activity Information  (BUFFERPOOL) = OFF
Lock Information                        (LOCK) = OFF
Sorting Information                     (SORT) = OFF
SQL Statement Information          (STATEMENT) = OFF
Table Activity Information             (TABLE) = OFF
Take Timestamp Information         (TIMESTAMP) = ON  08-01-2003 23:01:51.019864
Unit of Work Information                 (UOW) = OFF
End example

The monitor switches can be turned on at the instance level or at an application level. To switch the monitors at the instance level, modify the appropriate database manager parameter. After modifying the DFT_MON_BUFPOOL parameter, as shown in Example 9-13, all users with administration authorities will be able to collect buffer pool statistics on any database in the instance.

Example 9-13: Updating monitor switches at instance level
Start example
db2 update dbm cfg using DFT_MON_BUFPOOL ON
End example

To switch the monitors at the application level, issue UPDATE MONITOR SWITCHES from the command line. The changes will only be applicable to that particular prompt window. Example 9-14 shows how to update the suitable monitor switch for collecting buffer pool information.

Example 9-14: Updating monitor switches at application level.
Start example
db2 update monitor switches using BUFFERPOOL ON
End example

The complete list of monitor switches and related database manager parameters is presented on Table 9-2.

Table 9-2: List of monitor switches and related DBM parameters
Database manager parameter | Monitor switch | Information provided
DFT_MON_BUFFERPOOL | BUFFERPOOL | Number of reads and writes, time taken
DFT_MON_LOCK | LOCK | Lock wait times, deadlocks
DFT_MON_SORT | SORT | Number of heaps used, sort performance
DFT_MON_STMT | STATEMENT | Start/stop time, SQL statement identification
DFT_MON_TABLE | TABLE | Measure of activity (rows read/written)
DFT_MON_UOW | UOW | Start/end times, completion status
DFT_MON_TIMESTAMP | TIMESTAMP | Timestamps

Sample snapshots

The database manager snapshot (Example 9-15) captures information specific to the instance level. The information centers on the total amount of memory allocated to the instance and the number of agents that are currently active on the system.

Example 9-15: Database manager snapshot
Start example
db2 get snapshot for database manager
End example

The lock snapshot (Example 9-16) is very useful in determining what locks an application currently is holding, or what locks another application is waiting on. The snapshot lists all applications on the system and the locks that each is holding. Each lock, and each application, is given a unique identifier number.

Example 9-16: Lock snapshot.
Start example
db2 get snapshot for locks on db2_emp
End example

The table snapshot (Example 9-17) contains information on the usage and creation of all tables. This information is quite useful in determining how much work is being run against a table and how much the table data changes. This information can then be used to decide how your data should be laid out physically.

Example 9-17: Table snapshot
Start example
db2 get snapshot for tables on db2_emp
End example

The table space and buffer pool snapshots (Example 9-18) contain similar information. The table space snapshot returns information on the layout of the table space and how much space is being used. The buffer pool snapshot contains information on how much space is currently allocated for the buffer pool and how much space will be allocated when the database is next reset. Both snapshots contain a summary of the way in which data is accessed from the database. This access can be done from a buffer pool, direct from tables on disk, or through a direct read or write for LOBs or LONG objects.

Example 9-18: Table space and buffer pool snapshots
Start example
db2 get snapshot for tablespaces on db2_emp
db2 get snapshot for bufferpools on db2_emp
End example

The dynamic SQL snapshot is used extensively to determine how well SQL statements are performing. This snapshot summarizes the behavior of the different dynamic SQL statements that are run. The snapshot does not capture static SQL statements, so anything that was pre-bound will not show up in this list. The snapshot is an aggregate of the information concerning the SQL statements. If a SQL statement is executed 102 times, then there will be one entry with the summary of the total behavior of the 102 executions.

Example 9-19: Dynamic SQL snapshot
Start example
db2 get snapshot  for dynamic sql on db2_emp
End example

Snapshot table functions

As mentioned earlier DB2 UDB features the capability to capture snapshots using SQL table functions. Accessing snapshot information through SQL interface is very continent, because the requested information can be filtered and sorted, thereby presented in more readable format. The snapshot table functions can be also very helpful in analyzing system utilization over a time period.

Most of the snapshot table functions accept two input parameters. The first is a string representing the database name. Entering NULL value for the database name parameter instruct the function to get snapshot information for all databases in the instance. The second parameter represents partition number. To capture a snapshot for the currently connected partition, enter a value of -1 or a NULL.

The query in Example 9-20 uses table function SNAPSHOT_TABLE() to retrieve the five table names, which have the most read and write activity on database DB2_EMP.

Example 9-20: Sample snapshot table function
Start example
db2 "select snapshot_timestamp, table_name, rows_written, rows_read,
            rows_written + rows_read as rows_accessed
     from table (SNAPSHOT_TABLE('DB2_EMP', -1))as T
     order by rows_accessed desc
     fetch first 5 rows only"
TABLE_NAME    ROWS_WRITTEN  ROWS_READ  ROWS_ACCESSED
------------- ------------ ---------- --------------
EMPLOYEE                 0        256            256
STAFF                   35        105            140
SYSTABLES                0         30             30
SYSROUTINES              0         10             10
INTERNAL                 0          5              5
End example

Example 9-21 illustrates a usage of the SNAPSHOT_DYN_SQL function, which is very useful for finding the SQL statements that are taking the most time in the database.

Example 9-21: Sample snapshot table function
Start example
SELECT stmt_text, total_exec_time, num_executions
FROM TABLE( SNAPSHOT_DYN_SQL('DB2_EMP', -1)) as dynSnapTab
ORDER BY total_exec_time desc
FETCH FIRST 5 ROW ONLY
End example

Example 9-22 finds the five SQL statements with the worst average execution time.

Example 9-22: Sample snapshot table function
Start example
SELECT CASE WHEN num_executions = 0
            THEN 0
            ELSE (total_exec_time / num_executions)
       END avgExecTime,
       num_executions,
       stmt_text
FROM TABLE(SNAPSHOT_DYN_SQL('DB2_EMP', -1)) as dynSnapTab
ORDER BY avgExecTime desc
FETCH FIRST 5 ROWS ONLY
End example

Like snapshot commands, snapshot table functions access point-in-time data kept by monitors in memory. To keep the history of the snapshots include SNAPSHOT_TIMESTAMP column in the snapshot query. Create a table based on the snapshot query, such as presented in Example 9-23, and periodically stores the results of the query in the table.

Example 9-23: Storing snapshot data in a table
Start example
db2 create table table_snap_hist as
    (select snapshot_timestamp, table_name, rows_written, rows_read,
            rows_written + rows_read as rows_accessed
     from table (SNAPSHOT_TABLE('DB2_EMP', -1))as T) definition only
db2 "insert into table_snap_hist
     select snapshot_timestamp, table_name, rows_written, rows_read,
            rows_written + rows_read as rows_accessed
     from table (SNAPSHOT_TABLE('DB2_EMP', -1))as T
     order by rows_accessed desc fetch first 5 rows only"
End example

Table 9-3 lists the more commonly used snapshot table functions. A complete list and detailed descriptions of snapshot table functions can be found in DB2 UDB System Monitor Guide and Reference, SC09-4847.

Table 9-3: Common snapshot table functions
Snapshot table function | Information returned
SNAPSHOT_DBM | Database manager information
SNAPSHOT_DATABASE | Database information. Information is returned only if there is at least one application connected to the database.
SNAPSHOT_APPL | General application information for each application that is connected to the database on the partition. This includes cumulative counters, status information, and most recent SQL statement executed (if the statement monitor switch is set).
SNAPSHOT_APPL_INFO | General application identification information for each application that is connected to the database on the partition.
SNAPSHOT_LOCKWAIT | Application information regarding lock waits for the applications connected to the database on the partition.
SNAPSHOT_STATEMENT | Application information regarding statements for the applications connected to the database on the partition. This includes the most recent SQL statement executed (if the statement monitor switch is set).
SNAPSHOT_TABLE | Table activity information for each table that was accessed by an application connected to the database. Requires the table monitor switch.
SNAPSHOT_LOCK | Lock information at the database level, and application level for each application connected to the database. Requires the lock monitor switch.
SNAPSHOT_TBS | Information about table space activity at the database level, the application level for each application connected to the database, and the table space level for each table space that has been accessed by an application connected to the database. Requires the buffer pool monitor switch.
SNAPSHOT_BP | Buffer pool activity counters for the specified database. Requires the buffer pool monitor switch.
SNAPSHOT_DYN_SQL | Point-in-time statement information from the SQL statement cache for the database.

Similar to snapshot commands, the amount of information returned from table snapshots functions is controlled by the monitor switches. Because snapshots can collect large amounts of diagnostic data, enabling all monitor switches (especially DYNAMIC SQL) can have a very negative impact on database performance.

All the monitoring utilities uses memory heap, controlled by MON_HEAP_SZ database manager parameter. This monitoring heap size should be increased when many applications access snapshot data.

Event monitoring

Event monitors are used to monitor the performance of DB2 over a fixed period of time. The information that can be captured by an event monitor is similar to the snapshots, but event monitors examine transition events in the database, and consider each event as an object. Event monitors can capture information about DB2 events in the following areas:

  • Database: An event of database information is recorded when the last application disconnects from the database.

  • Tables: All active table events will be recorded when the last application disconnects from the database. An active table is one which has been altered or created since the database was activated. The monitor captures the number of rows read and written to the table.

  • Deadlocks: A deadlock event is recorded immediately when a deadlock occurs. This monitor also has an additional option, with details. The option will capture additional information, such as what SQL was being executed when the deadlock occurred, and what locks were held by the application that encountered the deadlock. The information captured by the monitor focuses on the locks involved in the deadlock and the applications that own them.

  • Buffer pools: A buffer pool event is recorded when the last application disconnects from the database. The information captured contains the type and volume of use of the buffer pool, use of pre-fetchers and page cleaners, and whether or not direct I/O was used.

  • Table spaces: A table space event is recorded when the last application disconnects from the database. This monitor captures the same information as the buffer pool monitor, but the information is summarized at a table space level.

  • Connections: A connection event is recorded whenever an application disconnects from the database.

  • Transactions: A transaction event is recorded whenever a transaction finishes. The event will be written out whenever a commit or rollback occurs. The monitor captures all of the individual statement data, and also information about the transaction, such as its start and stop time.

  • Statements: A statement event is recorded when SQL statement end. The monitor records statement start and stop time, CPU used, text of dynamic SQL, return code of SQL statement, and other metrics such as fetch count.

Event monitors are created with CREATE EVENT MONITOR SQL statement. Information about event monitors is stored in the system catalog table, and it can be reused later.

Example 9-24 creates sample event monitor named DEADLOCK_EVMON. The query in the example access SYSCAT.EVENTMONITORS view and displays names of event monitors that have been created in the database.

Example 9-24: Creating sample event monitor
Start example
db2 create event monitor deadlock_evmon for deadlocks with details write to
    table manualstart

db2 select evmonname from syscat.eventmonitors
End example

The output of the DEADLOCK_EVMON monitor will be recorded in newly created tables. To check in advance what tables are to be created, or to generate syntax that overrides the default table names, use db2evtbl tool as shown in the Example 9-25.

Example 9-25: Generating table syntax for specified event monitor
Start example
db2evtbl -evm deadlock_evmon deadlocks with details

CREATE EVENT MONITOR deadlock_evmon
           FOR DEADLOCKS WITH DETAILS
           WRITE TO TABLE
                 CONNHEADER (TABLE CONNHEADER_deadlock_evmon,
                               INCLUDES (AGENT_ID,
                                         APPL_ID,
                                         APPL_NAME,
                                         AUTH_ID,
[...]
End example

Because the DEADLOCK_EVMON monitor was created with a manual start, after creation it remains inactive. To activate a event monitor, change the state of the event monitor to value of 1 and use the event_mon_state() function to check for the current state, as shown in Example 9-26 (when calling event_mon_state() use event monitor name in uppercase). After activation of DEADLOCK_EVMON, each time a deadlock occurs in the database it will be recorded in the event monitor tables.

Example 9-26: Enabling event monitor
Start example
db2 set event monitor deadlock_evmon state = 1

db2 values event_mon_state('DEADLOCK_EVMON')
End example

To browse the data collected by event monitor, you can directly access the tables, or use the GUI tool db2eva. The sample db2eva screen capture is presented in Figure 9-10. For more information about db2eva, refer to DB2 UDB Command Reference.

Click To expand
Figure 9-10: Presenting event monitor data using db2eva GUI tool

Event monitors offer an option to write the monitored information to a binary file. This option is particularly useful when there is a need to prevent the event monitor from collecting uncontrolled amount of data. Example 9-27 shows creation of event monitor that writes the diagnostic data to files (extensions *.EVT) located on the 'c:\tmp\deadlock' directory (Windows example). If the total amount of collected data exceeds 5000 pages (4 KB) the event monitor will stopped.

Example 9-27: Creating event monitor with file option
Start example
db2 create event monitor deadlock_evmon for deadlocks with details
    write to file 'c:\tmp\deadlock' maxfilesize 5000 manualstart
End example

To convert the event monitor binary files to user readable form use db2evmon utility as shown in Example 9-28.

Example 9-28: Formatting event monitor output files
Start example
C:\tmp>db2evmon -path c:\tmp\deadlock

Reading c:\tmp\00000000.EVT ...
--------------------------------------------------------------------------
                            EVENT LOG HEADER
  Event Monitor name: DEADLOCK_EVMON
  Server Product ID: SQL08012
  Version of event monitor data: 7
  Byte order: LITTLE ENDIAN
  Number of nodes in db2 instance: 1
  Codepage of database: 1252
  Territory code of database: 1
  Server instance name: DB2
--------------------------------------------------------------------------

--------------------------------------------------------------------------
  Database Name: SAMPLE
  Database Path: C:\DB2\NODE0000\SQL00001\
  First connection timestamp: 08-05-2003 23:25:43.028006
  Event Monitor Start time:   08-06-2003 01:51:57.663712
--------------------------------------------------------------------------

3) Deadlock Event ...
  Deadlock ID:   4
  Number of applications deadlocked: 2
  Deadlock detection time: 08-06-2003 01:53:11.952919
  Rolled back Appl participant no: 2
  Rolled back Appl Id: *LOCAL.DB2.010686063633
  Rolled back Appl seq number: : 0005
[...]
End example

Visual Explain

Visual Explain is used to capture and view information about the access plan chosen by the DB2 optimizer for SQL statements as a graph. An access plan is a cost estimation of resource usage for a query, which is based on the available information, such as statistics for tables and indexes, instance and database configuration parameters, bind options and query optimization level, and so on. An access plan also specifies the order of operations for accessing the data.

The access plan acquired from Visual Explain helps to understand how individual SQL statements are executed. The information available from the Visual Explain graph can be used to tune the SQL queries for better performance.

To start Visual Explain, launch the Control Center, right-click the database name and select either the Explain SQL or Show Explained Statements History option. You can input an SQL statement manually or import the SQL statement through the Get button available in the Explain SQL window. You can also specify the optimization class for the SQL statement in the same window. The optimization class implies the effort the DB2 optimizer will spend on preparing execution plan (higher value means more sophisticated optimization). Figure 9-11 shows an example of an access plan graph.

Click To expand
Figure 9-11: A Visual Explain access plan graph

An access plan graph shows details of:

  • Tables (and their associated columns) and indexes

  • Operators (such as table scans, sorts, and joins)

  • Table spaces and functions

To get the details right-click the desired graph element.


9.5 Initial tuning

Performance of a DB2 database application can be influenced by many factors such as the type of workload, application design, database design, capacity planning, and instance and database configuration. Since databases created with default values are suited for computers with relatively small memory and disk storage, you may need to modify them to fit your environment. This section focuses on a number of DB2 UDB performance tuning tips that may be used for initial configuration.

9.5.1 Table spaces

At database creation time, three table spaces are created:

  • SYSCATSPACE - Catalog table space for storing information about all the objects in the database,

  • TEMPSPACE1 - System temporary table space for storing internal temporary data required during SQL operations such as sorting, reorganizing tables, creating indexes, and joining tables,

  • USERSPACE1 - For storing application data

By default all the three table spaces are created as System Managed Spaces (SMS) which means that the regular operating system functions will be used for handling I/O operations.

Reading and writing data from tables will be buffered by the operating system, and space will be allocated according to the operating system conventions: files with DAT extension for tables and INX files for table indexes. When the table is initially created only one page is allocated on disk. When records are inserted to a table, DB2 will extend the files one page at a time.

On heavy inserts, extending file by only one page at a time can be very expensive. To minimize internal overhead for the table space extension, you can enable database multi-page file allocation. With multi-page file allocation enabled for SMS table spaces, disk space is allocated one extent at a time (contiguous groups of pages defined for the table space).

To check whether the feature is enabled, look at the database configuration and search for the Multi-page word.

In Example 9-29 multi page was not enabled. This can be changed by running the db2empfa program on the target database. Since db2empfa connects to the database in exclusive mode, all other users should be disconnected from the database. After db2empfa execution against the target database, check the multi-page file allocation parameter for the status.

Example 9-29: Checking for current page allocation status
Start example
$db2 get db cfg for sample

…
Rollforward pending                                 = NO
Restore pending                                     = NO

Multi-page file allocation enabled                  = NO

Log retain for recovery status                      = NO
User exit for logging status                        = NO
…
End example
Example 9-30: Enabling multi page allocation
Start example
$db2empfa sample
$db2 get db cfg for sample
…
Rollforward pending                                   = NO
Restore pending                                       = NO

Multi-page file allocation enabled                    = YES

Log retain for recovery status                        = NO
User exit for logging status                          = NO
…
End example

Better insert performance can be achieved with database managed table spaces (DMS) because containers are pre-allocated and management of the I/O operations is shifted to the database engine. In DB2 UDB version 8 you can easily add new containers, drop, or modify the size of existing containers. Data is rebalanced to other containers automatically unless instructed. The administrative overhead is not so significant when compared to the SMS table spaces.

For optimal performance, large volume data and indexes should be placed on DMS table spaces, if possible, split to separate raw devices. Initially, system catalogs and system temporary table spaces should stay on the SMS table spaces. System catalogs contain large objects, which are not cached by the DB2 UDB engine, and can be cached by the operating system cache. In an OLTP-like environment, there is no need for creating large temporary objects to process SQL queries, so the SMS system temporary table space is a good starting point.

9.5.2 Physical placement of database objects

When creating a database, the first important decision is the storage architecture. The ideal situation is to have the fastest disks as possible and at least 5 to 10 disks per processor (for high I/O OLTP workload, use even more). The reality is the hardware is often chosen based on other considerations, so in order to achieve optimal performance, the placement of database objects should be carefully planned.

As shown in Figure 9-12, all data modifications are not only written to table space containers, but are also logged to ensure recoverability. Because every insert, update, or delete is replicated in the transactional log, the flushing speed of the logical log buffer can be crucial for the entire database performance. To understand the importance of logical log placement, you should keep in mind that the time necessary to write data to disk depends on the physical data distribution on disk. The more random reads or writes are performed, the more disk head movements are required, and therefore, the slowest is the writing speed. Flushing logical log buffer to disk by its nature is sequential and should not be interfered by other operations. Locating logical log files on separate devices isolates them from other processes, and ensures uninterrupted sequential writes.

Click To expand
Figure 9-12: Explaining logical log

To change logical log files to a new location you need to modify NEWLOGPATH database parameter as shown in Example 9-31. The logs will be relocated to the new path on the next database activation (this can take some time to create the files).

Example 9-31: Relocation of logical logs
Start example
db2 update db cfg for sample using NEWLOGPATH /db2/logs
End example

When creating a DMS table space with many containers, DB2 UDB automatically distributes the data across them in a round-robin fashion, similar to the striping method available in disk arrays. To achieve the best possible performance, each table space container should be placed on a dedicated physical device. To parallel asynchronous writes and reads from multiple devices, the number of database page cleaners (NUM_IO_CLEANERS) and I/O servers (NUM_IOSERVERS) should be adjusted. The best values for these two parameters depends on the type of workload and available resources. You can start your configuration with following values:

  • NUM_IOSERVERS = Number of physical devices, but not less that three and no more than five times the number of CPUs.

  • NUM_IO_CLEANERS = number of CPUs

Example 9-32 shows how to set initial values of the parameters for two processor machines with six disks available to DB2.

Example 9-32: Updating IO related processes
Start example
db2 update db cfg for sample using NUM_IOSERVERS 6
db2 update db cfg for sample using NUM_IOCLEANERS 2
End example

If there is relatively small number of disks available, it can be difficult to keep database logical logs, data, indexes, system temporary table spaces (more important for processing large queries in warehousing environment), backup files or operating system paging file on separate physical devices. A compromise solution is to have one large file system striped by disk array (RAID device) and create table spaces with only one container. The load balancing is shifted to hardware, and you don't have to worry about space utilization. In that case to parallel I/O operations on a single container. DB2_PARALLEL_IO registry variable should be set before starting DB2 UDB engine.

By performing the following command, I/O parallelism will be enabled within a single container for all table spaces:

db2set DB2_PARALLEL_IO="*"

The following example enables parallel I/O only for two table spaces: DATASP1 and INDEXSP1:

db2set DB2_PARALLEL_IO="DATASP1,INDEXSP1"

To check the current value for the parameter issue:

db2set DB2_PARALLEL_IO

9.5.3 Buffer pools

The default size for buffer pools is very small: only 250 pages (~ 1 MB) for Windows and 1000 pages (~ 4 MB) for UNIX platforms. The overall buffer size has a great effect on DB2 UDB performance, since it can significantly reduce I/O, which is the most time consuming operation. We recommend to increase the default values. However, the total buffer pool size should not be set too high, because there might be not enough memory to allocate them. To calculate the maximum buffer size, all other DB2 memory related parameters like database heap, the agent's memory, storage for locks, as well as the operating system, and any other applications should be considered.

Initially set the total size of buffer pools to 10% to 20% of available memory. You can monitor the system later and correct it. DB2 version 8 allows changing buffer pool sizes without shutting down the database. The ALTER BUFFERPOOL statement with the IMMEDIATE option will take effect right away, except when there is not enough reserved space in the database-shared memory to allocate new space. This feature can be used to tune database performance according to periodical changes in use, for example, switching from daytime interactive use to nighttime batch work.

Once the total available size is determined, this area can be divided into different buffer pools to improve utilization. Having more than one buffer pool can preserve data in the buffers. For example, let us suppose that a database has many very frequently used small tables, which would normally be in the buffer in their entirety, and thus would be accessible very fast. Now let us suppose that there is a query which runs against a very large table, which uses the same buffer pool and involves reading more pages than the total buffer size. When this query runs, the pages from the small, very frequently used tables will be lost, making it necessary to re-read them when they are needed again.

At the start you can create additional buffer pool for caching data and leave the IBMDEFAULTBP for system catalogs. Creating an extra buffer pool for system temporary data also can be valuable for the system performance, especially in OLTP environment, where the temporary objects are relatively small. Isolated temporary buffer pools are not influenced by the current workload, so it should take less time to find free pages for temporary structures, and it is likely that the modified pages will not be swapped out to disk. In a warehousing environment, the operation on temporary table spaces are considerably more intensive, so the buffer pools should be larger, or combined with other buffer pools if there is not enough memory in the system (one pool for caching data and temporary operations).

Example 9-33 shows how to create buffer pools assuming that additional table space DATASPACE for storing data and indexes was already created, and there is enough memory in the system. You can take this as a starting buffer pool configuration for a 2 GB RAM system.

Example 9-33: Increasing buffer pools
Start example
connect to sample;
   -- creating two buffer pools 256 MB and 64 MB
create bufferpool DATA_BP immediate size 65536 pagesize 4k;
create bufferpool TEMP_BP immediate size 16384 pagesize 4k;

   -- changing size of the default buffer pool
alter bufferpool IBMDEFAULTBP immediate size 16384;

   -- binding the table spaces to buffer pools
alter tablespace DATASPACE bufferpool DATA_BP;
alter tablespace TEMPSPACE1 bufferpool TEMP_BP;

   -- checking the results
select
   substr(bs.bpname,1,20) as BPNAME
   ,bs.npages
   ,bs.pagesize
   ,substr(ts.tbspace,1,20) as TBSPACE
from syscat.bufferpools bs join syscat.tablespaces ts on
     bs.bufferpoolid = ts. bufferpoolid;
End example

The results:

BPNAME               NPAGES      PAGESIZE    TBSPACE
-------------------- ----------- ----------- --------------------
IBMDEFAULTBP               16384        4096 SYSCATSPACE
IBMDEFAULTBP               16384        4096 USERSPACE1
DATA_BP                    65536        4096 DATASPACE
TEMP_BP                    16384        4096 TEMPSPACE1

The CHNGPGS_THRESH parameter specifies the percentage of changed pages at which the asynchronous page cleaners will be started. Asynchronous page cleaners will write changed pages from the buffer pool to disk. The default value for the parameter is 60%. When that threshold is reached, some users may experience a slower response time. Having larger buffer pools means more modified pages in memory and more work to be done by page cleaners, as shown on Figure 9-13. To guarantee more consistent response time and also shorter recovery phase, lower the value to 50 or 40 using the following command:

db2 update db cfg for sample using CHNGPGS_THRESH 40
Click To expand
Figure 9-13: Visualizing CHNGPGS_THRESH parameter

9.5.4 Large transactions

By default, databases are created with relatively small space for transactional logs, only three log files each 250 pages on Windows and 1000 pages on UNIX. A single transaction should fit available log space to be completed, if not the transaction is rolled back by system (SQL0964C The transaction log for the database is full). To process transactions which are modifying large numbers of rows, adequate log space is needed. Current total log space available for transactions can be calculated by multiplying the size of log file (database parameter LOGFILSIZ) and the number of logs (database parameter LOGPRIMARY). From the performance perspective, it is better to have a larger log file size, because of the cost for switching from one log to another. When log archiving is switched on, the log size also indicates the amount of data for archiving. In this case, a larger log file size is not necessarily better, since a larger log file size may increase the chance of failure, or cause a delay in archiving or log shipping scenarios. The log size and the number of logs should be balanced.

The following example allocates 400 MB of total log space.

Example 9-34: Resizing the transactional log
Start example
db2 update db cfg for sample using LOGFILSIZ 5120
db2 update db cfg for sample using LOGPRIMARY 20
End example

Locking is the mechanism that the database manager uses to control concurrent access to data in the database by multiple applications. Each database has its own list of locks (structure stored in memory which contains the locks held by all applications concurrently connected to the database). The size of the lock list is controlled by LOCKLIST database parameter. The default storage for LOCKLIST is 50 pages (200 KB) for Windows and 100 pages (400 KB) for UNIX. On 32-bit platforms, each lock requires 36 or 72 bytes of the lock list, depending on whether other locks are held on the object or not. For the default values, the maximum of 5688 (Windows) or 11377 (UNIX) locks can be allocated as shown in Figure 9-14.

Click To expand
Figure 9-14: Maximum number of locks available for default settings on UNIX

When the maximum number of lock requests has been reached the database manager will replace existing row level locks with table locks (lock escalation). This operation will reduce the requirements for locks space, because transactions will hold only one lock on the entire table instead of many locks on every row. Lock escalation has a negative performance impact because it reduces concurrency on shared objects. Other transactions must wait until the transaction holding the table lock commits or rollbacks work.

The lock escalation can also be forced by the MAXLOCKS database parameter, which defines a limit for maximum percentage of lock locks storage held by one application. The default value for UNIX is 10 (22 for Windows), which means that if one application requests more that 10% of total locks space (LOCKLIST), an escalation will occur for the locks held by that application. As an example, on UNIX inserting 1137 rows with one transaction will result in lock escalation, because the transaction requests 1138 locks (one per each inserted row plus one internal lock), which requires at least 1138*36 = 40968 bytes - more than 10% of global lock memory defined by default LOCKLIST parameter.

Initial values for LOCKLIST and MAXLOCKS should be based on maximum number of applications and average number of locks requested by transaction (for OLTP systems start with 512 locks for every application). When setting MAXLOCKS, you should take into account lock consuming batch processes that are run during daytime hours. To check current usage of locks use snapshots such as in Example 9-35.

Example 9-35: Invoking snapshot for locks on database sample
Start example
db2 get snapshot for locks on sample
End example

The snapshot will collect the requested information at the time the command was issued. On Figure 9-15 you can find sample lock snapshot output. For the time the snapshot was run there were two applications connected to the database SAMPLE, and in total 1151 locks were acquired on the database. Issuing the get snapshot command later can produce different results because in the meantime the applications may commit the transaction and release locks.

Click To expand
Figure 9-15: Explaining lock snapshot information

To check lock escalations occurrences look at the db2diag.log file. The lock escalation message should look like Example 9-36.

Example 9-36: Lock escalation message in db2diag.log file
Start example
2003-07-21-19.05.05.888741   Instance:db2inst1   Node:000
PID:56408(db2agent (SAMPLE) 0)   TID:1   Appid:*LOCAL.db2inst1.0DB5F2004313
data management  sqldEscalateLocks Probe:3   Database:SAMPLE
ADM5502W  The escalation of "1136" locks on table "DB2INST1.TABLE01" to lock
intent "X" was successful.
End example

Logical log buffer

The default size for logical log buffer is eight pages (32 KB) - often too small for an OLTP database, and not big enough for long running batch processes. In most cases the log records are written to disk when one of the transactions issue a commit, or the log buffer is full. Increasing the size of the log buffer may result in more efficient I/O operations, especially when the buffer is flushed to disk because of the second reason. The log records are written to disk less frequently and more log records are written each time. Initially, set LOGBUFSZ to 128, or 256 4 KB pages. The log buffer area uses space controlled by the DBHEAP database parameter, so consider increasing this parameter also.

Later use the snapshot for applications to check current usage of log spaces by transactions as presented on Example 9-37.

Example 9-37: Current usage of log space by applications
Start example
$db2 update monitor switches using uow on
$db2 get snapshot for applications on sample | grep "UOW log"

UOW log space used (Bytes)                 = 478
UOW log space used (Bytes)                 = 21324
UOW log space used (Bytes)                 = 110865
End example

Before running the application snapshot, the Unit Of Work monitor should be switched on. At the time the snapshot was issued, only three applications were run on the system. The first transaction used 478 bytes of log space, the second 21324, and the last used 110865, which is roughly 28 pages, more than the default log buffer size. The snapshot gives only current values from the moment the command was issued. To get more valuable information about the usage of log space by transactions, run the snapshot many times.

The Example 9-38 shows how to get information about log I/O activity.

Example 9-38: Checking log I/O activity
Start example
db2 reset monitor for database sample
   # let the transactions run for a while

db2 get snapshot for database on sample > db_snap.txt
egrep  -i "commit|rollback" db_snap.txt

Commit statements attempted                = 23
Rollback statements attempted              = 2
Internal commits                           = 1
Internal rollbacks                         = 0
Internal rollbacks due to deadlock         = 0

grep "Log pages" db_snap.txt
Log pages read                             = 12
Log pages written                          = 630
End example

Before running the database snapshot, you may have to reset the monitors. The values gathered by snapshot and presented here are cumulated since the last monitor reset or database activation, so wait for certain period after resetting the counters. For convenience, the snapshot output was directed into a file, and then analyzed using the UNIX grep tool. In the example, 630 pages were written for the period, which gives about 630 / (23+2+1) = 25 pages per transaction. Looking at the value "Log pages written" it is not possible to tell what was the average size of transactions, because the basic DB2 read or write unit is one page (4 KB). Issuing only one small insert will force a flush of 4 KB from log buffer to disk. The partially filled log page remains in the log buffer, and can be overwritten to disk more than once, until it is full; this guaranties that the log files are contiguous.

When setting the value for log buffer, also look at the ratio between log pages read and log pages written. An ideal value is zero log pages read, while seeing a large number of log pages written. When there are too many log pages read, it means a bigger LOGBUFSZ can improve performance.

9.5.5 SQL execution plan

When a query is issued against a database, DB2 prepares an execution plan. The execution plan defines the necessary steps that should be done to get the requested data. In order to prepare an optimal execution plan, the DB2 optimizer considers many elements such as configuration parameters, available hardware resources, or the characteristics of the database objects (available indexes, table relationships, number of records, data distribution). The database characteristics are collected manually with the RUNSTATS utility, and are stored in special system catalog tables. The RUNSTATS command should be executed:

  • When a table has been loaded with new data

    Recommendation:

    After loading data to DB2 tables, run the RUNSTATS before starting testing.

  • When the appropriate indexes have been created

  • When there have been extensive updates, deletions, and insertions that affect a table and its indexes (for example, 10% to 20% of the table and index data has been affected).

  • When a data has been physically reorganized (by running the RORG utility, or adding new containers)

The RUNSTAT command should be executed against each table in the database. DB2 Control Center can be very helpful with running statistics on a group of tables.

To run statistics using Control Center, select desired tables (to select more than one table, press the Ctrl or Shift key while clicking the table names; to select all tables, click any table name and then press Control + A), right-click the selection, and choose the Run Statistics option, as shown in Figure 9-16.

Click To expand
Figure 9-16: Running RUNSTATS on multiple tables

On the first Tables tab move all items from the Available list to the Selected list by clicking the >> button. Figure 9-17 presents the sample result of the operation.

Click To expand
Figure 9-17: Selecting tables for RUNSTAT command.

On the Statistics tab, you can specify options for the RUNSTAT command. You can start with collecting basic statistics on all columns and indexes, and distribution of values only for key columns, like presented on Figure 9-18. After setting the RUNSTAT option, you can execute the commands by clicking Apply button.

Click To expand
Figure 9-18: RUNSTAT command options

DB2 comes with a very powerful query optimization algorithm. This cost-based algorithm will attempt to determine the cheapest way to perform a query against a database. Items such as the database configuration, database physical layout, table relationships, and data distribution are all considered when finding the optimal access plan for a query. To check the current execution plan, you can use the Explain SQL function (described in "Visual Explain" on page 312).

9.5.6 Configuration advisor

The Configuration Advisor wizard is a GUI tool that can be helpful in preparing DB2 initial configuration. The wizard requests information about the database, its data, and the purpose of the system, and then recommends new configuration parameters for the database and the instance.

To invoke this wizard from the DB2 Control Center, expand the object tree until you find the database that you want to tune. Select the icon for the database, right-click and select Configuration Advisor. The wizard through several dialog widows collects information about percentage of memory dedicated to DB2, type of workload, number of statements per transaction, transaction throughput, trade-off between recovery and database performance, number of applications, and isolation level of applications connected to the database. Based on the supplied answers, the wizard proposes configuration changes, and gives the option to apply the recommendations, or save in them to the Task Center for later execution, as shown in Figure 9-19. The result window is presented in Figure 9-20.

Click To expand
Figure 9-19: Scheduling Configuration Advisor recommendations
Click To expand
Figure 9-20: Configuration Advisor recommendations

Initial configuration recommendations can be also acquired through the text based AUTOCONFIGURE command. Example 9-39 shows sample executions of the command.

Example 9-39: Autoconfigure command
Start example
db2 autoconfigure using mem_percent 40 tpm 300 num_local_apps 80 isolation CS apply none

[...]
Current and Recommended Values for Database Configuration

Description                            Parameter  Current Value  Recommended Value
---------------------------------------------------------------------------------------
 Max appl. control heap size (4KB)     (APP_CTL_HEAP_SZ) = 4096                128
 Max size of appl. group mem set (4KB) (APPGROUP_MEM_SZ) = 30000               9908
 Default application heap (4KB)             (APPLHEAPSZ) = 256                 256
 Catalog cache size (4KB)              (CATALOGCACHE_SZ) = (MAXAPPLS*4)        404
 Changed pages threshold                (CHNGPGS_THRESH) = 40                  60
 Database heap (4KB)                            (DBHEAP) = 600                 1461
 Degree of parallelism                      (DFT_DEGREE) = 1                   1
 Default tablespace extentsize (pages)   (DFT_EXTENT_SZ) = 32                  32
[...]
End example

Table 9-4 lists all AUTOCONFIGURE command parameters.

Table 9-4: Parameters for AUTOCONFIGURE command
Keyword | Values | Explanation
mem_percent | 1–100 default: 80 | Percentage of memory to dedicate to DB2
workload_type | simple, mixed, complex default: mixed | Type of workload: simple for transaction processing, complex for warehousing
num_stmts | 1-1 000 000 default: 10 | Number of statements per unit of work
tpm | 1-200 000 default: 60 | Transactions per minute
admin_priority | performance, recovery, both default: both | Optimize for better performance or better recovery time
is_populated | yes, no default: yes | Is the database populated with data?
num_local_apps | 0–5 000 default: 0 | Number of connected local applications
num_remote_apps | 0–5 000 default: 10 | Number of connected remote applications
isolation | RR, RS, CS, UR default: RR | Isolation levels: Repeatable Read, Read Stability, Cursor Stability, Uncommitted Read
bp_resizeable | yes, no default: yes | Are buffer pools re-sizeable?

9.5.7 Index Advisor

Well designed indexes are essential to database performance. DB2 UDB comes with utility called the Index Advisor, which can recommend indexes for specific SQL queries. Index Advisor can be invoked either using the DB2ADVIS command or using Design Advisor wizard from the Command Center or Control Center. This utility accepts one or more SQL statements and their relative frequency, known as a workload.

The Index Advisor is good for:

  • Finding the best indexes for a problem query

  • Finding the best indexes for a specified workload. When specifying the workload, you can use the frequency parameter to prioritize the queries. You can also limit disk space for the target indexes.

  • Testing an index on a workload without having to create the index

Example 9-40 shows a simple db2advis call against the single SQL query; for more options type db2advis -h from the command line.

Example 9-40: Finding indexes for particular query
Start example
db2advis -d db2_emp -s "select first_name, last_name, dept_name from
departments d, employees e where d.dept_code = e.dept_code and e.last_name like
'W%'"

execution started at timestamp 2003-08-01-14.15.00.408000
recommending indexes...
Initial set of proposed indexes is ready.
Found maximum set of [2] recommended indexes
Cost of workload with all indexes included [0.155868] timerons
total disk space needed for initial set [   0.018] MB
total disk space constrained to         [  -1.000] MB
  2  indexes in current solution
 [ 50.3188] timerons  (without indexes)
 [  0.1559] timerons  (with current solution)
 [%99.69] improvement

Trying variations of the solution set.
  2  indexes in current solution
 [ 50.3188] timerons  (without indexes)
 [  0.1559] timerons  (with current solution)
 [%99.69] improvement
--
--
-- LIST OF RECOMMENDED INDEXES
-- ===========================
-- index[1],    0.009MB
   CREATE UNIQUE INDEX IDX030801141500000 ON "DB2INST1"."DEPARTMENTS"
("DEPT_CODE" ASC) INCLUDE ("DEPT_NAME") ALLOW REVERSE SCANS ;
   COMMIT WORK ;
   --RUNSTATS ON TABLE "DEPARTMENTS" FOR INDEX "IDX030801141500000" ;
   COMMIT WORK ;
-- index[2],    0.009MB
   CREATE INDEX IDX030801141500000 ON "DB2INST1"."EMPLOYEES" ("LAST_NAME" ASC,
"FIRST_NAME" ASC, "DEPT_CODE" ASC) ALLOW REVERSE SCANS ;
   COMMIT WORK ;
   --RUNSTATS ON TABLE "EMPLOYEES" FOR INDEX "IDX030801141500000" ;
   COMMIT WORK ;
-- ===========================
--
DB2 Workload Performance Advisor tool is finished.
End example
Launching Index Advisor in a GUI environment

The Index Advisor can also be invoked as a GUI tool. From the Control Center, expand the object tree to find the Database folder. Right-click the desired database and select Design Advisor. The wizard guides you through all the necessary steps, and also helps construct a workload by looking for recently executed SQL queries, or looking through the recently used packages. In order to get accurate recommendations, it is important to have the current catalog statistics. With the Design Advisor there is an option to collect the required basic statistics, however, this increases the total calculation time. Figure 9-21 presents sample Design Advisor window.

Click To expand
Figure 9-21: The Design Advisor

The detailed usage of Design Advisor can be found in the following Redbooks:

  • DB2 UDB Evaluation Guide for Linux and Windows, SG24-6934

  • DB2 UDB Exploitation of the Windows Environment, SG24-6893

  • Up and Running with DB2 for Linux, SG24-6899


Appendix A: DB2 UDB Product Overview

In this appendix we provide a detailed description of the capabilities and features of IBM DB2 Universal Database for Linux, UNIX, and the Microsoft Windows product family.

DB2 family

The IBM DB2 database software family is the worldwide leader in the industry and marks the next stage in the evolution of the relational database. DB2 is the industry's first multimedia, Web-ready relational database management system delivering leading capabilities in reliability, performance, and scalability. DB2 is the database of choice for customers and partners developing and deploying critical solutions. The DB2 family is a consistent set of relational database management systems (RDBMS) utilizing shared technologies and a common application programming interface.

These are the specific RDBMS products that make up the DB2 family:

  • DB2 Universal Database for z/OS and OS/390: The premier IBM enterprise RDBMS for use on the mainframe to run powerful enterprise applications, and make large scale e-commerce a reality.

  • DB2 Universal Database for iSeries: An advanced, 64-bit relational database system that provides leading-edge performance in e-business and data warehousing environments (the iSeries and DB2 UDB for iSeries in combination provide the flexibility and adaptability to support any type of workload, small or large).

  • DB2 Server for VSE and VM: A full-function RDBMS supporting production and interactive IBM VM and VSE environments for your company.

  • DB2 Everyplace®: DB2 relational database and enterprise synchronization architecture for mobile and embedded devices.

  • DB2 Universal Database V8.1: An IBM relational database management system for AIX, Linux, HP-UX, Sun, and Windows (discussed in more detail in the next section).


DB2 UDB for Windows, UNIX, and Linux

In this section we consider the particular characteristics of DB2 UDB on the various platforms.

Overview

DB2 Universal Database (UDB) is the IBM object-relational database solution for the UNIX, Linux, and the Windows operating environments. It is built on a solid foundation, bringing together a client and server database product with IBM's leadership in mission-critical relational database technology. The result is a highly scalable, highly extensible, very easy-to-use and manage database that can be trusted with your most critical database applications. DB2 UDB is available on the following platforms:

  • Windows NT/2000/XP/Server 2003,

  • Windows 95/98/ME

  • Linux (on Intel)

  • Linux (on 390)

  • AIX

  • HP-UX

  • Sun Solaris

Key capabilities and benefits

We now consider the main capabilities and benefits of DB2 UDB.

Superior scalability

One of the major benefits of DB2 UDB is scalability. It can run on a laptop supporting a mobile worker, or it can run on a massively parallel machine supporting multiple terabytes of data and thousands of users, and of course, it can support various configurations of SMPs (symmetric multiprocessors) and clusters of SMPs in between.

It is important to note that this scalability includes the same object-relational function up and down the line. This makes DB2 UDB the perfect database platform for small to medium sized businesses that are growing; for large enterprises that need to deploy 2-tier or 3-tier applications from desktop to department to enterprise; and for ISVs and Business Partners who are servicing all of these customers.

You will probably not outgrow DB2 UDB as your applications and businesses grow. You will be able to add data and still maintain query performance; or add users and still maintain response time; or just add hardware to speed up your queries.

DB2 UDB's scalability features can be grouped into three major capabilities:

  • Advanced parallel processing

  • High-performance computing

  • Efficient large database operations

Advanced parallel processing

DB2 Universal Database uses parallel processing to speed up both transaction processing (OLTP) and query processing (OLAP, data warehousing, data mining) or mixed workloads involving both. It supports both parallel transactions and parallel query on all major hardware architectures, including symmetric multiprocessors (SMP), clusters, and massively parallel processors (MPP):

  • SMP parallel support

    UDB will automatically execute multiple transactions (SQL statements) in parallel by dispatching them to the multiple processors in an SMP machine. UDB can also automatically execute a single query (SQL statement) in parallel by breaking the query into subtasks and dispatching each subtask to a different processor. Furthermore, if the data for an SQL statement is spread across multiple disk locations, UDB can also use parallel I/O to execute the data retrieval in parallel.

  • Cluster and MPP parallel support

    When the Database Partitioning feature is used, a UDB database can be spread across multiple servers in a cluster or multiple nodes on an MPP. UDB will automatically execute multiple transactions (SQL statements) in parallel by dispatching them to the multiple nodes. UDB can also automatically execute a single query (SQL statement) in parallel by breaking the query into subtasks and dispatching each subtask to a different node.

    The key to efficient parallel processing across nodes is intelligent partitioning and parallel optimization. UDB will automatically spread (partition) the data across the nodes such that the optimizer will "know" where each row is located, and will be able to dispatch the processing to the node where the data is located — minimizing the movement of data between nodes. This is known as a shared-nothing architecture and it is the best approach for ensuring scalability across multiple nodes, particularly when very large databases of 100s of gigabytes or multiple terabytes are involved.

High-performance computing

In addition to advanced parallel processing, UDB supports a number of important high-performance computing features that significantly enhance performance of both queries and transactions. The combination of these and other features make DB2 UDB particularly good at handling mixed workloads. These high-performance features include:

  • 64-Bit memory support

    Support now exists for very large physical memory (64-bit memory support). DB2 exploits 64-bit systems and 32-bit systems capable of supporting greater than 4 GB of real memory. The buffer pool can be used to keep data available in this additional memory, thus reducing I/O, and significantly improving performance.

  • Multiple buffer pools

    You can create multiple buffer pools of various sizes (number of pages) and assign table spaces to them using the CREATE BUFFERPOOL SQL statement. This provides the database administrator greater control of the availability of data in memory. For example, operational transaction tables can be given their own bufferpool so they would not have to compete with ad hoc queries for memory. This could help maintain OLTP performance while still providing good response to end-user queries.

  • Asynchronous page cleaner

    The ability to offload buffer page writing operations from a task executing the SQL query to another task can significantly improve query response time. The asynchronous page cleaning tasks ensure that sufficient space exists in the database buffers for query data. This capability can eliminate the need for query to wait synchronously until modified pages are written from the buffer to disk in order to make room for query data.

  • Sequential prefetch

    The performance of queries, which require a large amount of sequential disk I/O is significantly improved due to the overlapping of I/O and CPU processing. This is particularly useful for query processing.

  • List prefetch

    The support for list prefetch improves the performance of queries that access data randomly or non-sequentially.

  • Media-spanning through table spaces

    With UDB, database administrators can partition a database into parts called table spaces. When creating a table, the name of the base, index, and long table space can be specified. Using index and long table spaces to store indexes and LOB data respectively allows these structures to be kept separate from the rest of table data. This flexibility can be used to increase database performance and availability. A table space can be spread over one or more physical storage device, providing the media-spanning capability.

  • Direct media access (raw device support)

    UDB has the ability to store data directly on a device, without incurring the overhead of using a file system, for improved performance and data integrity. The administrator can choose to define a table space that uses devices, or uses the native file system.

  • Big block reads

    This capability enables the reading of several disk pages using a single I/O operation, reducing the CPU usage, and in the process, improving query response time.

  • REORG utility

    UDB includes a REORG utility that will re-sequence rows in a clustered order and eliminate fragmenting due to updates and deletes. This can significantly enhance performance of tables with a high rate of change. A REORGCHK utility is also provided to determine if tables are in need of reorganization.

  • Connection concentrator

    The connection concentrator allows a physical database agent to be used by multiple logical agents, each representing a client connection. The restriction on the number of client connections is now solely based on the transaction load and the machine's ability to handle the workload. The connection concentrator uses scheduler technology to run individual transactions for multiple clients over the same physical database connection.

  • Multidimensional clustering (MDC)

    Multidimensional clustering (MDC) provides an elegant method for flexible, continuous, and automatic clustering of data along multiple dimensions. This results in significant improvement in the performance of queries, as well as significant reduction in the overhead of data maintenance operations, such as reorganization, and index maintenance operations during insert, update, and delete operations. Multidimensional clustering is primarily intended for data warehousing and large database environments, and it can also be used in online transaction processing (OLTP) environments.

    MDC enables a table to be physically clustered on more than one key (or dimension) simultaneously. Prior to the introduction of MDC, DB2 only supported single-dimensional clustering of data, through clustering indexes. Using a clustering index, DB2 maintains the physical order of data on pages in the key order of the index, as records are inserted and updated in the table. Clustering indexes greatly improve the performance of range queries that have predicates containing one or more keys of the clustering index. With good clustering, only a portion of the table needs to be accessed, and when the pages are sequential, more efficient prefetching can be performed.

    With MDC, these benefits are extended to more than one dimension, or clustering key. In terms of query performance, range queries involving any combination of specified dimensions of the table will benefit from clustering. Not only will these queries access only those pages having records with the correct dimension values, these qualifying pages will be grouped by extents. Furthermore, although a table with a clustering index can become unclustered over time as space fills up in the table, an MDC table is able to maintain its clustering over all dimensions automatically and continuously, thus eliminating the need to reorganize the table to restore the physical order of the data.

Efficient large database operations

Scalability requires much more than performing transactions and queries faster using parallel processing or other high-performance features. It also requires that maintenance operations like data loading, backup and recovery, and indexing are scalable such that large data volumes can be efficiently managed. DB2 UDB provides the following in support of large database operations:

  • High speed LOAD utility: DB2 UDB includes a high-speed LOAD utility that significantly increases the speed of doing data loads while ensuring recoverability of the data being loaded. It can take input from a number of file formats or an SQL SELECT statement, and directly builds table space pages without the overhead of logging or SQL INSERT processing. It can also build indexes and collect statistics during the load. The LOAD utility can significantly reduce the amount of time it may take refresh or add data to a data warehouse.

  • SMP support in utilities: DB2 UDB not only exploits SMP architectures in transaction and query processing, but in its utility operations as well:

    • Parallel data loading: Loading data is a heavily CPU-intensive task. The LOAD utility takes advantage of multiple processors for tasks such as parsing and formatting data. Also, the LOAD utility can use parallel I/O servers to write the data to the containers in parallel. The LOAD utility has been shown to scale linearly as the number of processors is increased.

    • Parallel index creation: DB2 exploits I/O parallelism and CPU parallelism when creating an index. This helps to speed up index creation when a CREATE INDEX command is issued during restart (if an index is marked invalid) and during REORG processing.

    • Parallel backup and restore: Backing up and restoring data are heavy I/O-bound tasks. DB2 exploits I/O parallelism and CPU parallelism when performing backups and restores. DB2 takes advantage of multiple CPUs by assigning buffer manipulators among the CPUs. You can also backup to or restore multiple devices (such as tapes) in parallel.

  • Cluster/MPP support in utilities: DB2 Universal Database with the Database Partitioning Feature can also exploit cluster and MPP architectures in its utility operations:

    • Parallel split: As mentioned above, the key to MPP parallelism is intelligent partitioning. The db2split utility is provided to split data into partitions prior to loading. It can run in parallel on multiple nodes thus significantly speeding up the overall load process.

    • Parallel data loading: Once the data is split, the LOAD utility can run in parallel on each node. If each node is an SMP, it takes advantage of multiple processors for tasks such as parsing and formatting data, and can use parallel I/O servers to write the data to the containers in parallel.

    • Autoloader: This simplifies the process of splitting and loading multiple partitions of a table.

    • Parallel index creation: The CREATE INDEX command runs in parallel on each node.

    • Parallel backup and restore: Backup and restore operations can be run in parallel across nodes. DB2 exploits I/O parallelism and CPU parallelism when performing backups and restores. DB2 takes advantage of multiple CPUs by assigning buffer manipulators among the CPUs.

These advanced parallel processing, high-performance computing, and efficient large database operation features make DB2 Universal Database the most scalable, object-relational, and Web-enabled database in the industry. If you start out on a small NT server, it is easy to upgrade your hardware or move your data to a larger UNIX server if you need more capacity. If you are building a large data warehouse, you can start out on a single node and easily add additional nodes to support more data, more users, or improved response times. Whether your needs today are large or small, you can rest assured that you will not get boxed in if you grow.

Multimedia extensibility

Another major benefit of DB2 UDB is extensibility. By extensibility, we mean the ability to store and manage not only traditional relational tables with characters and numbers, but also multimedia, complex objects such as documents, images, audio, video, spatial information, time-series data, etc. This may also include industry-specific objects such as X-rays, fingerprints, engineering drawings, insurance claim forms, etc.

The key to this capability is what is called object-relational technology. DB2 UDB's object-relational capabilities allow you to add your own data types and business functions to the database — effectively tailoring the database to fit your specific business or application requirements. IBM was first to deliver this capability in DB2 Common Server Version 2 in 1995. DB2 UDB's implementation is more advanced and more robust than any other "Universal Server" on the market, and it has been thoroughly field tested making it very reliable.

DB2 UDB's extensibility features can be grouped into the following categories:

  • Universal Data

  • Business rules

  • Advanced SQL

  • DB2 Extenders™

These extended object-relational capabilities open up a whole new world of potential applications for you, and a very productive and efficient way to deliver them.

Universal Database (object-relational)

DB2 Universal Database supports the following key object-relational features. These are implemented according to SQL3 standards so they represent an open, non-proprietary approach.

  • User-Defined Types (UDTs): UDTs allow users to define new data types, which are represented in the database using built-in types. For example, a user can define two currency types CDOLLAR for Canadian Dollars and USDOLLAR for U.S. Dollars. These types are distinct in the sense that they should not be directly compared to one another or to the decimal type, although the decimal type might be chosen for the internal representation of both UDTs in the database. UDTs, like built-in types, can be used for columns of tables as well as parameters of functions, including User-Defined Functions (UDFs). For example, a user can define a data type such as ANGLE (which varies between 1 and 360) and a set of UDFs to act on it, such as SINE, COSINE, and TANGENT.

  • User-Defined Functions (UDFs): UDFs allow queries to contain powerful computation and search predicates to filter irrelevant data close to the source of the data. UDFs enable users to provide a set of functions that interpret a UDT, thereby defining the semantics of the UDT. Support for UDFs enable the creation of function libraries, which can be developed by IBM, third party vendors, or customers and then integrated directly in the database. The SQL optimizer takes into account the semantics and execution cost of UDFs, thus treating User Defined Functions exactly as the built-in functions such as SUBSTR and LENGTH. Applications may be developed using different application language environments, such as C, C++, COBOL, and FORTRAN, while sharing a set of UDTs and UDFs through SQL.

  • Large Objects (LOBs): LOBs allow users to store very large (multi-gigabyte) binary or text objects in a database. Binary LOBs can be used to store multimedia objects such as documents, video, images, and voice. LOBs can also be used to store small structures whose semantics are defined by UDTs and UDFs. A powerful set of built-in functions, such as search, substring, and concatenation are supported for LOBs. Additional functions can be defined at any time by means of UDFs. More than one LOB column can be defined on a table.

  • User-Defined Table Functions (Table UDFs): SQL users can now access data not stored in the relational format, and makes full use of the query capabilities of the relational database. It is often difficult, if not impossible to subject data from non-relational data stores to relational operations. User-defined table functions are an extension to SQL which solves this problem. A table function is an external user-defined function that constructs a derived table. The program for the function can access data from the various sources and format it into a tabular form returned from the table function. Once the table function is written, it can be used in the FROM clause of queries. Table functions can be used not only to subject this external data to the power of SQL, but also to capture external data permanently into relational tables.

  • OLE User-Defined Functions (UDFs): Object Linking and Embedding (OLE) automation is part of Microsoft's architecture on Windows platforms. It enables applications (OLE automation servers) to expose objects and methods that can then be accessed by other applications (OLE automation controllers) including: Lotus SmartSuite® (R), Lotus Approach, MS Office/Backoffice, SAP R/3, QMF (TM) HPO/Shuttle, many Web tools, many Visual Basic applications, and others. DB2 provides OLE automation controller support for accessing OLE automation server data through UDFs. These external UDFs allow data from OLE automation servers to be returned to SQL queries through DB2.

Business rules

Business rules enable the definition of complex integrity rules, which can be used to enforce the correctness of a database. They enhance the power of the other object-oriented features. They augment object-code-only libraries (whose methods cannot be modified) to support additional specific object attributes and constraint checking. They also help to enforce inter-object data integrity rules. The key features supporting business rules include:

  • Defaults: Defaults allow you to set default values for columns that are not assigned values explicitly in INSERT statements.

  • Generated Columns: Generated columns let you specify an SQL function that will be used to calculate a value for a column that is not assigned a value in an INSERT statement. This might be used to generate a unique number for each new row, or to assign a tax code based on other columns such as salary or marital status.

  • Check Constraints: Check constraints are generally used to enforce business rules not covered by key uniqueness or referential integrity constraints. For example, a user may define constraints on the EMPLOYEE table, which specify that the job of an employee can only be one of Sales, Mgr, or Clerk, and that every employee that has been with the company for more than 8 years must have a salary of more than $40,000.

  • Referential Integrity: Referential integrity (RI) lets you define required relationships between and within tables. Referential constraints are declared when a table is defined, and ensure the consistency of data values between related columns in different tables. DB2 maintains these relationships, so you do not need to program this function into applications.

  • Triggers: Triggers may be used to maintain complex cross-table business rules, automatically generate a value for a newly inserted row, read from other tables for cross-referencing purposes, write to other tables for audit-trail purposes and provide an alert capability, by adding a trigger, which invokes a User-Defined Function (for example, to send an electronic mail message). A user might define a trigger that increments the number of employees each time a new row is inserted into the EMPLOYEE table.

  • Stored procedures: DB2 clients can call stored procedures that execute on the DB2 server. Stored procedures push processing back from the client to the server, and thus provide support for thinner clients and for execution of the logic at the server-side. They also cut back significantly on network traffic, resulting in better response time. DB2 UDB stored procedures are somewhat unique in that they are not written in some proprietary language, but can be written in Java, C, C++, etc. They can also be written in the stored procedure language defined by the database standards committee. Stored procedures can return multiple rows and multiple result sets for greater efficiency.

Advanced SQL

Advanced SQL queries allow you to encapsulate a great deal of processing logic into a single, non-procedural statement. Examples of this include:

  • Recursive SQL queries: Changes to the SQL optimizer will enable DB2 server databases to support not only the bills-of-material queries, but also the more powerful form of recursive queries such as path expression queries. Examples of queries that become possible with support for recursion are:

    • Bills-of-material queries where a user wants to return subparts of parts, and subparts of the subparts, and so on.

    • Path expression queries, where a user wants to calculate the lowest cost plane fares on multi-hop routes. For example, the following query can be formulated using recursive SQL: Return all possible flights from Toronto to Perth without making a stopover in London or Chicago, and with no more than a three-plane changes.

    • The optimizer is capable of making sophisticated transformations and optimizations for recursive queries and non-recursive queries, resulting in selection of better access plans for improved performance.

  • Outer join support: Left, right, and full outer join operations are supported using standard SQL92 syntax; that is, a join operation whose result includes unmatched rows in addition to matching rows.

DB2 Extenders

The DB2 Extenders build on the object-relational infrastructure of DB2. Each extender is a package of predefined UDTs, UDFs, triggers, constraints, and stored procedures that satisfies a specific application domain. With the Extenders, the user can store text documents, images, videos, and audio clips in DB2 tables by adding columns of the new data types provided by the extenders. The actual data can be stored inside the table or outside in external files.

These new data types also have attributes that describe aspects of their internal structures, such as "language" and "format" for text data. Each extender provides the appropriate functions for creating, updating, deleting, and searching through data stored in its data types. The user can now include these new data types and functions in SQL statements for integrated content searching across all types of data.

The following four DB2 Extenders are provided as part of the DB2 Developer's Editions.

DB2 Text Extender

Text Extender adds the power of full-text retrieval to SQL queries by making use of features available in DB2 that let you store unstructured text documents of up to 2 GB in databases. Text Extender offers DB2 users and application programmers a fast, versatile, and intelligent method of searching through such text documents. Text Extender's strength lies in its ability to search through many thousands of large text documents at high speed, finding not only what you directly ask for, but also word variations and synonyms. You are not restricted to searching only in text documents stored in DB2 databases, you can also search in text documents stored in files.

Text Extender can access various kinds of text documents, including word-processing documents in their original native form, and offers a rich set of retrieval capabilities including word, phrase, wild card, and proximity searching using Boolean logic ("and/or" logic).

At the heart of Text Extender is IBM's high-performance, advanced search engine. It allows your applications to access and retrieve text documents in a variety of ways. Your applications can:

  • Search for documents that contain specific text, synonyms of a word or phrase, or sought-for words in proximity, such as in the same sentence or paragraph

  • Do wild card searches, using front, middle, and end masking for word and character masking

  • Search for documents of various languages in various document formats

  • Make a fuzzy search for words having a similar spelling as the search term. This is useful for finding words even when they are misspelled

  • Make a free-text search in which the search argument is expressed in natural language

  • Search for the names of people, places, or organizations

  • Search for words that sound like the search term

You can integrate your text search with business data queries. For example, you can code an SQL query in an application to search for text documents that are created by a specific author, within a range of dates, and that contain a particular word or phrase. Using the Text Extender programming interface, you can also allow your application users to browse the documents. By integrating full-text search into DB2's SELECT queries, you have a powerful retrieval function that combines attribute and full-text search.

DB2 Image Extender

The DB2 Image Extender defines a data type and functions for images using DB2 UDB's built-in support for user-defined types and user-defined functions. It also exploits DB2 UDB's support for large objects of up to 2 GB and uses DB2 UDB triggers to automatically store and maintain attribute information for images. With the DB2 Image Extender, you can:

  • Import and export images: You can import and export images and image attributes into and out of a database. When an image is imported, the DB2 Image Extender stores and maintains image attributes such as size in bytes, format, height, width, and number of colors.

  • Control access to images: This can be done with the same level of protection as traditional business data.

  • Convert the format of images: You have the flexibility of importing or exporting an image in its source format or converting the format of the image when importing or exporting. You can also convert an image in other ways, such as rotating it or changing its scale.

  • Secure and recover images: Images and their attributes stored in a DB2 database are afforded the same security and recovery protection as traditional business data.

  • Query images: This can be done based on related business data or by image attributes. Images can be searched based on data that the user maintains, such as a name, number, or description; or by data that the DB2 Image Extender maintains, such as the format of the image or its distribution of colors.

  • Generate and display image thumbnails and full images: A thumbnail is a miniature version of an image. When an image is imported into a database, the DB2 Image Extender creates and stores a thumbnail of the image. You can use the DB2 Image Extender to retrieve a thumbnail or a full-size image, and then use the DB2 Image Extender to invoke a favorite browser to display the thumbnail or full-size image.

The DB2 Image Extender supports a wide variety of image formats, such as GIF (including animated GIFs), JPEG, BMP, and TIFF.

DB2 Audio Extender

The DB2 Audio Extender defines a new data type and functions for audio using DB2 UDB's built-in support for user-defined types and user-defined functions. It also exploits DB2 UDB's support for large objects of up to 2 GB and uses DB2 UDB triggers to automatically store and maintain attribute information for audio objects.

With the DB2 Audio Extender, you can:

  • Import and export audio clips: You can import and export audio clips and audio attributes into and out of a database. When an audio clip is imported, the DB2 Audio Extender stores and maintains audio attributes such as number of audio channels, transfer time, and sampling rate.

  • Secure and recover audio data: Audio clips and their attributes stored in a DB2 database are afforded the same security and recovery protection as traditional business data.

  • Query audio clips: This can be done based on related business data or by audio attributes. You can search for audio clips based on data that you maintain, such as a name, number, or description; or by data that the DB2 Audio Extender maintains, such as the format of the audio or the date and time that it was last updated.

  • Play audio clips: You can use the DB2 Audio Extender to retrieve an audio clip, and then use the DB2 Audio Extender to invoke a favorite audio browser to play the audio clip.

The DB2 Audio Extender supports a variety of audio file formats, such as WAVE, MIDI, MPEG1, and AU, and can work with different file-based audio servers.

DB2 Video Extender

The DB2 Video Extender defines a new data type and functions for video using DB2 UDB's built-in support for user-defined types and user-defined functions. It also exploits DB2 UDB's support for large objects of up to 2 GB and uses DB2 UDB triggers to automatically store and maintain attribute information for video objects.

With the DB2 Video Extender, users can:

  • Import and export video clips: You can import and export video clips and their attributes into and out of a database. When a video clip is imported, the DB2 Video Extender stores and maintains video attributes such as the frame rate, compression format, and number of video tracks.

  • Secure and recover video data: Video clips and their attributes stored in a DB2 database are afforded the same security and recovery protection as traditional business data.

  • Query video clips: This can be done based on related business data or by audio attributes. You can search for video clips based on data that you maintain, such as a name, number, or description; or by data that the DB2 Video Extender maintains, such as the format of the video or the date and time that it was last updated.

  • Build storyboards: You can use the DB2 Video Extender to automatically segment a video clip into shots based on scene changes. A scene change is a point in a video clip where there is a significant difference between two successive frames. When the DB2 Video Extender detects a scene change, it records data for the associated shot, including representative frames. This makes it easy to build summaries of a video, called storyboards.

  • Play video clips: You can use the DB2 Video Extender to retrieve a video clip, and then use the DB2 Video Extender to invoke a favorite video browser to play the video clip.

The DB2 Video Extender supports a variety of video file formats, such as MPEG1, MPEG2, AVI, and QuickTime, and can work with different file-based video servers.

DB2 XML Extender

The IBM DB2 XML Extender implements the IBM overall XML technical strategy. That is, to be the world leader in e-business. The XML Extender as a part of the IBM business to business(B2B) server offering, makes the DB2 server to be XML enabled. It provides new technology for emerging market of early XML adoption and evaluation. The Extender offers the capability of XML storage and data interchange. By storage, the XML Extender provides mechanism of storing and retrieving XML documents in DB2, and searching the content of XML with high performance. By data interchange, the XML Extender provides mapping between new and existing DB2 relational tables and XML formatted documents. Together, the XML Extender allows DB2 customers to do e-business anywhere, enabling XML with their B2B and business to consumer(B2C) applications.

With the content of your structured XML documents in the DB2 database, you can combine structured XML information with your traditional relational data. Based on the application, you can choose whether to store entire XML documents in DB2 as a nontraditional distinct data type, or you want to map the XML content as traditional data in relational tables. You can decide how structured XML documents be stored or created through the Document Access Definition (DAD).

For non-traditional XML data types, the XML Extender adds the power to search rich data types of XML element or attribute values, in addition to the structural-text search provided by the Text Extender. For traditional SQL data which are either decomposed from incoming XML documents, or in existing relational tables to be used to create outgoing XML documents, the XML extender provides a custom mapping mechanism to allow the transformation between XML documents and relational data.

Net.Data®, which connects Web applications to DB2, now has built in XML exploitation. This allows you to generate XML tags as output from your Net.Data macro, instead of manually entering the tags. You can also specify an XML style sheet (XSL) to be used to format and display the generated Output.

DB2 Spatial Extender

DB2 supports the notion of Spatially Enabled SQL Queries. You can now integrate spatial data (locations through coordinates) with normal SQL data. The combination of these two technologies gives users access to new types of queries that they could not previous run. The DB2 Spatial Extender is used to achieve this functionality. The Spatial extender will store and index the spatial data (coordinate information) and allow specific spatial queries against this data.

The following features are available with the DB2 UDB Spatial Extender:

  • Infrastructure to model and manipulate spatial data: spatial types, catalog views, spatial functions, support for spatial reference systems and spatial "layers"

  • Object types and operations that conform with OpenGIS Consortium (OGC) and ISO SQLMM standards

  • A multi-level grid index implementation modelled after the ESRI proprietary grid index technology

  • Stored procedure API to create and manage spatial resources

  • Geocoding is performed either incrementally or in batch mode. The Spatial Extender supports not only a default geocoder (shipped with the product), but also geocoders supplied by users and vendors.

  • Spatial Extender supports DB2 UDB spatial data. But you can use DB2 UDB to create joins between this data and data outside of DB2 UDB. You can do this if you install Spatial Extender on the server that includes a federated database, and if you then enable this database for spatial operations. Once this database is so enabled, you can create joins between its spatial data and data in federated data sources. Currently, federated data sources are relational only (Oracle and DB2 family)

  • Superior ease of use and ease of administration capabilities relative to other relational implementations

  • Import, Export, and Geocode operations

  • A sample application to help customers to set up and use Spatial Extender

DB2 Net.Search

The DB2 Net Search Extender contains a DB2 stored procedure that adds the power of fast full-text retrieval to DB2 applications. It offers application programmers a variety of search functions, such as fuzzy search, stemming, Boolean operators, and section search. Searching using DB2 Net.Search Extender can be particularly advantageous in the Internet, when search performance on large indexes and scalability according to concurrent queries are important factors.

The Net.Search extender in DB2 UDB allows very fast text search with:

  • Word or phrase searches

  • Stemmed searches

  • Boolean operations

  • Fuzzy searches

  • Wildcard searches

  • Fielded searches

  • Presorted searches

  • Cursor capability

  • High speed indexing

  • Creation of multiple indexes at the same time

  • Only read access to the user data is required

Net.Search uses main memory database technology to reach high performance levels. Load tests resulted in 90 million Web site hits per day without degradation in the search performance.

DB2 Universal Database's support for universal data, business rules, advanced SQL, and multimedia data objects and methods makes it among the most extensible object-relational database in the industry. Among the key differentiators is that this is built according to SQL standards, and that it is built into the optimizer. This makes the implementation more open and allows for better performance than other implementations.

Web enablement

Customers need to be able to make the data stored in their DB2 database systems accessible to employees of the company, and selectively to their suppliers and customers through private network (intranet) and public network (Internet) applications. DB2 Universal Database is fully integrated with Web technology so that data can be easily accessed from the Internet or from your intranet with complete security. The following facilities included with UDB allow you to Web-enable your database applications right out of the box:

  • DB2 Java support

  • Net.Data: A Webserver Database Gateway

DB2 Java support

Java applications are very attractive to customers who would like to develop a single application running on any operating system, and who would like to reduce the cost of application distribution and maintenance.

Java Database Connectivity (JDBC) is a database access interface for Java applications that are being delivered with DB2. The DB2 JDBC database interface supports this API.

DB2 provides native support for Java at client workstations and DB2 servers. Java is supported on the client workstations in three ways:

  • A Java application uses the DB2 Client Application Enabler, which must be installed on the client workstation to communicate with the DB2 server. Customers with existing DB2 client/server configurations can now use Java as a database application development tool.

  • Java applets allow applications to be developed that access DB2 servers without requiring DB2 Client Application Enabler code to be installed on client workstations. Java applets can be automatically downloaded to the client workstation at application invocation time.

  • The new type 4 JDBC driver is a two-tier pure Java JDBC driver, which allows a Java client to communicate directly with DB2 servers through the DRDA® protocol. This driver is designed to replace the type 3 driver. You should migrate applets that use the type 3 JDBC driver to the type 4 driver, in preparation for the end of type 3 driver support.

Java support in DB2 servers consists of the ability to create native Java-based, user-defined functions and stored procedures.

Net.Data

Included in the server product boxes is a copy of Net.Data, a Web-enabling tool for interactive database-to-Web applications. Net.Data is IBM's strategic product for enabling Internet/intranet access to relational data on a variety of platforms. It provides open data access to DB2 and other data sources including Oracle, Sybase, and any ODBC data server. With Net.Data, your application can use DB2 to build dynamic Web pages to support electronic commerce applications.

Net.Data provides for high-performance, robust, application development function and exploitation of existing business logic through open programming interfaces. Net.Data tightly integrates with Web-server APIs such as those from IBM, Lotus, Netscape, and Microsoft, providing higher performance than common gateway interface (CGI) applications.

Net.Data provides connection management to your key relational databases for optimum performance. Net.Data can establish a continuous connection to specified databases. Net.Data maintains the connection throughout the Web application and across invocations of Web applications. Since the database connection is continuous, the application does not experience the overhead of repeated connects to the database. The result is peak performance of your interactive Web application.

The Net.Data application is a macro with a rich macro language, variable substitution, conditional logic, and optional function calls. Net.Data supports client-side processing with Java applets and Java Script. Server-side processing includes Java applications and REXX, Perl, and C/C++ applications.

Net.Data and Java support make DB2 Universal Database Internet ready right out of the box. For the most complete Web-enabled database solution on the market, DB2 UDB teams with WebSphere for a complete e-business environment.

Partner solutions

In order to implement a data management solution that meets the changing needs of your business, you will need a robust relational database, and carefully chosen applications to run against it. DB2 Universal Database provides the rock-solid foundation required to successfully deploy enterprise solutions, while thousands of Independent Software Vendors (ISVs) offer a diverse range of sophisticated applications that support DB2.

In close partnership with IBM, leading software developers like Siebel, I2, SAP, Baan, Dassault, and PeopleSoft, develop enterprise resource planning (ERP) solutions and CRM solutions, as well as B2B solutions and other applications that deliver the functionality your user base needs. These premier ISVs recognize that DB2 Universal Database has the performance, reliability, and flexibility to meet the demands of today's operational and business intelligence applications.

So, if you are looking for a data management solution, IBM's many business partners offer an extraordinary range of applications designed to run on DB2. From the ERP solutions mentioned above, to the business intelligence tools offered by Andyne, Brio, Business Objects, and Cognos, to the DB2 Extenders created by Consistency Point Technologies, Environmental Systems Research Institute, Inc. (ESRI), The Fillmore Group, Formida Software, Innovus Corp., IsoQuest, Inc., OG Software (Oxford Group), and Prime Factors, Inc., you will find that our business partners offer a constantly expanding universe of solutions.

For the most up-to-date information on solutions, and to look through the on-line IBM Solutions Catalog, go to these two sites:

  • http://www.software.ibm.com/data/partners/

  • http://www.software.ibm.com/solutions/isv

Business Intelligence powerhouse

By Business Intelligence (BI) we mean applications like data warehousing, data mining, on-line analytical process (OLAP), and decision support. Many customers are looking for ways to mine and analyze their operational data for competitive advantage. These are among the most important uses of data management technology today, because they provide customers with excellent returns on their investment.

Several factors make DB2 UDB an outstanding data store for BI applications:

  • These applications often involve large volumes of data. Typically, small to medium size warehouses and datamarts might contain 50 GB to 300 GB. Large installations can contain several terabytes. UDB addresses these requirements with its outstanding scalability, including advanced parallel query, and VLDB operations.

  • Queries against the database tend to be very complex. UDB has the most advanced query optimizer in the industry, providing excellent query performance with a minimum of DBA time required for tuning.

  • DB2 UDB has some features specifically designed to assist with on-line analytical processing (OLAP) support.

  • DB2 also offers the Warehouse Manager feature, an integrated set of tools for building, managing, and maintaining data warehouses and datamarts. The Warehouse Manager tool works with the Warehouse Center, the integrated GUI tool, which co-ordinates and automates the activities needed to extract, clean, and populate the data into your informational data store.

Advanced optimizer

The DB2 SQL optimizer strengthens DB2's leadership position in query optimization for traditional applications, and also extends this robust support to new application domains enabled by the object-oriented extensions described earlier. This new optimization technology provides the function and performance needed by customers to analyze and exploit vast amounts of valuable information stored in their databases.

The increasing importance of decision support applications represents an important customer trend, which can result in very complex database queries. These queries may have been written by end-users, generated by automatic tools, or produced as a result of many point-and-click application interfaces popular in today's DOS, Windows, OS/2, and UNIX environments.

The optimizer incorporates a very sophisticated query rewrite phase that automatically transforms a complex query into a simpler query that is easy to optimize. As a result, the end user will realize the best possible performance regardless of the way a query is structured.

The optimizer also looks at a greater number of alternatives in its search for the best query execution plan, as well as employing more sophisticated techniques of modeling the cost of different ways of fetching the data from disk. All these techniques can result in orders of magnitude of performance improvement for complex queries as compared to existing SQL optimizer technology.

A related technology is DB2's support of Materialized Query Tables (MQT) or Automated Summary Tables (AST). Using AST queries that might take minutes or hours to complete can be shortened dramatically, often to seconds or even sub-second response times. This is done by precalculating summary information into a summary table, then using the power of the optimizer's query rewriting to change the submitted query so that it retrieves the information from the summary table, rather than recalculating it. Users do not have to change their queries to take advantage of this performance improvement, it is handled automatically by the DB2 optimizer once the administrator defines the AST.

OLAP support

Data warehouse and OLAP applications are characterized by the use of a special design technique, which is called star schema, to model relational data for multidimensional analysis (MDA). Under this schema it is common for a large "fact" table to be joined to multiple "dimension" tables in a very complex SQL join query. Any optimization techniques that can be used to improve the performance of these joins can significantly improve the performance of the overall application. DB2 Universal Database has special optimization techniques to do this:

  • Index ANDing using dynamic bit maps: UDB uses dynamic bit-map technology to efficiently combine multiple indexes. Performance is improved for queries that use columns that are key columns of different indexes over the same table. This includes the use of indexes for multi-way joins.

  • Star joins: DB2's star join algorithm exploits dynamic bit maps to join a large fact table with a series of relatively small dimension tables, thus minimizing data I/O.

OLAP and MDA applications are also characterized by queries involving complex grouping and aggregation of data. With DB2 UDB, the GROUP BY clause has been extended to support "super groups." One type of super group is a ROLLUP group, which is a result set that contains "sub-total" and "overall total" rows in addition to the regular grouped rows. Another type of super group is a CUBE group, which is a result set that contains "cross-tabulation" rows in addition to all the rows that would be in a ROLLUP group for the same columns.

The ROLLUP and CUBE aggregations are useful in OLAP (on-line analytical processing) decision support applications to aggregate base data in multiple dimensions and over roll-up/drill-down hierarchies. An example of a common usage of this is analyzing data in three dimensions, such as looking at sales by product, by store, and by month.

DB2 Universal Database's scalability and parallel query performance, advanced query optimization, and unique OLAP support make it the best database engine to power any Business Intelligence application.

DB2 UDB has particular strengths in supporting business intelligence applications such as data warehousing and on-line analytical processing (OLAP). DB2 leads the industry in parallel database technology and query optimization resulting in the proven ability to help customers find competitive advantage, better customer service, or reduce costs by mining their data for the knowledge required to make better decisions. Furthermore, this does not require the additional expense of a specialized database; DB2 UDB provides a single database that can be used across an enterprise for all data management requirements from OLAP to OLTP.

Ease of use and management

DB2 Universal Database is one of the easiest databases in the industry to use and manage. It includes a complete suite of graphical tools to satisfy the needs of:

  • Database administrators (DBAs)

  • Application programmers

It also includes tools to assist with client set-up and ad hoc query and reporting for end users.

Administering databases with the DB2 Administration Tools

You can administer local or remote servers using the DB2 Administration Tools. Use the Control Center to perform administration tasks such as configuring DB2 instances and databases, backing up and recovering data, scheduling jobs, and managing media, all from a graphical interface.

Managing instances and database objects using the Control Center

The Control Center displays instances and database objects (such as table spaces, tables, and packages) and their relationships to each other. Using the Control Center, you can manage local and remote servers from a single point of control.

From the Control Center, you can perform operations on database objects. You can:

  • Create and drop a database

  • Create, alter, and drop a table space or table

  • Create, alter, and drop an index

  • Back up and recover a database or table space

  • Define replication sources and subscriptions to replicate data between systems

  • Monitor resources and events on a server

You can also control DB2 instances by:

  • Maintaining communication protocols

  • Setting database manager and database configuration values that affect performance

SmartGuides or wizards are provided to help you perform complex tasks. For example, SmartGuides are available to tune the performance of your system or to recommend what indexes you need (and it will build them for you too).

The Control Center provides additional functionality to assist you in managing your servers:

  • Control Center: Use the Control Center to start another session of the Control Center to administer a server.

  • Satellite Center: Use the Satellite Center to manage the satellites that are served by a particular DB2 Control Server. It provides create, remove, modify, and manage functions for satellites and groups. You can also create and manage scripts to administer the satellites.

  • Command Center: Use the Command Center to enter DB2 commands and SQL statements in an interactive window and see the execution result in a result window. You can scroll through the results and save the output to a file.

  • Task Center: Use the Task Center to create scripts, which you can store and invoke at a later time. These scripts can contain DB2 commands, SQL statements, as well as operating system commands. Scripts can be scheduled to run unattended. These jobs can be run once or set up to run on a repeating schedule; a repeating schedule is particularly useful for tasks like backup.

  • Health Center: Use the Health Center to monitor your system for early warnings of potential problems, or to automate actions to correct problems discovered.

  • Journal: Use the Journal to view all available information about jobs that are pending execution, executing, or that have completed execution. You can also view the recovery history log, the alerts log, and the messages log; and review the results of jobs that are run unattended.

  • Tools Setting: Use the Tools Setting to change the settings for the DB2 Administration Tools.

  • License Center: Use the License Center to manage licenses and display license status and usage of any DB2 products installed on your system. You can also use the License Center to configure your system for proper license monitoring.

  • Data Warehouse Center: Use the Warehouse Center to manage data warehouses and datamarts. You can define data sources, cleansing steps, and target systems. You can set up a schedule for when data extractions are run on the data sources, and when data will be propagated to the target warehouses.

  • Information Center: The Information Center provides quick access to DB2 product information. This product information includes such items as: database tasks, reference material, DB2 documentation, troubleshooting aids, sample programs for application development, and DB2 Web-related URLs.

  • Development Center: The Development Center provides an easy-to-use interface for developing routines such as stored procedures and user-defined functions (UDFs). A set of wizards makes it easy to perform your development tasks. The Development Center provides a single development environment that supports the entire DB2 family ranging from the workstation to z/OS. You can launch the Development Center as a stand-alone application from the IBM DB2 Universal Database program group or from a DB2 Universal Database center, such as the Control Center, the Command Center, or the Task Center.

    With the Development Center, you can:

    • Create, build, and deploy Java and SQL stored procedures

    • Create, build, and deploy user-defined functions:

      • SQL table and scalar UDFs

      • UDFs that read MQSeries messages

      • UDFs that access OLE DB data sources

      • UDFs that extract data from XML documents

    • Debug SQL stored procedures using the integrated debugger

    • See the contents of the server for each database connection that is in your project or that you have explicitly added to the Server view. You can also view and work with other database objects such as tables, triggers, and views.

    • Export and import routines and project information

    The Development Center also provides a DB2 development add-in for each of the following development environments:

    • Microsoft Visual C++

    • Microsoft Visual Basic

    • Microsoft Visual InterDev

    With the add-ins, you can easily access the features of the Development Center and other DB2 centers from your Microsoft development environment, making it easy for you to develop and incorporate stored procedures and UDFs into your DB2 application development.

DB2 autonomic technology

IBM has put a lot of research and development effort into providing advanced automation functionality within DB2. The results of this effort is known as Self-Managing And Resource Tuning (SMART) technology. The purpose of SMART is to reduce the complexity of managing DB2 for inexperienced users, and to reduce the total cost of ownership by enabling many administrative and tuning functions to be carried out automatically by the DBMS.

These are some examples of SMART in DB2 UDB:

  • Configuration Advisor Wizard: This provides an easy-to-use GUI tool to tune the performance of a database with just minimal input about the anticipated workload.

  • Design Advisor Wizard: This provides recommendations on adding new indexes or removing existing indexes based on your input of workload characteristics.

  • DB2 Health Center: This constantly monitors the overall health of a system. It can automatically diagnose and fix many potential problems. In addition, it is able to contact an administrator by e-mail or pager, either to notify them that corrective action has been taken, or because a problem has been identified that is deemed by the administrator to be too risky to attempt an automated fix, or which cannot be fully automated because a hard limit has been reached or the task requires some form of manual intervention.

  • Memory Tracker and Visualizer: This shows all memory in all pools at a particular instant. It provides a graphical display of memory usage and also supplies information to the DB2 monitoring facilities for ongoing analysis.

  • Storage Management: This is a tool available through the Control Center. From this tool you can access the Storage Management view that displays a snapshot of the storage for a particular database, database partition group, or table space. Statistical information can be captured periodically and displayed depending on the object chosen:

    • For table spaces, information is displayed from the system catalogs and database monitor for tables, indexes, and containers defined under the scope of the given table space.

    • For databases or database partition groups, information is displayed for all the table spaces defined in the given database or database partition group.

    • For databases, information is also collected for all the database partition groups within the database.

    You can use the information displayed in this view to monitor various aspects of your storage, such as space usage for table spaces, data skew (database distribution) for database partition groups, and capture cluster ratio of indexes for database partition groups and table spaces. From the Storage Management view you can also set thresholds for data skew, space usage, and index cluster ratio. A warning or alarm flag will let you know if a target object exceeds a specified threshold.

Data access and replication

DB2 Universal Database is a distributed, fully networked RDBMS. It provides you with the flexibility of placing data anywhere in your network required for optimum service and productivity, and provides efficient means for clients to access that data over the network. Furthermore, DB2 provides the most efficient and seamless integration of data on mainframe and midrange data servers in the industry allowing you to reduce costs and improve cycle-times by leveraging your current investments in data, hardware, software, and skills.

DB2 UDB's support for distributed data can be grouped into three categories:

  • Client and server data access

  • Data replication

  • Host data integration through DRDA

Client/Server data access

DB2 UDB supports a number of features that provide for efficient access to UDB database servers from client workstations over a network:

  • Stored procedures: DB2 clients can call stored procedures that execute on the DB2 server. Stored procedures push processing back from the client to the server, and thus provide support for thinner clients. They also cut back significantly on network traffic resulting in better response time. UDB stored procedures are somewhat unique in that they are not written in some proprietary language, but can be written in Basic, Java, C, C++, etc. They can also be written in the standards based stored procedure language defined by the database standards committee. Stored procedures can return multiple rows and multiple result sets for greater efficiency.

  • Compound SQL: DB2 client applications can batch multiple SQL statements into a single compound SQL statement that is transmitted over the network and executed as one at the server. This can cut down on network traffic and is particularly good for mass inserts, updates, or deletes over the network.

  • Row blocking: DB2 UDB can reduce the number of network transmissions by buffering rows at both the client and server ends. The buffer sizes are tunable parameters.

  • Two-phase commit: DB2 clients can access and update multiple UDB servers in a single transaction (unit-of-work). UDB servers have built-in transaction monitors that log the transaction phases and handle rollback in case of failure. The two-phase commit process is coordinated from the client.

Data replication

Data Propagator Relational is built into DB2 Universal Database (and remains available as separate products or features for DB2 products on MVS™, OS/390, OS/400®, and VSE and VM). This feature is based on an advanced change-capture technology. It provides a highly efficient way for automatically maintaining consistent copies of relational data in the DB2 family of databases without requiring any batch processing windows and explicit knowledge of, or changes to, business applications. Data Propagator includes:

  • Easier and intuitive administration: The Control Center includes replication administration, provides many ease-of-use features, and acts as a single-point-of-control for the entire DB2 replication network.

  • Subscription sets for transaction consistency: With subscription sets, updates to all related target tables are committed in a single unit of work, supporting referential integrity requirements.

  • Update-anywhere replication: Robust, update-anywhere replication is enabled with rigorous conflict detection, and automatic compensation for a new breed of distributed applications.

  • On-demand replication for occasionally connected and mobile systems: With support for on-demand replication, auto connect and disconnect, and minimization of connection time, mobile or occasionally disconnected systems running DB2 Universal Database Personal Edition on Windows NT/2000/XP, or Windows 98/ME are enabled to participate fully and efficiently in read-only and update-anywhere replication scenarios.

  • DB2 source view replication: With support for view-based replication, you can subset and distribute data efficiently from normalized databases.

  • Event-driven propagation: This is an easy mechanism for you to control the timing of propagation, for example, at the end of day or after the completion of a particular batch run; or the content of propagation only on updates performed before 6:00 p.m.

Distributed database access through DRDA

Many customers have a need to distribute data across relational databases from different vendors or on different hardware platforms. IBM has developed the Distributed Relational Database Architecture™ (DRDA) to support this. It has become the standard for integrating client and server databases and client-based tools with mainframe and midrange databases on OS/390, MVS, VSE, VM, and OS/400. DB2 UDB uses DRDA to provide the most complete and efficient data integration with these platforms in the industry.

There are two major subsets of DRDA function: the client or requester side and the server-side:

  • DRDA Application Requester (DRDA-AR): This allows DB2 client workstations to transparently access data in DB2 for OS/390, DB2 for MVS, DB2 for OS/400 and/or DB2 for VSE & VM. The DRDA-AR is provided with DB2 Connect or is built into DB2 UDB Enterprise Server Edition.

  • DRDA Application Server (DRDA-AS): This allows other DRDA-ARs to access data stored in DB2 Universal Database. In particular, this capability allows DB2 for MVS, DB2 for VSE & VM (SQL/DS™), and DB2/400 applications (or any other application that implements the DRDA Application Requester functionality) to access data located in the UDB server databases. With this capability, thousands of existing database applications running on the MVS, VM, and OS/400 platforms are able to access data stored in DB2 UDB databases. The DRDA-AS is included in DB2 UDB Workgroup Server Edition and Enterprise Server Edition.

Federated systems

A DB2 federated system is a special type of distributed database management system (DBMS). A federated system consists of a DB2 instance that operates as a server, and a database that serves as the federated database, one or more data sources, and clients (users and applications) who access the database and data sources. With a federated system you can send distributed requests to multiple data sources within a single SQL statement. The power of a DB2 federated system is in its ability to:

  • Join data from local tables and remote data sources, as if all the data are local

  • Take advantage of the data source processing strengths, by sending distributed requests to the data sources for processing

  • Compensate for SQL limitations at the data source by processing parts of a distributed request at the federated server

  • Write capability to perform INSERT, UPDATE, and DELETE actions on the data sources

  • Ability to create remote tables on relational data sources

Federated database systems provide the middleware functionality for outstanding information integration. Built into DB2 Enterprise Server Edition is the ability to federate relational data across IBM's family of databases, including the DB2 family and Informix IDS.

Multi-platform support

DB2 Universal Database is one of the most open database platforms available. It runs on the most popular UNIX and Intel server platforms including AIX, HP-UX, Solaris, Linux, and Windows NT/2000/Server 2003. It supports all major industry standards relevant to distributed data so that it can be accessed using thousands of existing tools and applications, and can be easily managed within an open, network computing environment. These capabilities allow you to reduce costs and improve cycle-times by leveraging your current investments in data, hardware, software, and skills.

Bullet-proof reliability

DB2 Universal Database is setting the standard for quality and reliability in the client and server database industry. As more mission-critical applications are implemented on UNIX and Intel platforms, IBM's ability to bring mainframe-level reliability to this environment has become a major factor in choosing DB2. Better reliability and availability can reduce your costs, while scalability both within and across platforms can reduce the risk of dead-end projects.


Appendix B: Data Types

Overview

This appendix explains data types in different environments:

  • Supported SQL data types in C/C++

  • Supported SQL data types in Java

  • Mapping Oracle data types to DB2 UDB data types


Supported SQL data types in C/C++

Table 9-5 provides a complete list of SQL data types, C/C++ data type mapping, and a quick description of each. Note that DB2 UDB has multiple definitions for DATE and multiple types for NUMBER.

Table 9-5: Oracle to DB2 data type mapping

SQL data type sqltype

C/C++ type

sqllen

Description

integer

SMALLINT (500 or 501)

short

2

  • 16-bit signed integer

  • range between (-32,768 and 32,767)

  • precision of 5 digits

INTEGER INT (496 or 497)

long

4

  • 32-bit signed integer

  • range between (-2,147,483,648 and 2,147,483,647)

  • precision of 10 digits

BIGINT (492 or 493)

long

8

  • 64-bit signed integer

floating point

REAL FLOAT (480 or 481)

float

  • Single precision floating point

  • 32-bit approximation of a real number

  • FLOAT(n) can be synonym for REAL if 0 < n < 25

DOUBLE (480 or 481) DOUBLE PRECISION

double

8

  • Double precision floating point

  • 64-bit approximation of a real number

  • Range in (0, -1.79769E+308 to -2.225E-307, 2.225E-307 to 1.79769E+308)

  • FLOAT(n) can be synonym for DOUBLE if 24 < n < 54

decimal

DECIMAL(p,s) DEC(p,s) (484 or 485)

NUMERIC(p,s) NUM(p,s)

double / decimal

p/2+1

  • Packed decimal

  • If precision /scale not specified, default is (5,0)

  • Max precision is 31 digits, and max range between (-10E31 + 1 ... 10E31 -1)

  • Consider using char / decimal functions to manipulate packed decimal fields as char data

date / time

DATE (384 or 385)

struct {
  short len;
  char
 data[10];
} dt;

char dt[11];

10

  • Null-terminated character form (11 characters) or varchar struct form (10 characters); struct can be divided as desired to obtain the individual fields

  • Example: 11/02/2000

  • Stored internally as a packed string of 4 bytes

TIME (388 or 389)

char

8

  • Null-terminated character form (9 characters) or varchar struct form (8 characters); struct can be divided as desired to obtain the individual fields

  • Example: 19:21:39

  • Stored internally as a packed string of 3 bytes

TIMESTAMP

char

26

  • Null-terminated character form (27 characters) or varchar struct form (26 characters); struct can be divided as desired to obtain the individual fields

  • Example: 2003-08-04-01.02.03.0000 00 - Stored internally as a packed string of 10 bytes

character

CHAR (452 or 453)

char

n

  • Fixed-length character string consisting of n bytes

  • Use char[n+1] where 1 <= n <= 254

  • If length not specified, defaults to 1

VARCHAR (460 or 461)

char

n

  • Null-terminated variable length character string

  • Use char[n+1] where 1 <= n <=32672

VARCHAR (448 or 449)

struct {
  short len;
  char data[n
];
}

len

  • Non null-terminated varying character string with 2-byte string length indicator

  • Use char[n] in struct form where 1<= n <= 32672

  • Default SQL type

LONG VARCHAR (456 or 457)

struct {
  short len;
  char data[n
];
}

len

  • Non null-terminated varying character string with 2-byte string length indicator

  • Use char[n] in struct form where 32673<= n <= 32700

CLOB(n) (408 or 409)

clob

n

  • Non null-terminated varying character string with 4-byte string length indicator

  • Use char[n] in struct form where 1 <= n <= 2147483647

CLOB (964 or 965)

clob_locator

  • Identifies CLOB entities residing on the server

CLOB (808 or 809)

clob_file

  • Descriptor for file containing CLOB data

binary

BLOB(n) (404 or 405)

blob

n

  • Non null-terminated varying binary string with 4-byte string length indicator

  • Use char[n] in struct form where 1 <= n <= 2147483647

BLOB (960 or 961)

blob_locator

  • Identifies BLOB entities on the server

BLOB (804 or 805)

blob_file

  • Descriptor for the file containing BLOB data

double- byte

GRAPHIC(1) GRAPHIC(n) (468 or 469)

sqldbchar

24

  • sqldbchar is a single double-byte character string

  • For a fixed-length graphic string of length integer which may range from 1 to 127. If the length specification is omitted, a length of 1 is assumed.

  • Precompiled with CHARTYPE NOCONVERT option

VARGRAPHIC( n) (464 or 465)

struct {
  short int;
  sqldbchar[n
]
} tag;

alternately:
sqldbchar[n+
1]

n*2+ 4

  • For a varying-length graphic string of maximum length integer, which may range from 1 to 16336.

  • Precompiled with WCHARTYPE NOCONVERT option.

  • Null terminated variable-length

LONG VARGRAPHIC( n) (472 or 473)

struct {
  short int;
  sqldbchar[n
]
} tag;

  • For a varying-length graphic string with a maximum length of 16350 and a 2-byte string length indicator 16337<=n <=16350

  • Precompiled with WCHARTYPE NOCONVERT option

DBCLOB(n) (412 or 413)

dbclob

  • For non-null-terminated varying double-byte character large object string of the specified maximum length in double-byte characters.

  • 4 bytes string length indicator

  • Use dbclob(n) where 1<=n <= 1073741823 double-byte characters.

  • Precompiled with WCHARTYPE NOCONVERT option

DBCLOB

dbclob_locat or

  • Identifies DBCLOB entities residing on the server

  • Precompiled with WCHARTYPE NOCONVER option

DBCLOB

dbclob_file

  • Descriptor for file containing DBCLOB data

  • Precompiled with WCHARTYPE NOCONVERT option

external data

Datalink(n)

n+54

  • The length of a DATALINK column is 200 bytes

For more information, see the SQL Referencevol 1, SC09-4844; vol 2 - SC09-4845, the Application Development Guide, and the file that is supplied on DB2 clients: sqllib\include\sql.h


Supported SQL data types in Java

Table 9-6 shows the Java equivalent of each SQL data type, based on the JDBC specification for data type mappings. The JDBC driver converts the data exchanged between the application and the database using the following mapping schema. Use these mappings in your Java applications and your PARAMETER STYLE JAVA procedures and UDFs.

Table 9-6: SQL data types mapped to Java declarations
 | SQL data type sqltype | Java type | sqllen | Description
integer | SMALLINT (500 or 501) | short | 2 | 16-bit, signed integer
 | INTEGER (496 or 497) | int | 4 | 32-bit, signed integer
 | BIGINT 1 (492 or 493) | long | 8 | 64-bit, signed integer
floating point | REAL (480 or 481) | float |  | Single precision floating point
 | DOUBLE (480 or 481) | double | 4 | Single precision floating point
 | DOUBLE (480 or 481) | double | 8 | Double precision floating point
decimal | DECIMAL(p,s) (484 or 485) | java.math. BigDecimal | n/2 | Packed decimal
date / time | DATE (384 or 385) | java.sql.Date | 10 | 10-byte character string
 | TIME (388 or 389) | java.sql.Time | 8 | 8-byte character string
 | TIMESTAMP (392 or 393) | java.sql. Timestamp | 26 | 26-byte character string
character | CHAR (452 or 453) | java.lang.String | n | Fixed-length character string of length n where n is from 1 to 254
 | CHAR FOR BIT DATA | byte[] |  | Fixed-length character string of length n where n is from 1 to 254
 | VARCHAR (448 or 449) | java.lang.String | n | Variable-length character string, n <= 32672
 | VARCHAR FOR BIT DATA | byte[] |  | Variable-length character string
 | LONG VARCHAR (456 or 457) | java.lang.String | n | Long variable-length character string, n <= 32672
 | CLOB(n) (408 or 409) | java.lang.Clo b | n | Large object variable-length character string
binary | BLOB(n) (404 or 405) | ava.lang.Blob | n | Large object variable-length binary string
doublebyte | GRAPHIC(n) (468 or 469) | java.lang.String | n | Fixed-length double-byte character string
 | VARGRAPHIC(n) (464 or 465) | java.lang.String | n*2+4 | Non-null-terminated varying double-byte character string with 2-byte string length indicator
 | LONG VARGRAPHIC(n) (472 or 473) | java.lang.String | n | Non-null-terminated varying double-byte character string with 2-byte string length indicator
 | DBCLOB(n) (412 or 413) | java.lang.Clob |  | Large object variable-length double-byte character string
Note

For Java applications connected from a DB2 UDB Version 8.1 client to a DB2 UDB Version 7.x server, when the getObject() method is used to retrieve a BIGINT value, a java.math.BigDecimal object is returned.


Mapping Oracle data types to DB2 UDB data types

Table 9-7 summarizes the mapping from the Oracle data types to corresponding DB2 data types. The mapping is one to many and depends on the actual usage of the data.

Table 9-7: Mapping Oracle data types to DB2 UDB data types

Oracle data type

DB2 data type

Notes

CHAR(n)

CHAR(n)

1 <= n <= 254

VARCHAR2(n)

VARCHAR(n)

n <= 32762

LONG

LONG VARCHAR(n)

if n <= 32700 bytes

LONG

CLOB(2GB)

if n <= 2 GB

NUMBER(p)

SMALLINT / INTEGER / BIGINT

  • SMALLINT, if 1 <= p <= 4

  • INTEGER, if 5 <= p <= 9

  • BIGINT, if 10 <= p <= 18

NUMBER(p,s)

DECIMAL(p,s)

if s > 0

NUMBER

FLOAT / REAL / DOUBLE

RAW(n)

CHAR(n) FOR BIT DATA / VARCHAR(n) FOR BIT DATA BLOB(n)

  • CHAR, if n <= 254

  • VARCHAR, if 254 < n <= 32672

  • BLOB, if 32672 < n <= 2 GB

LONG RAW

LONG VARCHAR(n) FOR BIT DATA / BLOB(n)

  • LONG, if n <= 32700

  • BLOB, if 32700 < n <= 2GB

BLOB

BLOB(n)

if n <= 2 GB

CLOB

CLOB(n)

if n <= 2 GB

NCLOB

DBCLOB(n)

if n <= 2 GB, use DBCLOB(n/2)

DATE

TIMESTAPMP

  • Use Oracle TO_CHAR() function to extract for subsequent DB2 load.

  • Oracle default format is DD-MON-YY

DATE (only the date)

DATE (MM/DD/YYYY)

  • Use Oracle TO_CHAR() function to extract for subsequent DB2 load.

DATE (only the time)

TIME (HH24:MI:SS)

  • Use Oracle TO_CHAR() function to extract for subsequent DB2 load.


Appendix C: Oracle Call Interface (OCI) Mapping

This appendix provides a mapping of the most frequently used Oracle8 OCI calls to the closest DB2 Call Level Interface (CLI) equivalents. Refer to the DB2 Call Level Interface Guide and Reference, Volume 1, SC09-4849, Volume 2, SC09-4850 for details on the CLI calls. Numbers in parentheses refer to the corresponding notes below the tables. N/A means that the OCI call has no equivalent in CLI.

Table 9-8: Connect/initialize/authorize

OCI command

CLI command

OCIInitialize

N/A

OCIEnvInit

SQLAllocHandle ([1])

OCIServerAttach

SQLConnect ([2]), ([3])

OCIServerDetach

SQLDisconnect

OCISessionBegin

N/A ([3])

OCISessionEnd

N/A

OCILogon

SQLConnect ([2])

OCILogoff

SQLDisconnect

[1]SQLAllocHandle is passed the desired handle type: environment, connection, statement, or descriptor.

[2]SQLDriverConnect is an alternative to SQLConnect, providing additional parameters.

[3]OCISessionBegin has no CLI equivalent. To establish multiple database connections in CLI, multiple connection handles must be allocated and OCIServerAttach calls replaced by SQLConnect calls.
Table 9-9: Handles/descriptors

OCI command

CLI command

OCIHandleAlloc

SQLAllocHandle ([1])

OCIHandleFree

SQLFreeHandle

OCIAttrGet

SQLGet__Attr ([4])

OCIParamGet

N/A ([5])

OCIParamSet

N/A ([6])

OCIAttrSet

SQLSet__Attr ([7])

OCIDescriptorAlloc

SQLSetStmtAttr ([5])

OCIDescriptorFree

SQLFreeHandle ([8])

[1]SQLAllocHandle is passed the desired handle type: environment, connection, statement, or descriptor.

[4]OCIAttrGet can be replaced by SQLGetConnectAttr, SQLGetEnvAttr, or SQLGetStmtAttr, depending on the type of handle that the attribute value is wanted for.

[5]5. SQLSetStmtAttr must be called with an Attribute value of SQL_ATTR_APP_PARAM_DESC or SQL_ATTR_APP_ROW_DESC. However, descriptors can be allocated implicitly instead. The function of OCIParamGet is performed by SQLSetStmtAttr (or implicitly).

[6]CLI does not have complex object retrieval (COR) descriptors or handles.

[7]OCIAttrSet can be replaced by SQLSetConnectAttr, SQLSetEnvAttr, or SQLSetStmtAttr, depending on the type of handle for which an attribute value is to be set.

[8]SQLFreeHandle must be called with a HandleType of SQL_HANDLE_DESC (or the connection can be freed).

Table 9-10: Transaction management
OCI command | CLI command
OCITransCommit | SQLEndTran ([9])
OCITransDetach | N/A
OCITransRollback | SQLEndTran ([9])
OCITransStart | N/A
OCITransPrepare | N/A ([10])
OCITransForget | N/A ([10])
[9]SQLEndTran does either a commit or a rollback, depending on the completion type parameter value. [10]There are no CLI calls specifically for two-phase commit, but it is supported (see CLI Guide and Reference, volume 1, SC09-4849, and volume 2, SC09-4850).
Table 9-11: Bind/define/describe

OCI command

CLI command

OCIBindDynamic

SQL__Data ([11])

OCIBindByName

SQLBindParameter

OCIBindByPos

SQLBindParameter

OCIBindObject

N/A ([12])

OCIBindArrayOfStruct

SQLBindParameter ([13])

OCIStmtGetBindInfo

N/A ([14])

OCIDefineArrayOfStruct

N/A ([13])

OCIDefineDynamic

N/A

OCIDefineByPos

SQLBindCol ([15])

OCIDefineObject

N/A ([12])

OCIDescribeAny

(many) ([16])

[11]For piecewise operations there is no direct replacement for OCIBindDynamic, but for inserts, SQLParamData and SQLPutData must be called, and for selects, SQLGetData.

[12]CLI has no special support for user-defined types. CLI treats one as it does the underlying built-in type. In SQL statements the CAST function must be used to convert a parameter with a user-defined type to the corresponding built-in type (or vice-versa). For more information, see the topic "User Defined Types in Predicates" in the CLI Guide and Reference.

[13]To use array inserts, SQLBindParameter must be called. In addition, calls to SQLSetStmtAttr are needed to set attributes SQL_ATTR_PARAMSET_SIZE (array size) and SQL_ATTR_PARAM_BIND_TYPE (row-wise or column-wise binding of parameters). OCIDefineArrayOfStruct calls can be ignored.

[14]No direct equivalent, but SQLDescribeParam is the closest.

[15]To use array fetches, SQLBindCol must be called. In addition, calls to SQLSetStmtAttr are needed to set attributes SQL_ATTR_ROW_ARRAY_SIZE (array size) and SQL_ATTR_ROW_BIND_TYPE (row-wise or column-wise array retrieval).

[16]An OCIDescribeAny call should be replaced by the appropriate call from among SQLColAttribute, SQLColumns, SQLDescribeCol, SQLForeignKeys, SQLGetFunctions, SQLPrimaryKeys, SQLProcedures, SQLProcedureColumns, SQLSpecialColumns, SQLStatistics, SQLTablePrivileges, and SQLTables.

Table 9-12: Prepare/execute/fetch
OCI command | CLI command
OCIStmtPrepare | SQLPrepare
OCIStmtExecute | SQLExecute
OCIStmtFetch | SQLFetch ([17])
[17]SQLFetch fetches a single row. Use SQLFetchScroll to return a rowset; the simplest type of usage is a basic array fetch.
Table 9-13: Miscellaneous

OCI command

CLI command

OCIBreak

SQLCancel

OCIServerVersion

SQLGetInfo ([18])

OCIPasswordChange

N/A

OCIErrorGet

SQLGetDiagRec

OCIStmtGetPieceInfo

SQLGetData ([11])

OCIStmtSetPieceInfo

SQL__Data ([11])

OCILdaToSvcCtx

N/A

OCISvcCtxToLda

N/A

[18]SQLGetInfo provides much more than the server version. One call is needed per type of information wanted.

[11]For piecewise operations there is no direct replacement for OCIBindDynamic, but for inserts, SQLParamData and SQLPutData must be called, and for selects, SQLGetData.


Appendix D: Converter for SQL*Loader

Overview

This appendix contains the converter and generator scripts for the samples in Chapter 8, "Script conversion" on page 261. The scripts are referred to in the text of the book, and in the comments section of each listing contain a short description of their functionalities.

This appendix provides the following converters for the Oracle control files:

  • conv_ctl.pl

  • gen_load_update.pl

You can download the source of the scripts as well at the additional materials link on the IBM Redbooks Internet site. For more information see Appendix G, "Additional material" on page 415.


Converting control files for Oracle SQL*Loader

This Perl script generates a DB2 load command based on an Oracle control file. The script is tested with:

  • GNU Perl v5.8 on Windows 2000

  • GNU Perl v5.6 on AIX 5.1

GNU Perl v5.8.0 on Linux has a known bug with the split function used in function parse_field_list().

Example 9-41: Conversion of Oracle control file to DB2 load command
Start example
#!/usr/bin/perl
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#  Script:      conv_ctl.pl
#  Author:      Stefan Hummel
#  Date:        01/08/2002
#
#  Syntax:      perl conv_ctl.pl -c <controlfile> [options]
#               -t LOAD | INPORT
#               -m INSERT | REPLACE
#               -f ASC | IXF
#
#  Description: Conversion of Oracle control file (*.ctl) to DB2 load file
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

use Text::ParseWords;

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# initialization
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
$infile_name = '';
$table_name  = '';
$mode        = '';
$i           = 0;
$column      = 0;
$delimiter   = ';';
$method      = 'L';

$type     = 'LOAD';
$mode     = 'INSERT';
$filetype = 'ASC';

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# functions
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
sub usage {
  printf("USAGE: perl conv_ctl.pl -c controlfile [options]\n");
  printf("\t-t LOAD | INPORT\n");
  printf("\t-m INSERT | REPLACE\n");
  printf("\t-f IXF | ASC\n");
  exit;
}

sub read_controlfile {
  $delim = '\s+';
  $i     = 1;
  open(CTLFILE, $_[0]);
  @ctl_lines = <CTLFILE>;
  foreach (@ctl_lines) {
     @words = &parse_line($delim, 1, $_);
     foreach (@words) {
        if ($_ ne '","') {
           @parts = split (/([,])/, $_);
           $n = 0;
           foreach (@parts) {
              $array[$i++] = $parts[$n++];
           }
        }
        else {
           $array[$i++] = $_ ;
        }
     }
  }
  $max_line = $i-1;
  close(CTLFILE);
}

sub parse_load {
}

sub parse_data {
}

sub parse_into {
   $i++;
   $i++;
   $table_name = $array[$i];
}

sub parse_characterset {
}

sub parse_infile {
   $i++;
   $infile_name = $array[$i];
}

sub parse_delimiter {
   $i++; $i++; $i++;
   $delimiter = substr($array[$i],1,1);
   $method = 'P';
}

sub set_mode {
   if ('' eq $mode) {
      $mode = $_[0];
   }
}

sub parse_field_list {
   while (")" ne $array[$i]) {
      $column++;
      $i++;
      $field_list[$column][1] = $array[$i];          # 1. column name
      $i++;
      @position = split (/([:()])/, $array[$i]);
      $field_list[$column][2] = $position[2];        # 2. from column
      $field_list[$column][3] = $position[4];        # 3. up to column
      while (("," ne $array[$i]) && (")" ne $array[$i])) {
         $i++;
      }
   }
}

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# main
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# read command parameters
while ($parameter=shift(@ARGV)) {
   if ("-c" eq $parameter) {
      $filename = shift @ARGV;
   }
   elsif ("-t" eq $parameter) {
      $type = shift @ARGV
   }
   elsif ("-m" eq $parameter) {
      $mode = shift @ARGV
   }
   elsif ("-f" eq $parameter) {
      $filetype = shift @ARGV
   };
};
if ('' eq $filename) {
   &usage;
}

# read the control file, save each word in array
&read_controlfile($filename);

# read array and parse commands
$i = 1;
while ($i <= $max_line) {
   if ("LOAD" eq uc($array[$i])) {
      &parse_load($i);
   }
   elsif ("DATA" eq uc($array[$i])) {
      &parse_data;
   }
   elsif ("INTO" eq uc($array[$i])) {
      &parse_into;
   }
   elsif ("CHARACTERSET" eq uc($array[$i])) {
      &parse_characterset;
   }
   elsif ("INFILE" eq uc($array[$i])) {
      &parse_infile;
   }
   elsif ("INSERT" eq uc($array[$i])) {
      &set_mode('INSERT');
   }
   elsif ("APPEND" eq uc($array[$i])) {
      &set_mode('APPEND');
   }
   elsif ("REPLACE" eq uc($array[$i])) {
      &set_mode('REPLACE');
   }
   elsif ("TRUNCATE" eq uc($array[$i])) {
      &set_mode('TRUNCATE');
   }
   elsif ("FIELDS" eq uc($array[$i])) {
      &parse_delimiter;
   }
   elsif ("(" eq uc($array[$i])) {
      &parse_field_list;
   }
   ;
   $i++;
};

# generate DB2 Load File
printf("%s FROM %s of %s\n", $type, $infile_name, $filetype);
if ($method eq 'L') {
   printf("METHOD %s \n\t( ", $method);
   for ($c=1;$c<$column;$c++) {
      if (1 < $c) {
         printf("\n\t ,");
      }
      printf("%s %s", $field_list[$c][2]
                    , $field_list[$c][3]);
   }
   printf(")\n");
};
if ($method eq 'P') {
   printf("MODIFIED BY COLDEL%s \n", $delimiter);
   printf("METHOD %s (", $method);
   for ($c=1;$c<$column;$c++) {
      if (1 < $c) {
         printf(", ");
      }
      printf("%d", $c);
   }
   printf(")\n");
};
printf("%s INTO %s \n\t( ", $mode, $table_name);
for ($c=1;$c<$column;$c++) {
   if (1 < $c) {
      printf("\n\t ,");
   }
   printf("%s", $field_list[$c][1]);
}
printf(" )!\n");
End example


Generation of additional DB2 commands

In Example 9-42 is a sample script to generate DB2 UDB UPDATE commands from Oracle control files.

Example 9-42: Generation of additional DB2 update commands
Start example
#!/usr/bin/perl
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
#  Script:      gen_load_update.pl
#  Author:      Stefan Hummel
#  Date:        07/31/2003
#
#  Syntax:      perl gen_load_update.pl -c <controlfile>
#
#  Description: Generation of additional UPDATE commands for DB2 UDB
#               regarding to an Oracle control file
#
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

use Text::ParseWords;

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# initialization
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
$tablename   = '<missing>';

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# functions
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
sub usage {
  printf("USAGE: perl gen_load_update.pl -c controlfile\n\n");
  exit;
};

sub read_controlfile {
  $delim = '\s+';
  $i     = 1;
  open(CTLFILE, $_[0]);
  @ctl_lines = <CTLFILE>;
  foreach (@ctl_lines) {
     @words = &parse_line($delim, 1, $_);
     foreach (@words) {
        @parts = split (/([,])/, $_);
        $n = 0;
        foreach (@parts) {
           $array[$i++] = $parts[$n++]
        }
     }
  }
  $max_line = $i-1;
  close(CTLFILE);
};

sub current_columnname {
   $x = $_[0] - 1;
   while (('(' ne $array[$x]) && (',' ne $array[$x]) && ($x > 0)) {
      $x--;
   }
   return $array[$x + 1];
};

sub parse_nullif {
   $i++;
   $condition[$c][0] = $tablename;               # tablename
   $condition[$c][1] = &current_columnname($i);  # tablename
   $condition[$c][2] = 'NULL';                   # set condition
   $condition[$c][3] = $array[$i];               # where clause
   $c++;
};

sub parse_defaultif {
   $i++;
   $condition[$c][0] = $tablename;               # tablename
   $condition[$c][1] = &current_columnname($i);  # tablename
   $condition[$c][2] = 'DEFAULT';                # set condition
   $condition[$c][3] = $array[$i];               # where clause
   $c++;
};

sub parse_into {
   $i++;
   $i++;
   $tablename = $array[$i];
};

# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #
# main
# # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

# read the parameters
while ($parameter=shift(@ARGV)) {
   if ("-c" eq $parameter) {
      $filename = shift @ARGV;
   };
};
if ('' eq $filename) {
   &usage;
}

# read the control file, save each word in array
&read_controlfile($filename);

# read array and parse commands
$i = 1;
$c = 1;
while ($i <= $max_line) {
   if ("NULLIF" eq uc($array[$i])) {
      # print "NULLIF !!!"
      &parse_nullif;
   }
   elsif ("DEFAULTIF" eq uc($array[$i])) {
      # print "NULLIF !!!"
      &parse_defaultif;
   }
   elsif ("INTO" eq uc($array[$i])) {
      &parse_into;
   };
   $i++;
};
$max_condition = $c;

# generate DB2 update commend
for ($n=1;$n<$max_condition;$n++) {
   printf("UPDATE %s\n"     ,$condition[$n][0]);
   printf("SET %s=%s\n"     ,$condition[$n][1]
                            ,$condition[$n][2]);
   printf("WHERE %s\);\n\n" ,$condition[$n][3]);
};
End example


Appendix E: Terminology Mapping

This appendix contains the terminology mapping of Oracle to DB2 UDB.

Table 9-14: Oracle Terminology to DB2 UDB mapping
Oracle | DB2 UDB | Comments
Oracle EE | DB2 UDB ESE | Enterprise product
Oracle Parallel | DB2 UDB ESE DPF | Support node partitioning
Oracle Gateway | DB2 Connect | DRDA access to hosts
PL/SQL | SQL Procedural Language | Programming language extension to SQL. DB2 UDB stored procedures can be programmed in SQL Control Statements (subset of PSM standard), Java, C, C++, COBOL, Fortran, OLE, and REXX. DB2 functions can be programmed in Java, C, C++, OLE, or SQL control statements.
SQL*PLUS | DB2 CLP | Command line interface to the server
Instance | Instance | Processes and shared memory. In DB2 it also includes a permanent directory structure: an instance is usually created at install time (or can be later) and must exist before a database can be created. A DB2 instance is also known as the database manager (DBM). A DB2 UDB instance can have multiple databases. But an Oracle instance can only have one database.
Database | Database | Physical structure containing data. In Oracle, multiple instances can use the same database, and an instance can connect to one and only one database. In DB2, multiple databases can be created and used concurrently in the same instance.
Control files and .ora files | DBM and database configuration files, etc. | In Oracle, files that name the locations of files making up the database and provide configuration values. In DB2, each instance (DBM) and database has its own set of configuration parameters stored in a binary file; there are also other internal files and directories: none is manually edited.
Database Link | Federated System | In Oracle, an object that describes a path from one database to another. In DB2 a federated system is used. One database is chosen as the federated database and within it wrappers, servers, nicknames, and other optional objects are created to define how to access the other databases (including Oracle databases) and objects in them. Once an application is connected to the federated database it can access all authorized objects in the federated system.
Table spaces | Table spaces | Contains actual database data
Datafiles | Containers | Entities inside the table spaces
Segments | Objects | Entities inside the containers/data files
Extents | Extents | Entities inside the objects/segments
Data blocks | Pages | Smallest storage entity in the storage model
Clusters | N/A | Data structure that allows related data to be stored together on disk; can be table or hash clusters. The closest facility to this in DB2 is a clustering index, which causes rows inserted into a table to be placed physically close to the rows for which the key values of this index are in the same range.
Data dictionary | System catalog | Metadata of the database
N/A | SMS | System-managed table space
Datafiles | DMS containers | The file and raw devices under Database-managed table space.
Data cache | Buffer pools | Buffers data in the table spaces to reduce disk I/O
Statement cache | Package cache | Caches prepared dynamic SQL statements
Redo logs | Log files | Recovery logs
Rollback segments | N/A | Store the old version of data for a mutating table. In DB2 the old version of an updated row is stored in the log file along with the new version.
SGA | Database manager and database shared memory | Shared memory area(s) for the database server. In Oracle there is one, while in DB2 there is one at the database manager (instance) level any one for each active database.
UGA | Agent / application shared memory | Shared memory area to store user-specific data passed between application process and the database server.
N/A | Package | A precompiled access plan for an embedded static SQL application stored in the server.
Package | N/A | A logical grouping of PL/SQL blocks that can be invoked by other PL/SQL applications.


Appendix F: Example Oracle Database

This appendix contains the definitions of tables, views, triggers, and procedures of the Oracle database ORA_EMP used in this redbook. The complete source code can be downloaded from the IBM Redbooks Web site. Please refer to Appendix G, "Additional material" on page 415 for the details.

Table definition

There are nine tables in ORA_EMP database. The table definitions are:

CREATE TABLE accounts (
   acct_id           NUMBER(3) NOT NULL,
   dept_code         CHAR(3) NOT NULL,
   acct_desc         VARCHAR2(2000),
   max_employees     NUMBER(3),
   current_employees NUMBER(3),
   num_projects      NUMBER(1))
TABLESPACE user_data_tbs;
ALTER TABLE ACCOUNTS ADD (CONSTRAINT ACCOUNTS_DEPT_CODE_ACCT_ID PRIMARY KEY (
DEPT_CODE, ACCT_ID));

CREATE TABLE connect_audit (
   user_name VARCHAR2(30),
   operation VARCHAR2(30),
TABLESPACE user_data_tbs;

CREATE TABLE debug_table (
   linecount NUMBER NOT NULL,
   debug_str VARCHAR2(200))
TABLESPACE user_data_tbs;
ALTER TABLE DEBUG_TABLE ADD ( CONSTRAINT pk_debug_lineout PRIMARY KEY (
LINECOUNT ));

CREATE TABLE departments (
   dept_code       CHAR(3) NOT NULL,
   dept_name       VARCHAR2(30),
   total_projects  NUMBER,
   total_employees NUMBER)
TABLESPACE user_data_tbs;
ALTER TABLE departments ADD ( CONSTRAINT pk_dept_code PRIMARY KEY ( dept_code
));

CREATE TABLE destination (
   key   NUMBER(5),
   value NUMBER)
TABLESPACE user_data_tbs;

CREATE TABLE employees (
   emp_id             NUMBER(5) NOT NULL,
   first_name         VARCHAR2(20),
   last_name          VARCHAR2(20),
   department         VARCHAR2(30),
   current_projects   NUMBER(3),
   emp_mgr_id         NUMBER(5),
   dept_code          CHAR(3) NOT NULL,
   acct_id            NUMBER(3) NOT NULL,
   office_id          NUMBER(5),
   band               CHAR(1))
TABLESPACE user_data_tbs;
ALTER TABLE employees ADD ( CONSTRAINT pk_employees_emp_id PRIMARY KEY ( emp_id
));

CREATE TABLE emp_photo (
   emp_id          NUMBER(5) NOT NULL,
   photo_format    VARCHAR2(10) NOT NULL,
   picture         BLOB)
TABLESPACE user_data_tbs;
ALTER TABLE EMP_PHOTO ADD ( CONSTRAINT EMP_PHOTO_PK11058611148823 PRIMARY KEY (
emp_id ));

CREATE TABLE emp_resume (
   emp_id          NUMBER(5) NOT NULL,
   resume_format   VARCHAR2(10),
   resume          CLOB)
TABLESPACE user_data_tbs;
ALTER TABLE EMP_RESUME ADD ( CONSTRAINT EMP_RESUME_UK11058551798461 UNIQUE (
emp_id ));

CREATE TABLE log_table (
   code     NUMBER,
   message  VARCHAR2(200),
   info     VARCHAR2(100))
TABLESPACE user_data_tbs;

CREATE TABLE manager_audit (
   change_type        CHAR(1) NOT NULL,
   changed_by         VARCHAR2(8) NOT NULL,
   timestamp          DATE NOT NULL,
   old_employee_id    NUMBER(5),
   old_dept_code      CHAR(3),
   old_acct_id        NUMBER(3),
   old_band           CHAR(1),
   new_employee_id    NUMBER(5),
   new_dept_code      CHAR(3),
   new_acct_id        NUMBER(3),
   new_band           CHAR(1))
TABLESPACE user_data_tbs;

CREATE TABLE offices (
   office_id         NUMBER(5) NOT NULL,
   building          VARCHAR2(15),
   office_number     NUMBER(4),
   number_seats      NUMBER(4),
   description       VARCHAR2(50))
TABLESPACE user_data_tbs;
ALTER TABLE OFFICES ADD ( CONSTRAINT pk_offices_office_id PRIMARY KEY (
OFFICE_ID ));

CREATE TABLE source (
   key     NUMBER(5) NOT NULL PRIMARY KEY,
   value   VARCHAR2(50))
ORGANIZATION INDEX
TABLESPACE user_data_tbs;

CREATE TABLE temp_table (
   num_col   NUMBER,
   char_col  VARCHAR2(60))
TABLESPACE user_data_tbs;


View definition

There are two views in the ORA_EMP database:

CREATE VIEW employees_offices
  (dept_code,
   acct_id,
   building,
   office_id) AS
  SELECT dept_code,
         acct_id,
         building,
         offices.office_id
  FROM offices,
       employees
  WHERE offices.office_id = employees.office_id;

REATE VIEW office_summary
  (building,
   total_seats) AS
   SELECT building,
          sum(number_seats) total_seats
   FROM offices
   GROUP BY building;


Indexes

There are four indexes in the ORA_EMP database:

-- type:    normal
CREATE INDEX ind_acct_id
ON accounts ( acct_id )
STORAGE ( MAXEXTENTS UNLIMITED BUFFER_POOL KEEP)
TABLESPACE user_ind_tbs;

CREATE INDEX ind_dept_name
ON departments ( dept_name )
TABLESPACE user_ind_tbs;

CREATE INDEX ind_emp_name
ON employees ( last_name )
TABLESPACE user_ind_tbs;

CREATE INDEX ind_log_code
ON log_table ( code )
TABLESPACE user_ind_tbs;

CREATE INDEX ind_office_bld
ON offices ( building )
TABLESPACE user_ind_tbs
REVERSE;

-- table:   debug_table
-- type:    bitmap index
CREATE BITMAP INDEX bm_ind_debug_str
ON debug_table (debug_str)
TABLESPACE user_ind_tbs;

-- table:   accounts
-- type:    function based index
CREATE INDEX fb_ind_account_rate
ON accounts (current_employees / max_employees)
TABLESPACE user_ind_tbs;


Foreign keys

There are six foreign keys in ORA_EMP database:

ALTER TABLE ACCOUNTS
  ADD CONSTRAINT fk_acc_dept_code
  FOREIGN KEY (dept_code)
  REFERENCES departments (dept_code);

ALTER TABLE emp_photo
  ADD CONSTRAINT fk_emp_photo_id
  FOREIGN KEY (emp_id)
  REFERENCES employees (emp_id)
  ON DELETE CASCADE;

ALTER TABLE emp_resume
  ADD CONSTRAINT fk_emp_resume_id
  FOREIGN KEY (emp_id)
  REFERENCES employees (emp_id)
  ON DELETE CASCADE;

ALTER TABLE employees
  ADD CONSTRAINT fk_emp_mgr_id
  FOREIGN KEY (emp_mgr_id)
  REFERENCES employees (emp_id);
ALTER TABLE employees
  ADD CONSTRAINT fk_emp_office_id
  FOREIGN KEY (office_id)
  REFERENCES offices (office_id);

ALTER TABLE employees
  ADD CONSTRAINT m_dept_code_acct_id
  FOREIGN KEY (DEPT_CODE,ACCT_ID)
  REFERENCES ACCOUNTS (DEPT_CODE,ACCT_ID);

ALTER TABLE employees
  ADD CONSTRAINT m_band
  CHECK (band IN ('1', '2', '3', '4', '5'));


Functions

There are three function keys in the ORA_EMP database:

CREATE OR REPLACE FUNCTION AccountFull (
 p_dept_code accounts.dept_code%TYPE,
 p_acct_id     accounts.acct_id%TYPE)
RETURN BOOLEAN IS
 v_CurrentEmployees NUMBER;
 v_MaxEmployees     NUMBER;
 v_ReturnValue     BOOLEAN;
 v_FullPercent     CONSTANT NUMBER := 90;

BEGIN

 -- Get the current and maximum employees for the requested
 -- acct_id.

 SELECT current_employees, max_employees
 INTO   v_CurrentEmployees, v_MaxEmployees
 FROM   accounts
 WHERE dept_code = p_dept_code
   AND acct_id = p_acct_id;

 -- If the account is more full than the percentage given by
 -- v_FullPercent, return TRUE. Otherwise, return FALSE.

 IF (v_CurrentEmployees / v_MaxEmployees * 100) > v_FullPercent
  THEN
    v_ReturnValue := TRUE;
 ELSE
    v_ReturnValue := FALSE;
 END IF;
  RETURN v_ReturnValue;
 END AccountFull;

 CREATE OR REPLACE FUNCTION AVERAGEBAND (
  p_Department IN employees.department%TYPE,
  p_ACCT_ID IN employees.ACCT_ID%TYPE)
 RETURN CHAR AS
   v_AverageBAND CHAR(1);
   v_NumericBAND NUMBER;
  v_NumberEmployees NUMBER;

 BEGIN

 /* First we need to see how many employees there are for
    this account. If there aren't any, we need to raise an error. */

  SELECT COUNT(*)
    INTO v_NumberEmployees
    FROM employees
    WHERE department = p_Department
      AND acct_id = p_ACCT_ID;

  IF v_NumberEmployees = 0 THEN
    RAISE_APPLICATION_ERROR(-20001, 'No employees exist for ' ||
      p_Department || ' ' || p_ACCT_ID);
  END IF;

  /* Since bands are stored as letters, we can't use the AVG
     function directly on them. Instead, we can use the DECODE
     function to convert the bands to numeric values,
     and take the average of those. */

  SELECT AVG(DECODE(band, '1', 1,
                          '2', 2,
                          '3', 3,
                           '4', 4,
                          '5', 5))
     INTO v_NumericBAND
    FROM employees
    WHERE department = p_Department
    AND acct_id = p_ACCT_ID;

  /* v_NumericBAND now contains the average band, as a number from
     1 to 5. We need to convert this back into a letter. The DECODE
     function can be used here as well. Note that we are SELECTing
      the result into v_AverageBand rather than assigning to it,
     because the DECODE function is only legal in an SQL statement. */
  SELECT DECODE(ROUND(v_NumericBAND), 5, 'A',
                                      4, 'B',
                                      3, 'C',
                                      2, 'D',
                                      1, 'E')
    INTO v_AverageBand FROM dual;

  RETURN v_AverageBand;
 END AverageBand;

 CREATE OR REPLACE FUNCTION COUNTPROJECTS   (
  /* Returns the number of projects in which the employee
     identified by p_emp_ID is currently engaged */
  p_empID IN employees.emp_ID%TYPE)
 RETURN NUMBER AS

  v_TotalProjects NUMBER;
   -- Total number of projects
   v_AccountProjects NUMBER;
   -- projects for one account

   CURSOR c_DeptAccts IS
      SELECT dept_code, acct_id
       FROM employees
       WHERE emp_id = p_empID;

  BEGIN
   FOR v_AccountRec IN c_DeptAccts LOOP
     -- Determine the projects for this account.

     SELECT num_projects
        INTO v_AccountProjects
       FROM accounts
       WHERE dept_code = v_AccountRec.dept_code
       AND acct_id = v_AccountRec.acct_id;

     -- Add it to the total so far.
     v_Totalprojects := v_Totalprojects + v_AccountProjects;
   END LOOP;

   RETURN v_Totalprojects;
  ND CountProjects;

  CREATE OR REPLACE FUNCTION MAXPROJECTS
       (p_dept_code IN employees.dept_code%TYPE)
   RETURN NUMBER
  IS
   CURSOR projcur IS
      SELECT MAX(current_projects) maxprojects
       FROM employees
      WHERE p_dept_code = dept_code;
    projrec projcur%ROWTYPE;

  BEGIN
   OPEN projcur;
    FETCH projcur INTO projrec;
   RETURN projrec.maxprojects;
 END maxprojects;
 /


Packages

There are three package procedures in the ORA_EMP database:

CREATE OR REPLACE PACKAGE AccountPackage AS
 -- Add a new Employee into the specified Account.
 PROCEDURE AddEmployee(p_EmployeeID  IN Employees.emp_id%TYPE,
                      p_dept_code IN accounts.dept_code%TYPE,
                      p_acct_id     IN accounts.acct_id%TYPE);
 -- Removes the specified Employee from the specified Account.
 PROCEDURE RemoveEmployee(p_EmployeeID  IN Employees.emp_id%TYPE,
                          p_dept_code IN accounts.dept_code%TYPE,
                          p_acct_id     IN accounts.acct_id%TYPE);
 PROCEDURE AccountList(p_dept_code  IN  accounts.dept_code%TYPE,
                        p_acct_id      IN accounts.acct_id%TYPE,
                        p_NumEmployees OUT NUMBER);

 END AccountPackage;

 CREATE OR REPLACE PACKAGE BODY AccountPackage AS
 -- Add a new Employee for the specified account.
 PROCEDURE AddEmployee(p_EmployeeID  IN Employees.emp_id%TYPE,
                       p_dept_code IN accounts.dept_code%TYPE,
                       p_acct_id     IN accounts.acct_id%TYPE) IS
 BEGIN
   INSERT INTO Employees (Emp_id, dept_code, acct_id)
     VALUES (p_EmployeeID, p_dept_code, p_acct_id);
   COMMIT;
 END AddEmployee;
 -- Removes the specified Employee from the specified account.
 PROCEDURE RemoveEmployee(p_EmployeeID  IN Employees.emp_id%TYPE,
                          p_dept_code IN accounts.dept_code%TYPE,
                          p_acct_id IN accounts.acct_id%TYPE) IS
  e_EmployeeNotRegistered EXCEPTION;
 BEGIN
    DELETE FROM Employees
     WHERE Emp_id = p_EmployeeID
     AND dept_code = p_dept_code
     AND acct_id = p_acct_id;
   -- Check to see if the DELETE operation was successful. If
   -- it didn't match any rows, raise an error.
   IF SQL%NOTFOUND THEN
     RAISE e_EmployeeNotRegistered;
   END IF;
   COMMIT;
 END RemoveEmployee;
  PROCEDURE AccountList(p_dept_code  IN  accounts.dept_code%TYPE,
                         p_acct_id      IN  accounts.acct_id%TYPE,
                         p_NumEmployees OUT NUMBER) IS
      v_EmployeeID  Employees.Emp_id%TYPE;
      -- Local cursor to fetch the registered Employees.
      CURSOR c_RegisteredEmployees IS
        SELECT Emp_id
          FROM Employees
          WHERE dept_code = p_dept_code
          AND acct_id = p_acct_id;
    BEGIN
      /* p_NumEmployees will be the table index. It will start at
         0, and be incremented each time through the fetch loop.
         At the end of the loop, it will have the number of rows
         fetched, and therefore the number of rows returned in
         p_IDs. */
      p_NumEmployees := 0;
      OPEN c_RegisteredEmployees;
      LOOP
        FETCH c_RegisteredEmployees INTO v_EmployeeID;
        EXIT WHEN c_RegisteredEmployees%NOTFOUND;
        p_NumEmployees := p_NumEmployees + 1;
      END LOOP;
  END AccountList;
END AccountPackage;

CREATE OR REPLACE PACKAGE
            "REFPKG" AS
  TYPE RCT1 IS REF CURSOR;
END REFPKG;
/


Procedures

There are five procedures in the ORA_EMP database:

CREATE OR REPLACE PROCEDURE AddNewEmployee (
   p_FirstName  employees.first_name%TYPE,
   p_LastName   employees.last_name%TYPE,
   p_Department     employees.department%TYPE) AS
BEGIN
 -- Insert a new row in the employees table. Use
 -- employee_sequence to generate the new employee ID, and
 -- 0 for current_projects.

 INSERT INTO employees (emp_id, first_name, last_name,
                       department, current_projects)
   VALUES (employee_sequence.nextval, p_FirstName, p_LastName,
           p_Department, 0);
  COMMIT;
END AddNewEmployee;

CREATE OR REPLACE PROCEDURE Assign (
 /* Promotes the employee identified by the p_EmployeeID parameter in the
   account identified by the p_Dept_code and p_AcctId parameters. Before
   calling AccountPackage.AddEmployee, which actually adds the employee to the
   account, this procedure verifies that there is room in the account, and that
   the account exists. */

 p_EmployeeID IN employees.emp_id%TYPE,
 p_Dept_code IN accounts.dept_code%TYPE,
 p_AcctId IN accounts.acct_id%TYPE) AS

  v_CurrentEmployees NUMBER;
  -- Current number of empoloyees in the account
  v_MaxEmployees NUMBER;
  -- Maximum number of employees in the account

BEGIN

 /* Determine the current number of employees registered, and the maximum
    number of employees allowed to be hired for this dept. */

 SELECT current_employees, max_employees
   INTO v_CurrentEmployees, v_MaxEmployees
    FROM accounts
   WHERE acct_id = p_AcctId
   AND dept_code = p_Dept_code;
  /* Make sure there is enough room for this additional employees. */
  IF v_CurrentEmployees + 1 > v_MaxEmployees THEN

   RAISE_APPLICATION_ERROR(-20000, 'Can''t assign more employees to ' ||
     p_Dept_code || ' ' || p_AcctId);
  END IF;

  /* Add the employee to the account. */

 AccountPackage.AddEmployee(p_EmployeeID, p_Dept_code, p_AcctId);
EXCEPTION
  WHEN NO_DATA_FOUND THEN

   /* Account information passed to this procedure doesn't exist. Raise an
      error to let the calling program know of this. */

   RAISE_APPLICATION_ERROR(-20001, p_Dept_code || ' ' || p_AcctId ||
     ' doesn''t exist!');

END Assign;

CREATE OR REPLACE PROCEDURE EMPLOYEEDYNAMICQUERY  (
 /* Uses DBMS_SQL to query the employees table, and puts the
  * results in temp_table. The first names, last names, and
  * majors are inserted for up to two majors inputted. */

 p_department1 IN employees.department%TYPE DEFAULT NULL,
 p_department2 IN employees.department%TYPE DEFAULT NULL) AS

 v_CursorID   INTEGER;
 v_SelectStmt VARCHAR2(500);
 v_FirstName  employees.first_name%TYPE;
 v_LastName   employees.last_name%TYPE;
 v_Department employees.department%TYPE;
 v_Dummy      INTEGER;

BEGIN
 -- Open the cursor for processing.
 v_CursorID := DBMS_SQL.OPEN_CURSOR;

  -- Create the query string.
  v_SelectStmt := 'SELECT first_name, last_name, department
                    FROM employees
                    WHERE department IN (:d1, :d2)
                    ORDER BY v_Department, last_name';
  -- Parse the query.
 DBMS_SQL.PARSE(v_CursorID, v_SelectStmt, DBMS_SQL.NATIVE);

  -- Bind the input variables.
  DBMS_SQL.BIND_VARIABLE(v_CursorID, ':d1', p_department1);
  DBMS_SQL.BIND_VARIABLE(v_CursorID, ':d2', p_department2);

  -- Define the select list items.
 DBMS_SQL.DEFINE_COLUMN(v_CursorID, 1, v_FirstName, 20);
 DBMS_SQL.DEFINE_COLUMN(v_CursorID, 2, v_LastName, 20);
 DBMS_SQL.DEFINE_COLUMN(v_CursorID, 3, v_Department, 30);

  -- Execute the statement. We don't care about the return
  -- value, but we do need to declare a variable for it.

 v_Dummy := DBMS_SQL.EXECUTE(v_CursorID);
  -- This is the fetch loop.
  LOOP
   -- Fetch the rows into the buffer, and also check for the exit
   -- condition from the loop.

   IF DBMS_SQL.FETCH_ROWS(v_CursorID) = 0 THEN
     EXIT;
   END IF;

    -- Retrieve the rows from the buffer into PL/SQL variables.
   DBMS_SQL.COLUMN_VALUE(v_CursorID, 1, v_FirstName);
   DBMS_SQL.COLUMN_VALUE(v_CursorID, 2, v_LastName);
   DBMS_SQL.COLUMN_VALUE(v_CursorID, 3, v_Department);

    -- Insert the fetched data into temp_table.
   INSERT INTO temp_table (char_col)
     VALUES (v_FirstName || ' ' || v_LastName || ' is a ' ||
             v_Department || ' department.');
  END LOOP;

  -- Close the cursor.
  DBMS_SQL.CLOSE_CURSOR(v_CursorID);

  -- Commit our work.
 COMMIT;

EXCEPTION
  WHEN OTHERS THEN
   -- Close the cursor, then raise the error again.
   DBMS_SQL.CLOSE_CURSOR(v_CursorID);
    RAISE;

END EmployeeDynamicQuery;
/

CREATE OR REPLACE PROCEDURE SELECTROW
    (
       pEmp_ID IN EMPLOYEES.EMP_ID%TYPE,
        pRow OUT REFPKG.RCT1
    )
   IS
    BEGIN
       OPEN pRow FOR
       SELECT FIRST_NAME, LAST_NAME, DEPARTMENT, BAND
       FROM EMPLOYEES
       WHERE Emp_ID = Emp_ID;
   END;

CREATE OR REPLACE PROCEDURE ShowFullAccounts AS
 CURSOR c_Accounts IS
   SELECT dept_code, acct_id FROM Accounts;
BEGIN
 FOR v_AccountRecord IN c_Accounts  LOOP
   -- Record all Accounts which don't have very much room left
   -- in temp_table.

   IF AccountFull(v_AccountRecord.dept_code, v_AccountRecord.acct_id) THEN
     INSERT INTO temp_table (char_col) VALUES
       (v_AccountRecord.dept_code || ' ' || v_AccountRecord.acct_id ||
        ' is almost full!');
   END IF;
 END LOOP;
END ShowFullAccounts;


Triggers

There are seven trigger foreign keys in the ORA_EMP database:

CREATE TRIGGER CreateEmployeeID
  BEFORE INSERT ON employees
  FOR EACH ROW
BEGIN
  /* Fill in the emp_id field of employees with the next value from
     employee_sequence. Since emp_id is a column in employees, :new.emp_id
     is a valid reference. */
  SELECT employee_sequence.nextval
    INTO :new.emp_id
    FROM dual;
END CreateEmployeeID;
/
CREATE TRIGGER EmployeesOfficesInsert
  INSTEAD OF INSERT ON employees_offices
DECLARE
  v_office_ID offices.office_id%TYPE;
BEGIN
  -- First determine the office ID
  SELECT office_id
    INTO v_office_ID
    FROM offices
    WHERE building = :new.building
    AND office_id = :new.office_id;
  -- And now update the account
  UPDATE employees
    SET office_id = v_office_ID
    WHERE dept_code = :new.dept_code
    AND acct_id = :new.acct_id;
END EmployeesOfficesInsert;
/

CREATE TRIGGER InsertEmployee
  BEFORE INSERT ON employees
  FOR EACH ROW
DECLARE
  v_num_projects accounts.num_projects%TYPE;
BEGIN
  SELECT num_projects
    INTO v_num_projects
    FROM accounts
    WHERE dept_code = :new.dept_code
    AND acct_id = :new.acct_id;

  :new.current_projects := v_num_projects;

  UPDATE accounts
    SET current_employees = current_employees + 1
    WHERE dept_code = :new.dept_code
    AND acct_id = :new.acct_id;
END InsertEmployees;
/

CREATE TRIGGER ManagersChange
  BEFORE INSERT OR DELETE OR UPDATE ON Employees
  FOR EACH ROW
DECLARE
  v_ChangeType CHAR(1);
BEGIN
  /* Use 'I' for an INSERT, 'D' for DELETE, and 'U' for UPDATE. */
  IF INSERTING THEN
    v_ChangeType := 'I';
  ELSIF UPDATING THEN
    v_ChangeType := 'U';
  ELSE
    v_ChangeType := 'D';
  END IF;
  /* Record all the changes made to managers in
     managers_audit. Use SYSDATE to generate the timestamp, and
     USER to return the userid of the current user. */
  INSERT INTO manager_audit
    (change_type, changed_by, timestamp,
     old_employee_id, old_dept_code, old_acct_id, old_band,
     new_employee_id, new_dept_code, new_acct_id, new_band)
  VALUES
    (v_ChangeType, USER, SYSDATE,
     :old.emp_mgr_id, :old.dept_code, :old.acct_id, :old.band,
     :new.emp_mgr_id, :new.dept_code, :new.acct_id, :new.band);
END ManagersChange;
/

CREATE TRIGGER office_summary_delete
  INSTEAD OF DELETE ON office_summary
  FOR EACH ROW
BEGIN
  -- Delete all of the rows in rooms which match this single row
  -- in room_summary
  DELETE FROM offices
    WHERE building = :old.building;
END office_summary_delete;
/

CREATE TRIGGER UpdateDepartments
AFTER INSERT OR DELETE OR UPDATE ON employees
DECLARE
  CURSOR c_projects IS
    SELECT  dept_code
           ,COUNT(*) AS total_employees
           ,SUM(current_projects) AS total_projects
      FROM employees
      GROUP BY dept_code;
BEGIN
  FOR v_project_rec in c_projects LOOP
     UPDATE departments
     SET  total_projects  = v_project_rec.total_projects
         ,total_employees = v_project_rec.total_employees
     WHERE dept_code = v_project_rec.dept_code;
  END LOOP;
END UpdateDepartments;
/

CREATE TRIGGER UpdateEmployees
  BEFORE INSERT OR UPDATE ON employees
  FOR EACH ROW
DECLARE
   v_dept_name  departments.dept_name%TYPE;
   v_dept_code  departments.dept_code%TYPE;
BEGIN
   v_dept_code := :NEW.dept_code;
   SELECT dept_name
     INTO v_dept_name
     FROM departments
     WHERE dept_code = v_dept_code;
   :NEW.department := v_dept_name;
END UpdateEmployees;
/

ALTER TABLE accounts ADD (
   CONSTRAINT fk_acc_dept_code
   FOREIGN KEY ( dept_code )
   REFERENCES departments (dept_code));

CREATE INDEX ind_acct_id
   ON accounts (acct_id)
   TABLESPACE users;

CREATE INDEX ind_dept_name
   ON departments (dept_name)
   TABLESPACE users;


Appendix G: Additional Material

This redbook refers to additional material that can be downloaded from the Internet as described below.

Locating the Web material

The Web material associated with this redbook is available in softcopy on the Internet from the IBM Redbooks Web server. Point your Web browser to:

  • ftp://www.redbooks.ibm.com/redbooks/SG247048

Alternatively, you can go to the IBM Redbooks Web site at:

  • ibm.com/redbooks

Select the Additional materials and open the directory that corresponds with the redbook form number, SG24-7048.


Using the Web material

The additional Web material that accompanies this redbook includes the following files:

convert_load.zip | Perl scripts to convert Oracle control files. Includes: conv_ctl.pl gen_load_update.pl
data_unload.zip | Shell scripts to unload data from Oracle tables. Includes: data_unload.sh count.awk desc.awk
db2_emp.zip | Scrips to create DB2 UDB example database. Includes: crtdb.sql - create database crttbs.sql - create tablespaces
db2bkp.sh | Script to backup DB2 example database
exp.sh | Script to export Oracle logical DB
export_table.zip | Sample stored procedure to unload Oracle data. Includes: export_table.sql
hierarch_query.zip | DB2 UDB functions for recursive SQL. Includes: hierachical_query.fnc
put_line.zip | Zipped User-define function samples to enable file output from pure SQL for AIX, HP, Linux, Sun Solaris and Windows. Includes: put_lin_readme.pdf put_line_aix.db2v72.tar.Z put_line_aix.db2v81.tar.Z put_line_hpux.db2v72.tar.Z put_line_solaris.db2v72.tar.Z put_line_linux.db2v72.tar.Z put_lin_w2k.ZIP
ora_emp.zip | Scrips to create Oracle example database. Includes: 01_ora_emp_create_tbs.sql 02_ora_emp_create_user.sql 10_ora_emp_build_all.sql 11_ora_emp_seq.sql 12_ora_emp_tables.sql 13_ora_emp_fk.sql 14_ora_emp_views.sql 15_ora_emp_proc.sql 16_ora_emp_trigger.sql 17_ora_emp_indexes.sql 21_ora_emp_drop_fk.sql 22_ora_emp_drop_trigger.sql 23_ora_emp_drop_tables.sql 24_ora_emp_drop_indexes.sql accounts.ctl accounts.dat db2_emp.zip departments.ctl departments.dat employees.ctl employees.dat emp_photo.ctl emp_photo.dat emp_resume.ctl emp_resume.dat offices.ctl offices.dat readme.txt

System requirements for downloading the Web material

The following system configuration is recommended:

Hard disk space: | 5 MB minimum
Operating System: | Windows 2000
Processor: | Intel 386 or higher
Memory: | 16 MB

To download to AIX Linux or UNIX, use the equivalent or higher system capacity as specified for Windows

How to use the Web material

Create a subdirectory (folder) on your workstation, and unzip the contents of the Web material zip file into this folder. Ftp to the proper platform.


Previous Section
< Day Day Up >
Next Section

Related Publications

The publications listed in this section are considered particularly suitable for a more detailed discussion of the topics covered in this redbook.

IBM Redbooks

For information on ordering these publications, see "How to get IBM Redbooks" on page 421. Note that some of the documents referenced here may be available in softcopy only.

  • DB2 UDB Exploitation of the Windows Environment, SG24-6893

  • Up and Running with DB2 for Linux, SG24-6899

  • DB2 UDB Evaluation Guide for Linux and Windows, SG24-6934

  • Scaling DB2 UDB on Windows Server 2003, SG24-7019


Other publications

These publications are also relevant as further information sources:

  • IBM DB2 Universal Database Command Reference, SC09-4828

  • IBM DB2 Universal Database What's New, SC09-4848

  • IBM DB2 Universal Database Administration Guide: Planning, SC09-4822

  • IBM DB2 Universal Database Administration Guide: Implementation, SC09-4820

  • IBM DB2 Universal Database Administration Guide: Performance, SC09-4821

  • IBM DB2 Universal Database Data Movement Utilities Guide and Reference, SC09-4830

  • IBM DB2 Universal Database Data Recovery and High Availability Guide and Reference, SC09-4831

  • IBM DB2 Universal Database Federated Systems Guide, GC27-1224

  • IBM DB2 Universal Database Guide to GUI Tools for Administration and Development, SC09-4851

  • IBM DB2 Universal Database SQL Reference, Volume 1, SC09-4844

  • IBM DB2 Universal Database SQL Reference, Volume 2, SC09-4845

  • IBM DB2 Universal Database System Monitor Guide and Reference, SC09-4847

  • IBM DB2 Universal Database Application Development Guide: Building and Running Applications, SC09-4825

  • IBM DB2 Universal Database Application Development Guide: Programming Client Applications, SC09-4826

  • IBM DB2 Universal Database Application Development Guide: Programming Server Applications, SC09-4827

  • IBM DB2 Universal Database Call Level Interface Guide and Reference, Volume 1, SC09-4849

  • IBM DB2 Universal Database Call Level Interface Guide and Reference, Volume 2, SC09-4850

  • IBM DB2 Universal Database Data Warehouse Center Application Integration Guide, SC27-1124

  • IBM DB2 XML Extender Administration and Programming, SC27-1234

  • IBM DB2 Universal Database Quick Beginnings for DB2 Clients, GC09-4832

  • IBM DB2 Universal Database Quick Beginnings for DB2 Servers, GC09-4836

  • IBM DB2 Universal Database Installation and Configuration Supplement, GC09-4837


Online resources

These Web sites and URLs are also relevant as further information sources:

DB2 UDB

  • Database and Data Management home page

    http://www.ibm.com/software/data/

  • DB2 Universal Database home page

    http://www.ibm.com/software/data/db2/udb/

  • DB2 Technical Support

    http://www-3.ibm.com/cgi-bin/db2www/data/db2/udb/winos2unix/support/index.d2w/report

  • DB2 online library

    http://www.ibm.com/db2/library

  • DB2 for Microsoft Windows

    http://www.ibm.com/db2/windows

Migration to DB2 UDB

  • IBM Software Migration Project Office

    http://www.ibm.com/software/solutions/softwaremigration/contacts.html


How to get IBM Redbooks

You can search for, view, or download Redbooks, Redpapers, Hints and Tips, draft publications and Additional materials, as well as order hardcopy Redbooks or CD-ROMs, at this Web site:

  • ibm.com/redbooks


Help from IBM

IBM Support and downloads

  • ibm.com/support

IBM Global Services

  • ibm.com/services


Previous Section
< Day Day Up >
Next Section

Index

Symbols

! 142
$CLASSPATH 58
$INSTHOME 60
$PATH 58
%FOUND 172
%ISOPEN 169
%NOTFOUND 170
%ROWNCOUNT 170
%TYPE 145
.c 205
.exp 206
.NET 41
.rpt 52
.sqc 205
@ 142


Previous Section
< Day Day Up >
Next Section

Index

Numerics

32-bit 66–67
3-tier applications 337
64-bit 66–67
64-bit memory 338
7x24 213
8i 77


Previous Section
< Day Day Up >
Next Section

Index

A

Acceptance tests 280
Active subagent 14
ActiveX 40
administration 67
Administration scripts 267
administrator 73
ADO 40
Advanced SQL 345
AFTER trigger 136
AitinSoft 31
AIX 57, 66
Alert log file 14
Analyze 42
ANSI/IEEE 276
API 41, 227, 233
APPC 22
Applets 237
application 35
application layer 257
Application Shared Memory 9
architecture profiling 30
arrays 231
ASCII 255
ASN 292
assessment 30
Asynchronous Page Cleaner 339
audio 342
audio clips 348
authentication 75
authority level 75
Autoloade 341
Automated Summary Tables (AST) 355
availability 212, 226
awk 218


Previous Section
< Day Day Up >
Next Section

Index

B

background processes 11
backup 44, 75, 269
Backup scripts 269
Backup Wizard 270
BEFORE trigger 136
Big Block Reads 339
BIGINT 231
BIND 153
bldmapp.bat 236
bldrtn 205
Boolean operations 351
Buffer pools 9
buffer pools 338
buffer_size 233
build 77
built-in 229
BULK COLLECT 175
Business Intelligence 44, 354
business logic layer 257
Business rules 344


Previous Section
< Day Day Up >
Next Section

Index

C

C 40, 229
C++ 229
CASE 195
Catalog cache 9
CCA 292
Ckeckpoint 11
CKPT 11
CLI 39
CLI Call 292
client 30
CLP 39, 151
Cluster/MPP Support in Utilitie 341
COBOL 40, 228
collection 172
Columns 49
command 71
Command Center 357
Command Line Processor 39, 151
Command Window 151
common gateway interface (CGI) 352
communication 65–66
compatibility 226
complexity 33
components 61
Compound SQL 361
CONDITION HANDLER 169
condition handlers 180
configuration 30
Configuration Advisor 44
Configuration Assistant 22
connect 77
connection 229
Connection concentrator 340
connectivity 67
constraints 35, 49
containers 16
Content management 44
CONTINUE 182
Control Center 32, 39, 357
Control file 14
control file 263
ControlCenter 32
conventions 41
conversion 50, 72, 212
Convert 52, 63
criteria 279
Cube Views 272
CURSOR 140
cursor 231
Cursor capability 351


Previous Section
< Day Day Up >
Next Section

Index

D

Data 49
Data Conversion 211
Data Managed Space 34
Data Propagator 361
Data Warehouse Center 358
Database heap 9
database server. However 36
Database writer 10
DATABASE_MEMORY 9
databases 34, 49
datafiles 14, 269
DATALINK 262
DataMover 255
DB cfg file 16
DB2 292
DB2 Audio Extender 348
DB2 communication manager 13
DB2 coordinating agent 13
DB2 daemon spawner 12
DB2 Extenders 345
DB2 format log 12
DB2 Image Extender 347
DB2 Net.Search 351
DB2 Spatial Extender 350
DB2 subagen 13
DB2 system controller 12
DB2 system logger 12
DB2 TCP manager 13
DB2 Text Extender 346
DB2 Video Extender 348
DB2 watchdog 12
DB2 XML Extender 349
db2admin 61
db2agent 13
db2agnta 13
db2agntp 14
DB2COMM 22
db2dc 289
db2diag.log 16, 293
db2dlock 13
db2dump 18
db2fmtlg 12
db2gds 12
db2icrt 68, 70
db2ipccm 13
db2loggr 13
db2logw 13
db2look 283
db2pclnr 13
db2pfchr 13
db2set 70
db2setup 65–66, 68
db2start 59
db2stop 59
db2sysc 12
db2syslog 12
db2tcpcm 13
db2wdog 12
DBA 292
DBADM 75
DBI 41, 292
DBM cfg 16
DBMS_SQL 160
DBWR 10
DDL 35, 50–51, 55, 262
deadlock detector 13
DECLARE 153
DECODE 195
DELETE 76
delimiter 264
dense 173
DEPLOY 54
Deploy 53, 61, 63
DESCRIBE TABLE 218
Developer Domain 43
Development Center 150, 358
DGTT 173, 175
DIAGLEVEL 294
DIFF 285
Direct Media Access 339
directory 60
DML 38
DMS 34, 72–73
DRDA 362
DRDA Application Requester (DRDA-AR) 362
DRDA Application Server (DRDA-AS) 362
Driver Manager 245
drop 52
DSS 30
DWC 292
Dynamic performance views 267


Previous Section
< Day Day Up >
Next Section

Index

E

Edition 34
EDU 9, 11
education 228
Efficient Large Database Operations 340
EJBs 237
embedded 40
EMEA 45
Engine dispatchable Units 9
enterprise resource planning (ERP) 353
entity-relation 32
Entity-Relationship 35
environment 59, 74
environment variables 60
eSeries or 65
estimation 32
Event Monitor 43–44
EXCEPTION HANDLERS 180
EXEC SQL 230
EXECUTE 162
EXECUTE IMMEDIATE 161
EXIT Handler 145
EXPLAIN 44
explicit cursors 167
explicitly 167
export file 205
External procedures 204
Extracting 51


Previous Section
< Day Day Up >
Next Section

Index

F

fallback 213
Federated Systems 362
Federation 45
Fenced User 69
FETCH FIRST N ROWS ONLY 171
FETCH INTO 175
Fielded searches 351
fixed-length 231
FixPak 65–66
flat files 214
FOR 153
FOR LOOP 167
FORTRAN 40
Functional testing 279
functions 41, 49
Fuzzy search 351


Previous Section
< Day Day Up >
Next Section

Index

G

Generate Data Transfer 54
Generate Data Transfer Scripts 63
generator 227
GET DIAGNOSTICS 153, 172
Global Declared Temporary Table 173
Global Memory 8
GRANT 76
Group 75
groupadd 70
GUI 50


Previous Section
< Day Day Up >
Next Section

Index

H

Health Center 357
health Monitor 44
hierarchy 189
High availability 44
High speed indexing 351
High Speed Load Utility 341
host variable 229–230
HP-UX 64, 336
HTML 40


Previous Section
< Day Day Up >
Next Section

Index

I

IBM Migration Toolkit 48, 63
id 76
IF 153
ime planning 213
Implicit privilege 76
Import 54, 80
importing 51
Indexes 35, 49–50
Individual privileges 76
Information Center 358
Information integration 44
Information Integrator. 222
INOUT 188, 234
INSERT 76
installation 34, 59, 64–67
instance 34, 60, 68
instance-owning 68
interface 35, 39
Internet 351
inter-process communication 13
intranet 351
IPC 13
iSeries 49, 336
ITERATE 153
IXF 256


Previous Section
< Day Day Up >
Next Section

Index

J

J2EE 31
J2SE 236
Java 30, 37, 39, 50, 60, 66
Java ServerPages 237
Java Support 352
javac 207
JDBC 39, 51, 352
Journal 357
JRE 66


Previous Section
< Day Day Up >
Next Section

Index

L

language 36
LANGUAGE SQL is 154
LEAVE 153
LGWR 10
License Center 358
LINESIZE 218
Linux 41, 57
List Prefetch 339
Load 54, 77
Load authority 75
LOB 72
Locklist 9
log reader 13
Log writer 10
log writer 13
long character 72
Long tablespace 72
LOOP 158
Lotus Approach 344
Lotus SmartSuite (R) 344


Previous Section
< Day Day Up >
Next Section

Index

M

Manual methods 35
Materialized Query Tables (MQT) 355
MAX_CONNECTIONS 9
MDAC 245
mechanisms 232
Memory Tracker 359
message_buffer is 233
metadata 49
Metadata transport 35
Microsoft 78
Microsoft SQL Server 31, 49
migration 48, 77
Migration keys 251
Migration Toolkit 31
migration tools 35, 37
mkfifo 222
mkuser 70, 76
MODE DB2SQL 155
model 35
modeling tools 32
monitor 42
MPP Parallel Suppor 338
MQSeries 150
MS Office/Backoffice 344
MTK 31, 47, 63, 77
multidimensional analysis (MDA). 355
Multidimensional clustering 340
multimedia 342
multi-partitioned 68
Multiple buffer pools 338


Previous Section
< Day Day Up >
Next Section

Index

N

named pipe 222
nested tables 172
Net.Data 352
NetBIOS 22
Netscape 60
NEWLOGPATH 17
NO CASCADE 155
non-ANSI data types 254
non-ANSI SQL 254
NPIPE 22
NULL 172


Previous Section
< Day Day Up >
Next Section

Index

O

object-relational technology 342
objects 35–36
OCI 243
ODBC 39–40, 51, 244
OFA 15
OLAP 272, 355
OLE (Object Linking and Embedding) 344
OLE DB 41
OLTP 30, 337
ON COMMIT PRESERVE ROWS 187
Open Database Connectivity 250
Operating Systems 49
Optimal Flexible Architecture 15
optimizer 43, 354
Oracle 8i 49, 78
Oracle Applicaiton Clusters 25
Oracle Call Interface 243
Oracle Net Services. 21
OS/390 336
outer join 193
Outer Join Support 345


Previous Section
< Day Day Up >
Next Section

Index

P

Package cache 9
Packages 49
page cleaner 13
PAGESIZE 218
Parallel 341
Parallel Backup 341
Parallel Data Loading 341
Parallel Index Creation 341
parallel processing 337
Parallel Split 341
Parameter file 14
partition 27, 68
Partner Solutions 353
Password file 14
Pentium 67
Performance Expert 44
Performance tuning 42
performance tuning 43
PERL 37
Perl 41
PL/SQL 50, 158
planning tools 33
PMON 11
point-and-click 354
Porting 35
porting plan 33
PowerBuilder 31
precompiler 244
preparation 59
Presorted searches 351
privilege level 75
privileges 75
problem determination 291
Process Monitor 11
processes 10
processor 67
project 79
Project Name - Required 78
protocol 22
protocols 65–66
pSeries DB2 65


Previous Section
< Day Day Up >
Next Section

Index

Q

QMF 272, 344


Previous Section
< Day Day Up >
Next Section

Index

R

RAC 25
RAISE_APPLICATION_ERROR 184
reader 222
recovery 44, 75
recursive 190
Redbooks Web site 421
Contact us xxi
Redo Log Files 14
REF Cursor 201
REFERENCE NEW AS n 155
Referential integrity (RI) 344
Refine 53, 63
registry variable 22
Regular tablespace 72
remote 67
REORG 339
REPLACE 154
replication 23, 44
Reports 53
Repository 227
requirements 33–34
resouce 32
RETURN TO CALLER 178
RETURN TO CLIENT 179
RETURNING INTO 175
reverse-engineer 32
RISC/6000, eSeries 65
roll-out 228
root 61
Row Blocking 361
ROWNUM 196
run-time 233


Previous Section
< Day Day Up >
Next Section

Index

S

SAP R/3 253, 344
SAT 292
Satellite Center 357
Scope 276
scripts 39
SDK 245
security 14, 75
SELECT 76
SELECT INTO 175
Sequences 49
Sequential Prefetch 339
server 36
Servlets 237
SET 153, 158
SET INTEGRITY 284
Setup.exe 62
Shared Memory 8
shared nothing architecture 26
SIGNAL 153
SIGNAL SQLSTATE 184
single-dimensional clustering 340
size 214
SMON 11
SMP 337
SMP Parallel Support 338
SMP Support in Utilities 341
SMPO 33
SMS 34, 72
SNAPSHOT_DATABASE 267
SNAPSHOT_DBM 267
SNAPSHOT_STATEMENT 267
SNAPSHOT_TABLE 267
Snapshots 43
software requirements 61
source 49, 77
space requirements 64–65
sparse 173
spatial information 342
specifications 67
Specify Source 51, 79
SPM 292
SQJ 292
SQL 40, 43, 292
SQL Communication Area 233
SQL cursor 165
SQL Server, versions 78
SQL standards 35
SQL Translator 53, 56
SQL*Loader 262
SQL*Plus 21, 50, 215, 218
SQLCA 233, 248
SQLCODE 168, 185, 292
SQLDA 235
SQLERRM 185
SQLEXCEPTION 181
SQLEXEPTION 180
sqlint32 231
sqlint64 231
SQLj 40, 236
SQLSTATE 168, 180
SQLWARNING 181
SQLWays 31
Star Joins 355
Stemmed searches 351
step 59
stored procedure 33, 36, 38, 49, 345, 360
storyboards 349
stress testing 280
structure 35
su 77
subscript 172
Sybase 31, 78
Sybase Enterprise 49
syntax 74, 227
SYSADM 75
SYSCAT 20
SYSCATSPACE 71
sysctl 60
SYSCTRL 75
SYSIBM 20
SYSMAINT 75
SYSSTAT 20
System Managed Space 34
System monitor 11


Previous Section
< Day Day Up >
Next Section

Index

T

table function 267
tables 35, 49
tablespace 73
target 49, 77
Task Center 271, 357
TCP 22, 65–67
Temporary tablespace 72
TEMPSPACE1 71
terminating character 142
test phases 279
text 40
Text Extender 346
time-series data 342
TNS 21
tools 30
Tools and wizards 270
Tools catalog 69
Tools Setting 358
Transaction log 16
Translator 50
Triggers 49, 344
triggers 36, 38, 136
Type 2 39
Type 3 39
Type 4 39
Type 4 JDBC driver 352


Previous Section
< Day Day Up >
Next Section

Index

U

UDF 191, 207
ulimit 214
UNIX 41
Unload 54
UPDATE 76
update database manager 59
user process 10
User-Defined
Table Functions 343
user-defined functions 36, 38
User-Defined Types (UDTs) 343
USERSPACE1 71
utilemb.h 236
utilemb.sqc 236
Utility heap 9
UTL_FILE_DIR 219


Previous Section
< Day Day Up >
Next Section

Index

V

V$DATABASE 267
V$DATAFILE 267
V$INSTANCE 267
V$TABLESPACE 267
validation 279
variables 41, 229
varrays 172
Version 77
video 40, 342
Video Extender 349
Views 49
violation 262
VLDB 24
VM 336
VSE 336


Previous Section
< Day Day Up >
Next Section

Index

W

WEB 280
Web enablement 351
Web integration 44
WebSphere Studio 32
WHILE 153
Wildcard searches 351
wizard 44, 67
workshop 45
writer 222


Previous Section
< Day Day Up >
Next Section

Index

X

XML 150


Previous Section
< Day Day Up >
Next Section

Index

Z

z/OS 336


Previous Section
< Day Day Up >
Next Section

List of Figures

Preface

Figure 0-1: From left to right, Ranjit, Ken, Fadel, Whei-Jen, Stefan, Artur

Chapter 1: Introduction

Figure 1-1: Oracle architecture overview
Figure 1-2: DB2 architecture overview
Figure 1-3: Oracle memory architecture
Figure 1-4: DB2 UDB memory architecture
Figure 1-5: Oracle process architecture
Figure 1-6: DB2 processor architecture
Figure 1-7: Oracle database files
Figure 1-8: Oracle directory structure using OFA
Figure 1-9: DB2 Instance and database files
Figure 1-10: DB2 directory structure for a simple create database command
Figure 1-11: DB2 UDB directory structure
Figure 1-12: Configuring the database connection using Configuration Assistant
Figure 1-13: Shared disk architecture
Figure 1-14: Shared nothing architecture

Chapter 3: MTK

Figure 3-1: The IBM DB2 Migration Toolkit (MTK)
Figure 3-2: MTK GUI interface
Figure 3-3: Specify source
Figure 3-4: Convert
Figure 3-5: Refine
Figure 3-6: Generate Data Transfer script
Figure 3-7: Deploy to DB2
Figure 3-8: MTK conversion tasks overview
Figure 3-9: The MTK SQL Translator

Chapter 4: Porting with MTK

Figure 4-1: MTK Project management screen
Figure 4-2: The Specify Source tab
Figure 4-3: Detail of the Connect to Database screen
Figure 4-4: The Extract screen with the ORA_USR schema selected
Figure 4-5: The Extract screen with tables, views and sequences selected
Figure 4-6: The Extract screen with schema and categories expanded
Figure 4-7: The Extract screen with tables, views and sequences selected
Figure 4-8: MTK during the Extract process
Figure 4-9: The categories for the second Extract file
Figure 4-10: The Specify Source tab after all extraction files have been created
Figure 4-11: Viewing extracted files in the Text Editor
Figure 4-12: The Convert tab
Figure 4-13: The Global Type Mapping screen
Figure 4-14: The Advanced Options screen
Figure 4-15: Executing the conversion
Figure 4-16: The Refine tab
Figure 4-17: The Messages sub-tab
Figure 4-18: The Messages sub-tab opened to a specific line in the Oracle source
Figure 4-19: The DB2 file view for message 120
Figure 4-20: Message Help screen displayed for message 120
Figure 4-21: Editing the EMP_ID column in the Text Editor
Figure 4-22: The Generate Data Transfer Scripts tab
Figure 4-23: Advanced Options screen for LOAD
Figure 4-24: The Generate Data Transfer Scripts screen after scripts generated
Figure 4-25: The MTK Deploy to DB2 task screen
Figure 4-26: The Deploy to DB2 screen with deployment information entered
Figure 4-27: The Verification report
Figure 4-28: The Set Context screen after a file has been selected as Context.
Figure 4-29: The Convert tab - context file indicated and the remaining file selected
Figure 4-30: The Refine tab after the conversion of procs_pkgs_trigs.src
Figure 4-31: The Deployment screen before launching procs_pkgs_trgs.db2
Figure 4-32: The Verification Report showing the tally of deployed objects
Figure 4-33: The Verification Report showing objects missing from DB2

Chapter 5: Conversion Reference

Figure 5-1: The Development Center
Figure 5-2: The DB2 Command Window on AIX

Chapter 6: Data Conversion

Figure 6-1: Data movement strategy in a high availability environment

Chapter 7: Application Conversion

Figure 7-1: DB2 CLI and ODBC
Figure 7-2: SAP R/3 database migration project
Figure 7-3: SAP R/3 database migration timeline
Figure 7-4: Siebel migration process

Chapter 8: Script Conversion

Figure 8-1: Backup Wizard
Figure 8-2: Task Center

Chapter 9: Testing

Figure 9-1: Phases during a migration project
Figure 9-2: Table "table01" definition for Example 9-1
Figure 9-3: Data file "table01.unl" for Example 9-1
Figure 9-4: Development Center debug window.
Figure 9-5: Sample db2level output
Figure 9-6: Searching for problem resolutions using TechNotes
Figure 9-7: Sample TechNotes search results
Figure 9-8: Sample TechNotes document link
Figure 9-9: Subscribing DB2 alert
Figure 9-10: Presenting event monitor data using db2eva GUI tool
Figure 9-11: A Visual Explain access plan graph
Figure 9-12: Explaining logical log
Figure 9-13: Visualizing CHNGPGS_THRESH parameter
Figure 9-14: Maximum number of locks available for default settings on UNIX
Figure 9-15: Explaining lock snapshot information
Figure 9-16: Running RUNSTATS on multiple tables
Figure 9-17: Selecting tables for RUNSTAT command.
Figure 9-18: RUNSTAT command options
Figure 9-19: Scheduling Configuration Advisor recommendations
Figure 9-20: Configuration Advisor recommendations
Figure 9-21: The Design Advisor


Previous Section
< Day Day Up >
Next Section

List of Tables

Chapter 1: Introduction

Table 1-1: Mapping of Oracle terminology to DB2 UDB
Table 1-2: Database memory segments and parameters
Table 1-3: Data Dictionary and Catalog
Table 1-4: Shared disk architecture vs. shared nothing architecture

Chapter 4: Porting with MTK

Table 4-1: Disk space requirements on AIX
Table 4-2: Disk space requirements on AIX
Table 4-3: Disk space requirements on Windows
Table 4-4: Differences between SMS and DMS table spaces
Table 4-5: Message 20 objects

Chapter 5: Conversion Reference

Table 5-1: Mapping of conditional statements
Table 5-2: Mapping Oracle and DB2 Cursor operation
Table 5-3: Mapping of cursor attributes
Table 5-4: Mapping of join definition
Table 5-5: Mapping of ROWNUM function
Table 5-6: Use of dummy table for system information
Table 5-7: Mapping of set operations

Chapter 7: Application Conversion

Table 7-1: JDBC driver
Table 7-2: Return code mapping from OCI to CLI functions

Chapter 8: Script Conversion

Table 8-1: V$ views and table functions
Table 8-2: Commands and DDL conversion

Chapter 9: Testing

Table 9-1: Aggregations for data migration verification
Table 9-2: List of monitor switches and related DBM parameters
Table 9-3: Common snapshot table functions
Table 9-4: Parameters for AUTOCONFIGURE command

Appendix B: Data Types

Table 9-5: Oracle to DB2 data type mapping
Table 9-6: SQL data types mapped to Java declarations
Table 9-7: Mapping Oracle data types to DB2 UDB data types

Appendix C: Oracle Call Interface (OCI) Mapping

Table 9-8: Connect/initialize/authorize
Table 9-9: Handles/descriptors
Table 9-10: Transaction management
Table 9-11: Bind/define/describe
Table 9-12: Prepare/execute/fetch
Table 9-13: Miscellaneous

Appendix E: Terminology Mapping

Table 9-14: Oracle Terminology to DB2 UDB mapping


Previous Section
< Day Day Up >

List of Examples

Chapter 4: Porting with MTK

Example 4-1: Create database
Example 4-2: Example of the create database command
Example 4-3: Create table space command
Example 4-4: Creating a table space of type Large
Example 4-5: Creating a table space to store indexes
Example 4-6: Granting Create table privilege to user smith
Example 4-7: Trigger InsertEmployee Oracle source code
Example 4-8: Trigger InsertEmployee DB2 conversion code
Example 4-9: Trigger ManagersChange Oracle source
Example 4-10: Trigger ManagersChange DB2 code
Example 4-11: Alternative DB2 conversion of trigger ManagersChange
Example 4-12: Trigger UpdateDepartments Oracle source code
Example 4-13: DB2 conversion of trigger UpdateDepartments
Example 4-14: InsertEmployee.db2
Example 4-15: EmployeeDynamicQuery Oracle source code
Example 4-16: Converted DB2 code of Procedure EmployeeDynamicQuery
Example 4-17: SelectRow Oracle source
Example 4-18: SelectRow DB2 conversion

Chapter 5: Conversion Reference

Example 5-1: Simple Oracle trigger
Example 5-2: Simple DB2 trigger
Example 5-3: Oracle trigger with DML command
Example 5-4: DB2 trigger with DML command
Example 5-5: PL/SQL procedure with usage of DBMS_SQL
Example 5-6: PL/SQL procedure with usage of native dynamic SQL
Example 5-7: SQL PL procedure with native dynamic SQL
Example 5-8: Dynamic UPDATE with EXECUTE IMMEDIATE
Example 5-9: Dynamic UPDATE with EXECUTE and PREPARE
Example 5-10: Java User Defined Function with dynamic SQL
Example 5-11: Oracle procedure with explicit cursor
Example 5-12: DB2 store procedure with cursor
Example 5-13: Function with an explicit cursor in Oracle
Example 5-14: Conversion using a FOR LOOP in DB2
Example 5-15: Oracle code using nested table
Example 5-16: DB2 UDB code using DGTT
Example 5-17: Efficient DB2 UDB code using DGTT
Example 5-18: DB2 UDB code using INSERT INTO
Example 5-19: PL/SQL procedure returns nested table
Example 5-20: SQL Procedure returns multiple rows using CURSOR WITH RETURN
Example 5-21: DB2 Store procedure calls AccountPackage.AccountList
Example 5-22: Condition handler - SQL EXCEPTION
Example 5-23: Condition handler - handle a long value
Example 5-24: Condition handler - SIGNAL SQLSTATE
Example 5-25: Oracle package with initialization
Example 5-26: Oracle package with initialization as procedure
Example 5-27: Definition of global variables in Oracle
Example 5-28: Temporary table with global variables
Example 5-29: Oracle hierarchical query
Example 5-30: Computing of direct child data
Example 5-31: Hierarchical query with entry point
Example 5-32: Compute hierarchy level
Example 5-33: Sample use of hierarchical query
Example 5-34: Oracle outer joins
Example 5-35: DB2 outer join conversion
Example 5-36: Oracle code using RETURNING INTO
Example 5-37: DB2 code using SELECT INTO
Example 5-38: DB2 CODE using SELECT
Example 5-39: DB2 dummy view for system information
Example 5-40: Oracle function with a REF cursor
Example 5-41: Conversion to a procedure with a Result Set in DB2
Example 5-42: Oracle procedure with Local function
Example 5-43: DB2 Conversion of Oracle Procedure with Local Function
Example 5-44: Stored Procedure in C
Example 5-45: UDF Java source

Chapter 6: Data Conversion

Example 6-1: The data_unload.sh script
Example 6-2: The desc.awk script
Example 6-3: The count.awk script
Example 6-4: Procedure to export_ table data

Chapter 7: Application Conversion

Example 7-1: Passing data to store procedure
Example 7-2: Oracle JDBC connection
Example 7-3: DB2 JDBC connection
Example 7-4: Java call of Oracle or DB2 UDB procedure with input parameter
Example 7-5: Java call of Oracle procedure with result set
Example 7-6: Java call of DB2 UDB procedure with result set
Example 7-7: Java call of Oracle procedure with input parameter and result set
Example 7-8: Java call of DB2 UDB procedure with input parameter and result set
Example 7-9: Java of Oracle function with input parameter and result set

Chapter 8: Script Conversion

Example 8-1: SQL*Loader control file with fixed-format fields
Example 8-2: DB2 UDB Load file for table ACCOUNTS
Example 8-3: SQL*Loader control file with variable-length fields
Example 8-4: DB2 load commend with variable-length fields
Example 8-5: SQL*Loader control file with conditions for table ACCOUNTS
Example 8-6: Export script in Oracle
Example 8-7: BACKUP database script in DB2

Chapter 9: Testing

Example 9-1: Sample IMPORT messages
Example 9-2: LOAD messages
Example 9-3: Turning integrity checking back on.
Example 9-4: Table for storing number of rows (Oracle)
Example 9-5: Table for storing number of rows (DB2)
Example 9-6: Sample table CK_ROW_COUNTS contents
Example 9-7: PL/SQL program that generates scripts for counting rows
Example 9-8: Explaining error codes
Example 9-9: Example of db2diag.log file
Example 9-10: Example snapshot
Example 9-11: Resetting snapshot monitor counters
Example 9-12: Displaying monitor switches
Example 9-13: Updating monitor switches at instance level
Example 9-14: Updating monitor switches at application level.
Example 9-15: Database manager snapshot
Example 9-16: Lock snapshot.
Example 9-17: Table snapshot
Example 9-18: Table space and buffer pool snapshots
Example 9-19: Dynamic SQL snapshot
Example 9-20: Sample snapshot table function
Example 9-21: Sample snapshot table function
Example 9-22: Sample snapshot table function
Example 9-23: Storing snapshot data in a table
Example 9-24: Creating sample event monitor
Example 9-25: Generating table syntax for specified event monitor
Example 9-26: Enabling event monitor
Example 9-27: Creating event monitor with file option
Example 9-28: Formatting event monitor output files
Example 9-29: Checking for current page allocation status
Example 9-30: Enabling multi page allocation
Example 9-31: Relocation of logical logs
Example 9-32: Updating IO related processes
Example 9-33: Increasing buffer pools
Example 9-34: Resizing the transactional log
Example 9-35: Invoking snapshot for locks on database sample
Example 9-36: Lock escalation message in db2diag.log file
Example 9-37: Current usage of log space by applications
Example 9-38: Checking log I/O activity
Example 9-39: Autoconfigure command
Example 9-40: Finding indexes for particular query

Appendix D: Converter for SQL*Loader

Example 9-41: Conversion of Oracle control file to DB2 load command
Example 9-42: Generation of additional DB2 update commands