Back to Contents


ODI Adaptation Guide For IBM DB2 UDB 8.x, 9x

Installation

Install DB2 and create a database
Prepare the runtime environment

Database concepts

Database concepts
Data storage concepts
Data consistency and concurrency management
Transactions handling
Defining database users
Setting privileges

Data dictionary

BOOLEAN data type
CHARACTER data types
NUMERIC data types
DATE and DATETIME data types
INTERVAL data type
SERIAL data types
ROWIDs
Very large data types
Constraints
Triggers
Stored procedures
Name resolution of SQL objects
Setup database statistics
The ALTER TABLE instruction
Data type conversion table

Data manipulation

Reserved words
Outer joins
Transactions handling
Temporary tables
Substrings in SQL
Name resolution of SQL objects
String delimiters and object name delimiters
Getting one row with SELECT
MATCHES and LIKE conditions
SQL functions and constants
Querying system catalog tables
The GROUP BY clause
The star in SELECT statements
The LENGTH() function

BDL programming

SERIAL data type
INFORMIX specific SQL statements in BDL
INSERT cursors
Cursors WITH HOLD
SELECT FOR UPDATE
SQL parameters limitation
The LOAD and UNLOAD instructions
SQL Interruption
Scrollable Cursors

Connecting to DB2 OS/400

DB2 Architecture on OS/400
Log in to the AS/400 server
Collection (Schema) Creation
Source Physical File Creation
Trigger Creation
Permission Definition
Relational DB Directory Entry Creation
DB2 Client Configuration on Windows
Differences Between DB2 UNIX & DB2 OS/400
Naming Conventions

Runtime configuration

Install DB2 and create a database - database configuration/design tasks

If you are tasked with installing and configuring the database, here is a list of steps to be taken:

  1. Install the IBM DB2 Universal Server on your database server.

  2. Create a DB2 database entity: dbname

  3. Declare a database user dedicated to your application: the application administrator. This user will manage the database schema of the application (all tables will be owned by it).

  4. Give all requested database administrator privileges to the application administrator.

  5. If you plan to use temporary table emulation, you must setup the database for DB2 global temporary tables (create a user temporary tablespace and grant privileges to all users). See issue Temporary tables for more details.

  6. Connect as the application administrator:

   $ db2 "CONNECT TO dbname USER appadmin USING password"

  1. Create the application tables. Do not forget to convert INFORMIX data types to DB2 data types. See issue Data Type Conversion Table  for more details.

  2. If you plan to use SERIAL column emulation, you must prepare the database. See issue Serial Data Type  for more details.

Prepare the runtime environment - connecting to the database

  1. In order to connect to IBM DB2, you must have a database driver "dbmdb2*" in FGLDIR/dbdrivers.

  2. If you want to connect to a remote DB2 server, the IBM DB2 Client Application Enabler must be installed and configured on the computer running the BDL applications. You must declare the data source set up as follows:

  1.  Login as root.
    1. Create a user dedicated to the db2 client instance environment, for example, "db2cli1".
    2. Create a client instance environment with the db2icrt tool as in following example:
           # db2dir/instance/db2icrt -a server -s client instance-user
  1. Login as the instance user (environment should be set automatically, verify DB2DIR).
    1. Catalog the remote server node:
           # db2 "catalog tcpip node db2node remote hostname server tcp-service"
    2. Catalog the remote database:
           # db2 "catalog database datasource at node db2node authentication server"
    3. Test the connection to the remote database:
           # db2 "connect to datasource user dbuser using password"
                   ( where dbuser is a database user declared on the remote database server )

See IBM DB2 documentation for more details.

  1. Important: If you have a non-English environment, you may need to set the PATCH2=15 configuration parameter in the DB2CLI.INI file to ensure that DECIMAL values will be properly inserted or fetched:
       [datasource]
       PATCH2=15

For more details, see the DB2 README.TXT file in the SQLLIB directory.

  1. Make sure that the DB2 client environment variables are properly set. Check variables such as DB2DIR (the path to the installation directory), DB2INSTANCE (the name of the DB2 instance), INSTHOME (the path to the home directory of the instance owner). On UNIX, you will find environment settings in the file $INSTHOME/sqllib/db2proffile. See IBM DB2 documentation for more details.

  2. Verify the environment variable defining the search path for database client shared libraries (libdb2.so on UNIX, DB2CLI.DLL on Windows). On UNIX platforms, the variable is specific to the operating system. For example, on Solaris and Linux systems, it is LD_LIBRARY_PATH, on AIX it is LIBPATH, or HP/UX it is SHLIB_PATH. On Windows, you define the DLL search path in the PATH environment variable.

    DB2 UDB version

    Shared library environment setting

    DB2 UDB 7.x and 8.x

    UNIX: Add $DB2DIR/lib (for 32 bit) or $DB2DIR/lib64 (for 64 bit) to LD_LIBRARY_PATH (or its equivalent).
    Windows: Add %DB2DIR%\bin to PATH.

    DB2 UDB 9.x

    UNIX: Add $DB2DIR/lib32 (for 32 bit) or $DB2DIR/lib64 (for 64 bit) to LD_LIBRARY_PATH (or its equivalent).
    Windows: Add %DB2DIR%\bin to PATH.

     

  3. To verify if the DB2 client environment is correct, you can, for example, start the db2 command interpreter and connect to the server:
         $ db2
         db2 => CONNECT TO dbname USER username USING password

  4. Check the database locale settings (DB2CODEPAGE, etc). The DB locale must match the locale used by the runtime system (LANG).

  5. Setup the fglprofile entries for database connections.
    Important:   Make sure that you are using the ODI driver corresponding to the database client and server version. Because Informix features emulation is dependent on the database server version, it is mandatory to use the same version of the database client and ODI driver as the server version.
     
  6. Define the database schema selection if needed. Use the following entry to define the database schema to be used by the application. The database interface will automatically perform a "SET SCHEMA <name>" instruction to switch to a specific schema:
       dbi.database.dbname.db2.schema = 'name'

Here dbname identifies the database name used in the BDL program ( DATABASE dbname ) and name is the schema name to be used in the SET SCHEMA instruction. If this entry is not defined, no "SET SCHEMA" instruction is executed and the current schema defaults to the user's name.


DATE and DATETIME data types

INFORMIX provides two data types to store date and time information:

IBM DB2 provides only one data type to store dates :

String representing date time information:

INFORMIX is able to convert quoted strings to DATE / DATETIME data if the string content matches environment parameters (i.e. DBDATE, GL_DATETIME). As INFORMIX, IBM DB2 can convert quoted strings to dates, times or timestamps. Only one format is possible: 'yyyy-mm-dd' for dates, 'hh:mm:ss' for times and 'yyyy-mm-dd hh:mm:ss:f' for timestamps.

Date time arithmetic:

Solution:

DB2 has the same DATE data type as INFORMIX ( year, MIX DATE columns.

DB2 TIME data type can be used to store INFORMIX DATETIME HOUR TO SECOND values. The database interface makes the conversion automatically.

INFORMIX DATETIME values with any precision from YEAR to FRACTION(5) can be stored in DB2 TIMESTAMP columns. The database interface makes the conversion automatically. Missing date or time parts default to 1900-01-01 00:00:00.0. For example, when using a DATETIME HOUR TO MINUTE with the value of "11:45", the DB2 TIMESTAMP value will be "1900-01-01 11:45:00.0".

Important Notes:


Reserved words

Even if IBM DB2 allows SQL reserved keywords as SQL object names ( "create table table ( column int )" ), you should take care in your existing database schema and check that you do not use DB2 SQL words. An example of a common word which is part of DB2 SQL grammar is 'alias'.

Solution:

See IBM DB2 documentation for reserved keywords.


ROWIDs

When creating a table, INFORMIX automatically adds a "ROWID" integer column (applies to non-fragmented tables only). The ROWID column is auto-filled with a unique number and can be used like a primary key to access a given row.

IBM DB2 ROWID columns were introduced in version 9.7. Unlike Informix integer row ids, DB2 row ids are based on VARCHAR(16) FOR BIT DATA (128 bit integer) that are usually represented as a 32 char hexadecimal representation of the value. The IBM DB2 ROWID is actually an alternative syntax for RID_BIT(), and a qualified reference to ROWID like tablename.ROWID is equivalent to RID_BIT(tablename).

For example : x'070000000000000000000065CE770000'

In DB2 SQL, to find a row with a rowid, you must specify the rowid value as an hexadecimal value:

SELECT * FROM customer WHERE ROWID = x'070000000000000000000065CE770000'

or convert the ROWID to an hexadecimal representation and then you can compare to a simple string:

SELECT * FROM customer WHERE HEX(ROWID) = '070000000000000000000065CE770000'

With INFORMIX, SQLCA.SQLERRD[6] contains the ROWID of the last INSERTed or UPDATEd row. This is not supported with ORACLE because ORACLE ROWID are not INTEGERs.

Solution:

If the BDL application uses ROWIDs, the program logic should be reviewed in order to use the real primary keys (usually, serials which can be supported).

The DB2 database driver will convert the ROWID keyword to HEX(ROWID), so it can be used as a VARCHAR(32) with the hexadecimal representation of the BIT DATA. You need however to replace all INTEGER variable definitions by VARCHAR(32) or CHAR(32).

To emulate Informix integer ROWIDs, you can also use the DB2 GENERATE_UNIQUE built-in function, or the IDENTITY attribute of the INTEGER or BIGINT data types.

All references to SQLCA.SQLERRD[6] must be removed because this variable will not hold the ROWID of the last INSERTed or UPDATEd row when using the IBM DB2 interface.


SERIAL data types

INFORMIX supports the SERIAL, SERIAL8 and BIGSERIAL data types to produce automatic integer sequences. SERIAL is based on INTEGER (32 bit), while SERIAL8 and BIGSERIAL can store 64 bit integers:

INFORMIX allows you to insert rows with a value different from zero for a serial column. Using an explicit value will automatically increment the internal serial counter, to avoid conflicts with future INSERTs that are using a zero value:
    CREATE TABLE tab ( k SERIAL ); --> internal counter = 0
    INSERT INTO tab VALUES ( 0 );  --> internal counter = 1
    INSERT INTO tab VALUES ( 10 ); --> internal counter = 10
    INSERT INTO tab VALUES ( 0 );  --> internal counter = 11
    DELETE FROM tab;               --> internal counter = 11
    INSERT INTO tab VALUES ( 0 );  --> internal counter = 12

IBM DB2 has no equivalent for INFORMIX SERIAL columns.

DB2 version 7.1 supports IDENTITY columns:
    CREATE TABLE tab ( k INTEGER GENERATED ALWAYS AS IDENTITY);
To get the last generated IDENTITY value after an INSERT, DB2 provides the following function:
    IDENTITY_VAL_LOCAL( )

DB2 version 8.1 supports SEQUENCES:
    CREATE SEQUENCE sq1 START WITH 100;
To create a new sequence number, you must use the "NEXTVAL FOR" operator:
    INSERT INTO table VALUES ( NEXTVAL FOR sq1, ... )
To get the last generated sequence number, you must use the "PREVVAL FOR" operator:
    SELECT PREVVAL FOR sq1 ...

Solution:

The choices are:

  1. Use IDENTITY columns
  2. Insert triggers using SEQUENCES (works only with DB2 version 8 and higher)

The first solution is faster, but does not allow explicit serial value specification in insert statements; the second solution is slower but allows explicit serial value specification. You can start to use the second solution to make unmodified 4gl programs work on DB2, but you should update your code to use native IDENTITY columns for performance.

The serial emulation type is defined by the following FGLPROFILE entry. The 'native' value defines the IDENTITY column technique and the 'trigseq' defines the trigger technique:

   dbi.database.<dbname>.ifxemul.datatype.serial.emulation = {"native"|"trigseq"}

This entry must be used with:

   dbi.database.<dbname>.ifxemul.datatype.serial = {true|false}

If the datatype.serial entry is set to false, the emulation method specification entry is ignored.

Note: When no entry is specified, the default is SERIAL emulation enabled with 'native' method (IDENTITY-based).

1. Using IDENTITY columns

In database creation scripts, all SERIAL[(n)] data types must be converted by hand to:

    INTEGER GENERATED ALWAYS AS IDENTITY[( START WITH n, INCREMENT BY 1)]

while the SERIAL8 and BIGSERIAL[(n)] types must be converted to:

    BIGINT GENERATED ALWAYS AS IDENTITY[( START WITH n, INCREMENT BY 1)]

Tables created from the BDL programs can use the SERIAL data type : When a BDL program executes a CREATE [TEMP] TABLE with a SERIAL column, the database interface automatically converts the "SERIAL[(n)]" data type to an IDENTITY specification.

In BDL, the new generated SERIAL value is available from the SQLCA.SQLERRD[2] variable. This is supported by the database interface which performs a call to the IDENTITY_VAL_LOCAL() function. However, SQLCA.SQLERRD[2] is defined as an INTEGER, it cannot hold values from BIGINT identity columns. If you are using BIGINT IDENTITY columns, you must use the IDENTITY_VAL_LOCAL() function.

Since IBM DB2 does not allow you to specify the value of IDENTITY columns, it is mandatory to convert all INSERT statements to remove the SERIAL column from the list.
For example, the following statement:
   INSERT INTO tab (col1,col2) VALUES (0, p_value)
must be converted to :
   INSERT INTO tab (col2) VALUES (p_value)
Static SQL INSERT using records defined from the schema file must also be reviewed :
   DEFINE rec LIKE tab.*
   INSERT INTO tab VALUES ( rec.* )   -- will use the serial column
must be converted to :
   INSERT INTO tab VALUES rec.* -- without braces, serial column is removed

2. Using triggers with the SEQUENCE

In database creation scripts, all SERIAL[(n)] data types must be converted to INTEGER data types, SERIAL8/BIGSERIAL must be converted to BIGINT, and you must create a sequence and a trigger for each table using a SERIAL. To know how to write those triggers,  you can create a small Genero program that creates a table with a SERIAL column. Set the FGLSQLDEBUG environment variable and run the program. The debug output will show you the native SQL commands to create the sequence and the trigger.

Tables created from the BDL programs can use the SERIAL data type : When a BDL program executes a CREATE [TEMP] TABLE with a SERIAL column, the database interface automatically converts the "SERIAL[(n)]" data type to "INTEGER" and creates the sequence and the insert trigger.

Note:  IBM DB2 performs NOT NULL data controls before the execution of triggers. If the serial column must be NOT NULL (for example, because it is part of the primary key), you cannot specify a NULL value for that column in INSERT statements.
For example, the following statement :
   INSERT INTO tab VALUES (NULL,p_value)
must be converted to :
   INSERT INTO tab (col2) VALUES (p_value)

Important Notes:


Outer joins

The original OUTER join syntax of INFORMIX is different from the IBM DB2 outer join syntax:

SELECT ... FROM cust, OUTER(order)
 WHERE cust.key = order.custno
SELECT ... FROM cust, OUTER(order,OUTER(item))
 WHERE cust.key = order.custno
   AND order.key = item.ordno
   AND order.accepted = 1
SELECT ... FROM cust LEFT OUTER JOIN order
                     ON cust.key = order.custno
SELECT ...
  FROM cust LEFT OUTER JOIN order
                 LEFT OUTER JOIN item
                 ON order.key = item.ordno
            ON cust.key = order.custno
 WHERE order.accepted = 1

See the IBM DB2 SQL reference for a complete description of the syntax.

Solution:

For better SQL portability, you should use the ANSI outer join syntax instead of the old Informix OUTER syntax.

The IBM DB2 interface can convert most INFORMIX OUTER specifications to IBM DB2 outer joins.

Prerequisites :

  1. In the FROM clause, the main table must be the first item and the outer tables must figure from left to right in the order of outer levels.
       Example which does not work : "FROM OUTER(tab2), tab1".
  2. The outer join in the WHERE clause must use the table name as prefix.
       Example : "WHERE tab1.col1 = tab2.col2".

Restrictions :

  1. Additional conditions on outer table columns cannot be detected and therefore are not supported :
      Example : "... FROM tab1, OUTER(tab2) WHERE tab1.col1 = tab2.col2 AND tab2.colx > 10"
  2. Statements composed by 2 or more SELECT instructions using OUTERs are not supported.
      Example : "SELECT ... UNION SELECT" or "SELECT ... WHERE col IN (SELECT...)"

Notes:


Database concepts

As with INFORMIX, an IBM DB2 database server can handle more than one database entity. INFORMIX servers have an ID (INFORMIXSERVER) and databases are identified by name. IBM DB2 instances are identified by the DB2INSTANCE environment variable and databases have to be cataloged as data sources (see IBM DB2 documentation for more details).


 Data consistency and concurrency management

Data consistency involves readers that want to access data currently modified by writers and concurrency data access involves several writers accessing the same data for modification. Locking granularity defines the amount of data concerned when a lock is set (row, page, table, ...).

INFORMIX

INFORMIX uses a locking mechanism to manage data consistency and concurrency. When a process modifies data with UPDATE, INSERT or DELETE, an exclusive lock is set on the affected rows. The lock is held until the end of the transaction. Statements performed outside a transaction are treated as a transaction containing a single operation and therefore release the locks immediately after execution. SELECT statements can set shared locks according the isolation level. In case of locking conflicts (for example, when two processes want to acquire an exclusive lock on the same row for modification or when a writer is trying to modify data protected by a shared lock), the behavior of a process can be changed by setting the lock wait mode.

Control :

Defaults :

IBM DB2

As in INFORMIX, IBM DB2 uses locks to manage data consistency and concurrency. The database manager sets exclusive locks on the modified rows and shared locks when data is read, according to the isolation level. The locks are held until the end of the transaction. When multiple processes want to access the same data, the latest processes must wait until the first finishes its transaction.  The lock granularity is at the row or table level. For more details, see DB2's Administration Guide, "Application Consideration".

Control :

Defaults :

Solution:

The SET ISOLATION TO ... INFORMIX syntax is replaced by an ODBC API call setting the SQL_ATTR_TXN_ISOLATION connection attribute. The next table shows the isolation level mappings done by the database driver:

SET ISOLATION instruction in program ODBC SQL_ATTR_TXN_ISOLATION connection attribute
SET ISOLATION TO DIRTY READ SQL_TXN_READ_UNCOMMITTED
SET ISOLATION TO COMMITTED READ
  [READ COMMITTED] [RETAIN UPDATE LOCKS]
SQL_TXN_READ_COMMITTED
SET ISOLATION TO CURSOR STABILITY SQL_TXN_REPEATABLE_READ
SET ISOLATION TO REPEATABLE READ SQL_TXN_SERIALIZABLE

For portability, it is recommended that you work with INFORMIX in the read committed isolation level, to make processes wait for each other (lock mode wait) and to create tables with the "lock mode row" option.

See INFORMIX and IBM DB2 documentation for more details about data consistency, concurrency and locking mechanisms.


SELECT FOR UPDATE

A lot of BDL programs use pessimistic locking in order to prevent several users editing the same rows at the same time.

   DECLARE cc CURSOR FOR
         SELECT ... FROM tab WHERE ... FOR UPDATE
   OPEN cc
   FETCH cc <-- lock is acquired
   ...
   CLOSE cc <-- lock is released

In both INFORMIX and DB2, locks are released when closing the cursor or when the transaction ends; DB2's locking granularity is at the row level.

To control the behavior of the program when locking rows:

     SET LOCK MODE TO { WAIT | NOT WAIT | WAIT seconds }

The default mode is NOT WAIT. This as an INFORMIX-specific SQL statement.

Solution:

The database interface is based on an emulation of an INFORMIX engine using transaction logging. Therefore, opening a SELECT ... FOR UPDATE cursor declared outside a transaction will raise an SQL error -255 (not in transaction).

You must review the program logic if you use pessimistic locking because it is based on the NOT WAIT mode which is not supported by IBM DB2.


Transactions handling

INFORMIX and IBM DB2 handle transactions differently. The differences in the transactional models can affect the program logic.

Transactions in stored procedures:

Avoid using transactions in stored procedures to allow the client applications to handle transactions, in accordance with the transaction model.

Savepoints:

    SAVEPOINT name [UNIQUE]
    ROLLBACK [WORK] TO SAVEPOINT [name] ]
    RELEASE SAVEPOINT name
  1. Savepoints must be declared with the ON ROLLBACK RETAIN CURSORS clause
  2. Rollback must always specify the savepoint name

Solution:

The INFORMIX behavior is simulated with an auto-commit mode in the IBM DB2 interface. A switch to the explicit commit mode is done when a BEGIN WORK is performed by the BDL program. Regarding the transaction control instructions, the BDL applications do not have to be modified in order to work with IBM DB2.

Note:  If you want to use savepoints, always specify the savepoint name in ROLLBACK TO SAVEPOINT.

See also SELECT FOR UPDATE


BOOLEAN data type

INFORMIX supports the BOOLEAN data type, which can store 't' or 'f' values. Genero BDL implements the BOOLEAN data type in a different way: As in other programming languages, Genero BOOLEAN stores integer values 1 or 0 (for TRUE or FALSE). The type was designed this way to assign the result of a Boolean expression to a BOOLEAN variable.

IBM DB2 9.x does not implement a BOOLEAN SQL type.

Solution:

The DB2 database interface converts BOOLEAN type to CHAR(1) columns and stores '1' or '0' values in the column.


CHARACTER data types

INFORMIX supports the following character data types:

In INFORMIX, both CHAR/VARCHAR and NCHAR/NVARCHAR data types can be used to store single-byte or multi-byte encoded character strings. The only difference between CHAR/VARCHAR and NCHAR/NVARCHAR is for sorting: N[VAR]CHAR types use the collation order, while [VAR]CHAR types use the byte order. The character set used to store strings in CHAR/VARCHAR/NCHAR/NVARCHAR columns is defined by the DB_LOCALE environment variable. The character set used by applications is defined by the CLIENT_LOCALE environment variable. Note that INFORMIX uses Byte Length Semantics (the size N that you specify in [VAR]CHAR(N) is expressed in bytes, not characters as in some other databases)

IBM DB2 implements the following character data types:

Like INFORMIX, IBM DB2 uses Byte Length Semantics to define the length of CHAR/VARCHAR columns. However, GRAPHIC and VARGRAPHIC lengths are specified in characters (i.e. max number of double-byte characters).

The character set used by DB2 to store CHAR and VARCHAR data is defined in the database locale section when creating a new database with the DB2 Control Center.

DB2 can automatically convert from/to the client and server characters sets. In the client applications, you define the character set with the DB2CODEPAGE profile variable.

Solution:

INFORMIX CHAR(N) types must be mapped to BD2 CHAR(N) types, and INFORMIX VARCHAR(N) or LVARCHAR(N) columns must be mapped to DB2 VARCHAR(N).

Important Notes:

See also the section about Localization.


Constraints

Constraint naming syntax:

Both INFORMIX and BD2 support primary key, unique, foreign key, default and check constraints. But the constraint naming syntax is different : DB2 expects the "CONSTRAINT" keyword before the constraint specification, and INFORMIX expects it after.

UNIQUE constraint example:

INFORMIX IBM DB2
CREATE TABLE scott.emp (
...
empcode CHAR(10) UNIQUE
   [CONSTRAINT pk_emp],
...
CREATE TABLE scott.emp (
...
empcode CHAR(10)
   [CONSTRAINT pk_emp] UNIQUE,
...

Primary keys:

Like INFORMIX, DB2 creates an index to enforce PRIMARY KEY constraints (some RDBMS do not create indexes for constraints).  Using "CREATE UNIQUE INDEX"  to define unique constraints is obsolete (use primary keys or a secondary key instead).

Note: DB2 primary key constraints do not allow NULLs; make sure your tables do not contain NULLs in the primary key columns.

Unique constraints:

Like INFORMIX, DB2 creates an index to enforce UNIQUE constraints (some RDBMS do not create indexes for constraints).

Note: DB2 unique constraints do not allow NULLs; make sure your tables do not contain NULLs in the unique columns.

Foreign keys:

Both INFORMIX and DB2 support the ON DELETE CASCADE option.

Check constraints:

The check condition may be any valid expression that can be evaluated to TRUE or FALSE, including functions and literals. You must verify that the expression is not INFORMIX-specific.

Null constraints:

INFORMIX and DB2 support NOT NULL constraints, but INFORMIX does not allow you to give a name to "NOT NULL" constraints.

Solution:

Constraint naming syntax: The database interface does not convert constraint naming expressions when creating tables from BDL programs. Review the database creation scripts to adapt the constraint naming clauses for DB2.


Triggers

INFORMIX and IBM DB2 provide triggers with similar features, but the trigger creation syntax and the programming languages are totally different.

INFORMIX triggers define which stored procedures must be called when a database event occurs (before | after  insert | update | delete ...), while IBM DB2 triggers can hold a procedural block.

IBM DB2 provides specific syntax to define triggers. See documentation for more details.

Solution:

INFORMIX triggers must be converted to IBM DB2 triggers "by hand".


Stored procedures

Both INFORMIX and IBM DB2 support stored procedures and user functions, but the programming languages are totally different.

INFORMIX implements the SPL language, while DB2 allows you to write stored procedures or user defined functions in the DB2 SQL or with an external language, such as JAVA, C or C++.

Solution:

INFORMIX stored procedures must be converted to IBM DB2 "by hand".


Defining database users

Until version 11.70.xC2, INFORMIX database users had to be created at the operating system level and be members of the 'informix' group. Starting with 11.70.xC2, INFORMIX supports database-only users with the CREATE USER instruction, as in most other db servers. Any database user must have sufficient privileges to connect and use resources of the database; user rights are defined with the GRANT command.

IBM DB2 users are operating system users with a specific DB2 environment. The database administrator must grant the CONNECT authority to these users.

Together, privileges and authorities act to control access to an instance and its database objects. Users can access only those objects for which they have the appropriate authorization, that is, the required privilege or authority.

Note: As in INFORMIX, DB2 user names that connect to the database server must be a maximum of eight characters long.

Solution:

Set up the IBM DB2 environment for each user as described in the documentation.


Setting privileges

INFORMIX and IBM DB2 user privileges management is quite similar.

Solution:

Make sure DB2 users have the right privileges to access the database.

See also Temporary Tables


Temporary tables

INFORMIX temporary tables are created through the CREATE TEMP TABLE DDL instruction or through a SELECT ... INTO TEMP statement. Temporary tables are automatically dropped when the SQL session ends, but they can also be dropped with the DROP TABLE command. There is no name conflict when several users create temporary tables with the same name.

INFORMIX allows you to create indexes on temporary tables. No name conflict occurs when several users create an index on a temporary table by using the same index identifier.

Note: BDL reports create a temporary table when the rows are not sorted externally (by the source SQL statement).

IBM DB2 7 supports the DECLARE GLOBAL TEMPORARY TABLE instruction. Native DB2 temporary tables are quite similar to INFORMIX temporary tables with some exceptions:

For more details, see the DB2 documentation.

Solution:

In accordance with some prerequisites, temporary tables creation in BDL programs can be supported by the database interface.

How does it work ?

Prerequisites:

Limitations:


Substrings in SQL

INFORMIX SQL statements can use subscripts on columns defined with the character data type:
    SELECT ... FROM tab1 WHERE col1[2,3] = 'RO'
    SELECT ... FROM tab1 WHERE col1[10]  = 'R'   -- Same as col1[10,10]
    UPDATE tab1 SET col1[2,3] = 'RO' WHERE ...
    SELECT ... FROM tab1 ORDER BY col1[1,3]

.. while IBM DB2 provides the SUBSTR( ) function, to extract a substring from a string expression:
    SELECT .... FROM tab1 WHERE SUBSTR(col1,2,2) = 'RO'
    SELECT SUBSTR('Some text',6,3) FROM DUAL       -- Gives 'tex'

Solution:

You must replace all INFORMIX col[x,y] expressions by SUBSTR(col,x,y-x+1).

Important Notes:


Name resolution of database objects

Case sensitivity in object names:

   CREATE TABLE Tab1 ( Key INT, Col1 CHAR(20) )
   SELECT COL1 FROM TAB1

   CREATE TABLE tab1 ( Key INT, Col1 CHAR(20) )
       => Table name is "TAB1", column names are "KEY" and "COL1"

   CREATE TABLE "Tab1" ( "Key" INT, "Col1" CHAR(20) )
       => Table name is "Tab1", column names are "Key" and "Col1"

The DB2 schema concept:

With non-ANSI INFORMIX databases, you do not have to give a schema name before the tables when executing an SQL statement.

    SELECT ... FROM <table> WHERE ...

In an IBM DB2 database, tables always belong to a database schema. When executing a SQL statement, a schema name must be used as the high-order part of a two-part object name, unless the current schema corresponds to the table's schema.

The default (implicit) schema is the current user's name but it can be changed with the "SET SCHEMA" instruction.

Example: The table "TAB1" belongs to the schema "SCH1". User "MARK" (implicit schema is "MARK") wants to access "TAB1" in a SELECT statement :

   SELECT ... FROM TAB1 WHERE ...
       => Error "MARK"."TAB1" is an undefined name. SQLSTATE=42704
   SELECT ... FROM SCH1.TAB1 WHERE ...
       => OK.
   SET SCHEMA SCH1
       => Changes the current schema to SCH1.
   SELECT ... FROM TAB1 WHERE ...
       => OK.

Note: When executing the "SET SCHEMA" instruction, the database interface does not use double quotes around the schema name ( = name is converted to uppercase letters). Make sure that the schema name is created with uppercase letters in the database.

DB2 provides "aliases", but they cannot be used to make a database object name public because aliases belong to schemas also.

Solution:

Case sensitivity in object names:

Avoid the usage of double quotes around the database object names. All names will be converted to uppercase letters.

The DB2 schema concept:

After a connection, the database interface can automatically execute a "SET SCHEMA <name>" instruction if the following FGLPROFILE entry is defined:

   dbi.database.<dbname>.db2.schema = "<name>"

Here <dbname> identifies the database name used in the BDL program ( DATABASE dbname ) and <name> is the schema name to be used in the SET SCHEMA instruction. If this entry is not defined, no "SET SCHEMA" instruction is executed and the current schema defaults to the user's name.

Examples:
   dbi.database.stores.db2.schema = "STORES1"
   dbi.database.accnts.db2.schema = "ACCSCH"

Note:  DB2 does not check the schema name when the SET SCHEMA instruction is executed. Setting a wrong schema name results in "undefined name" errors when performing subsequent SQL instructions like SELECT, UPDATE, INSERT.

In accordance with this automatic schema selection, you must create a DB2 schema for your application :

  1. Connect as a user with the DBADM authority.
  2. Create an administrator user dedicated to your application. For example, "STORESADM". Make sure this user has the IMPLICIT_SCHEMA privilege (this is the default in DB2).
  3. Connect as the application administrator "STORESADM" to create all database objects ( tables, indexes, ...). In our example, a "STORESADM" schema will be created implicitly and all database objects will belong to this schema.

As a second option you can create a specific schema with the following SQL command :
  CREATE SCHEMA "<name>" AUTHORIZATION "<appadmin>"
 

See the IBM DB2 manuals for more details about schemas.


String delimiters

The ANSI string delimiter character is the single quote ( 'string'). Double quotes are used to delimit database object names ("object-name").

Example: WHERE "tabname"."colname" = 'a string value'

INFORMIX allows double quotes as string delimiters, but IBM DB2 doesn't. This is important since many BDL programs use that character to delimit the strings in SQL commands.

This problem concerns only double quotes within SQL statements. Double quotes used in pure BDL string expressions are not subject to SQL compatibility problems.

Solution:

The IBM DB2 database interface can automatically replace all double quotes by single quotes. However, we recommend that you use only single quotes to enforce portability.

Escaped string delimiters can be used inside strings as in the following :

     'This is a single quote : '''
     'This is a single quote : \''
     "This is a double quote : """
     "This is a double quote : \""

Database object names cannot be delimited by double quotes because the database interface cannot determine the difference between a database object name and a quoted string!

For example, if the program executes the SQL statement:
   WHERE "tabname"."colname" = "a string value"
replacing all double quotes by single quotes would produce:
   WHERE 'tabname'.'colname' = 'a string value'
This would produce an error since 'tabname'.'colname' is not allowed by IBM DB2.


NUMERIC data types

INFORMIX provides the following data types to store numbers :

INFORMIX Data Type Description
SMALLINT 16 bit signed integer
INT / INTEGER 32 bit signed integer
BIGINT 64 bit signed integer
INT8 64 bit signed integer (replaced by BIGINT)
DEC / DECIMAL Equivalent to DECIMAL(16)
DEC(p) / DECIMAL(p) Floating-point decimal number
DEC(p,s) / DECIMAL(p,s) Fixed-point decimal number
MONEY Equivalent to DECIMAL(16,2)
MONEY(p) Equivalent to DECIMAL(p,2)
MONEY(p,s) Equivalent to DECIMAL(p,s)
REAL / SMALLFLOAT 32-bit floating point decimal (C float)
DOUBLE PRECISION / FLOAT[(n)] 64-bit floating point decimal (C double)

Most data types supported by IBM DB2 UDB are compatible to Informix data types. DB2 V 9.1 introduces the DECFLOAT(16) and DECFLOAT(34) floating point decimal types to store large decimals. The next table lists the Informix types and DB2 equivalents.

INFORMIX Data Type IBM DB2 equivalent
INT8 Use BIGINT instead
DECIMAL(p) With DB2 V9.1, DECIMAL(p<=16) can be stored in DECFLOAT(16) and DECIMAL(p>16) can be stored in DECFLOAT(34).
With older versions of DB2, we can use DECIMAL(p*2,p), but with a limitation of 15 for the original Informix DECIMAL precision.
DECIMAL(32,s) DB2 decimals maximum precision is 31 digits!
MONEY DECIMAL(16,2)
MONEY(p) DECIMAL(p,2)
MONEY(p,s) DECIMAL(p,s)
SMALLFLOAT REAL
FLOAT[(n)] FLOAT[(n)]  (DOUBLE)

Solution:

SQL scripts to create databases must be converted manually. Tables created from BDL programs do not have to be converted; the database interface detects the MONEY data type and uses the DECIMAL type for DB2.

The maximum precision for DB2 decimals is 31 digits, while INFORMIX supports 32 digits:

When using DB2 V8 and prior: There is no DB2 equivalent for the INFORMIX DECIMAL(p) floating point decimal (i.e. without a scale). If your application is using such data types, you must review the database schema in order to use DB2 compatible types. To workaround the DB2 limitation, the DB2 database drivers convert DECIMAL(p) types to a DECIMAL( 2*p, p ), to store all possible numbers an INFORMIX DECIMAL(p) can store. However, the original INFORMIX precision cannot exceed 15 ((2*15) = 30), since DB2 maximum DECIMAL precision is 31. If the original precision is bigger than 15, a CREATE TABLE statement executed from a Genero program will fail with a DB2 SQLSTATE 42611.

When using DB2 V9.1 and higher: The DECIMAL(p) data type is converted to DECFLOAT(16) (for p<=16) or DECFLOAT(34) (for p>16) to store floating point decimals. Note that if you create tables with DECFLOAT columns, you will lose the original DECIMAL precision when extracting the schema with fgldbsch, because IBM DB2 supports only two precision specifications (16 or 34). Note also the DECFLOAT(34) will be extracted as DECIMAL(32), since the Genero DECIMAL type has a maximum precision of 32 digits.


Getting one row with SELECT

With INFORMIX, you must use the system table with a condition on the table id :

   SELECT user FROM systables WHERE tabid=1

With IBM DB2, you have to do the following :

   SELECT user FROM SYSIBM.SYSTABLES WHERE NAME='SYSTABLE'

Solution:

Check the BDL sources for "FROM systables WHERE tabid=1" and use dynamic SQL to resolve this problem.


MATCHES and LIKE in SQL conditions

INFORMIX supports MATCHES and LIKE in SQL statements, while IBM DB2 supports the LIKE statement only.

MATCHES allows you to use brackets to specify a set of matching characters at a given position :
   ( col MATCHES '[Pp]aris' ).
   ( col MATCHES '[0-9][a-z]*' ).
In this case, the LIKE statement has no equivalent feature.

The following substitutions must be made to convert a MATCHES condition to a LIKE condition :

Solution:

SQL statements using MATCHES expressions must be reviewed in order to use LIKE expressions.

See also: MATCHES operator in SQL Programming.


INFORMIX specific SQL statements in BDL

The BDL compiler supports several INFORMIX-specific SQL statements that have no meaning when using IBM DB2:  

Solution:

Review your BDL source and remove all static SQL statements that are INFORMIX-specific.


INSERT cursors

INFORMIX supports insert cursors. An "insert cursor" is a special BDL cursor declared with an INSERT statement instead of a SELECT statement. When this kind of cursor is open, you can use the PUT instruction to add rows and the FLUSH instruction to insert the records into the database.

For INFORMIX databases with transactions, OPEN, PUT and FLUSH instructions must be executed within a transaction.

IBM DB2 does not support insert cursors.

Solution:

Insert cursors are emulated by the IBM DB2 database interface.


SQL functions and constants

Both INFORMIX and DB2 provide numerous built-in SQL functions. Most INFORMIX SQL functions have the same name and purpose in DB2 ( DAY(), MONTH(), YEAR(), UPPER(), LOWER(), LENGTH() ).

INFORMIX IBM DB2
today current date
current hour to second current time
current year to fraction(5) current timestamp
trim( [leading | trailing | both "char" FROM] "string") ltrim( ) and rtrim( )
pow(x,y) power(x,y)

Solution:

You must review the SQL statements using TODAY / CURRENT / EXTEND expressions.

You can create user defined functions ( UFs ) in the DB2 database.


Very large data types

Both INFORMIX and IBM DB2 provide special data types to store very large texts or images.

IBM DB2 supports the following large object types:

Solution:

The DB2 database interface can convert BDL TEXT data to CLOB and BYTE data to BLOB. Note that DB2 CLOB and BLOB columns are created with a size of 500K, while Genero TEXT/BYTE program variables have a limit of 2 gigabytes; make sure that the large object data does not exceed this limit.


Cursors WITH HOLD

INFORMIX provides the WITH HOLD option to prevent cursors being closed when a transaction ends.

This feature is well supported when using the DB2 interface, except when a transaction is canceled with a ROLLBACK, because DB2 automatically closes all cursors when you rollback a transaction.

Solution:

Check that your source code does not use  WITH HOLD cursors after transactions canceled with ROLLBACK.


Querying system catalog tables

As in INFORMIX, IBM DB2 provides system catalog tables (systables,syscolumns,etc.) in each database, but the table names and their structures are quite different.

Solution:

No automatic conversion of INFORMIX system tables is provided by the database interface.


INTERVAL data type

INFORMIX INTERVAL data type stores a value that represents a span of time. INTERVAL types are divided into two classes : year-month intervals and day-time intervals.

DB2 does not provide a data type corresponding the INFORMIX INTERVAL data type.

Solution:

The INTERVAL data type is not well supported because the database server has no equivalent native data type. However, BDL INTERVAL values can be stored into and retrieved from CHAR columns.


Data storage concepts

An attempt should be made to preserve as much of the storage information as possible when converting from INFORMIX to IBM DB2. Most important storage decisions made for INFORMIX database objects (like initial sizes and physical placement) can be reused for the IBM DB2 database.

Storage concepts are quite similar in INFORMIX and in IBM DB2, but the names are different.

The following table compares INFORMIX storage concepts to IBM DB2 storage concepts :

INFORMIX IBM DB2
Physical units of storage
The largest unit of physical disk space is a "chunk", which can be allocated either as a cooked file ( I/O is controlled by the OS) or as raw device (=UNIX partition, I/O is controlled by the database engine). A "dbspace" uses at least one "chunk" for storage.
You must add "chunks" to "dbspaces" in order to increase the size of the logical unit of storage.
One or more "containers" are created for each "tablespace" to physically store the data of all logical structures. Like INFORMIX "chunks", "containers" can be an OS file or a raw device.
You can add "containers" to a "tablespace" in order to increase the size of the logical unit of storage or you can define EXTEND options.
A "page" is the smallest physical unit of disk storage that the engine uses to read from and write to databases.
A "chunk" contains a certain number of "pages".
The size of a "page" must be equal to the operating system's block size.
At the finest level of granularity, IBM DB2 stores data in "data blocks" with size corresponding to a multiple of the operating system's block size.
You set the "data block" size when creating the database.
An "extent" consists of a collection of contiguous "pages" that the engine uses to allocate both initial and subsequent storage space for database tables.
When creating a table, you can specify the first extent size and the size of future extents with the EXTENT SIZE and NEXT EXTENT options.
For a single table, "extents" can be located in different "chunks" of the same "dbspace".
An "extent" is a specific number of contiguous "data blocks", obtained in a single allocation.
When creating a table, you can specify the first extent size and the size of future extents with the STORAGE() option.
For a single table, "extents" can be located in different "data files" of the same "tablespace".
Logical units of storage
A "table" is a logical unit of storage that contains rows of data values. Same concept as INFORMIX.
A "database" is a logical unit of storage that contains table and index data. Each database also contains a system catalog that tracks information about database elements like tables, indexes, stored procedures, integrity constraints and user privileges. Same concept as INFORMIX.

An IBM DB2 instance can manage several databases.
Database tables are created in a specific "dbspace", which defines a logical place to store data.
If no dbspace is given when creating the table, INFORMIX defaults to the current database dbspace.
Database tables are created in a specific "tablespace", which defines a logical place to store data. The main difference with INFORMIX "dbspaces", is that IBM DB2 tablespaces belong to a  "database", while INFORMIX "dbspaces" are external to a database.
Other concepts
When initializing an INFORMIX engine, a "root dbspace" is created to store information about all databases, including storage information (chunks used, other dbspaces, etc.). Each IBM DB2 database uses a set of "control files" to store internal information. These files are located in a dedicated directory : ".../$DB2INSTANCE/NODEnnnn"
The "physical log" is a set of continuous disk pages where the engine stores "before-images" of data that has been modified during processing.

The "logical log" is a set of "logical-log files" used to record logical operations during on-line processing. All transaction information is stored in the logical log files if a database has been created with transaction log.

INFORMIX combines "physical log" and "logical log" information when doing fast recovery. Saved "logical logs" can be used to restore a database from tape.

DB2 uses "database log files" to record SQL transactions.

SQL parameters limitation

The IBM DB2 SQL parser does not allow some uses of the '?' SQL parameter marker.

The following SQL expressions are not supported :

     ? IS [NOT] NULL
     ? <operator> ?
     <function>( ? )

SQL instructions containing these expressions raise an error during the statement preparation.

Solution:

Check that your BDL programs do not use these types of conditional expressions.

If you really need to test a BDL variable during the execution of a SQL statement, you must use the CAST() function for DB2 only :
    WHERE CAST( ? AS INTEGER ) IS NULL
See the DB2 documentation for more details.


The LOAD and UNLOAD instructions

INFORMIX provides two SQL instructions to export / import data from / into a database table: The UNLOAD instruction copies rows from a database table into an text file, and the LOAD instruction inserts rows from an text file into a database table.

IBM DB2 does not provide LOAD and UNLOAD instructions.

Solution:

LOAD and UNLOAD instructions are supported.

Note: There is a difference when using DB2 TIME and TIMESTAMP columns: TIME columns created in the IBM DB2 database are similar to INFORMIX DATETIME HOUR TO SECOND columns. In LOAD and UNLOAD, all DB2 TIME columns are treated as INFORMIX DATETIME HOUR TO SECOND columns and thus will be unloaded with the "hh:mm:ss"  format.


Set up database statistics

INFORMIX provides a special instruction to compute database statistics in order to improve query optimization plans :

     UPDATE STATISTICS [options]

IBM DB2 provides the following equivalent:

     RUNSTATS ON TABLE full-qualified-table-name [options]

Note: RUNSTATS is not a SQL instruction, it is a DB2 command and therefore cannot be executed from a BDL program.

Solution:

You must execute the RUNSTATS command manually from a DB2 Command Center.


The GROUP BY clause

INFORMIX allows you to use column numbers in the GROUP BY clause

     SELECT ord_date, sum(ord_amount) FROM order GROUP BY 1

IBM DB2 does not support column numbers in the GROUP BY clause.

Solution:

Use column names instead:

     SELECT ord_date, sum(ord_amount) FROM order GROUP BY ord_date


The ALTER TABLE instruction

INFORMIX and IBM DB2 use different implementations of the ALTER TABLE instruction. For example:

INFORMIX:
     ALTER TABLE customer ADD(col1 INTEGER), ADD(col2 CHAR(20))
IBM DB2:
     ALTER TABLE customer ADD col1 INTEGER  ADD col2 CHAR(20)

INFORMIX:
     ALTER TABLE customer MODIFY ( col1 INTEGER )
IBM DB2:
     ALTER TABLE customer ALTER COLUMN col1 SET DATA TYPE VARCHAR(200)

Solution:

 No automatic conversion is done by the database interface. Read the SQL documentation and review the SQL scripts or the BDL programs in order to use the database server specific syntax for ALTER TABLE.


The star (asterisk) in SELECT statements

INFORMIX allows you to use the star character in the select list along with other expressions :

   SELECT col1, * FROM tab1 ...

IBM DB2 does not support this. You must use the table name as a prefix to the star :

   SELECT col1, tab1.* FROM tab1 ...

Solution:

Always use the table name with stars.


The LENGTH() function

INFORMIX provides the LENGTH() function:

    SELECT LENGTH("aaa"), LENGTH(col1) FROM table

IBM DB2 has a equivalent function with the same name, but there is some difference:

Solution:

You must check if the trailing blanks are significant when using the LENGTH() function.

If you want to count the number of characters by ignoring the trailing blanks, you must use the RTRIM() function:

    SELECT LENGTH(RTRIM(col1)) FROM table


SQL Interruption

With INFORMIX, it is possible to interrupt a long running query if the SQL INTERRUPT ON option is set by the Genero program. The database server returns SQLCODE -213, which can be trapped to detect a user interruption.

    MAIN
      DEFINE n INTEGER
      DEFER INTERRUPT
      OPTIONS SQL INTERRUPT ON
      DATABASE test1
      WHENEVER ERROR CONTINUE
      -- Start long query (self join takes time)
      -- From now on, user can hit CTRL-C in TUI mode to stop the query
      SELECT COUNT(*) INTO n FROM customers a, customers b
           WHERE a.cust_id <> b.cust_id
      IF SQLCA.SQLCODE == -213 THEN
         DISPLAY "Statement was interrupted by user..."
         EXIT PROGRAM 1
      END IF
      WHENEVER ERROR STOP
      ...
    END MAIN

DB2 UDB 9 supports SQL Interruption in a similar way as INFORMIX. The db client must issue an SQLCancel() ODBC call to interrupt a query.

Solution:

The DB2 database driver supports SQL interruption and converts the native SQL error code -952 to the INFORMIX error code -213.


Scrollable Cursors

The Genero programming language supports scrollable cursors with the SCROLL keyword, as shown in the following code example: 

   DECLARE c1 SCROLL CURSOR FOR SELECT * FROM customers ORDER BY cust_name
   ...
   FETCH FIRST c1 INTO rec_cust.*
   ...
   FETCH NEXT c1 INTO rec_cust.*
   ...
   FETCH LAST c1 INTO rec_cust.*

DB2 UDB supports native scrollable cursors.

Solution:

The DB2 database driver uses the native DB2 scrollable cursors by setting the CLI statement attribute SQL_ATTR_CURSOR_TYPE to SQL_CURSOR_STATIC.


Data type conversion table

INFORMIX Data Types DB2 Data Types (V<9.1) DB2 Data Types (V>=9.1)
CHAR(n) CHAR(n) (limit = 254c!) CHAR(n) (limit = 254c!)
VARCHAR(n[,m]) VARCHAR(n) (limit = 32672c!) VARCHAR(n) (limit = 32672c!)
LVARCHAR(n) VARCHAR(n) (limit = 32672c!) VARCHAR(n) (limit = 32672c!)
NCHAR(n) N/A N/A
NVARCHAR(n[,m]) N/A N/A
BOOLEAN CHAR(1) CHAR(1)
SMALLINT SMALLINT SMALLINT
INT / INTEGER INTEGER INTEGER
BIGINT BIGINT BIGINT
INT8 BIGINT BIGINT
SERIAL[(start)] INTEGER (see notes) INTEGER (see notes)
BIGSERIAL[(start)] BIGINT (see notes) BIGINT (see notes)
SERIAL8[(start)] BIGINT (see notes) BIGINT (see notes)
DOUBLE PRECISION / FLOAT[(n)] FLOAT[(n)] / DOUBLE FLOAT[(n)] / DOUBLE
REAL / SMALLFLOAT REAL REAL
NUMERIC / DEC / DECIMAL(p,s) DECIMAL(p,s) (limit = 31 digits) DECIMAL(p,s) (limit = 31 digits)
NUMERIC / DEC / DECIMAL(p) with p<=15 DECIMAL(2*p,p) DECFLOAT(16)
NUMERIC / DEC / DECIMAL(p) with p>15 N/A DECFLOAT(16) if p=16,
DECFLOAT(34) if p>16
NUMERIC / DEC / DECIMAL N/A DECFLOAT(34)
MONEY(p,s) DECIMAL(p,s) (limit = 31 digits) DECIMAL(p,s) (limit = 31 digits)
MONEY(p) DECIMAL(p,2) (limit = 31 digits) DECIMAL(p,2) (limit = 31 digits)
MONEY DECIMAL(16,2) DECIMAL(16,2)
DATE DATE DATE
DATETIME HOUR TO SECOND TIME TIME
DATETIME q1 TO q2 (different from above) TIMESTAMP TIMESTAMP
INTERVAL q1 TO q2 CHAR(50) CHAR(50)
TEXT CLOB(500K) CLOB(500K)
BYTE BLOB(500K) BLOB(500K)

Connecting to DB2 OS/400

Note : Some of the following actions can be taken via the OS/400 Operations Navigator.

DB2 Architecture on OS/400

On OS/400 machines, the DB2 Universal Database is integrated to the operating system. Therefore, some concepts change. For example, the physical organization of the database is quite different from UNIX or Windows platforms.

Common terms:

SQL Terms DB2 OS/400 Terms
Table Physical file
Row Record
Column Field
Index Keyed logical file, access path
View Non keyed logical file
Schema Library, Collection, Schema (OS/400 V5R1 only)
Log Journal
Isolation Level Commitment control level

A Collection is a library containing a Journal, Journal Receivers, Views on the database catalogues.

Login to the AS/400 server

First, login to the AS/400 machine with a 5250 display emulation. All the commands are executed in the 5250 display emulation (or telnet connection).

Collection (Schema) Creation

A collection or library in DB2 for OS/400 is equivalent to a schema in DB2 for UNIX.

  1. Launch "Interactive SQL"

STRSQL COMMIT(*NONE)

  1. Create a Collection

CREATE COLLECTION
Press F4
Enter field values:
    LIBRARY : name of the collection (Schema)
    ASP : 1
    WITH DATA DICTIONARY : Y
Press ENTER
Press F3 to quit ( choose Option 1 (save and exit) ). 

Note: The name of the Schema should not begin with “Q”; libraries beginning with “Q” are system libraries.

This procedure creates:

Source Physical File Creation

Each table in the database is stored in a Physical file. They can be created in the control center with SQL scripts (CREATE TABLE), or with OS/400 commands.

The table creation script file must be copied in the library in the form: library/sourcefile.member

Creation of a physical file:

Type:
    CRTSRCPF
Enter field values:
    FILE = name of the table (10 characters max).
    LIBRARY = name of the library in which the table is created (schema).
    RECORD LENGTH = length of the script creation file (in bytes)
    MEMBER = *FILE

Execution of the SQL creation script:

Type
    RUNSQLSTM
Press F10 for additional parameters
Enter field values:
    SOURCE FILE = name of the source file of the script creation file
    LIBRARY = name of the library (schema)
    SOURCE MEMBER = name of the member of the script creation file
    NAMING FIELD = *SQL (SQL Naming convention library.table)
    COMMITMENT CONTROL = *NONE
    IBM SQL FLAGGING FIELD = *FLAG

If errors occur, you can use WRKSPLF to display error information saved in the spool file. Use option 5 in the Opt Field on the line of the script file you tried to execute.

Trigger Creation

With DB2 on OS/400, triggers need to be external programs written in a high level language such as C, COBOL, RPG, or PL/I.

To create a trigger, use the following steps:

  1. Create an OS/400 Source file for the trigger programs

Create a source physical file on your AS/400 for the trigger programs. Each trigger program will be stored in a separate member within this source file.

Type:
    CRTSRCPF FILE(library/file)
where:
    - library : name of the library you created for your new database
    - file : name you want to call the trigger source physical file

The file name should be ten characters or fewer.

  1. Create a member for each trigger program

Create a source file member for each trigger program. After the creation of trigger programs (in the next step), the programs will be forwarded to these members. 

Type:
     ADDPFM
Enter field values:
    FILE = name of the source file you just created
    LIBRARY = name of the library you created for your database
    MEMBER = name you want to give the trigger source member

Repeat this operation for each trigger.

  1. Create trigger programs in an OS/400 supported high level language

The OS/400-compatible languages include: ILE C/400, ILE COBOL, ILE RPG, COBOL, PL/I, and RPG.
The script creation file of the trigger should be send via FTP into library/sourcefile.member, where sourcefile and member are the values specified in the previous step.

  1. Compile the trigger programs

Once the trigger programs are in AS/400 members, you can compile them. Use whichever compiler is appropriate for the language you used to create the trigger program.

  1. Bind the trigger programs

After you compile the trigger programs, "bind" each compiled program file. Binding will establish a relationship between the program and any tables or views the program specifies.

Type:
    CRTPGM PGM (library/program) ACTGRP(*CALLER)
where:
    library is the name of the library you created for your new database
    program is the name of the compiled trigger program

Repeat this operation for each trigger.

  1. Add the trigger programs to physical files

The final step for migrating triggers is to add each program to a physical file. This will tie the trigger program to the table that calls it.

Type:
    ADDPFTRG
Enter field values:
    PHYSICAL FILE = name of the table you want to attach the trigger to
    PHYSICAL FILE LIBRARY = name of the database library
    TRIGGER TIME = either *BEFORE or *AFTER.
    TRIGGER EVENT = *INSERT, *DELETE, or *UPDATE.
    PROGRAM = name of the compiled program file
    PROGRAM LIBRARY = name of the database library.
    REPLACE TRIGGER = *YES.
    ALLOW REPEATED CHANGES = *YES.

Note: The trigger program should be in the same library as the database.

The trigger program is now tied to the table specified in the Physical File field and will be called each time the database action you specified above occurs. The trigger program may be called from interactive SQL, another AS/400 program, or an ODBC insert, delete, update, or procedure call.

Permission Definition

On OS/400, database security is managed at the operating system level, not at the database level. When you set up permissions for the database, you determine the degree of access (read, add, delete, etc.) individual users, groups, and authorization lists may have. This operation can easily be done via Operation Navigator.

The privileges must include the following system authorities:

To define a foreign key, the privileges must include the following on the parent table: 

The REFERENCES privilege on a table consists of:

The REFERENCES privilege on a column consists of:

To EXECUTE a user-defined function, the privilege consists of:

Relational DB Directory Entry Creation

The relational database directory is equivalent to the database directory of the DB2 client. This is necessary to access the database with DRDA clients (Distributed Relational Database Architecture) like DB2 client.

Use the WRKRDBDIRE tool to add the entry in the database directory:

Start the DDM server on the OS/400 which listens on the DRDA 446 port:

Start the database server:

The DDM/DRDA server that listens on TCP/IP port 446 handles requests from a DRDA client (examples are DB2 Connect or another AS/400).

The database server is not needed for DRDA clients, but it is needed for Client Access.

If a TCP/IP connection is desired, then your AS/400 server cannot have a release prior to V4R2 installed.

To manually configure the connection via the DB2 command line, you will need to enter catalog commands:

> db2 catalog tcpip node <node-name> remote <as400-adress> server 446
> db2 catalog db <db-name-alias> at node <node-name> authentication dcs
> db2 catalog dcs db <db-name-alias> as <local-RDB-name-of-AS400>

If you catalogue the DB2 UDB for iSeries server incorrectly, you may get an SQL5048N error message. SQL7008N is another common error in that the DB2 UDB for iSeries tables being accessed on the server are not being journaled. To correct the SQL7008N error, you need to start journaling your tables or change the isolation level to No Commit.

The proper CCSID value (normally 37 for US English customers) is needed for any tables on the iSeries accessed via DB2 Connect. You can view the CCSID value with the DSPFD CL command or Operations Navigator. CCSID values can be changed with the ALTER TABLE statement or CHGPF CL command. Furthermore, to successfully connect, you may need to change one of the following: the CCSID of the job, the CCSID of the user profile used, or the system CCSID value (QCCSID) if it's the default 65535.

DB2 Client Configuration on Windows

To configure a DB2 client on Windows platforms, use the Client Configuration Assistant. This tool is available only under Microsoft Windows. Under Unix, you have to use the command line as described in the previous chapter.

1. Source:

- Select “Manually configure a connection to a database”.

2. Protocol:

- Select “TCP/IP”.

- Check “The database physically resides on a host or AS/400 System”.

3. TCP/IP:

- Host Name : AS/400 system name.

- Port Number : Port where DDM/DRDA server is listening (default : 446).

4. Database:

- Database name : name defined in the relational database directory entries (with WRKRDBDIRE).

5. ODBC:

- You can register the database as an ODBC data source. Not needed for DRDA connection used by ODI.

6. Node Options:

- Optional, but needed to access the database via the control center.

- System name : AS/400 system name.

- Instance name : not used for a connection to AS400 (because only one instance is running on an AS/400).

- Operating System : OS/400.

7. Security Options:

- Optional.

8. Host or AS400 Options:

- Optional.

Differences Between DB2 UNIX & DB2 OS/400

Some of the differences between DB2 for Unix/Windows and DB2 for OS/400 are:

Naming Conventions

The naming convention defines how database tables are identified.

DB2 OS/400 can use two kinds of naming conventions: