Oracle to IBM Informix Server Porting Guide

103
IBM Software Group IBM Information Management Version 1.6 1 Oracle to IBM Informix Server Porting Guide A discussion of porting issues and Informix Server 11 Prepared By: Business Partner Technical Enablement Competitive Technologies and Enablement IBM Data Servers, IBM Software Group June 2012

Transcript of Oracle to IBM Informix Server Porting Guide

Page 1: Oracle to IBM Informix Server Porting Guide

IBM Software Group IBM Information Management

Version 16 1

Oracle to IBM Informix Server Porting Guide A discussion of porting issues and Informix Server 11 Prepared By

Business Partner Technical Enablement Competitive Technologies and Enablement IBM Data Servers IBM Software Group June 2012

IBM Software Group IBM Information Management

Version 16 2

copy Copyright IBM Corporation 2012 All Rights Reserved

Trademarks IBM AIX DB2 DB2 Universal Database Informix and iSeries are trademarks of the International Business Machines Corporation in the United States other countries or both UNIX and Unix-based trademarks and logos are trademarks or registered trademarks of The Open Group Intel and Intel-based trademarks and logos are trademarks or registered trademarks of Intel Corporation Windows is a trademark of Microsoft Corporation in the United States and other countries or both Linux is a registered trademark of Linus Torvalds in the United States other countries or both Oracle and Java are registered trademarks of Oracle andor its affiliates Other company product or service names may be the trademarks or service marks of others

Disclaimer References in this publication to IBM products or services do not imply that IBM intends to make them available in all countries in which IBM operates

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

The use of this information or the implementation of any of these techniques is your responsibility and depends on your ability to evaluate and integrate them into your operational environment While each item may have been reviewed by IBM for accuracy in a specific situation there is no guarantee that the same or similar results will be obtained elsewhere Customers attempting to adapt these techniques to their own environments do so at their own risk

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 andor changes in the product(s) andor the program(s) described in this publication at any time without notice

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

The information in this white paper is provided AS IS without warranty Such information was obtained from publicly available sources is current as of December 2011 and is subject to change Any performance data included in the paper was obtained in the specific operating environment and is provided as an illustration Performance in other operating environments may vary More specific information about the capabilities of products described should be obtained from the suppliers of those products

IBM Software Group IBM Information Management

Version 16 3

Document History Revision History

Authoring Original Document (May 2000) Glen Black Frank Martino amp Tim Tobey Informix Software Incorporated Partner Engineering Organization Revisions for Informix Dynamic Server2000 Version 6 (July 2000) Tim Tobey Informix Software Incorporated Partner Engineering Organization Updated to IBM Informix Dynamic Server Database Version 9 Release 4 (February 2004) Christine Normile Informix Dynamic Server Product Manager IBM Software Group Information Management Updated material for Sequence Objects (December 2004) Sam Marino DB2 Business Partner Technical Enablement IBM Information Management Solutions IBM Software Group Updated to IBM Informix Dynamic Server Database Version 1000 (January 2006) Sam Marino Business Partner Technical Enablement ndash Data Services IBM Information Management IBM Software Group Updated to IBM Informix Dynamic Server Database Version 1110 (December 2007) Sam Marino IBM Business Partner Technical Enablement ndash Data Services IBM Information Management IBM Software Group Updated material for delimited identifiers metadata extraction type conversion and miscellaneous (June 2012) Chris Golledge IBM Information Management IBM Software Group

Contributions Technical Reviewers Keshava Murthy IBM Informix Database Server Development IBM Software Group Information Management Lakshman Sakaray IBM Database Migration Toolkit IBM Software Group Information Management

IBM Software Group IBM Information Management

Version 16 4

Table of Contents

C H A P T E R 1 INTRODUCTION 8

PURPOSE 8 PRODUCT OVERVIEW 8 ORGANIZATION 8 CONVENTIONS 9

C H A P T E R 2 DEFINING THE PROBLEM SPACE 11

EXTRACTING THE OBJECTS TO BE MIGRATED 11 Working With Oracle Dump Files 11

C H A P T E R 3 DATA DEFINITION LANGUAGE 15

IDENTIFIERS 15 Delimited identifiers 15 Explicit versus implicit schemaowner names 17 Reserved words or keywords 18 Summary 19

DATABASES 19 Databases database names and instances 19 ANSI vs non-ANSI 20

TABLESPACES AND DBSPACES 20 TABLES 21

Attributes and general syntax 21 Lock mode 21 Storage 21 Constraints 22 ALTER TABLE 22 Data Partitioning 23

DATA TYPES 25 Numeric 25 CHAR VARCHAR and LVARCHAR 26 Date and Time 27 Interval 27 Raw data and Large Objects 28 ROWID 28 User-defined types 29 Complex data types 30

SEQUENCE OBJECTS 30 Oracle sequences 30 Informix sequences 30

INDEXES 30 Composite indexes 30 Maximum key size 31 Index fragmentation 31 General index information 31

VIEWS 32 STORED PROCEDURES AND TRIGGERS 32 ORACLE EXTENSIONS 33

C H A P T E R 4 DATA MANIPULATION LANGUAGE 34

SQL 34 Labels using keywords 34 Inequality operations 34 Selects 34 Optimizer directives 34

IBM Software Group IBM Information Management

Version 16 5

External optimizer directives 35 Inserts 36 Temporary tables 36 Outer joins 36 Sorts 36 Exceptions 37 Correlation names 37 Aliases 37 Hierarchical queries 37 Truncate 39

HOST VARIABLES 40 DATE AND TIME FUNCTIONS 41

SYSDATE 41 Number formats 41 Date formats 42 The RR date format element 43

USER-DEFINED ROUTINES 43 COMPATIBLE SQL FUNCTIONS 43 AGGREGATE FUNCTIONS 43 MATHEMATICAL FUNCTIONS 44 STRING FUNCTIONS 44

LENGTH 44 LTRIM and RTRIM 44 Oracle Extensions 44

OTHER ORACLE FUNCTIONS 44 MACROS 45

ISOPEN and NOT FOUND 45 ROWTYPE 45 TYPE 45

PSEUDO-COLUMNS 45 LEVEL 46 ROWID 46 ROWNUM 46

UPDATE USING CURSORS 49 SYSTEM TABLES 50 STORED PROCEDURES 50

Size limit 50 Parameter limit 50 Packages 51 Routines 51 Exceptions 51 Error handling 52 Cursors 52 Variable declaration and assignment 53 Boolean 53 Binary data types 53 Dynamic SQL 53 Compiler 53

TRIGGERS 54 CONSTRAINTS 55 DUAL TABLE 55

C H A P T E R 5 EMBEDDED SQL 57

HOST VARIABLES 57 Declaration override 57 Arrays 57 Formatting 58

SQL STRUCTURES 59

IBM Software Group IBM Information Management

Version 16 6

SQLCA 59 SQLDA 60 ORACA 61

PRE-COMPILER OPTIONS 61 EMBEDDED PLSQL 61 ORACLE CALL INTERFACE 61

Database library calls 62 Global area processing 62 Fetch cycle 62 RAW binary data type processing 62 Parameter bindings 62

EMBEDDED SQL FOR C 63 VARCHAR 63 Host variables 63

EMBEDDED SQL FOR COBOL 63 VARCHAR 63 Level 88 64 SQLDA 64 REDEFINES 64 Tips 64

ODBC 64

C H A P T E R 6 APPLICATION ARCHITECTURE 65

TRANSACTION PROCESSING 65 Autonomous Transaction 66 Savepoints 67

CONCURRENCY 67 Row Level Locking 67 Transaction Isolation Level 68

C H A P T E R 7 SECURITY 70

USER AUTHENTICATION 70 Operating system security 70 Non-operating system security 70

ROLE BASED AUTHORITY 71 COLUMN-LEVEL ENCRYPTION 71

Passwords and hints 71 Encrypting a column 72 Querying an encrypted column 72 Performance impact of encryption 73 Storage considerations 73 Compliance regulations 73

C H A P T E R 8 ENVIRONMENT 74

SCRIPTS 74 SQL script substitution variables 74

UTILITIES 75 SYSTEM CATALOG 75

C H A P T E R 9 USING BLADELETS 76

WHAT IS A BLADELET 76 INFORMIX EXEC BLADELET FOR DYNAMIC SQL 77 SQLLIB DATABLADE MODULE (SQLLIBC11 SQLLIBJ11) 78

A P P E N D I X A PLANNING GUIDE 79

A P P E N D I X B SYNTAX COMPARISON 82

IBM Software Group IBM Information Management

Version 16 7

A P P E N D I X C DATABASE CONCEPTS 84

A P P E N D I X D SAMPLE CODE 85

DATE ARITHMETIC 88 UNITS Keyword 88 Using EXTEND function 88

STRING REPRESENTATION OF DATE AND TIME 88 Day and date 88 Abbreviation of day of week 88

USING AN INFORMIX COLLECTION DATA TYPE 89 A collection data type as a VARRAY 89 Using MULTISET and ROW to replace PLSQL TABLE and RECORD types 91

A P P E N D I X E COUNTING SYSTEM OBJECTS 93

USING THE SYSTEM CATALOG 93 System catalog 93

USING SQL CODE 94 Built-in function references 94 Object types and counts 95

A P P E N D I X F DATA TYPE MAPPING 97

DOUBLE 101 VARCHAR 101 NUMBER 101 National language types 102 ROWID 102 TYPE 102 ROWTYPE 102 FLOAT 102 XMLType 103

IBM Software Group IBM Information Management

Version 16 8

C H A P T E R 1 Introduction

This document is a technical document describing the differences between Oracle and Informixreg Dynamic Server (IDS) functionality and syntax This porting guide details differences between Oraclersquos 10g release 1 (101) and 10g release 2 (102) and Informix Dynamic Server (version 1110) In addition it can be a useful reference for all migrations between the two database servers regardless of version In addition to DDL DML and overall SQL syntax this document explores the differences between Oracle and Informix with regards to object technology through the use of large objects user defined types and user defined routines It also looks at the differences between Oraclersquos table partitioning and Informixrsquos table fragmentation Part of the explanation is a discussion on what needs to be changed to make an application running on an Oracle database run on an Informix database If there is more than one way to port some piece of functionality alternatives and recommendations are also discussed This document is intended to be a living document Missing items better ways of implementing Oracle functionality in Informix other than what is documented here examples to better illustrate a point and other suggestions should be sent to Chris Golledge (golledgeusibmcom) so they may be included with future revisions

Purpose This document should be used as a guide to assist in porting applications that run on an Oracle database server to run on an Informix database server Regardless of whether a porting effort will be completely manual or if tools will be utilized this document can provide value Obviously if the port is performed manually this guide will provide the most value If the port will utilize tools then analysis can be performed using this guide to determine how much of the application the tools will convert and how much must be converted manually In any case this guide is intended to be used to both visualize the scope of a porting effort and to aid in the porting effort by addressing the technical issues This document will be refined based on usersrsquo experiences to identify as many of the porting issues as possible at the beginning of a project

Product overview IBM Informix Server provides high performance and scalability with legendary reliability and nearly hands-free administration of databases of all size IDS is industry proven on UNIX Linux or Windows platforms with online transaction processing (OLTP) systems data marts data warehouses and e-business applications The IDS 11 release features significant additions over prior versions It supports the services-oriented architecture (SOA) model for application integration and offers many new features for data replication continuous availability and ldquohands freerdquo database administration

Organization This document is broken into sections to logically discuss the different database concepts Some of the sections may contain the same sub-sections for example stored procedures and triggers

IBM Software Group IBM Information Management

Version 16 9

are discussed in the DDL and DML sections This allows separate discussions on the issues facing the same item in each area For example the issues surrounding creating a stored procedure are discussed in the DDL section and the issues surrounding the stored procedure language are discussed in the DML section Among the other references the ldquoPlanning Guiderdquo appendix contains a quick reference of most of the differences between Oracle and Informix along with the degree of difficulty to port each difference This reference is intended for use in the planning process to illustrate the scope and the effort required to perform the porting project Some of the stored procedure logic used to convert Oracle functions is included in the appendix rdquoSample coderdquo

Conventions The conventions used in this document include

Courier Text Distinguishes a logic example

from regular text

Example Illustrates a point In most cases an Oracle example will be followed by an Informix example

Italicized Text Signifies a substitution in other words substitutes for the italicized word the actual object the word is describing for example table_name column_name and so on

UPPER CASE TEXT Signifies database vendor reserved words or statements such as INTEGER CREATE TABLE and so on

Bold example text highlights the item that is being explained

IBM Software Group IBM Information Management

Version 16 10

IBM Software Group IBM Information Management

Version 16 11

C H A P T E R 2 Defining the Problem Space

It is important to define the set of objects to be migrated and it is better if effort is put into this prior to beginning the actual migration This is true if you are the responsible for both the database in general and its migration from one supporting DBMS to another but it is particularly true that there be a clear agreement on the scope of what is to be migrated if the migration is to be performed by a party other than the one with long term responsibility for the database Defining the scope will involve extracting a representation of the objects to be migrated out of the Oracle system catalogs and representing them in some format that can be manipulated into constructs that can be used in Informix

Extracting the objects to be migrated It is possible to represent the objects in more than one language Using the SQL language is the most common method and it will be the only one discussed at length in this document (in its current revision) However it is also possible to express database objects in XML SQL has the advantage that the standard common grammars are widely understood in the context of defining tables indexes etc XML would have an advantage of not requiring parsing that is sensitive to the minor differences in ways of expressing essentially the same object

Working With Oracle Dump Files

There exist 3rd

-party tools for reading system catalogs but it is doubtful that any can read the Oracle catalogs more reliably than Oraclersquos own tools There are two incompatible export and import tool sets used by Oracle The older tools are imp and exp and the newer ones are impdp and expdp where dp stands for Data Pump Oracle has encouraged the use of the newer tools instead of the older ones since the newer ones were introduced at version 10 Nonetheless there are many Oracle users still using imp and exp In the discussions below only the metadata will be extracted into a dump file That is because any data in the dump file will be in a proprietary format and very likely some of the data will have to go through a type conversion process before being loaded into an Informix system Oracle exported data generally cannot be used to load a database in Informix Export and Import

If someone has given you a dump file created with the older export tool there exist tools such as The DDL Wizard by Net 2000 Limited which can be used to extract viable DDL The contents of the dump file contain the SQL for re-creating the database but they are not in a readily usable format The older export and import tools are also more sensitive to the layout of the tablespaces than impdb The ability to extract DDL from the dump file in a usable form segmented by whatever grouping you choose is limited compared to what can be achieved through the Data Pump versions

IBM Software Group IBM Information Management

Version 16 12

It may be tempting to feed the dump file into the IBM Migration Toolkit (MTK) or other tool that works on SQL flat files This will not work MTK works on flat text SQL files and the dump file is binary If you open it up you can see what may be a large number of SQL statements but there are also binary codes within the same file That binary data will prevent MTK from being able to process it Getting SQL statements

If you want to get the SQL statements out of the dump file as they would be executed on the server there is an option available from the import tool itself show=y

imp myIDmyPWD as sysdba file=myFiledmp

full=yes show=y gt dmp_showtxt

This will produce a file which contains the statements but they are wrapped in quotes The contents will look something like

ALTER SESSION SET CURRENT_SCHEMA= SYSTEM CREATE UNDO TABLESPACE TBSPC1 BLOCKSIZE 8192 DATAFILE DORACLEORADA TASCHEMA1CHUNKDBF SIZE 387973120 AUTOEXTEND ON NEXT 5242880 MAXS IZE 32767M EXTENT MANAGEMENT LOCAL

which makes them strings instead of SQL statements Fixing this is a two-step process

-- removes quotes from the start of lines

sed s^ g dmp_showtxt gt step1txt

-- removes quotes from the end of lines

sed s$g step1txt gt dmp_step2sql

The statements are still not correctly formatted because they have been truncated to a fixed length and line-endings inserted However at this point it is possible to get a count of how many of each object type there is using the script in the appendix ldquoGetting an initial count of database objectsrdquo

Data Pump Export and Import

These newer tools provide better performance and more capabilities than their predecessors Please refer to documentation on Oracle for a complete description searches for ldquoData Pump Importrdquo and ldquoData Pump Exportrdquo should return relevant results quickly Below is enough information to get started on defining and extracting the objects to be migrated Metadata can be filtered through the use of the export mode clause and INCLUDE and EXCLUDE parameters However any dependent object of an included or excluded object is likewise included or excluded For example if you include an index then the table associated with the index will also be included and if you exclude a table then any associated indexes will also be excluded The SQL that will generate all the objects in the dump file can be created by the impdp command with the SQLFILE parameter If the output file is very large you might want to break it into smaller pieces There are a couple of ways to do this and the one that is best for you somewhat depends

IBM Software Group IBM Information Management

Version 16 13

on how you intend to proceed with the conversion Data definition language (DDL) SQL for all the objects can be put into one file or the INCLUDE or EXCLUDE parameters can be added to direct Data Pump to filter on the types of objects If you put all the objects into one file then you can break that into smaller files by object type fairly easily because the objects are sorted by type in the SQL file So it is just a matter of cutting the file into smaller pieces This method may be preferred because it allows for you to do things like create all tables load the data and then create the indexes and triggers If the data set is large creating the indexes after loading the data can yield substantial performance improvements However this is less useful if you want to convert sets of objects according to dependencies in which case the filtering option is likely to be more useful Just to illustrate a difference between these two methods in one customer case the metadata dump file was about 18MB and putting all objects in one SQL file resulted in a file that was about 15MB The table definitions occupied a little under 300KB of the 15MB The output file generated by filtering on objects of type TABLE was just over 1MB The addition content was mostly GRANT INDEX and TRIGGER creation statements There were no differences in the CREATE TABLE statements themselves Examples

Prerequisite The Data Pump tools require the use of an Oracle DIRECTORY object This is basically a mapping between a name that exists within the DBMS and a system path It can be a tripping point but it provides an abstraction layer that for instance allows the same commands to work across systems with different disk layouts or different operating systems Creating a DIRECTORY on a Windows system from SQLPlus

SQLgtconnect as sysdba

SQLgtCREATE OR REPLACE DIRECTORY dumpDir AS ctemp

Note Make sure this directory is not read-only There also could be problems if the directory is a network drive on Windows these can be related to there being different users between the Oracle executable and the current user and those users having different permissions on the network drive

SQLgtGRANT read write ON DIRECTORY dumpDir TO userID

Creating a dump file of the entire database

expdp userNameuserPwd as sysdba FULL=Y dumpfile=DB_fulldmp

LOGFILE=LG_expdplog CONTENT=METADATA_ONLY DIRECTORY=dumpDir

Creating a dump file of just one schema

expdp userNameuserPwd as sysdba SCHEMAS=hr DIRECTORY=dumpDir

DUMPFILE=hr dmp LOGFILE=hr log CONTENT=METADATA_ONLY

Creating a dump of just the tables and their dependents

expdp userNameuserPwd as sysdba SCHEMAS=hr INCLUDE=TABLE

DIRECTORY=dumpDir DUMPFILE=hrdmp LOGFILE=hrlog

CONTENT=METADATA_ONLY

Creating a dump of just one table

expdp userNameuserPwd as sysdba SCHEMAS=hr

INCLUDE=TABLELIKE COUNTRIES DIRECTORY=dumpDir

DUMPFILE=hrdmp LOGFILE=hrlog CONTENT=METADATA_ONLY

IBM Software Group IBM Information Management

Version 16 14

Creatinge an SQL file from a dump file

impdp userNameuserPwd as sysdba DIRECTORY=dumpDir

DUMPFILE=hrdmp SQLFILE=dumpDirhrsql

The INCLUDE and EXCLUDE options are also valid when used with impdb so it may be easier to get a complete dump of everything to be migrated then use these options to create subsets of objects it smaller SQL files than it would be to create separate dump files It is easier to divide objects than to merge them together if they are not divided initially as wanted There is a caveat when using this impdp to generate an SQL file the object names will all be delimited identifiers Example

CREATE TABLE HRCOUNTRIES Because of differences between how Informix handles these and how Oracle handles these case-sensitivity issues could occur See the chapter on ldquoDelimited Identifiersrdquo and in particular the description of default shift problems If it can be determined that there are no name collisions if regular identifiers are used removing the quotation marks as part of the conversion might avoid many problems In other words if there are no objects whose names only differ in case like foo and FOO then changing every occurrence of ldquoFOOrdquo to FOO in the DDL could eliminate case-sensitivity issues in the application DML It depends on if the application code uses the delimited form of the name predominantly or not

IBM Software Group IBM Information Management

Version 16 15

C H A P T E R 3 Data Definition Language

Identifiers An identifier specifies the simple name of a database object such as a table name column name index name view name stored procedure name and so on The maximum length of an Oracle identifier is 30 characters and can contain letters numbers ldquo_rdquo ldquo$rdquo and ldquordquo although Oracle highly recommends that ldquo$rdquo and ldquordquo should not be used In contrast Informix identifiers have a maximum length of 128 characters and may contain letters numbers ldquo_rdquo and ldquo$rdquo (as long as ldquo$rdquo is not the first character) See the Delimited Identifiers section below for information This means that all Oracle identifiers containing a ldquordquo anywhere in the identifier or a ldquo$rdquo as the first character must be replaced or modified to remove those characters from the identifier

Delimited identifiers

Delimited identifiers are also known as quoted identifiers and sometimes as escaped identifiers They have been part of the SQL standard since SQL92 but existed in various database management systems (DBMS) prior to that time In a nutshell they are a way to preserve case sensitivity in object names as well as to allow objects to have names outside of the conventions of SQL regular identifiers Prior to the behavior of identifiers in general being standardized different DBMS vendors implemented different means of achieving case-insensitivity for object names some converted all regular identifiers to uppercase and some converted regular identifiers to lowercase By SQL99 the concept of case normal form was standardized to mean simply stated that if there exists an uppercase equivalent of any character in a name then the uppercase version is stored in the system catalogs and used for comparison purposes See the SQL99 standard chapter 5 section 2 and in particular items 21 and 22 for a formal description of case normal form and how it applies to identifier comparisons Delimited identifiers can be used to specify names for database objects that are otherwise identical to SQL reserved keywords such as TABLE WHERE DECLARE and so on The only database object for which delimited identifiers cannot be used is a database name Database administrators and application programmers do not always communicate to each other with 100 efficiency and there is no guarantee that within either of these pools every member codes by the standard practice of the other members After describing how delimited identifiers work in Informix there will be a description of how any inconsistency of usage and the differences between Oracle and Informix can introduce some migration hurdles DELIMIDENT Environment Variable

To use delimited identifiers with Informix you must set the DELIMIDENT environment variable While DELIMIDENT is set strings enclosed in quotation marks ( ldquo ) are treated as identifiers of database objects and strings enclosed in apostrophes ( rsquo ) are treated as literal strings If the

IBM Software Group IBM Information Management

Version 16 16

DELIMIDENT environment variable is not set strings enclosed in quotation marks are also treated as literal strings When you set the DELIMIDENT environment variable you cannot use quotation marks ( rdquo ) to delimit literal strings If DELIMIDENT is set the database server interprets all strings enclosed in quotation marks as SQL identifiers not string literals Commonly within Informix systems DELIMIDENT is set or not on the client side according to the design of the application However if you are converting a database and all applications accessing it from a system where every occurrence of quotation marks (ldquoobjectNamerdquo) indicates an identifier and not a string literal you may want to consider setting it in the server environment in order to avoid any inconsistency between clients where it is set and where it might not be Using Quotes in Strings The apostrophe ( rsquo ) has no special significance in string literals delimited by quotation marks Conversely double quote ( Prime ) has no special significance in strings delimited by apostrophes For example these strings are valid Nancyrsquos puppy jumped the fence

rsquoBilly told his kitten No rsquo A string delimited by quotation marks can include a double quote character by preceding it with another double quote as the following string shows Enter y to

select this row When the DELIMIDENT environment variable is set quotation marks can only delimit identifiers not strings Use of Uppercase Characters You can specify the name of a database object with uppercase characters but the Informix server shifts these to lowercase characters unless the DELIMIDENT environment variable is set and the name of the database object is enclosed in quotation marks In this case the database server treats the name of the database object as a delimited identifier and preserves the uppercase characters in the name Delimited Identifiers By default the character set of a valid SQL identifier is restricted to letters digits underscore and dollar-sign symbols If you set the DELIMIDENT environment variable however SQL identifiers can also include additional characters from the codeset implied by the setting of the DB_LOCALE environment variable See the Identifier section of the Informix Guide to SQL Syntax for more information Storage Object Names In Informix delimited identifiers can be used to specify non-alphanumeric characters in the names of database objects However delimited identifiers can not be used to specify non-alpha characters in the names of storage objects such as dbspaces and blobspaces To use delimited identifiers DELIMIDENT must be set both at compile and run times For example to set DELIMIDENT environment variable with sh or ksh issue the following at the command line prompt

export DELIMIDENT=

Note You do not need to assign a value to the environment variable and counter-intuitively setting DELIMIDENT=n has the same effect as DELIMIDENT=y Also in a Windows environment

set DELIMIDENT=

effectively undefines the variable Default shift problems

Any direct access of system catalog information involving names will cause problems when migrating from a system like Oracle where system catalog names are stored in uppercase to a system like Informix where the catalog names are stored in lowercase For example

CREATE TABLE foo (c1 int)

IBM Software Group IBM Information Management

Version 16 17

Within Oracle the following will return information about the table

select from sysall_objects where object_name = FOO

and the following will not

select from sysall_objects where object_name = foo

Conversely in Informix

select from systables where tabname = foo

will be successful and the same with FOO will not be A similar if not more common problem can occur when the table has been created without the name being delimited but is sometimes delimited when accessed by the application Per the standard foo == FOO == ldquoFOOrdquo but in Informix foo == FOO == ldquofoordquo In Oracle the following SELECT statement will be successful

SELECT FROM ldquoFOOrdquo

but within Informix this will result in an error ldquo206 The specified table (FOO) is not in the databaserdquo Likewise if the name is delimited in its definition such as

CREATE TABLE SCHEMA1TABLE1

this creates a table that can be referenced in Oracle without the name being delimited The statements

SELECT FROM schema1table1

and SELECT FROM SCHEMA1TABLE1

will be successful in the Oracle system but will fail in the Informix one In theory whether on object name is delimited or not should be the same in the database and at every occurrence within the application but this is not always the case It may be beneficial to examine whether delimited identifiers or regular identifiers are most commonly used in application code and use whichever is most common as a naming convention when translating the DDL

Explicit versus implicit schemaowner names

Another complication to keep in mind is that when the log mode is ANSI implicit and explicit owner names are treated differently between the Oracle and Informix servers In Oracle there is no difference in the case handling of an implicit owner name and an explicit one For example if connected to Oracle as scott the following CREATE TABLE statements

create table foo1(c1 int) create table scottfoo2(c1 int) create table SCOTTfoo3(c1 int)

all result in tables owned by SCOTT The following select statements in various forms that may be in application code will all run without error

select from foo1 select from scottfoo1

IBM Software Group IBM Information Management

Version 16 18

select from SCOTTfoo1 select from foo2 select from scottfoo2 select from SCOTTfoo2 select from foo3 select from scottfoo3 select from SCOTTfoo3

These statements will also run without error within a non-ANSI mode Informix database but not all of them will run successfully within an ANSI mode database This is because Informix does not uniformly fold the case of owner names and handles implicit names differently from explicit names so there will always be some combination of DDL and DML usage patterns that work within an Oracle system that do not work in an Informix one You can set ANSIOWNER before starting your Informix server but that will merely change which combinations do not work You may want to examine usage patterns within the applications and choose a naming convention when translating the DDL that matches the most common naming convention used in the applications Note This behavior of Informix forces a tradeoff between using an ANSI mode database which most closely matches the transaction behavior of Oracle and a non-ANSI mode database which has the least mismatch in identifier case sensitivity

Reserved words or keywords

Oracle and Informix both allow identifiers to be reserved words as long as they are delimited However Oracle and Informix reserved words differ In addition both systems have keywords like FROM that are not always reserved in the sense that using them as an identifier will always generate a syntax error There should be few problems with reserved words or keywords if identifiers that are delimited in the original database remain delimited in the destination database The appendix Keywords of SQL for IBM Informix in the Guide to SQL Syntax contains more information about Informix keywords Also one word non-delimited identifiers should be verified against the Informix reserved words list to ensure that they do not need to be delimited or renamed Although almost any word can be used as an identifier in Informix syntactic ambiguities can result from using reserved words as identifiers in SQL statements Delimited identifiers provide a way to use a reserved word as an identifier without causing syntactic ambiguities However doing this changes a case-insensitive name into a case-sensitive one and that means that every reference to the object has to be checked for issues related to case-sensitivity Essentially this is not much less work than changing the name of the object because in essence it is changing the name of the object Examples

The following example shows how to create an Informix table with a case sensitive table name

CREATE TABLE My_Customers (hellip)

The following example shows how to create a table whose name includes a space character If the table name were not in quotation marks () a space character or any other non-alpha character except an underscore ( _ ) or dollar sign ($) (see special conditions above) could be used in the name

CREATE TABLE My Customers (hellip)

IBM Software Group IBM Information Management

Version 16 19

The following example shows how to create a table that uses a keyword as the table name

CREATE TABLE TABLE (hellip)

To include a double-quote () within a delimited identifier the double-quote () must be preceded with another double-quote () as shown in the following example

CREATE TABLE MyGoodData (hellip)

Summary

The main points to keep in mind when deciding about any questions on how identifiers should be translated are

Oracle always has delimited identifiers enabled and Informix does not

Oracle folds regular identifiers to uppercase and Informix folds to lowercase

Informix has behavioral differences between an ANSI mode database and a non-ANSI mode one

It is beneficial to consider the most common usage patterns within the existing application code prior to deciding default identifier translation patterns

Databases

Databases database names and instances

Oracle and Informix implement databases and instances differently Oracle considers a database to be a set of data files control file(s) and log files while an instance is a set of background processes and memory structures accessing database data Oracle instances are also known as servers Each Oracle instance or server runs against one database but through the use of Oracle Parallel Server a database may have multiple instances accessing it An Oracle database is named at initialization and the name has a limit of 8 ASCII characters Informix databases are defined as ldquoa collection of information contained in tables that are useful to a particular organization or used for a specific purposerdquo Informix database names may be up to 128 characters in length An Informix instance is a set of processes memory and disk allocations that manage data and will contain at least two and in most cases many databases Informix instances are also referred to as servers Informix databases may share disk allocations (dbspaces) with other databases within an Informix instance Oracle databases cannot share disk allocations (tablespaces) Informix databases should be created in a dbspace other than the root dbspace The root dbspace holds data for the system configuration information for the engine and so on If user-defined objects are created in this dbspace then the dbspace may become unmanageably large and during backup the system information may also get backed up unnecessarily The CREATE DATABASE statements of Informix and Oracle have differences which may require modification to routines responsible for database creation Informix will accept the same minimal syntax required by Oracle (eg CREATE DATABASE myDB) however issuing the command will implicitly accept the creation of a database without transaction logging enabled and establish the default location for all database objects as the instancersquos default storage location The instancersquos default storage location or ldquorootrdquo dbspace should not contain user-defined objects The root dbspace holds data for the system and some configuration information for the engine If user-

IBM Software Group IBM Information Management

Version 16 20

defined objects are created in this dbspace it may become unmanageable and result in the system contending with user objects for the available space

ANSI vs non-ANSI

Informix supports both ANSI and non-ANSI databases Informix non-ANSI databases are most common but there are some advantages of ANSI databases when porting from Oracle

Oraclersquos transaction behavior is more or less like that of an ANSI database Applications ported on Oracle are always in a transaction In Oracle and ANSI databases transactions begin implicitly with the first of a series of SQL statements and will end immediately after a commit or rollback statement Therefore unlike a non-ANSI database a COMMIT WORK statement does not need to be preceded with a BEGIN WORK statement

In ANSI databases database object references must be prefixed by the ownerrsquos name unless the owner is the one referencing the object If Oracle applications reference database objects with a both parts of the object name prefixing the object name with schema using an ANSI database may ease modifications necessary when porting to Informix

The ldquolsquogrant to PUBLICrdquorsquo concept provide by Informix database security does not apply to ANSI databases Every database object is private and privileges must be explicitly granted to each user

If an Informix ESQLC or 4GL application was developed to run on a non-ANSI Informix database (including BEGIN WORK statements) the application could run on an ANSI Informix database in one of two ways

By placing the BEGIN WORK statement in a pre-processor directive such as IFDEF object_name and omitting the proper preprocessor compile options such as -D object_name

By compiling the application normally and ignoring the resulting warning messages

Additionally the LOG MODE ANSI clause must be added to the CREATE DATABASE statements ANSI mode databases cannot have buffered logging Applications written to use an open API like ODBC or JDBC are compiled without awareness of the database and these APIs are written with the intent to abstract specific database behavior For instance in one of these the application developer would call a function to begin or end a transaction rather than execute a BEGIN and COMMIT or ROLLBACK The API would execute these statements internally or not as necessary for the database connection See the Transaction Processing section in Application Architecture for more information on how an application running on a non-ANSI Informix database can simulate Oracle transaction behavior

Tablespaces and dbspaces Oracle tablespace names need to be replaced with Informix dbspace names Unlike the Oracle tablespace the Informix dbspace cannot be created using DDL (SQL) scripts It must be created using the Informix onspaces utility before any DDL (SQL) scripts are executed Therefore Oraclersquos CREATE TABLESPACE statements should be removed from the DDL (SQL) scripts The user interface for accomplishing these tasks is onmonitor The command line utility is onspaces Therefore the onspaces commands can be placed in shell or batch scripts After successfully executing the onspaces commands the DDL (SQL) scripts may be called through the same shell or batch scripts For example

IBM Software Group IBM Information Management

Version 16 21

onspaces hellip onspaces hellip hellip dbaccess database_name DDL_script_file_name dbaccess database_name DDL_script_file_name hellip

Tables

Attributes and general syntax

When creating tables the Oracle CREATE TABLE statement must be converted to Informix taking advantage of the Informix options IN EXTENT NEXT and LOCK MODE

IN specifies the dbspace in which the table will reside

EXTENT specifies the amount of space that will initially be allocated to the table (16K default on most platforms)

NEXT specifies the amount of space that will be allocated when additional space is needed (16K default on most platforms

Lock mode

LOCK MODE specifies whether to use row or page locks for the table In Oracle the default is row level locking in Informix the default setting is page level locking However it can be changed by using one of the following methods (resolved in the following order of precedence)

1 LOCK MODE specified using an attribute of the CREATE TABLE or ALTER TABLE command syntax

2 IFX_DEF_TABLE_LOCKMODE environment variable setting 3 DEF_TABLE_LOCKMODE parameter setting in the ONCONFIG file

NOTE If the DEF_TABLE_LOCKMODE parameter cannot be found in the ONCONFIG file it can be added to make the specification for every database within the instance The Informix instance must be restarted for this parameter to take effect The new ldquodefaultrdquo LOCK MODE will apply to all tables created after the parameter has been changed To change the LOCK MODE of existing objects use the ALTER TABLE statement

Storage

The Oracle STORAGE INITIAL and STORAGE NEXT clauses must be changed to the Informix EXTENT SIZE and NEXT SIZE clauses respectively In Oracle the STORAGE clause options MINEXTENTS MAXEXTENTS and PCTINCREASE should be removed For example Oracle

CREATE TABLE dept(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13)

)

STORAGE (INITIAL 100K NEXT 50K MINEXTENTS 1 MAXEXTENTS 50

PCTINCREASE 5)

Informix CREATE TABLE dept (

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

IBM Software Group IBM Information Management

Version 16 22

EXTENT SIZE 200 NEXT SIZE 50

When an Oracle CREATE TABLE statement does not include a STORAGE clause the table will be created using the tablespace STORAGE clause by default If an Oracle tablespace is created specifying a STORAGE INITIAL of 100KB and a STORAGE NEXT of 50KB then all tables created within that tablespace will have a default value of STORAGE INITIAL 100KB and STORAGE NEXT 50KB Oracle tables cannot be created with smaller STORAGE clause values than the tablespace default they are created in Informix dbspaces do not have storage clauses attached to them As stated earlier the default Informix EXTENT and NEXT sizes are 16KB on most platforms The minimum EXTENT and NEXT sizes are 4 times the page size

Constraints

The Oracle constraint syntax must be changed to the Informix syntax for primary keys foreign keys unique and so on For example

Oracle CONSTRAINT PK_NUMBER PRIMARY KEY(CUST_NUM)

CONSTRAINT CK_EMP_CODE CHECK (EMP_CODE gt 100)

Informix PRIMARY KEY(CUST_NUM) CONSTRAINT PK_NUMBER

CHECK (EMP_CODE gt 100) CONSTRAINT CK_EMP_CODE

An Oracle check constraint statement may contain functions that are not available in Informix In this circumstance it may be necessary to code the combination of a trigger and a stored procedure to emulate the same functionality A trigger based on an insert or update event can execute a stored procedure which tests the constraint condition and if necessary raise an exception to reject the row data which violates the constraint The Oracle PARALLEL clause which specifies parallel execution of an operation must be removed from any SQL statements (such as CREATE TABLE and ALTER TABLE) In Informix there are ways to accomplish this parallel execution depending on the context in which these SQL statements are called (shell script file batch file and so on)

ALTER TABLE

Informix offers a rich set of ALTER TABLE features adding and dropping columns (rename by using the RENAME statement) changing column data types altering the next size and changing the lock mode Informix will choose one of three algorithms when executing an ALTER TABLE statement depending upon the operation to be performed For certain conditions the database server uses either a ldquoslowrdquo ldquoin-place or ldquofastrdquo alter algorithm to modify the table Informix provides ldquoin-placerdquo alter table support for adding or dropping a column anywhere in the table changing the column length and changing the column data type without an exclusive lock on the table An ldquoin-placerdquo alter will modify the tablersquos definition without changing the existing rows or unloading and reloading the data After the ALTER TABLE operation the database server inserts rows using the latest definition Informix will not change the row structure until a data row is touched by a user operation Once a query accesses a row that is not yet converted there can be a slight degradation in the performance because the database server reformats each row in memory before it is returned Informix uses the ldquoslowrdquo alter algorithm when the ALTER TABLE statement makes column changes that it cannot perform in place This type of alter would be

Adding or drop a column created with the ROWIDS keyword

Dropping a column of the TEXT or BYTE data type

IBM Software Group IBM Information Management

Version 16 23

Converting an INT or a SMALLINT column to SERIAL or SERIAL8

Modifying the data type of a column so that some possible values of the old data type cannot be converted to the new data type

For example if you modify a column of data type INTEGER to CHAR(n) the database server uses the slow ALTER algorithm if the value of n is less than 11 An INTEGER requires 10 characters plus one for the minus sign for the lowest possible negative values

Modifying the data type of a fragmentation column in a way that value conversion might cause rows to move to another fragment

Adding dropping or modifying any column when the table contains user-defined data types or smart large objects

When the database server uses the slow alter algorithm to process an ALTER TABLE statement the table can be unavailable to other users for a long period of time because the database server will lock the table exclusively for the duration of the operation make a copy of the table to convert the table to the new definition and convert the data rows This type of ALTER TABLE processing can encounter the scenario of a statement being a long transaction and abort it if the Long Transaction High Water Mark (LTXHWM) threshold is exceeded Informix will use the ldquofastrdquo alter algorithm when the ALTER TABLE statement changes attributes of the table but does not affect the data The database server uses the fast alter algorithm when you use the ALTER TABLE statement to make the following changes

bull Change the next-extent size

bull Add or drop a constraint

bull Change the lock mode of the table

bull Change the unique index attribute without modifying the column type

With the ldquofastrdquo alter algorithm the database server holds a lock on the table for a very brief period In some cases the database server will lock the system catalog tables but only long enough to change the attribute In either case the table is unavailable for queries for only a short time

Data Partitioning

Informix Table Fragmentation is the counterpart to Oraclersquos Table Partitioning and allows the user to control where data is physically placed at the table level Table Fragmentation or Data Partitioning is typically done to large tables but Informix and Oracle implement fragmentation and partitioning for different reasons and with different results Informix recommends using table fragmentation to improve single-user response time concurrency data availability backup restore characteristics and data-load performance While Oracle does state that table partitioning may improve the performance of queries and that the Oracle optimizer takes partitioning into account the primary goal of partitioning in Oracle is improving database maintenance Partitioning strategies in Oracle include range partitioning as well as hash and composite partitioning Composite partitioning combines range and hash partitions through the use of sub-partitions Tables incorporating Oracle LOBrsquos (large objects) cannot be partitioned Informix fragmentation strategies include expression-based and round robin Basic expression-based fragmentation can replace Oracle range partitioning Unlike Oracle LOBs Informixrsquos Smart Large Objects can be fragmented Examples of creating tables with Oracle range partitioning and Informix fragmentation by expression are shown below Oracle range partitioning

CREATE TABLE dept

IBM Software Group IBM Information Management

Version 16 24

(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13) )

partition by range (deptno)

(partition PART1 values less than (11)

tablespace PART1_TS

partition PART2 values less than (21)

tablespace PART2_TS

partition PART3 values less than (31)

tablespace PART3_TS

partition PART4 values less than (MAXVALUE)

tablespace PART4_TS)

Informix expression based fragmentation CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

deptno lt 11 IN dbspace1

deptno gt= 11 AND deptno lt 21 IN dbspace2

deptno gt= 21 AND deptno lt 31 IN dbspace3

REMAINDER IN dbspace4

Oracle uses MAXVALUE for values not found in the specified range while Informix uses the REMAINDER keyword for values that fall outside the specified expression or expressions Prior to IDS version 1000 each table fragment had to go into a separate dbspace Now tables can be fragmented within a single dbspace You can create partitions within a dbspace that can each support a table fragment It is better to have one chunk per disk drive and now it is not necessary to create a dbspace just to facilitate fragmentation This feature can simplify the management of dbspaces The benefits gained through this new development include

It reduces the total number of dbspaces needed for a fragmented table

Storing multiple table fragments in a single dbspace improves query performance over storing each fragmented expression in a different dbspace

For example Informix partition fragmention in a single dbspace

CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

PARTITION part1 (deptno lt 11) IN dbspace1

PARTITION part2 (deptno lt 21) IN dbspace1

PARTITION part3 (deptno lt 31) IN dbspace1

PARTITION part4 REMAINDER IN dbspace1

Partitions of an Informix fragmented table can be manipulated using the ALTER FRAGMENT statement which supports attaching detaching adding modifying and dropping as well as initializing the distribution strategy

IBM Software Group IBM Information Management

Version 16 25

For example the following SQL removes a partition fragment and places the contents into a new table

ALTER FRAGMENT ON TABLE dept DETACH PARTITION part3 dept_part3

Making use of ALTER FRAGMENT to detach fragments can be an effective way of deleting large quantities of rows from a table quickly and easily After the above statement completes the table will no longer contain rows with a deptno greater than 21 and less than 31 Refer to the Informix Guide to SQL Syntax for a complete description on how to use the ALTER FRAGMENT statement to change the distribution strategy or the storage location of an existing table or index

Data types

Numeric

Oraclersquos NUMBER data type needs to be replaced with one of the following Informix equivalent data types depending on the size of the column The Informix numeric data types are listed below

SMALLINT (-32767 to 32767)

INTEGER (-2147483647 to 2147483647)

BIGINT (-9223372036854775807 to 9223372036854775807)

INT8 (-9223372036854775807 to 9223372036854775807)

The BIGINT type is more efficient in terms of space and speed there are few reasons to use INT8 now that BIGINT is available

DECIMAL (floating point up to 32 significant digits -10-130

to 10124

)

In an ANSI database there is an implied scale of 0 when no scale is given so this is not strictly speaking a floating point type within an ANSI database

NUMERIC (floating point up to 32 significant digits -10-130

to 10124

)

FLOAT (double precision like double data type of C)

SMALLFLOAT (single precision like float data type of C)

REAL (same as SMALLFLOAT)

DOUBLE (same as FLOAT)

LONG (same as long data type of C)

Oraclersquos NUMBER data type is used to store zero positive and negative fixed size and floating point numbers with magnitudes between 10 x 10

-130 and 999 x 10

125 (38 9s followed by 88 0s)

with 38 digits of precision A fixed-point number is specified by NUMBER(p s) where p is the precision or the total number of digits and s is the scale or the number of digits to the right of the decimal point For example a column defined as NUMBER(104) would contain numbers in the format 9999999999 In Oracle the scale can range from -84 to 127 If the scale is 0 or not mentioned then the data type can be converted into Informixrsquos SMALLINT INTEGER or BIGINT depending on the precision or FLOAT SMALLFLOAT DOUBLE or REAL depending on usage in the application When the scale is positive the data type should be converted to Informixrsquos DECIMAL or NUMERIC A floating-point data type in Oracle is declared using the type NUMBER without mentioning scale and precision In Informix this can be replaced with FLOAT SMALLFLOAT REAL DOUBLE PRECISION or DECIMAL(p) in an non-ANSI database

IBM Software Group IBM Information Management

Version 16 26

Oracle allows a negative scale If the scale is negative the actual data is rounded to the specified number of places to the left of the decimal point For example a specification of NUMBER (10 -2) means to round to the hundred If the general form for any number is

mantissa X 10exponent

then precision is the number of digits in the mantissa and scale is the negative exponent Example

select cast( 987654321 AS NUMBER(10-2) ) from dual

returns

987654300

Informix does not support a negative scale If precision - scale is less than the maximum precision of an integer type then that is the most efficient type to use Failing that and if the database is non-ANSI a floating point DECIMAL can be used If that is not sufficient then it may be necessary to define a user type and associated functions Oracle also allows the scale to be greater than the precision Precision is just the number of digits that will be preserved A NUMBER(3 5) might have the value 000123 If the Oracle scale is less than the Informix maximum precision then the Oracle scale can be used for both the Informix precision and scale A NUMERIC(55) column could also store the value 000123 You may need to take into consideration not only the minimum and maximum values but the default size for data types For example when the size of the NUMBER data type is absent Oracle will default to NUMBER(38) while Informix defaults to NUMERIC(16) Oracle and Informix support the ANSI DECIMAL data type Therefore in the case of an ANSI data type the Oracle data type can be converted to the same Informix data type There are differences between conversions based on theory versus those based on practice For instance it is very common to see an undecorated NUMBER declaration where the customer database and applications are using integer data When converting NUMBER declarations it may be necessary to consider how the data is being used in order to determine the best type mapping

CHAR VARCHAR and LVARCHAR

In Oracle the default for a CHAR column is one character and the maximum allowed is 255 characters In Informix the maximum length of CHAR and LVARCHAR columns is 32767 Therefore Oraclersquos CHAR columns can always be converted to an Informix CHAR column The CHAR data type columns can only contain printable characters tabs and spaces The CHAR columns store leading and trailing spaces In Oracle a zero-length string can be inserted into a CHAR column but the column is padded with one blank character when it is used in comparisons Also in Informix a zero-length string can be inserted into a CHAR column however the column is padded with enough spaces to fill the column In the case of inserting NULL into an Informix CHAR column no padding occurs Oraclersquos VARCHAR and VARCHAR2 are currently synonymous and have a maximum data length of 4000 bytes while the maximum length for the Informix VARCHAR data type is 255 Informixrsquos CHAR and LVARCHAR data types have a maximum length of 32767 and 32739 respectively measured in bytes These should be used to replace Oraclersquos VARCHAR VARCHAR2 LONG and LONG VARCHAR if the data length is between 256 and the maximum If the data length exceeds the maximum use Informixrsquos TEXT BYTE BLOB or CLOB data types See the Raw Data section below for more information on TEXT BYTE BLOB and CLOB data types

IBM Software Group IBM Information Management

Version 16 27

Empty Oracle VARCHAR2 strings are considered NULL Empty Informix VARCHAR and LVARCHAR strings are not considered NULL rather they contain at least one space Oracle

compares VARCHAR2 values using non-padded comparison semantics Therefore ldquoBOBrdquo ldquoBOB ldquo Informix ignores trailing blanks Therefore ldquoBOBrdquo = ldquoBOB ldquo or ldquordquo = ldquo rdquo Hence checks for NULL within the application must be replaced with checks for an empty string (such as ldquordquo or ldquo rdquo) whenever an empty string is inserted into the column If NULL is truly inserted into the column checking for NULL is appropriate (for example SELECT FROM hellip WHERE hellip IS NULL) In Oracle LONG columns store variable length character strings containing up to 2 gigabytes or 2

31-1 bytes Informix LONG columns store numeric data Oraclersquos LONG columns have many of

the characteristics of VARCHAR2 columns They can be used in a SELECT list in the SET clause of an UPDATE statement and in an INSERT statement but they cannot be used in a WHERE clause a GROUP BY clause or an ORDER BY clause and they cannot be indexed Oraclersquos LONG columns should be converted to an Informix Smart Large Object or ldquoSLOBrdquo (BLOB CLOB) column

Date and Time

Oraclersquos DATE data type contains date and time components from year down to second It can be to be replaced most directly with Informixrsquos DATETIME YEAR TO SECOND Some analysis may be necessary to determine whether the time is really necessary In other words does the application reference the date and time portions of the values If the application only references the date portion then replace Oraclersquos DATE with Informixrsquos DATE and change the host variable to X(10) or char(10) accordingly The Informix DATE default display format is MM-DD-YYYY although the DATE data type stores the calendar date The Informix DATE data type requires 4 bytes which is stored internally as an integer value equal to the number of days since December 31 1899 The default display format can be changed with the environment variable DBDATE If the application uses different date formats then using DBDATE is not a solution Sometimes it might be necessary to write small subroutines to emulate Oraclersquos DATE representations See the Informix Guide to SQL Reference manual for details on DBDATE and also DBCENTURY If the application only references the time portion of the values replace Oraclersquos DATE with Informixrsquos DATETIME using the EXTEND function to specify precision In addition Informix provides the data type INTERVAL for use while performing DATE and DATETIME calculations In Oracle the DATE data type is used to store date and time information Although date and time information can be represented in both CHAR and NUMBER data types the DATE data type has special associated properties For each DATE value the following information is stored

century

year

month

day

hour

minute

second

Also regarding the Oracle DATE data type if a date value without a time component is specified the default time is 120000am If a DATE value without a date is specified the default date is the first day of the current month

Interval

Within Informix there are two classes of interval types YEAR-MONTH and DAY-FRACTION There are different numbers if days in different months so the MONTH-DAY boundary cannot be crossed without creating ill-defined results Within each of these classes Informix allows you to declare columns or variables as any subset of the start and end fields Oracle has one INTERVAL

IBM Software Group IBM Information Management

Version 16 28

type for each of the two classes YEAR(p) TO MONTH and DAY(p) TO SECOND(s) The Oracle scale on the SECOND field is logically equivalent to the Informix scale on the FRACTION field

Raw data and Large Objects

Oraclersquos support of large blocks of raw unstructured data (such as graphic images video clips and sound waveforms) in binary or character format is provided by the large object (LOB) data types BLOB CLOB NCLOB and BFILE Traditional Oracle data types MLSLABEL (used with Trusted Oracle) RAW and LONG RAW are also used for data that is not to be interpreted by the engine and converted when moving data between different systems Informix supports two types of large objects (LOBs Simple Large Objects and Smart Large Objects Simple LOBs consist of the TEXT and BYTE data types and can be 2

31 bytes or 2

Gigabytes in size Smart LOBs include both Character Large Object (CLOB) and Binary Large Object (BLOB) data types and may be up to 42

40 bytes or 4 Terabytes in size Simple LOBs can

be stored either in-line with table data or in blobspaces while Smart LOBrsquos are stored in sbspaces Oraclersquos CLOB BLOB MLSLABEL RAW and LONG RAW data types should be replaced with Informixrsquos BYTE TEXT CLOB or BLOB depending on the columnrsquos size and usage Informixrsquos Smart BLOB data types CLOB and BLOB should be used under the following conditions and considerations

The large object needs to be referenced by multiple sources

The object size exceeds 2 GB

Fragmentation is required

Byte level locking is available making it possible to lock only a portion of the object

Logging can be specified at the object level

Updates are done in place or moved as needed

Be aware of the following restrictions for Simple Large Objects

Data can only be inserted into a BYTE or TEXT column with the dbload or onload utilities the DBACCESS load statement BYTE or TEXT host variables respectively in ESQLC or declaring a file in ESQLCOBOL

BYTE and TEXT columns cannot be inserted or updated with a literal neither quoted text string nor number

BYTE or TEXT columns cannot be used in string operations with aggregate functions with the GROUP BY ORDER BY IN LIKE or MATCHES clauses

ROWID

The implementation of ROWID differs between Oracle and Informix Oraclersquos ROWID is both a pseudo-column and a data type See the ROWID subsection in the Pseudo-Columns section in CHAPTER 3 Data Manipulation Language for more information Informix implements ROWID as a pseudo-column only Oracle stores the ROWID column and ROWID data type column values in hexadecimal format Informix stores the ROWID column values in INTEGER format The Oracle and Informix engines maintain the values of the ROWID pseudo-column Oraclersquos engine does not maintain the values of other columns of type ROWID In Informix the term rowid refers to an integer that defines the physical location of a row Informix assigns rows in a non-fragmented table a unique rowid which allows applications access to a particular row in a table Rows in fragmented tables in contrast are not assigned a rowid To access data by rowid in a fragmented table a rowid column must be explicitly created as is described in the Informix Guide to SQL Reference manual Creating a Rowid Column If applications attempt to reference a rowid in a fragmented table that does not contain a rowid that was explicitly created Informix displays an appropriate error message and execution of the application is halted

IBM Software Group IBM Information Management

Version 16 29

When used as a data type for a column Oracle does not guarantee that the values are valid ROWIDs For example if the ROWID is used as a data type on a column such as a column in a child table named parent_rowid containing the ROWID of the parent then the values are maintained by the application outside of the engine The application must read the ROWID of the parent and insert it into the parentrsquos corresponding child table rows This is usually done so the two tables can be joined on the parentrsquos ROWID and the childrsquos parent_rowid column This functionality can be duplicated in Informix by using primary and foreign keys Informix recommends that primary keys are used as a method of access in applications rather than rowids because primary keys are defined in the ANSI specification of SQL using them to access data makes applications more portable Refer to the Informix Guide to SQL Reference and the Informix Guide to SQL Syntax for a complete description on how to define and use primary keys to access data

User-defined types

Both Oracle and Informix allow the user to create and define data types Oracle refers to these as abstract data types while Informix refers to these as user-defined types In Oracle all user-defined types are referred to as abstract data types while Informix may refer to user-defined types as COLLECTION types ROW types DISTINCT types and OPAQUE types Currently the Informix ROW type is closest in form and function to the Oracle abstract data type An example of syntax for creating both an Oracle abstract data type and an Informix ROW type is shown below

Oracle abstract data type

CREATE TYPE name_type AS OBJECT

(first_name VARCHAR2(25)

middle_initial CHAR(1)

last_name VARCHAR2(30))

Informix row type

CREATE ROW TYPE name_type

(first_name VARCHAR(25)

middle_initial CHAR(1)

last_name VARCHAR(30))

Both Oracle and Informix support the use of user-defined types for table definition or column definition within a table Building on the example above the following create table example show a table definition and column definition within a table based on user-defined types Oracle table creation

CREATE TABLE name OF name_type

Informix table creation

CREATE TABLE name OF type name_type

Oracle column definition

CREATE TABLE employee

(empno NUMBER(9)

name name_type)

Informix column definition

CREATE TABLE employee

IBM Software Group IBM Information Management

Version 16 30

(empno INTEGER

name name_type)

For more information on User Defined Types see the Informix Guide to SQL Syntax

Complex data types

Informix offers users the ability to create data types from existing built-in types OPAQUE types DISTINCT types and other complex types Complex data types may either be a ROW type or a COLLECTION type Oracle treats complex data types as abstract data types For more information on Oracle abstract data types see the User Defined Types section above For more information on Complex Data Types see the Informix Guide to SQL Syntax For recommended type mappings and additional information see the appendix ldquoData type mappingsrdquo

Sequence objects

Oracle sequences

An Oracle sequence is a database object from which multiple users or transactions may generate unique integers For example sequences can be used to automatically generate primary key values When a sequence object is queried the sequence number is incremented and passed to the query independent of the transaction committing or rolling back If two applications increment the same sequence the sequence numbers each application acquires may not be sequential since sequence numbers are being generated by the other application One user or transaction can never acquire the sequence number generated by another user or transaction Once a user or transaction generates a sequence value that value will never be generated and passed to another user or transaction

Informix sequences

Informix rsquos implementation of sequence objects is identical to that of Oracle Issues regarding syntax compatibility should be negligible with the exception of some keywords which have no effect on the behavior of the sequence Informix supports DML statements (CREATE SEQUENCE ALTER SEQUENCE RENAME SEQUENCE DROP SEQUENCE) for sequence objects that multiple users can access concurrently to generate unique integers in the 8-byte integer range GRANT and REVOKE statements support access privileges on sequence objects and the CREATE SYNONYM and DROP SYNONYM statements can be used to reference synonyms for sequence objects in the local database The operators CURRVAL and NEXTVAL can read or increment the value of an existing synonym with behavior the same as Oracle

Indexes

Composite indexes

A composite index can have up to 16 key parts that are columns or up to 341 key parts that are values returned by a UDR This limit is language-dependent and applies to UDRs written in SPL or Javatrade functional indexes based on C language UDRs can have up to 102 key parts A composite index can have any of the following items as an index key

One or more columns

IBM Software Group IBM Information Management

Version 16 31

One or move values that is returned by a user-defined function (referred to as a functional index)

A combination of columns and user-defined functions

Maximum key size

The total widths of all indexed columns in a single CREATE INDEX statement have a limitation based upon the page size of the dbspace in which the index resides This limitation does not apply to functional indexes An enhancement introduced with Informix Dynamic Server Version 1110 is configurable page sizes for dbspaces Prior to this release the page size of dbspaces were restricted to that of the operating system and could not be changed thus Informix was limited to 390 byte indexes With page sizes configurable from 2K through 16K wider indexes are supported Refer to the table below 16K page sizes raises the limit on index width to over 3000 bytes Lifting the 390 byte limit also permits LVARCHAR columns larger than 387 bytes to be included in an index definition

Page Size Maximum Key Size

2 kilobytes 387 bytes

4 kilobytes 796 bytes

8 kilobytes 1615 bytes

12 kilobytes 2435 bytes

16 kilobytes 3245 bytes

In addition to aiding the porting process wider indexes have satisfied requirements for Unicode data as well as provide performance gains by reducing B-Tree index traversal costs since indexing can be built with more items on an index page and produce fewer levels

Index fragmentation

Just as Oracle and Informix support table fragmentation or partitioning in Oracle both support index fragmentation as well See the Table fragmentation section above for more information regarding Informix table fragmentation and Oracle table partitioning Oracle indexes that are partitioned in the same manner as the table they are indexing are referred to as local indexes Informix refers to these as attached indexes Oracle indexes that span partitions are known as global indexes Informix refers to these as detached indexes Informix detached indexes may also refer to indexes that do not follow the same fragmentation scheme as the table they are indexing Starting with Informix version 1110 indexes can be fragmented similarly to tables on a partition level

General index information

The Informix CLUSTER option should be used when appropriate This option orders the data within the table in the order the index requires It is important to note that the CLUSTER index is not maintained over time The primary factor determining the frequency of CLUSTER index rebuilds is the amount of DML performed against the table Frequent INSERTS UPDATES and DELETES make it necessary to closely monitor CLUSTER indexes There is only one clustered index per table since a tablersquos data can only be stored in one order Oraclersquos INITRANS and PCTFREE functionality is similar to the Informix index FILLFACTOR option of the CREATE INDEX statement or the FILLFACTOR configuration parameter in the ONCONFIG file In either case the functionality is handled by Informixrsquos engine once it is set and can be removed from the application FILLFACTOR specifies the degree of index-page

IBM Software Group IBM Information Management

Version 16 32

compactness A low value provides room for growth in the index A high value compacts the index If an index is fully compacted (100 percent) any new inserts result in splitting nodes The setting on the CREATE INDEX statement overrides the ONCONFIG file value The FILLFACTOR default value for both the CREATE INDEX statement as well as the ONCONFIG is 90 Informix has no support for bitmap indexes

Views Oraclersquos CREATE VIEW statement contains three options FORCE NO FORCE and WITH READ ONLY FORCE creates the view regardless of whether the views base tables exist or the owner of the schema containing the view has privileges on them NO FORCE creates the view only if the base tables exist and the owner of the schema containing the view has privileges on them WITH READ ONLY specifies that no deletes inserts or updates can be performed through the view These options must be removed from the Informix CREATE VIEW statements Because a view is not really a table it cannot be indexed and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE The columns of a view cannot be renamed with RENAME COLUMN To change anything about the definition of a view you must drop the view and re-create it Because it must be merged with the userrsquos query the SELECT statement on which a view is based cannot contain any of the following clauses

INTO TEMP The userrsquos query might contain INTO TEMP if the view also contains it the data would not know where to go

UNION The userrsquos query might contain UNION No meaning has been defined for nested

UNION clauses

ORDER BY The userrsquos query might contain ORDER BY If the view also contains it the choice of columns or sort directions could be in conflict

Stored procedures and triggers The ways stored procedures and triggers are created differ between Oracle and Informix Oracle allows a REPLACE clause in the CREATE statement to handle situations when the object already exists Informix does not support the REPLACE option Instead a DROP PROCEDURE or DROP TRIGGER statement must precede the CREATE PROCEDURE or CREATE TRIGGER statement respectively to handle the situation when the object already exists It should be noted a DROP statement will generate an error when the object does not exist If it is run interactively within the DBACCESS user interface the DROP statement error will terminate processing If it is run using script execution using DBACCESS at the command line processing will continue To run DBACCESS from the command line type

dbaccess db_name

To run the file containing the create statements from the command line type dbaccess db_name sql_file_name

Informix introduced an IF EXISTS clause to most of the CREATE and DROP statements at 117 but the logic is different from Oraclersquos OR REPLACE clause For example these statements

IBM Software Group IBM Information Management

Version 16 33

DROP PROCEDURE IF EXISTS hellip

CREATE PROCEDURE hellip

are logically the same as this Oracle statement

CREATE OR REPLACE PROCEDURE hellip

So it is possible to achieve the same result but not necessarily the same number of statements

Oracle extensions The Oracle CLUSTER option in CREATE statements should be removed These are not to be confused with Informix CLUSTER index statements (See Indexes section above) An Oracle cluster is a database schema object that contains one or more tables that all have one or more columns in common Rows of one or more tables that share the same value in these common columns are physically stored together within the database Removing this Oracle feature will not affect the application Other non-Informix DDL statements like CREATE DATAFILE CREATE CONTROLFILE CREATE ROLLBACK SEGMENT CREATE SNAPSHOT CREATE DATABASE and CREATE DATABASE LINK must be removed or changed (in the case of the CREATE DATABASE statement) The Oracle CREATE PROFILE statement must be removed An Oracle profile is a set of limits on database resources Profiles can be used to limit the database resources available to a user for a single SQL statement or a single session

IBM Software Group IBM Information Management

Version 16 34

C H A P T E R 4 Data Manipulation Language

SQL

Labels using keywords

Oracle displays labels in SQL statements that are Informix reserved words such as UNITS YEAR MONTH DAY HOUR and so on must be converted by using the Informix AS clause between the column name and the display label Otherwise syntactic ambiguities will cause errors

Inequality operations

In addition to the Informix supported ldquonot equal tordquo symbols ldquoltgtrdquo and ldquo=rdquo Oracle supports the symbol ldquo^=rdquo All occurrences of ^= must be replaced with one of the Informix supported symbols

Selects

Queries are executed based on how the optimizer determines the best path to the data Oracle and Informix developed their own query optimizers with their proprietary methods and rules A query that looks exactly the same in both environments may run differently in each following a different path and executing faster or slower Therefore every query in the ported application should be tested for performance regardless of whether a query had to be converted Furthermore Oracle supports optimizer hints within a SELECT statement Prior to IDS 73 and Informix Dynamic Server 92 Informix did not allow optimizer hints See the Optimizer Directives subsection below for more information on porting Oraclersquos optimizer hints to Informixrsquos optimizer directives

Optimizer directives

Informix offers optimizer directives similar to Oraclersquos optimizer hints This feature provides the query developer the flexibility to direct the optimizer to follow specific paths rather than choosing a plan through its analysis A query is processed in two steps First it is optimized and compiled to product a query plan Secondly it is executed to produce a result Optimizer directives are a method for influencing the choice of the optimizer in the creation of the plan

IBM Software Group IBM Information Management

Version 16 35

Optimizer directives address the following key issues

Reduced time for correcting performance problems Rewriting queries can be very time consuming and this allows you to have a quick way to alter a plan

Competitive pressure Users accustomed to this function were looking for it in Informix

Product development tuning This allows product development to alter plans dynamically rather than through code changes to evaluate the effect of different optimization techniques

The syntax and behavior of Informixrsquos implementation is compatible with Oraclersquos optimizer hints which eases the porting of applications from Oracle to Informix Directives are written as a comment whose first character is a lsquo+rsquo (plus sign) An example is

select + ORDERED AVOID_FULL(e) empname deptno

from employee e department d

where edept_no = ddept_no

This above example specifies that the tables should be joined in the order specified in the query and that the employee table (e) should NOT be accessed with a full table scan The Informix implementation differentiates itself significantly from Oraclersquos in one way Informix supports the notion of negative directives whereas Oracle only supports direct hints A directive that tells the optimizer what to avoid rather than what to choose is unique to Informix The query result can be realized by writing a directive to avoid certain actions known to cause performance issues but allow any new indexes or table attributes to be explored by the optimizer as they are added over the life of the table and query This allows a DBA to continue to add indexes to tables and not have to rewrite directives Additionally Informix supports full recognition of directives with SET EXPLAIN output Informix will highlight semantic and syntactic errors which Oracle does not Optimizer directives support control in the following areas of the optimization process

Access methods Index versus scans

Join Methods Forcing hash joins nested loop joins

Join Order Specify which order the tables are joined

Goal Specify first rows or all rows (response time versus throughput) See the Informix Guide to SQL Syntax or Reference for more information

External optimizer directives

External optimizer directives give the DBA the ability to specify query directives and save them in the database These directives are applied automatically to subsequent instances of the same query The SAVE EXTERNAL DIRECTIVES statement associates one or more optimizer directives with a query and stores a record of this association in the sysdirectives system catalog table for subsequent use with queries that match the specified query string The query string must be an exact match that includes case and white space positioning This statement establishes an association between the list of optimizer directives and the text of a query but it does not execute the specified query Only the DBA or user informix can execute SAVE EXTERNAL DIRECTIVES This associates AVOID_INDEX and FULL directives with the specified query

SAVE EXTERNAL DIRECTIVES

+ AVOID_INDEX (table1 index1) + FULL(table1)

ACTIVE FOR

SELECT col1 col2 FROM table1 table2

IBM Software Group IBM Information Management

Version 16 36

WHERE table1col1 = table2col1

These directives are applied automatically to subsequent instances of the same query You must include one of the ACTIVE INACTIVE or TEST ONLY keyword options to enable disable or restrict the scope of external directives When external directives are enabled and the sysdirectives system catalog table is not empty the database server compares every query with the query text of every ACTIVE external directive and for queries executed by the DBA or user informix with every TEST ONLY external directive External directives are ignored if the EXT_DIRECTIVES parameter is set to 0 in the ONCONFIG file In addition the client system can disable this feature for its current session by setting the IFX_EXTDIRECTIVES environment variable to 0 If an external directive has been applied to a query output from the SET EXPLAIN statement indicates ldquoEXTERNAL DIRECTIVES IN EFFECTrdquo for that query Any inline directive is ignored by the optimizer when the external directives are applied to a query that matches the SELECT statement Like inline optimizer directives that are embedded within a query external directives can improve performance in some queries for which the default behavior of the query optimizer is not satisfactory Unlike inline directives external directives can be applied without revising or recompiling existing applications

Inserts

Informix does not support Oraclersquos INSERT with SELECT statement utilizing an UNION clause (although a view with an UNION clause can be referenced resulting in an UNION operation) Additionally Informix does not support an INSERT statement with a VALUE clause with SELECT statements The SELECT statement within a VALUE clause can be rewritten by omitting the VALUE clause and performing an INSERT INTO table_name SELECT hellip FROM other_table_name

Temporary tables

Informix and Oracle implemented the concept of temporary tables differently Oracle implements temporary tables as a work area during batch data loads Informix implements temporary tables just like regular database tables These temporary tables can be created manipulated and dropped only within a session such as stored procedures and ESQL programs Once the session ends any remaining temporary tables are automatically dropped Temporary tables can give an application extra functionality however their use should be limited if reducing database extensions to increase database independence within an application is a priority

Outer joins

Both Oracle (starting with Oracle 9i) and Informix support ANSI standard syntax for outer join specification The syntax for left and right outer join using the plus sign (+) in the WHERE clause is only supported for backward compatibility however it is still in existence The use of ANSI outer join syntax is recommended The Oracle outer join syntax + (placed after the column which has values not matching the corresponding column in the joined table) can be replaced with the Informix equivalent OUTER The OUTER keyword is placed within the SELECT statement before the name of the subservient table Unlike Oracle in Informix multiple outer joins per SELECT statement are allowed grouped with parentheses

Sorts

In Oracle sorts NULL values are considered the highest value and are therefore ordered last in ascending sorts Informix sorts with NULLS as the lowest value ordering them first in ascending sorts First it must be determined whether this sorting difference will affect the outcome enough to warrant a work around In most cases it will not If it does then a stored procedure can be

IBM Software Group IBM Information Management

Version 16 37

written to evaluate whether a column is NULL and if so replace it with a high value so that it will sort last Once the application receives the results it must replace the high values with NULL if the column is going to be displayed or manipulated

Exceptions

Error handling using hard coded Oracle SQL codes must be replaced with the corresponding Informix SQL codes

Correlation names

Informix does not support correlation names with aliases on the main table of an UPDATE or DELETE statement Such cases must be converted For example

Oracle UPDATE customer C

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE Ccreate_date lt= Zeffective_date)

Informix UPDATE customer

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE customercreate_date lt= Zeffective_date)

-and-

Oracle DELETE customer C

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND Cstate = Tstate )

Informix DELETE customer

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND customerstate = Tstate )

Note that Informix allows correlation names with aliases on tables other than the updated or deleted table

Aliases

Unlike Oracle in Informix if an alias is used in the FROM clause of a SELECT statement it must also be used in the SELECT list and WHERE clauses The original table name should be replaced with the alias wherever aliases and original names are used together within a SELECT statement in an Oracle application

Hierarchical queries

Informix does not allow query results to be organized hierarchically in a B-tree fashion Oracle does allow it by using the clauses START WITHhellip and CONNECT BY PRIOR in the SQL

IBM Software Group IBM Information Management

Version 16 38

statement In Oracle if a table contains hierarchical data a bill of materials for example rows can be selected in a hierarchical order using the following clauses START WITH

The START WITH clause identifies the row(s) to be used as the root(s) of a hierarchical query This clause specifies a condition that the root(s) must satisfy If this clause is omitted Oracle uses all rows in the table as root rows A START WITH condition can contain a subquery

CONNECT BY

The CONNECT BY clause specifies the relationship between parent and child rows in a hierarchical query This clause contains a condition that defines this relationship The part of the condition containing the PRIOR operator must have one of the following forms

PRIOR expression comparison_operator expression -or- expression comparison_operator PRIOR expression

To find the children of a parent row Oracle first evaluates the PRIOR expression to identify the parent row(s) and the other expression for each row in the table Rows for which the other expression is true are the children of the parent The CONNECT BY clause can contain other conditions to further filter the rows selected by the query

WHERE

The WHERE clause can restrict the rows returned by the query without affecting other rows of the hierarchy

Oracle uses the information from each of the clauses mentioned above to form the hierarchy using the following steps

1 Oracle selects the root row(s) of the hierarchy These are the rows that satisfy the condition of the START WITH clause

2 Oracle selects the child rows of each root row Each child row must satisfy the condition of the CONNECT BY clause with respect to one of the root rows

3 Oracle selects successive generations of child rows Oracle first selects the children of the rows returned in step 2 and then the children of those children and so on Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row

4 If the query contains a WHERE clause Oracle removes all rows from the hierarchy that do not satisfy the condition of the WHERE clause Oracle evaluates the WHERE condition for each row individually after the row has been fetched rather than only fetching rows that satisfy the WHERE condition

5 Oracle returns the rows in the order of an in-order or left-root-right binary tree traversal

IBM Software Group IBM Information Management

Version 16 39

For example the following SQL statement returns the data in the adjacent table in hierarchical order The root row is defined to be the employee whose job is lsquoPRESIDENTrsquo The child rows of a parent row are defined to be those rows whose manager number is the employee number of the parent row

SELECT ename empno mgr job FROM emp START WITH job = lsquoPRESIDENTrsquo CONNECT BY PRIOR empno = mgr

To duplicate this hierarchical functionality in Informix stored procedures or functions can be written requiring intensive use of cursors and program arrays Informix offers the choice of creating and using a User Defined Routine or ldquoUDRrdquo See User Defined Routines section below Use of Informix global arrays will help considerably To maximize read processing at the expense of insert processing another method is to break the table into two tables one containing the data and the other containing the relationship (foreign keys) between each parent and child A parent row would have an entry in the relationship table for each of its children grandchildren great grandchildren and so on The opposite is true where a child row would have an entry in the relationship table for its parent grandparent great grandparent and so on

Truncate

Informix supports the TRUNCATE statement for deleting all active data rows from a table and associated indexes When using Informixrsquos TRUNCATE you also have the option of releasing the storage space that was occupied by the rows and index extents or keeping the space allocated to be used as the table is repopulated with new data

TRUNCATE [TABLE] table [ [ DROP | REUSE ] STORAGE ]

You may use the commandrsquos simplest usage

TRUNCATE my_table

In the example above the TRUNCATE statement drops all the data for the table and keeps only the initial extents There is a minor difference from Oracle syntax as Informix does not require the keyword TABLE Another example

TRUNCATE my_table REUSE STORAGE

ENAME EMPNO MGR JOB

KING 7839 PRESIDENT

JONES 7566 7839 MANAGER

SCOTT 7788 7566 ANALYST

ADAMS 7876 7788 CLERK

FORD 7902 7566 ANALYST

SMITH 7369 7902 CLERK

BLAKE 7698 7839 MANAGER

ALLEN 7499 7698 SALESMAN

WARD 7521 7698 SALESMAN

MARTIN 7654 7698 SALESMAN

TURNER 7844 7698 SALESMAN

JAMES 7900 7698 CLERK

CLARK 7782 7839 MANAGER

MILLER 7934 7782 CLERK

IBM Software Group IBM Information Management

Version 16 40

This example drops all the data for the table but retains all the space allocated The permissions needed for TRUNCATE TABLE depend on the existence of DELETE triggers on the table For tables with DELETE triggers ALTER permission on the table is required and RESOURCE or DBA privileges because the DELETE triggers will be bypassed For tables without DELETE triggers you need DELETE permission on the table and CONNECT privilege to the database While Oracle does not provide rollback Informix does permit TRUNCATE TABLE to execute within a transaction When you rollback a TRUNCATE statement no rows are removed from the table and the storage extents that hold the data rows and index pages continue to be allocated to the table In a database that supports transaction logging only the COMMIT WORK or ROLLBACK WORK statement is valid after the TRUNCATE statement within a transaction Any other statement will generate an error The TRUNCATE statement does not reset the serial value of SERIAL or SERIAL8 columns To reset the counter of a serial column you must do so explicitly by using the MODIFY clause of the ALTER TABLE statement either before or after you execute the TRUNCATE statement After the TRUNCATE statement successfully executes Informix automatically updates the statistics and distributions for the table and for its indexes in the system catalog to show no rows in the table nor in its dbspace partitions It is not necessary to run the UPDATE STATISTICS statement immediately after you commit the TRUNCATE statement

Host variables Host variable formats should not change during the porting process Instead data types should be converted in a manner to preserve the column and host variablersquos formats However there are times when the database schema changes in a way where the host variable format must change Any column converted to a different format in Informix than that of Oracle requires that its corresponding host variable format be changed to be consistent Alternatively if an Oracle format such as date and numeric variables is not directly supported in Informix then the conversion may require some format processing before or after the SQL statement For example the Oracle function TO_CHAR is used to format both date and numerical values A similar function or at least two functions one to handle date data types and another to handle numeric data types can be declared and used in the Informix application Informix provides two built-in functions TO_DATE which converts a character string to a DATETIME variable and TO_CHAR which converts a DATETIME variable to a character string When converting variables an optional formatting string is allowed which determines how the string is displayed (full day names partial day names full months month number and so on) There is also a function ifx_to_gl_datetime() which takes an Oracle date format and returns the corresponding Informix date format This function is supplied in genlib and is for use in ESQL programs to ease migration efforts from Oracle The syntax is as follows

TO_CHAR (source_date fmt) Returns a character string containing the date specified in source_date in the format specified by fmt if one is provided If fmt is missing the function will use the default date format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

TO_DATE (source_string fmt) Evaluates source_string as a date according to the

format fmt If fmt is missing the function will use the

IBM Software Group IBM Information Management

Version 16 41

default format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

These functions are mainly useful for simplifying migration from Oracle to Informix but are also useful for performing advanced searches on DATETIME data types and for better output presentation

Date and time functions Informix version now has built-in support for most of Oraclersquos date functions so it will not be necessary to modify or replace Oraclersquos SYSDATE or ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat)

SYSDATE

IDS 1110 will support the SYSDATE operator which returns a single value representing the current date and time from the operating system clock SYSDATE is identical to the Informixrsquos CURRENT operator except that the default precision of SYSDATE is YEAR TO FRACTION(5) while the default precision of CURRENT is YEAR TO FRACTION(3) On Windows platforms that do not support a seconds scale greater than FRACTION(3) SYSDATE is effectively a synonym for the CURRENT operator In addition to SYSDATE Informix version 1110 has support for Oraclersquos date functions ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat) Depending on the whether or not the Oracle date_format argument is supported by Informix TO_CHAR(date char_format) and TO_DATE(character_string date_format) may have to be converted to Informix date processing Date processing may be required because the Oracle application may format the date in many different ways unsupported by Informix The formats used in the Oracle functions TO_CHAR TO_NUMBER and TO_DATE are illustrated below These formats should be replaced with Informix formats wherever possible format processing functions or stored procedures written to duplicate the Oracle functionality Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

Number formats

Element Example Description 9 9999 Return value with the specified number of digits with a leading

space if positive Return value with the specified number of digits with a leading minus if negative Leading zeros are blank except for a zero value which returns a zero for the integer part of the fixed-point number

0 09999990 Return leading zeros Return trailing zeros $ $9999 Return value with a leading dollar sign B B9999 Return blanks for the integer part of a fixed-point number

when the integer part is zero (suppress leading zeros regardless of whether zeros are used in the format model ie B00999 )

MI 9999MI Return negative value with a trailing minus sign ldquo-ldquo Return positive value with a trailing blank

S S9999999 Return negative value with a leading minus sign ldquo-ldquo Return

IBM Software Group IBM Information Management

Version 16 42

Element Example Description S positive value with a leading plus sign ldquo+rdquo Return negative

value with a trailing minus sign ldquo-ldquo Return positive value with a trailing plus sign ldquo+rdquo

PR 9999PR Return negative value in ltangle bracketsgt Return positive value with a leading and trailing blank

D 99D99 Return a decimal point ldquordquo In the specified position G 9G999 Return a group separator in the specified position C C999 Return the ISO currency symbol in the specified position L L999 Return the local currency symbol in the specified position 9999 Return a comma in the specified position 9999 Return a decimal point ldquordquo In the specified position V 999V99 Return a value multiplied by 10

n (and if necessary round it

up) where n is the number of ldquo9rdquos after the ldquoVrdquo EEEE 99EEEE Return a value in scientific notation RNrn RN Return a value as Roman numerals in uppercase Return a

value as Roman numerals in lowercase Value can be an integer between 1 and 3999

FM FM909 Return a value with no leading or trailing blanks

Date formats

Element Meaning -rdquotextrdquo Punctuation and quoted text is reproduced in the result AD or AD AD indicator with or without periods AM or AM Meridian indicator with or without periods BC or BC BC indicator with or without periods CC or SCC Century ldquoSrdquo prefixes BC dates with ldquo-ldquo D Day of week (1-7) DAY Name of day padded with blanks to length of 9 characters DD Day of month (1-31) DDD Day of year (1-366) DY Abbreviated name of day IW Week of year (1-52 or 1-53) based on the ISO standard IYY or IY or I Last 3 2 or 1 digit(s) of ISO year IYYY 4-digit year based on the ISO standard HH or HH12 Hour of day (1-12) HH24 Hour of day (0-23) J Julian day the number of days since January 1 4712 BC Number

specified with lsquoJrsquo must be integers MI Minute (0-59) MM Month (01-12 JAN = 01) MONTH Name of month padded with blanks to length of 9 characters MON Abbreviated name of month RM Roman numeral month (I-XII JAN = I) Q Quarter of year (1 2 3 4 JAN-MAR = 1) RR Last 2 digits of year see below for years in other centuries WW Week of year (1-53) where week 1 starts on the first day of the year

and continues to the seventh day of the year W Week of month (1-5) where week 1 starts on the first day of the

month and ends on the seventh PM or PM Meridian indicator with and without periods SS Second (0-59) SSSSS Seconds past midnight (0-86399) YYYY Year with comma in the ldquordquo position YEAR or SYEAR Year spelled out ldquoSrdquo prefixes BC dates with ldquo-ldquo YYYY or SYYYY 4-digit year ldquoSrdquo prefixes BC dates with ldquo-ldquo

IBM Software Group IBM Information Management

Version 16 43

YYY or YY or Y Last 3 2 or 1 digit(s) of year

The RR date format element

The RR date format element is similar to the YY date format element but it provides additional flexibility for storing date values in other centuries The RR date format element allows storing the century even though only two digits are entered for the year The table below illustrates how the year is stored based on only two digits

If the year is entered as

0 ndash 49 50 - 99 If the last two digits of the

0 - 49 The return date is in the current century

The return date is in the century before the current one

current year are

50 - 99 The return date is in the century after the current one

The return date is in the current century

User-defined routines User-defined data types user defined behaviors and user defined access methods add rich functionality to Informix A user-defined routine (UDR) can be developed in C Java or Informix SPL language to vastly extend the capabilities of the database Porting applications to Informix gives the option to create UDRs for aggregate and mathematical functions or to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or you can rename an Informix function to the corresponding Oracle function name

Compatible SQL Functions Informix Dynamic Server version 1110 has added support for a number of built-in SQL functions to ease a migration effort These new functions which perform common operations and data manipulation provide compatibility with Oracle routines thus simplifying the migration of applications that have been developed for an Oracle database

Date and time functions ROUND TRUNC ADD_MONTHS LAST_DAY NEXT_DAY MONTHS_BETWEEN SYSDATE

Conversion functions ASCII TO_CHAR TO_NUMBER

String manipulation LTRIM RTRIM

Number manipulation ROUND TRUNC CEIL FLOOR POWER

Bit manipulation BITAND BITOR BITXOR BITNOT BITANDNOT

Others NULLIF FORMAT_UNITS These functions are documented with examples in the IBM Informix Guide to SQL Syntax

Aggregate functions Like Oracle the result returned by an Informix aggregate function is NULL if all of the column values are NULL with the exception of COUNT which returns 0 (zero) Like Oracle Informix aggregate functions cannot be used in a WHERE clause unless it is on a corresponding column originating from a parent query and the WHERE clause is within a sub-query that is within a HAVING clause or the aggregate function is contained within a sub-query Unlike Oracle in Informix the argument of an aggregate function cannot be another aggregate function Informix supports the SELECT COUNT (column_name) hellip statement where the number of rows containing non-null values in the specified column is returned

IBM Software Group IBM Information Management

Version 16 44

The Oracle aggregate functions STDDEV and VARIANCE are supported however the Informix standard deviation routine is named STDEV thus all references to Oraclersquos STDDEV must be changed to match Informixrsquos STDEV Informix does not support Oraclersquos greatest lower boundary (GLB ) or least upper boundary (LUB) Therefore UDRs must be written to provide equivalent functionality Informix allows users to define their own aggregate functions known as user-defined aggregates (UDA) This extension of existing aggregates can be used for new data types as well as the definition of new aggregates In Informix TEXT and BYTE columns cannot be used in aggregate functions such as COUNT AVG MAX MIN and SUM

Mathematical functions Informix does not support all of Oraclersquos mathematical functions such as SIGN COSH SINH and TANH Therefore functions or UDRs must be written in the Informix application to provide equivalent functionality In Informix the rounding factor within the ROUND function must be a value from -32 to 32 This limitation has seldom been encountered as a migration issue

String functions

LENGTH

Oraclersquos LENGTH function will return different values than Informix for strings stored in CHAR data types The numeric return value representing the string length returned by Oracle will include all trailing spaces Whereas Informixrsquos LENGTH function will ignore trailing blanks regardless of data type For example for the two CHAR strings ldquoBOBrdquo and ldquoBOB ldquo Oraclersquos LENGTH function will return different values for each string 3 and 5 respectively Whereas Informixrsquos LENGTH function will ignore trailing blanks and return the value 3 for both When the input string is NULL both database functions will return a NULL

LTRIM and RTRIM

The SQL Compatibility features of Informx has support for LTRIM and RTRIM and will return identical values to that of Oracle No modifications will be necessary to SQL statements utilizing these functions

Oracle Extensions

Informix does not support all of Oraclersquos string functions such as CHR INSTR SOUNDEX and TRANSLATE Therefore corresponding user-defined routines or UDRs (ie functions or stored procedures) must be written in the Informix application to provide equivalent functionality Please note that the VERITY and EXCALIBUR Datablades included with Informix will work with Oraclersquos string function SOUNDEX

Other Oracle Functions Informix does not support the following Oracle functions Therefore corresponding functions must be written in the Informix application to provide equivalent functionality Alternatives to some of the more common Oracle functions follow this list

CHARTOROWID CONVERT DUMP GREATEST GREATEST_LB

IBM Software Group IBM Information Management

Version 16 45

HEXTORAW LEAST LEAST_UB RAWTOHEX ROWIDTOCHAR TO_LABEL TO_MULTI_BYTE TO_SINGLE_BYTE UID USERENV(OSDBA LABEL LANGUAGE TERMINAL SESSIONID ENTRYID) VSIZE

Macros Oracle contains macros sometimes referred to as language constructs which can determine the status of an object Informix does not support Oraclersquos macros These macros must be removed from the code and the associated logic should be implemented with equivalent Informix logic where applicable

ISOPEN and NOT FOUND

The macro cursor_nameISOPEN returns a Boolean value to indicate whether the cursor is open and cursor_nameNOTFOUND indicates whether there are any more rows yet to be fetched from the cursor cursor_name These macros used in condition statements are followed by some logic to handle the true andor false conditions In the case of ISOPEN this macro and its associated logic can just be omitted since the FOREACH loop processing does not explicitly open a cursor and therefore the condition cannot be checked In the case of NOTFOUND this macro should be omitted and its associated logic converted to Informix logic within an Informix FOREACH loop

ROWTYPE

The Oracle macro prefixROWTYPE is used in the declarative section as a data type to declare variables similar to the structure construct of C or RECORD of INFORMIX The prefix can be either a table name or another structure name Structure names ultimately refer back to a table name This macro may be replaced with the Informix statement LIKE table_name The construct LIKE table_name cannot be used in SPL Instead the construct DEFINE column1 LIKE table_namecolumn1 DEFINE column2 LIKE table_namecolumn2 and so on should be used to declare variables corresponding to all the columns of the table Then operations on the whole or part of the structure should be replaced with operations on single SPL variables

TYPE

The Oracle macro prefixTYPE is used in the declarative section as a data type to declare single variables The prefix is either a table_namecolumn_name or a structure_namevariable_name A structure_namevariable_name ultimately refers back to a table_namecolumn_name This macro can be replaced with the Informix statement LIKE table_namecolumn_name

Pseudo-columns Pseudo-columns are columns that exist in tables but are not displayed from a SELECT FROM table_name query Informix pseudo-columns are generally reserved for the enginersquos use Eliminating the use of such columns increases an applicationrsquos portability and eliminates the need for future modifications if the engine is ever modified to process the column differently or not at all

IBM Software Group IBM Information Management

Version 16 46

LEVEL

In Oracle for each row returned by a hierarchical query the pseudo-column LEVEL returns 1 for a root node 2 for a child of a root 3 for a child whose parent is at level 2 and so on A root node is the highest node within an inverted tree and therefore has no parent A child node is any non-root node A parent node is any node that has children A leaf node is any node without children To define a hierarchical relationship in a query you must use the START WITH and CONNECT BY clauses Informix does not support the LEVEL clause See the Hierarchical Queries subsection in the SQL section in the ldquoData Manipulation Languagerdquo chapter for more information on how to process these queries

ROWID

Oraclersquos ROWID pseudo-column returns the rows address for each row in the database ROWID values contain the following information necessary to locate a row

Which data block in the data file

Which row in the data block (first row is 0)

Which data file (first file is 1)

Usually a ROWID value uniquely identifies a row in the database However rows in different tables that are stored together in the same cluster can have the same ROWID Values of the ROWID pseudo-column have the data type ROWID ROWID values have several important uses

They are the fastest way to access a single row

They can show you how a tables rows are stored

They are unique identifiers for rows in a table

A ROWID does not change during the lifetime of its row However you should not use ROWID as a tables primary key If a row is deleted and re-inserted its ROWID may change even when using the export and import utilities If a row is deleted Oracle may re-assign its ROWID to a new row inserted later Although you can use the ROWID pseudo-column in the SELECT and WHERE clauses of a query these pseudo-column values are not actually stored in the database The value of a ROWID pseudo-column cannot be inserted updated or deleted For example the following Oracle statement selects the address of all rows that contain data for employees in department 20

SELECT ROWID ename FROM emp WHERE deptno = 20

The equivalent pseudo-column in Informix is also known as ROWID and although the behavior is similar the data type is different from Oraclersquos See the ROWID subsection in the Data Types section in the chapter ldquoData definition languagerdquo for more information

ROWNUM

In Oracle for each row returned by a query the ROWNUM pseudo-column returns a number indicating the order in which Oracle selected the row from a table or set of joined rows The first row selected has a ROWNUM of 1 the second has 2 and so on ROWNUM can be used to limit the number of rows returned by a query as in this example to read 9 rows

SELECT

FROM emp

WHERE ROWNUM lt 10

ROWID ENAME 0000000F00000002 SMITH 0000000F00030002 JONES 0000000F00070002 SCOTT 0000000F000A0002 ADAMS 0000000F000C0002 FORD

IBM Software Group IBM Information Management

Version 16 47

You can also use ROWNUM to assign unique values to each row of a table as in this example

UPDATE tabx

SET col1 = ROWNUM

Oracle assigns a ROWNUM value to each row as it is retrieved before the rows are sorted by an ORDER BY clause Therefore the final order of the rows is in ORDER BY order not in ROWNUM order An ORDER BY clause does not affect the ROWNUM values except in the case where the ORDER BY clause causes Oracle to use an index In that case the ROWNUM values are set in the order the rows are retrieved using the index and hence in ORDER BY order This order is different than if the rows were retrieved without the index So in this case the ORDER BY can affect the ROWNUM values Conditions which test for ROWNUM values greater than zero are always false For example this query returns no rows

SELECT FROM employee WHERE ROWNUM gt 1

The first row fetched is assigned a ROWNUM of 1 thus making the condition false The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 making the condition false All rows subsequently fail to satisfy the condition so no rows are returned Although there is no ROWNUM equivalent in Informix there are solutions Beginning with IDS 73 and in Informix Dynamic Server 2000 Informix provides a feature which allows the user to limit the results of a query to the first N rows This was implemented for TPC-D compliance and to support ldquorankrdquo queries Rank queries can be assembled by using FIRST N with the ORDER BY clause Informix will return the top N rows according to some ordering criteria Therefore the following Oracle SELECT utilizing ROWNUM

SELECT FROM emp WHERE ROWNUM lt 10

can be ported to Informix as follows

SELECT FIRST 9 FROM emp

Informix does not support SELECT FIRST N in complex cases as the following

Sub-queries (SELECT within a SELECT)

View definitions (Cannot be used by a SELECT statement which references a view)

UNION queries The behavior of SELECT FIRST N depends on the presence of an ORDER BY clause If no order by clause is specified the first N rows returned may be in any order Examples are as follows

find 10 highest paid employees

SELECT FIRST 10 name salary

FROM emp

ORDER BY salary

find 10 highest salary values

SELECT FIRST 10 DISTINCT salary

FROM emp

ORDER BY salary

IBM Software Group IBM Information Management

Version 16 48

Informix supports column names of ldquofirstrdquo Thus without a positive integer following the word ldquofirstrdquo the token is parsed as a column name rather than a keyword The value of N may be between 1 and (2

31-1)

When ROWNUM is used in a WHERE clause the same results can be obtained through the use of the FIRST N and SKIP clauses but if ROWNUM is used in the select list the solution is a little more complicated Simply stated you can construct a query where the ROWNUM column in any row is the count of the rows that came before This involves creating a correlated subquery where the subquery contains a self-join This can be done for any table or set of tables which has a unique key defined on it Here is an example using the customer table of the stores7 database

select

counterrownum

basecustomer_num

basefname

baselname

from

-- There can be more than one table here and the result

-- set should thought of as a table (just not a base table)

-- The result table has to be joined to itself in the

-- subquery so if there are multiple tables in this FROM

-- clause the expansion can get messy You have to have a

-- set of columns that uniquely identify each row in the

-- result table and join across them ROWID would

-- likely work if the table is not fragmented but if it is

-- there is no guarantee the final results would be accurate

-- because ROWID is not guaranteed to be unique across

-- fragments

customer base

(select

count() as rownum

acustomer_num -- any unique key possibly multiple

-- columns

from

customer a

customer b

where

-- This is where the rownum is determined the relationship

-- here has to match the outer order-by where the rows

-- are sorted and has to create a unique sort order

--

-- Any columns to be ordered by go here

-- Also the unique key has to be used to keep rows

-- that do not have a unique sort order from being merged

(alname gt blname) -- example sorting by last name

or

(alname = blname and afname gt bfname)

-- sorting by fname where lname is equal

or

(alname = blname and afname = bfname

and acustomer_num gt= bcustomer_num)

-- sorting by unique key where all the

-- other sort columns are equal

-- The expansion above is logically the same as

-- alname || afname || to_char(acustomer_num) gt=

-- blname || bfname || to_char(bcustomer_num)

-- but it allows the server to utilize any indexes that

-- may exist

group by

-- unique key columns go here

IBM Software Group IBM Information Management

Version 16 49

acustomer_num

) counter

where

-- key columns in the base tables go here

basecustomer_num = countercustomer_num

-- if you want to limit on rownum it goes here

-- and rownum lt= 10

order by

counterrownum

If using ROWNUM as an assignment as in

UPDATE tabx

SET col1 = ROWNUM

The following Informix-ESQLC pseudo-code example would have to be used

int counter = 0

EXEC SQL declare c1 cursor for

SELECT col1 col2

INTO col1 col2

FROM table 1

WHERE col1 = XX

EXEC SQL open c1

while (SQLCODE == 0)

EXEC SQL fetch c1

counter++ Increment counter for each row

fetched

if (counter gt= 5)

break

logic

End if

End while

Update using cursors There are slight differences between the ways Informix and Oracle process cursors Unlike Oracle in Informix the WHERE CURRENT OF clause cannot be used to update tables in a SELECT statement joining multiple tables since the WHERE CURRENT OF clause requires a FOR UPDATE cursor and Informix does not support the FOR UPDATE clause in SELECT statements that join multiple tables Therefore in the multi-table join statements the Oracle options FOR UPDATE and WHERE CURRENT OF should be removed and the update of the rows should be done using a separate UPDATE statement in the same cursor loop

IBM Software Group IBM Information Management

Version 16 50

In Informix a commit or rollback statement closes all cursors open in a given transaction boundary See the Transaction Processing section in CHAPTER 5 Application Architecture for more information In situations where the intention is to commit or rollback without closing the cursor in other words where the commit or rollback is executed within a cursor fetch loop the cursor can be declared as a HOLD cursor This requires that a BEGIN WORK is issued before the cursor loop starts A HOLD cursor is not closed when a commit or rollback statement is issued In Informix the FOR UPDATE clause cannot be used when declaring a HOLD cursor Thus where an Oracle application updates a table from which it fetches data in the fetch loop or issues a commit work in the fetch loop it must be converted to Informix The cursor can be declared with HOLD and then an UPDATE statement can be issued without the WHERE CURRENT OF clause In order to uniquely identify the row to be updated in the table in other words in order to simulate the WHERE CURRENT OF clause the ROWID or unique primary key columns of the table(s) to be updated must also be fetched and the WHERE CURRENT OF clause can be replaced with WHERE ROWID = fetched rowid or WHERE unique primary key column(s) = fetched unique primary key column(s) A BEGIN WORK must follow immediately after a COMMIT WORK or ROLLBACK WORK in the fetch loops to simulate Oracle implied transaction boundaries These transaction control statements work for either Informix logged databases or Informix ANSI mode databases however ANSI mode database processing with these statements will set certain warning flags after executing the BEGIN WORK statement and continue processing without failure See the ANSI vs Non-ANSI subsection in the Databases section in the chapter ldquoData Manipulation Languagerdquo for more information

System tables References to Oracle system tables should be replaced with corresponding references to Informix system tables The information schema views provided by Informix can be used These views are created after the database is installed They are populated by data in the system catalog tables and are used for easier porting

Stored procedures Informix procedures and functions are considered to be user-defined routines (UDR) A UDR can be written in Informixrsquos Stored Procedure Language (SPL) or an external language such as C or Java A procedure is a routine written that does not return a value A function is a routine written that returns a single value a value with a complex data type or multiple values Informix SPL is an extension to Informix SQL and provides procedural flow control such as looping and branching A SPL routine is a generic term that includes both SPL procedures and SPL

functions You use SQL and SPL statements to write an SPL routine SPL statements can be used only inside the CREATE PROCEDURE CREATE PROCEDURE FROM CREATE FUNCTION and CREATE FUNCTION FROM statements SPL routines are parsed optimized and stored in the system catalog tables in executable format Like Oracle Informix stored procedures support input output and inputoutput parameters and can be used in SQL statements wherever expressions are allowed

Size limit

Informix stored procedures have a size limit of approximately 64K Oracle stored procedures greater than 64K in size can be broken into smaller Informix stored procedures communicating with each other as though they were one by passing and returning the necessary values

Parameter limit

IBM Software Group IBM Information Management

Version 16 51

Informix has a limit of 341 parameters for each stored procedure This limit also applies to UDRs written in the Java language UDRs written in the C language can have no more than 102 parameters You can define any number of SPL routine parameters but the total length of all parameters passed to an SPL routine must be less than 64 kilobytes No more than nine arguments to a UDR written in the Java language can be DECIMAL data types of SQL that the UDR declares as BigDecimal data types of the Java language Any C language UDR that returns an opaque data type must specify opaque_type in the var binary declaration of the C host variable

Packages

An Oracle package is a collection of functions procedures and variables that can be enabled and accessed as a unit There is no direct equivalent within Informix but there are ways of achieving similar capabilities Within Oracle a procedure within a package can be accessed through grammar such as package_nameprocedure_name If you create an owner or schema name within the Informix system the same as the package name then it will be easier to migrate calls to that procedure because the grammar is effectively the same although the meaning changes somewhat Using this practice a call to a migrated procedure would be ownerprocedure_name where the owner name is the same as the package name Translating package names as owner names is a way to maintain the scoping of the objects within the package Maintaining the aspect of being able to enable use of or upgrade the collection of package objects can be done by creating a datablade that contains all the objects that used to be part of the package Datablade routines can be procedures or functions written in Stored Procedure Language (SPL) C and Java In addition routines can be written in C++ on Windows platforms

Routines

Oraclersquos stored functions and stored procedures are similar in concept to Informixrsquos stored procedures Oraclersquos user defined database level functions such as stored functions stored procedures all need to be converted to Informix stored procedures using the Informix SPL C or Java Routines written in SPL have the advantage of being maintained and backed up with database backups Routines written in C are fast but are not automatically backed up when the database is and need to be compiled specifically for the operating system on which it will run Routines written in Java also not backed up by the DBMS itself but they are platform independent However probably as a result of having to convert between system memory where the objects have C structures and Java virtual machine memory where the objects have Java structures the performance of Java routines can be slow compared with the C equivalent All procedures written in an Oracle package body must be rewritten as separate Informix procedures When rewriting package bodies into separate procedures Oraclersquos variable declarations can be replaced at the package level (global) with Informixrsquos global variables The Informix global variables must be defined in the first stored procedure of the logical group

Exceptions

The method of handling exceptions is different between Informix and Oracle Oracle has many predefined and user defined exception labels such as CURSOR_ALREADY_OPEN NO_DATA_FOUND ZERO_DIVIDE and so on The labels can be used in the logic to identify errors Only one exception check is allowed per BEGIN and END block using the EXCEPTION construct and it is normally placed just before the END statement Informix also supports predefined and user defined exceptions however they are represented numerically not with labels In Informix all the exceptions checked in the stored procedure control blocks delimited with BEGIN and END statements must be declared explicitly at the top of each

IBM Software Group IBM Information Management

Version 16 52

control block with the Informix EXCEPTION construct Therefore Oracle procedure code must be restructured to manipulate these exceptions In Oracle an exception can be raised globally and acted upon globally In Informix the scope of an exception mechanism is always restricted to the block in which it is located This leads to the addition of multiple Informix exception handling mechanisms for each Oracle exception raised as well as a redesign of the overall stored procedure to a more blocked format

Error handling

In Oracle errors are processed as part of a function call return value In Informix errors are retrieved as a separate function call that has multiple structures that have to be created in order to retrieve error and status The SQLCA structure is not fully available in Informix stored procedures It is not possible to check the SQLCODE variable in the stored procedure body Instead the function DBINFO can be used to extract the value of two members of the SQLCA structure sqlcasqlerrd1 and sqlcasqlerrd2 This function should be used inside the FOREACH construct while the cursor is open Once the cursor is closed the DBINFO function cannot return proper values The sqlcasqlerrd1 option returns different values depending on the type of SQL statement For INSERT statements if the table contains a serial column then the sqlcasqlerrd1 option will return the serial value of the last row inserted into the table For SELECT DELETE and UPDATE statements the sqlcasqlerrd1 option will return the number of rows processed by the query In these cases upon each pass through the FOREACH loop sqlcasqlerrd1 is the same value the number of rows the FOREACH loop will process The sqlcasqlerrd1 value can still be interrogated during each pass through the FOREACH loop The sqlcasqlerrd2 option returns the number of rows processed by a SELECT INSERT UPDATE DELETE or EXECUTE PROCEDURE statement It should not be interrogated until after the cursor has finished processing In other words within the FOREACH loop the sqlcasqlerrd2 value can be moved to a variable which is then interrogated outside of the FOREACH loop

Cursors

Unlike Informix in Oracle cursors can be global to a package In Informix Oraclersquos global cursors can be replaced with temporary tables A temporary table can be created and populated in place of where the cursor is opened The temporary table can then be processed the same way the cursor is processed Finally the temporary table should be dropped in place of where the cursor is closed Cursors are explicitly declared opened and fetched in Oracle stored procedures In Informix cursors do not need to be explicitly declared opened and fetched in stored procedures Instead Oracle stored procedure cursors can be replaced with Informixrsquos FOREACH construct The Oracle cursor name should be used in the FOREACH statement for example FOREACH cursor_name SELECT hellip END FOREACH In order to update a cursor row in Oracle the cursor must be declared with the FOR UPDATE clause In Informix if the SELECT statement in the FOREACH construct is not a multi-table join then each fetched row can be updated using the UPDATE lttable_namegt WHERE CURRENT OF ltcursor_namegt statement See the Update Using Cursors section in ldquoData Manipulation Languagerdquo for more information Informix does not support the SELECT FOR UPDATE statement in a stored procedure Therefore the SELECT FOR UPDATE clause cannot be used in the FOREACH construct

IBM Software Group IBM Information Management

Version 16 53

Variable declaration and assignment

Oracle allows implicit variable definitions within a FOR loop The variables are defined using an assignment operator and a column name For example

out_customer_name = customername

The variable out_customer_name is defined as the same type as the column name in the customer table Informix requires that all variables be defined at the beginning of each stored procedure control block For example

DEFINE out_customer_name LIKE customername

DEFINE counter INTEGER

Therefore Oraclersquos implicit variable declaration must be replaced with Informixrsquos explicit variable declaration before the control block Additionally assignment operations will need to be ported Oracle uses a colon and an equal sign (=) for assignment while Informix utilizes the LET keyword in combination with an equal sign (=) (ie LET var = 1) Therefore assignment statements must be modified with the LET keyword and an equal sign

Boolean

Oraclersquos BOOLEAN variable type can be replaced with Informixrsquos BOOLEAN data type

Binary data types

Binary data types are very different between Oracle and Informix In Oracle the binary type is defined as a type RAW and is explicitly defined with a maximum length as part of the declaration In Informix the binary type is defined as REFERENCES BYTE which deals only with pointers to BLOBs It implicitly defines a maximum length as part of the function call in which the pointer to the BLOB and maximum length (as used in the function call) was passed as values As a result the binary type cannot be assigned a binary value in a stored procedure nor can it be inserted into a table via the SQL INSERT statement in a stored procedure These operations that initialize a binary type must be performed outside of stored procedures

Dynamic SQL

Unlike Oracle Informix does not support dynamic SQL within the Stored Procedure Language In other words a statement such as SELECT variable_name FROM variable_name WHERE variable_name is not supported This kind of processing can be achieved in Informix within an embedded SQL program This requires that either the Oracle stored procedure be converted to an embedded SQL program or just the Dynamic SQL portion be placed in an embedded SQL program and then called from within the stored procedure The latter option will have performance implications since calling an embedded SQL program from a stored procedure requires an operating system call Another option is to use the Informix EXEC Bladelet The EXEC Bladelet consists of user-defined functions that take a SQL query as an argument execute it and return a result (the format of which varies depending on the function and the kind of query) The EXEC Bladelet functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries Further details can be found in Chapter 7 Using Bladelets

Compiler

Unlike Oracle the Informix compiler was developed with the concept that developers can create stored procedures independently of the database Therefore Informixrsquos stored procedure

IBM Software Group IBM Information Management

Version 16 54

compiler has a limited set of errors that it checks compared to Oraclersquos For example the Informix stored procedure compiler does not validate database object names such as table column and view names Therefore database object naming errors will occur at runtime not compile time Additionally the error messages generated from the compiler are not very specific Identifying a problem in a stored procedure may require breaking it apart and recompiling the pieces until the problem is found This may impact the time necessary to unit test the stored procedures

Triggers Oracle supports the use of multiple trigger events for example insert update and delete within the same trigger Informix only supports one trigger event per trigger In Informix the Oracle trigger body in this example must be copied into three different triggers each with only one event Informix triggers have some constraints Oraclersquos do not In Informix if a trigger is fired due to inserting a row into a table a trigger can only act on any rows or columns within that table using the EXECUTE PROCEDURE hellip INTO syntax Similarly if a trigger is fired due to updating a row then the trigger can only act on the column that caused the trigger to fire using the EXECUTE PROCEDURE hellip INTO syntax Like Oracle if a trigger is fired due to deleting a row there are no restrictions Prior to IDS 73 when a trigger was fired on an INSERTUPDATE action no modification could be done to the columns (in the row) which just fired the trigger The reentrant UPDATEINSERT triggers feature introduced with IDS 1110 enables users to update the triggering columns by using the EXECUTE PROCEDURE INTO syntax Additionally the feature enforce that this action will not cause any additional triggers to be fired (same or different trigger) causing a cascading of triggers and potentially an infinite loop The following example demonstrates how the reentrant UPDATEINSERT trigger feature is used

create table foo

(

x int default NULL

y int default NULL

z int default NULL

)

create procedure reentrant()

returning int

return 56

end procedure

create trigger reentrant_trigger insert on foo for each row

(

execute procedure reentrant() into z

)

insert into foo values

(

1

2

3

)

The following SELECT will result in the following returned data

select from foo

x y z

1 2 56

IBM Software Group IBM Information Management

Version 16 55

Oracle allows SQL statements logical statements and stored procedure calls within a trigger body Informix allows only SQL statements and stored procedure calls within a trigger body Oracle triggers containing logical statements must be converted to Informix by moving their contents into a stored procedure The stored procedure should then be executed from the trigger

Constraints Constraints in both Oracle and Informix can be enabled and disabled within an application transaction however there are behavioral differences In Oracle the application is always executing within a transaction In Informix transaction boundaries are explicitly declared and care should be taken to ensure that this functionality is performed within the boundaries of a transaction See the Transaction Processing section in CHAPTER 5 Application Architecture for more information The constraint syntax available in Informix is

SET CONSTRAINTSINDEXESTRIGGERS FOR table_name

ENABLED|DISABLED

SET CONSTRAINTS comma_separated_constraint_names

ENABLED|DISABLED

SET INDEXES comma_separated_index_names ENABLED|DISABLED

SET TRIGGERS comma_triggers_constraint_names ENABLED|DISABLED

SET CONSTRAINTS ALLconstraint_name IMMEDIATE|DEFERRED

The first four statements must be executed with DBA privileges if placed in the application Therefore care should be taken when using them Note that the last statement contains a DEFERRED clause This is the statement used if the users of the application do not have DBA privileges When the constraint is set with the DEFERRED clause the specified constraints are not checked until the transaction is committed If a constraint violation occurs while the transaction is being committed the transaction is rolled back

DUAL table Oraclersquos DUAL table is a system table with only one row containing one column named DUMMY This table is used to complete the syntax of an SQL statement that does not involve an existing table such as

A SELECT statement which assigns some constant value (which can only be derived in an SQL statement) to a host variable

SELECT TO_CHAR(SYSDATE) INTO date_var FROM DUAL

A SELECT statement which assigns a value of another variable to a variable

SELECT source_var INTO dest_var FROM DUAL

A SELECT statement which unions application host variable values with another SELECT statement to return a result containing a row of application variable values

SELECT col1 col2 col3 FROM table_name

UNION

SELECT host_var1 host_var2 host_var3 FROM DUAL

Converting Oraclersquos DUAL table functionality to Informix depends on the way it is used Converting statements that just assign constants is as simple as replacing the DUAL statement with an Informix assignment statement The solutions below apply to Informix versions prior to 11 At 11 and above the concept of a DUAL table as well as sysdate is supported

IBM Software Group IBM Information Management

Version 16 56

SELECT sysdate FROM sysmastersysdual

If you want a dual table in your local database then create the following synonym The sysmastersysdual table is much faster than a physical table in your database because it is an in- memory pseudo table

CREATE SYNONYM dual FOR sysmastersysdual

If you are restricted to using a version of Informix prior to 11 then the following solutions can be used A dummy table can be created to mimic the behavior of simple SELECT INTO statements used to assign values to variables

CREATE TABLE dual (dummy VARCHAR(1))

INSERT INTO dual VALUES(lsquoXrsquo)

An alternate solution to widespread use of the DUAL table could be creating a permanent view that is generally accessible

CREATE VIEW dual (d) as SELECT X

FROM systables WHERE tabid = 1

The exact definition could be used or modified as needed but this would solve the problem of having DUAL be permanent usable by anyone and not modifiable

IBM Software Group IBM Information Management

Version 16 57

C H A P T E R 5 Embedded SQL

Oraclersquos embedded SQL products are ProC and ProCOBOL Informixrsquos corresponding embedded SQL products are ESQLC and ESQLCOBOL

Host variables

Declaration override

The Oracle EXEC SQL VAR declarative statement (host variable equivalency of Oracle external data types by overriding the default assignment) can be converted to an Informix explicit declaration statement For example

Oracle char char_var[20]

EXEC SQL VAR char_var IS STRING(11)

Informix

char char_var[11]

Note that the size and type used in the EXEC SQL VAR section is the final information required to declare the host variable in Informix

Arrays

Oracle arrays are not subscripted in SQL statements since it is not required to process the host arrays in a loop in the SQL statement In Informix subscripting is mandatory In Oracle if an array is defined of size 200 then an SQL statement would be

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A

VAR-B

VAR-C

END-EXEC

-or- EXEC SQL SELECT COL1 COL2 COL3

INTO VAR-A

VAR-B

VAR-C

FROM TABLE1

WHERE COL2 gt 100

END-EXEC

where VAR-A VAR-B and VAR-C are each an array of say 200

IBM Software Group IBM Information Management

Version 16 58

In Informix the first example would be converted to

PERFORM VARYING LOOP-CTR FROM 1 BY 1 UNTIL

LOOP-CTR IS GREATER THAN 200

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A(LOOP-CTR)

VAR-B(LOOP-CTR)

VAR-C(LOOP-CTR)

END-EXEC

IF SQLCODE = 100

GO TO EXIT-PERFORM

END-IF

END-PERFORM

EXIT-PERFORM

For the second Oracle example given above a cursor must be declared in Informix opened and fetched for 200 rows or less (less because there may be less than 200 qualifying rows) into the host array and then should be closed If the number of qualifying rows is more than 200 then the extra rows must be ignored to duplicate the Oracle functionality But for the first example each fetch in Oracle will return the next 200 or less number of rows Therefore each Oracle fetch needs to be replaced by another call to the Informix fetch loop Oracle also uses this method for inserts deletes and updates These array techniques are mainly used in batch SQL processing

Formatting

In Informix when a DECIMAL MONEY DATE or DATETIME value is selected into a host variable of the same data type the value must be formatted using the available Informix formatting routines before they can be printed or displayed For example

hellip

dec_t dec_host_var

char formatted_dec[40]

EXEC SQL SELECT DEC_COLUMN INTO dec_host_var FROM TABLE_NAME

rfmtdec(ampdec_host_var ldquoampampampampampampampampampamprdquo formatted_dec)

printf(ldquoThe Decimal Value is snrdquo formatted_dec)

hellip

IBM Software Group IBM Information Management

Version 16 59

Informix supplies many formatting functions and formatting strings The names of these functions are different in Informix ESQLC and ESQLCOBOL but the functionality is the same Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

SQL structures

SQLCA

Oraclersquos SQLCA structure is different from that of Informix However the components of both structures are logically the same Oraclersquos SQLCA components can be replaced with the corresponding Informix components Oraclersquos SQLCA structure

SQLCAID string containing ldquoSQLCArdquo SQLCABC length of SQLCA data structure SQLCODE Oracle error message code SQLERRM sub-record for error message

SQLERRML length of error message SQLERRMC text of error message SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) reserved for future use SQLERRD(1) reserved for future use SQLERRD(2) number of rows processed SQLERRD(3) reserved for future use SQLERRD(4) parse error offset SQLERRD(5) reserved for future use

SQLWARN array of eight warning flags SQLWARN(0) another warning flag set SQLWARN(1) character string truncated SQLWARN(2) no longer in use SQLWARN(3) SELECT list not equal to INTO list SQLWARN(4) DELETE or UPDATE without WHERE clause SQLWARN(5) reserved for future use SQLWARN(6) no longer in use SQLWARN(7) no longer in use

SQLTEXT reserved for future use

IBM Software Group IBM Information Management

Version 16 60

Informixrsquos SQLCA structure

SQLCODE Informix error code SQLERRM error message parameter SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) estimated number of rows returned SQLERRD(1) serial value of INSERT or ISAM error code SQLERRD(2) number of rows processed SQLERRD(3) estimated cost SQLERRD(4) parse error offset SQLERRD(5) ROWID after INSERT

SQLWARN structure of eight warning flags SQLWARN0 another warning flag set SQLWARN1 character string truncated or no privileges revoked SQLWARN2 NULL value returned or ANSI database SQLWARN3 SELECT list not equal to INTO list or turbo back-end SQLWARN4 DELETE or UPDATE without WHERE clause SQLWARN5 if non-ANSI statement SQLWARN6 if server is in data replication secondary mode SQLWARN7 reserved

In order to get Oracle error messages an application normally uses the SQLCA element SQLERRMC The Informix equivalent is SQLERRM On the HPUX and Solaris platforms the Informix function rgetmsg should be used instead of the element SQLERRM At the time of this writing using SQLERRM would cause an error on the HPUX and Solaris platforms

SQLDA

The implementation of Oraclersquos SQLDA structure is very different from that of Informix Significant changes are necessary to convert Oraclersquos functionality to Informix Oraclersquos sqlald function can be replaced with Informixrsquos ALLOCATE DESCRIPTOR statement Since Oraclersquos and Informixrsquos SQLDA structures are so different Oraclersquos SQLDA logic must be rewritten with the more powerful Informix SQLDA logic or alternatively the Informix system-descriptor area logic Oraclersquos SQLDA Structure

N maximum number of SELECT list items or placeholders V pointer to array of address of SELECT list items or bind variables L pointer to array of lengths of SELECT list items or bind variables T pointer to array of data types of SELECT list items or bind variables I pointer to array of addresses of indicator variable values F actual number of SELECT list items or placeholders S pointer to array of addresses of SELECT list items or placeholder names M pointer to array of max lengths of SELECT list items or placeholder names C pointer to array of current lengths of SELECT list items or placeholder names X pointer to array of addresses of indicator variable names Y pointer to array of maximum lengths of indicator variable names Z pointer to array of current lengths of indicator variable names

IBM Software Group IBM Information Management

Version 16 61

Informixrsquos SQLDA Structure SQLD count of the following SQLVAR members SQLVAR pointer to array of structures

SQLDATA pointer to actual data SQLTYPE data type of placeholder or SELECT item SQLLEN length of the placeholder or SELECT item SQLIND pointer to the indicator SQLNAME pointer to placeholder or SELECT item name SQLFORMAT reserved SQLIDATA indicator data pointer SQLITYPE indicator variable type SQLILEN length of indicator variable

If an Oracle application uses the simple dynamic SQL method using macros only not the SQLDA structure directly the value indicatorsplaceholders can be replaced with a lsquorsquo in Informix For example Oracle sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES (v1 v2)rdquo) Informix sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES ( )rdquo)

ORACA

Oraclersquos ORACA structure is not supported by Informix This structure is used to handle Oracle specific communication and more runtime information than SQLCA Oracle statements containing references to this structure should be removed from the application

Pre-compiler options The Oracle options beginning with the EXEC ORACLE OPTION statement can be removed from the application The options set after this statement do not affect the application logic They may affect some application performance only

Embedded PLSQL Oracle allows procedure language (PLSQL) blocks inside ProC and ProCOBOL code delimited by the EXEC SQL EXECUTE and END-EXEC statements In Informix these blocks must be replaced with the equivalent ESQLC or ESQLCOBOL code

Oracle Call Interface Oracle call interface (OCI) is the base layer for a variety of other application programming interfaces such as JDBC-OCI Oracle Precompilers and Oracle ODBC It is also used directly by customers who are willing to develop their code using a lower level proprietary API From a high level it can be thought of as if IBM Informix had standardized and published the function calls in the ESQLC library Although some customers have reverse engineered these calls and developed applications using them this is generally discouraged because there is no guarantee that the library of calls will not change There is no direct equivalent to this Oracle API in Informix Migrating applications written using Oracle Call Interface (OCI) will require rewriting the code from scratch OCI is native to the C language and so it should be less effort to migrate the application to an Informix API that is also native to C This could be ESQLC or CLI The following information explains differences between Oracle OCI and Informix ODBC

IBM Software Group IBM Information Management

Version 16 62

The following table is an approximate mapping of the differences between the Informix CLI and Oracle OCI function calls in which there is not a direct one-to-one mapping

Oracle Informix Buffer Areas HAD LDA CDA HENV HDBC HSTMT

Connect and allocate resources

OLOG OOPEN SQLConnect SQLAllocEnv SQLAllocConnect SQLAllocStmt

Update delete insert select OPARSE OBNDRV OEXEC SQLPrepare SQLBindParameter SQLExecute

Select ODEFIN OFETCH SQLBindCol SQLFetch

Commit Rollback OCOM OROL SQLTransact

Disconnect OLOGOF OCLOSE SQLDisconnect SQLFreeStmt SQLFreeConnect SQLFreeEnv

Database library calls

One of the first main differences between Informix CLI and Oracle OCI calls is the overall data structures and mechanisms used to process database library calls Oracle uses direct connections to the database server Informix uses an ODBC connection to the database server As a result the Informix calls will be implemented as ODBC SQL calls utilizing three tiers of increasing SQL levels of complexity

Global area processing

Another main difference between Informix CLI and Oracle OCI is Informixrsquos use of pointers to three global areas versus Oraclersquos use of pointers to three different but similar global areas Hence the Oracle OCI calls that utilize HAD (Handle Data Area) LDA (Logon Data Area) and CDA (Cursor Data Area) pointers must be translated over to Informix CLI calls that utilize HENV (Environment Area) HDBC (Database Connection Area) and HSTMT (Statement Area) pointers respectively in conjunction with an ODBC interface

Fetch cycle

Another difference between Informix CLI and Oracle OCI calls is that the overall fetch cycle is different for each and must be modified accordingly In Oracle the fetch cycle for selecting multiple rows utilizing a cursor area involves parsing binding defining fetching and then executing into a cursor data area These must be translated to a cycle that involves preparing binding executing binding and then fetching via the ldquoFor Eachrdquo cycle

RAW binary data type processing

RAW binary data types in Oracle will need to be translated to a pointer-to-BLOB REFERENCES BYTE type in Informix See the Binary Data Types subsection of the Stored Procedures section in CHAPTER 3

Parameter bindings

In Oracle multiple output bindings of parameters are declared as type ldquoOUTPUTrdquo in the ODEFIN() calls In Informix convert the calls to Informix SQLBindCol() calls and bind the output parameters as columns Differences also exist between Informix CLI and Oracle OCI in the use of inputoutput bindings In Oracle these bindings are declared as type ldquoINPUTOUTPUTrdquo in the ODEFIN() calls In Informix a ldquoround robinrdquo approach is used using three variables in the following manner A=B B=C C=A A variable (A) is declared before the SQL bindings as an input variable The function is called

IBM Software Group IBM Information Management

Version 16 63

using a second input variable (B) that is set to the first input variable (A) The function returns a third variable (C) that is bound as an output column Finally the first variable (A) is now set to the returned third variable (C) that made the first variable (A) appear as an ldquoinputoutputrdquo variable to the rest of the program

Embedded SQL for C

VARCHAR

Oraclersquos ProC VARCHAR data type is expanded after pre-compiling into a structure with two elements one is unsigned short len and the other is unsigned char arr[size] The name of the expanded structure is the same name as the VARCHAR variable and size is replaced with the size of the VARCHAR variable In Informix the VARCHAR data type is just a synonym for the C languagersquos char data type Therefore statements that use variable_namelen can be removed from the application and all occurrences of variable_namearr can be replaced with variable_name For example

Oracle VARCHAR vName[40]

strcpy(vNamearr ldquoCompany Namerdquo)

vNamelen = strlen(vNamearr)

Informix VARCHAR vName[40]

strcpy(vName ldquoCompany Namerdquo)

Host variables

The Oracle statement EXEC SQL TYPE is synonymous with the C languagersquos typedef declarative instruction It can be easily replaced with the Informix declarative instruction typedef

Embedded SQL for COBOL

VARCHAR

Oraclersquos ProCOBOL character host variable declaration statementrsquos VARYING clause is expanded after pre-compiling into a group with two elements one is variable-name-LEN PIC S9(4) COMP and the other is variable-name-ARR PIC X(size) The group name is the same as the host variable name and size is replaced with the size of the VARYING variable Informix does not support this concept Therefore statements that use variable-name-LEN must be removed from the application and all occurrences of variable-name-ARR must be replaced with variable-name Also the VARYING clause must be removed from the declarative statement For example

Oracle

05 vName PIC X(40) VARYING

hellip

MOVE ldquoCompany Namerdquo TO vName-ARR

MOVE 12 TO vName-LEN

Informix

05 vName PIC X(40)

hellip

MOVE ldquoCompany Namerdquo TO vName

IBM Software Group IBM Information Management

Version 16 64

Level 88

COBOLrsquos level 88 functionality is not supported within an Informix ESQLCOBOL host variable declaration section in versions prior to 72 Level 88 functionality is supported in Informix ESQLCOBOL 72

SQLDA

In Informix ESQLCOBOL the SQLDA structure is not available The Informix macros such as ALLOCATE DESCRIPTOR DESCRIBE GET DESCRIPTOR and SET DESCRIPTOR must be used to retrieve and manipulate the SQLDA data

REDEFINES

Oracle supports the use of the REDEFINES clause at the elementary level in the host variable declaration section In other words the redefined item cannot be a group item but the redefining item may be a group item Informix does not support the use of the REDEFINES clause in the host variable declaration section in versions prior to 72 The REDEFINES clause is supported in Informix ESQLCOBOL 72

Tips

If the Informix pre-compiler finds an SQL statement within an IF [ELSE IF hellip ] END-IF or EVALUATE END-EVALUATE or PERFORM END-PERFORM block then the pre-compiler adds a period after the generated COBOL statements regardless of whether there is a period at the end of the SQL statement This is a violation of COBOL rules for such blocks and the code may cause syntax errors during compilation or may behave unexpectedly To avoid these problems each SQL statement group should be moved to a new paragraph and these paragraphs should be performed from the block from which they were moved

ODBC Although the Open Database Connectivity (ODBC) API is designed to make it possible to write and compile an application once and use it with any ODBC driver on the same platform there are frequently differences between the underlying DBMSs that can expose problems to the applications For instance there can be differences between how unspecified parts of a date-time value are filled Most of these kinds of differences that get exposed through ODBC have their origins in the differences between the DBMSs themselves There are also cases where there are gaps in the ODBC standard for example there is a standard ODBC call that allows the application to ask the driver if it can support scrollable cursors and there is another call to ask if it can support updateable cursors There is no call to ask if it can support both at the same time With Informix you can have a scrollable cursor and you can have an updateable cursor but you can not have one cursor that is both scrollable and updateable A more complete description of ODBC application migration issues is beyond the scope of this article

IBM Software Group IBM Information Management

Version 16 65

C H A P T E R 6 Application Architecture

Transaction processing Transaction boundaries are defined differently in Oracle and Informix Oraclersquos transactions begin implicitly in one of two ways either by issuing a CONNECT statement or issuing a COMMIT or ROLLBACK statement A CONNECT statement marks the beginning of a transaction and a COMMIT or ROLLBACK statement commits or rolls back the previous transaction respectively and then implicitly begins a new transaction CONNECT statements are usually issued once at the beginning of a program however they may be nested or issued more than once serially to connect to the same or a different database When using more than one CONNECT statement within a program each CONNECT statement must be named This marks the beginning of named transactions Every SQL statement within a named transaction must also be named with the same transaction name as the CONNECT statement at where the SQL is to be executed SQL is named using the EXEC SQL statementrsquos AT clause Informixrsquos transaction boundaries are explicitly marked with the reserved words BEGIN WORK and COMMIT WORK or ROLLBACK WORK Note that once a transaction has begun for a given connection it stays open until a COMMIT or ROLLBACK is executed In other words if an ESQL program begins a transaction and then calls a stored procedure the stored procedure executes within the same transaction If the stored procedure issues a COMMIT then the whole transaction is committed and the calling ESQL program should not issue a COMMIT or ROLLBACK Informix transactions can be written to behave the same way as Oraclersquos To simulate Oraclersquos CONNECT statement behavior an Informix CONNECT should also be issued followed by a BEGIN WORK statement If more than one CONNECT statement is used in a program Informix also requires that the CONNECT and SQL statements be named To simulate Oraclersquos COMMIT and ROLLBACK statement behavior an Informix COMMIT WORK or ROLLBACK WORK statement should be issued followed by a BEGIN WORK statement Nested transactions can be simulated in Informix with the CONNECT statement and naming the transactions Then the Informix SET CONNECTION connection_name statement can be used to switch between transactions Committing or rolling back each named transaction does not commit or roll back other active transactions The Oracle statement EXEC SQL COMMITROLLBACK RELEASE should be replaced with the Informix statements EXEC SQL COMMITROLLBACK [WORK] followed by EXEC SQL DISCONNECT CURRENT In the following examples ws-dbenviron is the database name ws-connect-nm is the user name and ws-identity-nm is the password set in the program enp and connection-name are the connection names For Informix the user name and password information should correspond to the entries in the etcpasswd file on the UNIX system See the User Authentication section later in this chapter for more information The default server name is automatically obtained from the environment variable INFORMIXSERVER The following examples illustrate how Oracle and Informix implement the CONNECT functionality

IBM Software Group IBM Information Management

Version 16 66

Simple Connect

Oracle

CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm

Informix

CONNECT ws-dbenviron USER ws-connect-nm USING ws-identity-nm

Named Connect with Literal

Oracle

DECLARE enp DATABASE hellip CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm AT enp USING ws-dbenviron hellip AT enp SELECT col1 col2 INTO var1 var2

FROM table_name

Informix

CONNECT TO ws-dbenviron AS ldquoenprdquo USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION ldquoenprdquo hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Named Connect with Variable

Oracle

CONNECT ws-connect-nm

IDENTIFIED BY ws-identity-nm AT connection-name USING ws-dbenviron hellip AT connection-name SELECT col1 col2 INTO var1 var2 FROM table_name

Informix

CONNECT TO ws-dbenviron AS connection-name USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION connection-name hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Autonomous Transaction

An autonomous transaction is an independent transaction that is initiated by another transaction (the parent transaction) An autonomous transaction can modify data and commit or rollback independent of the state of the parent transaction The autonomous transaction must commit or roll back before the autonomous transaction is ended and the parent transaction continues

IBM Software Group IBM Information Management

Version 16 67

An autonomous transactions has been available since the release of Oracle 8i An autonomous transaction is defined in the declaration of a PLSQL block This can be an anonymous block function procedure object method or triggerThis is done by adding the statement PRAGMA AUTONOMOUS_TRANSACTION anywhere in the declaration block There isnt much involved in defining a PLSQL block as an autonomous transaction You simply include the following statement in your declaration section PRAGMA AUTONOMOUS_TRANSACTION Sample code

PROCEDURE test_autonomous

IS

PRAGMA AUTONOMOUS_TRANSACTION

BEGIN

insert

commit

END test_autonomous

Autonomous transactions can be used for logging in the database independent of the rollbackcommit of the parent transaction

Savepoints

Oracle allows savepoints within its PLSQL For example a PLSQL block can be structured so that SAVEPOINT A is issued upon entry and SAVEPOINT B is issued after some processing Then after some more processing a COMMIT or ROLLBACK can be issued against all the logic since the last COMMIT point which is before the PLSQL block or up to any of the savepoints by naming the COMMIT or ROLLBACK with the savepoint name In other words a savepoint can be issued at the beginning of a stored procedure and then only the stored procedure logic can be committed without committing the changes pending before the stored procedure was executed Those changes can be committed or rolled back once processing is returned from the stored procedure Informix does not support savepoint processing within a stored procedure

Concurrency Database concurrency can be managed through the combination of two configurable settings one specifies the lock granularity on database objects while the other influences how the application behaves in regards to the presence and placement of locks using a transaction isolation level

Row Level Locking

Oracle and Informix implement locking differently on database objects Oracle defaults to row level locking whereas Informix defaults to page level In most cases row level locking is preferred to improve concurrency Informix supports row level locking however it must be either explicitly requested specified by an environment variable or permanently changed in the instancersquos configuration Having three methods for establishing the lock level there is an order of precedence

1 To be explicitly requested the CREATE TABLE statement must include the specification of the LOCK MODE attribute

CREATE TABLE emp (

name CHAR(40)

salary MONEY

ssn LVARCHAR(64)

) LOCK MODE ROW

IBM Software Group IBM Information Management

Version 16 68

2 The environment variable IFX_DEF_TABLE_LOCKMODE will establish the default for CREATE TABLE statements issued without the LOCK MODE attribute and will override the Instancersquos configuration setting The variable setting on the client will override the server environment setting

set IFX_DEF_TABLE_LOCKMODE=ROW -or- export IFX_DEF_TABLE_LOCKMODE=ROW

3 Informix allows the instancersquos lock level default to be changed using a configuration parameter Row level locking can be as the default by adding the parameter DEF_TABLE_LOCKMODE to the instancersquos ONCONFIG file This parameter may not be found in the existing file and if not present can be added using an editor and establish a new default setting of ROW

DEF_TABLE_LOCKMODE ROW

None of the steps will apply a change to existing tables only establish the lock level for the CREATE TABLE statement

Transaction Isolation Level

Oracle databases incorporate a feature known as ldquoread consistencyrdquo which allows a query return a result based on the state of the data when the query started regardless of other processes updating or deleting the same data while the query is running Informix facilitates this type of behavior differently by providing control of the applicationrsquos placement of locks as well as how it reacts to those placed by other processes through the use of the transactionrsquos isolation level If Oraclersquos technique of ldquoreaders not blocking writersrdquo is a requirement then in many circumstance Informixrsquos DIRTY READ isolation level can be used The readers will not block the writers with dirty read processing however the query result may contain updates performed while the query was running which may be uncommitted If the emulation of Oraclersquos ldquoread consistencyrdquo is desired the LAST COMMITTED option of Informixrsquos COMMITTED READ isolation level can reduce the risk of locking conflicts when two or more sessions attempt to access the same row in a table whose locking granularity is row-level When an application attempts to read a row on which another session holds an exclusive lock these keywords instruct the database server to return the most recently committed version of the row rather than wait for the lock to be released This isolation level attribute could be preferable to executing queries using DIRTY READ since it will return only the most recently committed versions of the data The LAST COMMITTED option can be enabled in the following ways

1 Setting the USELASTCOMMITTED parameter in the Instancersquos configuration (ONCONFIG) will apply this feature as the default isolation level to all database transactions The parameterlsquos values will designate the scope of applying the LAST COMMITED option to either ALL NONE or only COMMITED READ and DIRTY READ isolation levels

USELASTCOMMITTED [ALL | NONE | COMMITTED READ | DIRTY READ]

2 The SET ENVIRONMENT statement can override the USELASTCOMMITTED configuration parameter setting for the duration of the current session The same semantics apply as the parameter within the ONCONFIG file with the setting value enclosed in quotes (lsquo)

SET ENVIRONMENT USELASTCOMMITTED lsquoALLrsquo

IBM Software Group IBM Information Management

Version 16 69

3 The SET ISOLATION statement can be used to override the instance configuration and session environment setting The SET ISOLATION statement is an Informix extension to the ANSI SQL-92 standard and provides the same functionality as the ISOANSI-compliant SET TRANSACTION statement There is no support for the LAST COMMITTED option with the SET TRANSACTION statement SET TRANSACTION complies with ANSI SQL-92 and only ANSI supported isolation levels are supported

SET ISOLATION TO COMMITTED READ LAST COMMITTED

4 PREPARE statements in ODBCJDBC applications

This feature is primarily documented in the Guide to SQL Syntax Guide to SQL Reference Administrators Reference and Administrators Guide

IBM Software Group IBM Information Management

Version 16 70

C H A P T E R 7 Security

User authentication In Oracle security information is stored in the database Up until recently Informix has used only the operating system security subsystem to check security For security purposes Oracle connects to the server and passes the user ID and password information to the database for verification

Operating system security

Informix does not store user ID and password information in the database Instead they are validated against the operating systemrsquos security mechanism on the server for example the etcpasswd file in UNIX Therefore either every database user must have an entry in the serverrsquos password file or the application must handle a level of security where user IDs are converted into a group id based on database permissions and only those group IDs are entered into the password file Note that if the second alternative is chosen then auditing capabilities based on user ID are lost Also if the application performs security functions then those functions are not applicable to third party applications such as report writers application development tools and so on when they access the database The home directory of all the users should point to the same physical directory where the application executable resides The Informix method of using the operating system for security checking allows external programs to be called from within stored procedures This capability is not allowed in Oracle In Oracle the OPS$User_name is sometimes used to connect to the database where OPS$User_name is a valid Oracle user and User_name is a valid operating system level user In this case the connection is made to the database using just the lsquorsquo character without the user id and password Informixrsquos technique of using the etcpasswd file for security works fine for this type of connection

Non-operating system security

In previous releases each user who needed to access the database server also needed an operating system account on the host computer Now you can configure Informix so that users who are authenticated by an external authentication service (such as Kerberos or Microsoft Active Directory) can connect to Informix The new USERMAPPING configuration parameter specifies whether or not such users can access the database server and whether any of those users can have administrative privileges When Informix is configured to allow user mapping you can still control which externally authenticated users are allowed to connect to Informix and their privileges Please refer to the IBM Informix documentation on connection security for more information

IBM Software Group IBM Information Management

Version 16 71

Informix supports for the pluggable authentication module (PAM) framework which lets an administrator customize authentication for individual applications and permits column-level encryption

Role based authority Role based authority can help you manage your database permissions As of version 1110 you can create a role and assign that as a default role for individual users (or to PUBLIC) A role is a work-task classification such as ldquopayrollrdquo or ldquomanagerrdquo Each defined role has privileges on the database object granted to the role You use the CREATE ROLE statement to define a role and GRANT DEFAULT ROLE to establish the userrsquos initial setting when connecting to the database A userrsquos role can be changed after connecting by using the SET ROLE statement

Column-level encryption You can use column-level encryption to improve the confidentiality of your data IDS Version 1110 has new built-in SQL scalar functions provide methods for data in columns to be stored in an encrypted format Use the ENCRYPT_AES or the ENCRYPT_TDES function to define encrypted data Use the DECRYPT_BINARY() and DECRYPT_CHAR() functions to query encrypted data When using the routines the encryption of data is under application control and the DBMS is not aware that data is encrypted Informixrsquos support of column level encryption is analogous to Oraclersquos DBMS Obfuscation Tool Kit Built-in ENCRYPT functions provide methods for encrypting and decrypting the following character data types or smart large object data types

CHAR

NCHAR

VARCHAR

NVARCHAR

LVARCHAR

BLOB

CLOB

Passwords and hints

Passwords are necessary when using the encryption functions Only users who can provide a secret password can view copy or modify encrypted data The password must be a minimum of 6 bytes and can be a maximum of 128 bytes When you set an encryption password you have the option of specifying a password hint Hints can be up to 32 bytes of text If you specify a hint you can store the hint with the encrypted password or in another location Passwords (and hints) to be used by default can be set for a session using the SET ENCRYPTION PASSWORD statement

SET ENCRYPTION PASSWORD lsquopasswordrsquo [ WITH HINT lsquohint stringrsquo ]

Hence the password and hint parameters can be optional when calling the encryption function Explicit values override the session default values The password or hint can be a single word or several words The hint should be a word or phrase that helps you to remember the password but does not include the password You can subsequently execute the built-in GETHINT function (with an encrypted value as its argument) to return the plain text of hint Calling the GETHINT function with an argument of encrypted data will return the hint (if any) from the encrypted data or an empty string (NULL) is no hint was provided There is no privilege needed anybody can get any hint at any time When you set a password Informix transfers the password and any hint to 128-bit key that is used to encrypt the password and hint Passwords and hints are not stored as plain text any table of the system catalog The key is a time-based random value per instance The database server

IBM Software Group IBM Information Management

Version 16 72

initializes the key when the server starts the key is destroyed when the database server shuts down

Encrypting a column

Column data can be encrypted through the use of two functions ENCRYPT_TDES and ENCRYPT_AES corresponding to the two data encryption standards Triple Data Encryption Standard (Triple-DES) and Advanced Encryption Standard (AES) which describes the cipher algorithm used to protect data from unauthorized viewing AES encryption (also known as Rijndael) uses a 128-bit key size and Triple-DES encryption uses two 56-bit keys for 112-bits overall Both functions are variant functions and will return a different result every time it is used The following example demonstrates how to use the encryption functions with a column that contains a social security number

CREATE TABLE emp (name CHAR (40) salary MONEY ssn LVARCHAR(64))

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890one two

three 123))

-or-

CREATE TABLE emp (name CHAR(40) salary MONEY ssn LVARCHAR(64))

SET ENCRYPTION PASSWORD one two three 123

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890))

Querying an encrypted column

Encrypted data can be translated using Informixrsquos DECRYPT_CHAR and DECRYPT_BINARY scalar functions Encrypted data contains information about the encryption method and all the other data needed to decrypt it except the password The encrypted data value is passed as the first argument and a password as the second unless the SET ENCRYPTION statement has specified for this session with the same session password by which the first argument was encrypted If the data is not encrypted the function call will return an error The DECRYPT_CHAR function is used to invoke a decryption routine on character data types (ie CHAR LVARCHAR NCHAR NVARCHAR and VARCHAR) while the DECRYPT_BINARY function accepts an encrypted large object of type BLOB or CLOB If the first argument to DECRYPT_CHAR or DECRYPT_BINARY is not an encrypted value or if the second argument (or the default password specified by SET ENCRYPTION) is not the password that was used when the first argument was encrypted Informix will issue an error and the call fails If the call to the decryption function is successful it returns the plain text version of the encrypted data argument The following example demonstrates how to use the decrypt function to query encrypted data

SELECT name salary DECRYPT_CHAR(ssn lsquoone two three 123rsquo)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

-or-

SET ENCRYPTION PASSWORD lsquoone two three 123rsquo

SELECT name salary DECRYPT_CHAR(ssn)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

The first argument to DECRYPT_BINARY is expected to be an encrypted value of a large object data type however if it is called with a character data type Informix invokes the DECRYPT_CHAR function and attempts to decrypt the specified value

IBM Software Group IBM Information Management

Version 16 73

Do not use either decryption function to create a functional index on an encrypted column This would store the decrypted values as plain text data in the database defeating the purpose of encryption

Performance impact of encryption

The performance impact of encryption is significant Encryption by its nature will slow down most SQL statements If some care and discretion are used the amount of extra overhead should be minimal Also encrypted data will have a significant impact on your database design In general you want to encrypt a few very sensitive data elements in a schema like social security numbers credit card numbers patient names and so on The effect on performance depends on direction encrypting is slower than decrypting It does not depend measurably on which algorithm is used AES performs at the same speed as Triple-DES It does depend on data size the relative overhead is less when there is more data to encrypt

Storage considerations

An encrypted value uses more storage space than the corresponding plain text value Data encrypted using AES can be bigger than Triple-DES but not by a significant amount This occurs because all of the information needed to decrypt the value except the encryption key is stored with the value Therefore before you set the encryption password and encrypt the data you must be sure the encrypted data can fit in the column A chart of the expected sizes can be found in the IBM Informix Administrator Guide

Compliance regulations

Informixrsquos encryption routines comply with the United Statesrsquo regulations of Health Insurance Portability and Accountability Act (HIPAA) Sarbanes-Oxley Gramm-Leach-Bliley and California Personal Information Privacy (SB 1386) as well as the international requirements of Basel II Also they comply with the latest cryptographic standards (OpenSSL 097c)

IBM Software Group IBM Information Management

Version 16 74

C H A P T E R 8 Environment

Scripts Oracle make files used to build the application should be modified to invoke the appropriate Informix ESQLCOBOL ESQLC MF COBOL and other application language commands The shell scripts shell startup scripts and command files should be modified for Informix compliant statements

SQL script substitution variables

In Oracle a substitution variable is a user variable name preceded by one or two ampersands (amp) When Oracle (SQLPlus) encounters a substitution variable in a command Oracle executes the command as though it contained the value of the substitution variable rather than the variable itself In Oracle the substitution variables can be used anywhere in SQL and SQLPlus commands except as the first word entered at the command prompt When SQLPlus encounters an undefined substitution variable in a command SQLPlus prompts the user for the value SQLPlus reads the responses from the keyboard even if terminal input or output has been redirected to a file If a terminal is not available (if for example the command file is run in batch mode) SQLPlus uses the redirected file Informixrsquos dbaccess does not provide this functionality however a work-around for the redirected file type of substitution is a follows (no user prompting) Create the following shell script (named subvalsksh in this case)

binkshif [[ $ -ne 2 ]]

then

echo nUsage $0 ltdfilegt ltcfilegtn

echo Desc This script accepts two files - dfile the decode

file

echo and cfile the change file It modifies the

change file

echo using the values listed in the decode file

echo The decode file should contain two columns - old

value

echo and new value

echo Ex

echo changethis tothis

echo

echo In this case every occurance of changethis

would be

echo replaced with tothisn

exit 1

fi

IBM Software Group IBM Information Management

Version 16 75

-----------------------

Declare variables

-----------------------

dfile=$1

cfile=$2

awk print s$1$2 $dfile gt $dfile_sed

sed -f $dfile_sed $cfile

The preceding script is used by creating a ldquodecoderdquo file (named decodefile in this case) which holds two columns in the form which may contain multiple rows

oldval newval

Executing the following command

subvalsksh decodefile chgfile

will replace every occurrence of oldval with newval in the file chgfile The shell script (subvalsksh) writes to standard output therefore the output should be redirected The redirected file will then be able to run with dbaccess

Utilities To improve performance the Informix EXPLAIN utility should be used by executing the SET EXPLAIN ON command to see how an SQL statement accesses the database From that point forward the access path for every SQL statement is written in the SQEXPLAINOUT file in the current working directory or the home directory of the process that initiated the request on the host machine The Informix SET EXPLAIN OFF should be executed to turn off this feature when finished The overall system performance should be monitored using the Informix ONSTAT utility

System catalog The following items discuss how Informix implements the system catalog differently than Oracle Each item refers to the Informix implementation only Object names are stored in lower case The system catalog tables are owned by lsquoinformixrsquo To query the systables table use SELECT from lsquoinformixrsquosystables Each table in systables is assigned a tabid by the system It is used as the primary key and therefore the foreign key for the other catalog tables The identifier information is stored in sysindexes Columns part1 - part16 each contain a column component of a composite index They are integers positive for ascending order negative for descending order In syscolumns collength and coltype have special meanings depending on the data type of the column See the Informix Guide to SQL Reference Version for details

IBM Software Group IBM Information Management

Version 16 76

C H A P T E R 9 Using Bladelets

What is a Bladelet

A Bladelet is a small informal Informix Datablade module Its meant to be useful out of the box and is offered complete with source code at no cost -- and no support or warranty In the context of this document the term Datablade refers to an extension to the standard IBM Informix database engine These generally take the form of new data types (for example timeseries or video) andor new routines that execute inside the server The new routines might operate on new data types or on existing ones A Datablade module is usually a formal product available for sale In addition a Datablade is

Developed either by IBM Informix or by a third-party developer

Rigorously tested

Packaged and sold for profit

May or may not be formally certified by IBM Informix as having been developed according to approved Datablade coding practices

In contrast a Bladelet is

Not rigorously tested

Not sold for profit

Not certified by IBM Informix A Bladelet is an extension to the database engine that is narrow in scope and thought to be generally useful being offered at no cost complete with source Just remember before you use any of this code in mission-critical applications its up to you to thoroughly test it and fix any problems you find Please review the disclaimer which applies to any sample code you find on this site httpwwwibmcomdeveloperworksdb2zonesinformixlibrarysamplesdb_downloadshtml Note The bladelets at this link have not been updated for some time (at the time of this writing) some of the capabilities especially simple function call that increase compatibility may have been introduced into the Informix server itself since they were written

Useful Bladelets

Bladelet Description

Exec Defines two user-defined functions that provide dynamic SQL functionality within a SPL procedure

Flat File Access Method A complete access method that lets you build virtual tables based on operating system files

IUtil Implements a collection of other database vendor functions for Informix

IBM Software Group IBM Information Management

Version 16 77

JPEG Image Bladelet Provides a user-defined type for JPEG images that allows you to manipulate images and to extract and search on image properties

Multirepresentational lvarchar Opaque Type

Creates the idn_mrLvarchar opaque type which stores character data up to 2 gigabytes

Node Datablade Module Creates the node opaque type which is intended to solve one of the hardest problems in relational databases transitive closure

Regexp Creates routines that let you manipulate character and clob data using regular expressions

Shapes DataBlade Module Creates several opaque types for managing spatial data including R-tree index support

Smart Blob Information DataBlade Module

Includes a variety of useful routines for working with smart blobs

SqlLib C SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

SqlLib Java SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

Versioning Table Access Method

Permits users to create and manage versioned tables

We will look closer at two bladelets which could assist with migration the Exec datablade and SQLLib

Informix Exec bladelet for Dynamic SQL Often it is desirable to execute a SQL query that is generated at run-time within the RDBMS For example a developer may not know the name of the temporary table they wish to run the query against or they might want to append predicates to a query In external programs this can be accomplished using the ESQLC SQLCA and DESCRIPTOR facilities Unfortunately the INFORMIX Stored Procedure Language (SPL) does not support Dynamic SQL Queries must be hard-coded into the SPL logic The objective of the Exec bladelet is to remedy this situation Exec consists of user-defined functions that take an SQL query as an argument execute it and return the result (the format of which varies depending on which function is called and the kind of query) The Exec functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries For more details and download refer to

httpwwwibmcomdeveloperworksdb2zonesinformixlibrarydemoids_exechtml

There are three User Defined Routines (UDRs) in the Exec bladelet Two of them are external C functions that use the Server API (SAPI) These must be compiled into shared libraries on the target machine and you need to declare them to the server using CREATE FUNCTION statements The third UDR is a routine written in Informix Stored Procedure Language (SPL) that uses the first two UDRs to return a collection of items The Exec bladelet module consists of the following

1 EXEC The EXEC() function takes an LVARCHAR that it treats as a SQL query executes the query and returns a single LVARCHAR result string Depending on what kind of SQL statement is submitted Exec() returns a different result format

IBM Software Group IBM Information Management

Version 16 78

2 EXEC_FOR_ROWS The EXEC_FOR_ROWS() UDR is an iterator function which means it can return more than one result row Of course it only does so when it is asked to execute a SELECT Otherwise it behaves exactly as the EXEC() UDR Being an iterator function limits the ways in which such a UDR can be used It cannot be used in another SQL query The only place it can be used effectively is inside a SPL routine

3 EXEC_FOR_MSET EXEC_FOR_MSET() is a SPL routine that uses the EXEC_FOR_ROWS() routine introduced above Instead of returning a set of rows as an iterator or a single row as the EXEC() UDF does this UDR collects the results of the SQL query together into a single object a multi-set

Refer to Appendix E Sample Code for examples on using the EXEC bladelet functions

SqlLib DataBlade module (SqlLibC11 SqlLibJ11) The SqlLib DataBlade module implements SQL routines that the Informix does not support natively but that are supported by some other database vendors Source code is freely available for download and includes two implementations one in C (SqlLibC) and the other in Java (SqlLibJ)

The following routines are included

ascii - takes a single character as input and returns the ASCII value in decimal that corresponds to that character

ceil - takes a single numeric value as input and returns the smallest integer that is either equal to or greater than the input value

chr - takes an integer value and returns the character that is represented by the ASCII value (in decimal) of that integer

instr - searches for a value in a string and returns the position where it was found It

returns 0 if the search value was not found instrb - provides the exact same functionality as instr() but for single-byte character sets

sign - takes a numeric argument and returns an integer that indicates if the input value is

positive (1) negative (-1) or zero (0) to_decimal - converts the input character argument into a decimal type

to_float - converts the input character argument into a float type

to_integer - converts the input character argument into an integer type For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

IBM Software Group IBM Information Management

Version 16 79

A P P E N D I X A Planning guide

The checklist below will help an analyst determine which Oracle features which need to be converted to Informix and give some guidance on the effort involved Each porting task is listed They are followed by a quantity field used to determine how prevalent the item the difficulty or amount of effort involved 1 (low) to 5 (high) is used to estimate the amount of time needed to perform the task when the associated item exists in the application a moderate number of times What is moderate depends on the size of the application If there are an unusually large number of occurrences of an item then the effort should be increased Conversely if there are a small number of occurrences of an item then the effort should be decreased Each of these items is discussed in detail within this document Each heading corresponds to a section heading within the document

Tasks Quantity Effort

DDL

Identifiers Delimit identifiers named with Informix reserved words 2 Databases Determine database names and create databases 3 Replace Oracle tablespace names with Informix dbspace names 1 ANSI vs Non-ANSI considerations 3 Tables Convert create table statements 2 Convert DDL syntax 3 Reduce primary key length to 390 bytes 5 Data Types Convert Oraclersquos NUMBER data type 3 Convert VARCHAR columns 2 Convert Oraclersquos DATE data type 5 Convert raw data types 2 Convert Rowids 2 Indexes Convert Indexes 2 Views Remove CREATE VIEW statement options 1 Stored Procedures and Triggers Convert CREATE and REPLACE Stored Procedure and Trigger syntax 1 Oracle Extensions Remove non-supported Oracle extensions from DDL 1

Tasks Quantity Effort

DML

SQL Add the Informix AS clause to display labels 1 Replace non-supported DML syntax ^= hellip = ELSE IF 2 Convert Optimizer DirectiveHints 2 Convert InsertSelectUnion and InsertValueSelect statements 3

IBM Software Group IBM Information Management

Version 16 80

Convert Delete statement syntax 1 Convert temporary table processing 2 Convert Join statements + MINUS INTERSECT different data types 2 Convert sorts 4 Convert hard coded SQL error messages 3 Remove correlation names on the main table of Update and Delete statements

2

Replace original table names in SELECT statements using aliases 1 Convert hierarchical implementation (CONNECT BY PRIOR) 5 Host Variables Convert host variable format or add conversion processing 5 Functions Convert date and time functions 5 Convert aggregate functions 3 Convert mathematical functions 5 Convert string function syntax 1 Convert other unsupported Oracle functions 5 Macros Convert ISOPEN NOT FOUND ROWTYPE and TYPE macros 3 Pseudo-Columns Convert Level processing 3 Convert Rownum processing 2 Update Using Cursors Convert WHERE CURRENT OF processing for multiple table joins 5 Convert FOR UPDATE with a HOLD cursor processing 2 Convert concurrency processing from Oraclersquos implicit to Informixrsquos explicit

4

System Tables Convert system table references 1

Tasks Quantity Effort

Stored procedures Break stored procedures greater than 64K in size into smaller ones 2 Convert Oraclersquos stored procedure packages 3 Convert exception processing 5 Convert error handling (SQLCA) 2 Convert Oraclersquos global cursor processing 5 Convert Oraclersquos explicit cursor processing 2 Convert flow control processing 5 Convert Oraclersquos implicit variable declaration and assignment 3 Convert Oraclersquos BOOLEAN variable type 1 Convert binary data type processing Convert Oraclersquos dynamic SQL processing 5 Triggers Convert multi-functional triggers 3 Convert Insert and Update triggers which are not supported in Informix 5 Place logical statements in a stored procedure 5 Constraints Convert constraint enabling and disabling processing 5 DUAL table Convert Dual table processing 4

Embedded SQL

Host variables

IBM Software Group IBM Information Management

Version 16 81

Convert declaration overrides 1 Convert array processing 5 Convert Oraclersquos formatting functions 4 SQL structures Convert SQLDA processing 5 Convert ORACA processing 1 Pre-compiler options Convert Oracle pre-compiler options 1 Embedded PLSQL Convert Oraclersquos Embedded PLSQL 5 ODBC Convert Oraclersquos OCI 5 Convert database library calls Convert global area processing Convert fetch cycle Convert RAW data type processing Convert parameter bindings Embedded SQL for C Convert VARCHAR processing 2 Embedded SQL for COBOL Convert VARCHAR processing 2 Convert 88 Level processing in COBOL 2 Convert Redefine processing in COBOL 4

Tasks Quantity Effort

Application architecture

Transaction processing Convert application to Informix transaction processing 5 Convert multiple connect processing 5 Convert savepoints Concurrency Address Informix locking processing na 2 User authentication Address Informix security processing na 4

Environment

Convert make files 2 Convert shell scripts shell startup scripts and command files 2 Convert script substitution variables

IBM Software Group IBM Information Management

Version 16 82

A P P E N D I X B Syntax comparison

See the Informix Guide to SQL Syntax for more information on each item

Oracle Informix Boolean AND AND AND NOT NOT NOT OR OR OR Greater Than or Equal To gt= gt= Less Than or Equal TO lt= lt= Not Equal ltgt = or ^= ltgt or = Identifiers letters numbersrdquo_rdquordquo$rdquordquordquo letters numbers and ldquo_rdquo Data types Character CHAR CHAR Long Character VARCHAR (2000) if lt= 2000

LONG VARCHAR if gt 2000 CHAR or TEXT

Number (2 bytes) NUMBER SMALLINT Number (4 bytes) NUMBER INTEGER Number (gt 4 bytes) NUMBER DECIMAL Image LONG RAW CLOB BLOB BYTE TEXT CLOB BLOB DML Comments -- hellip -- hellip Assignment var1 = expression LET var1 = expression Condition ELSE IF ELSE or ELIF

IF Aggregate functions Average AVG(expression) AVG(ALL

expression) AVG(DISTINCT expression)

AVG(expression) AVG(ALL expression) AVG(DISTINCT column_name) AVG(UNIQUE column_name)

Count COUNT() COUNT (expression) COUNT(ALL expression) COUNT (DISTINCT expression)

COUNT() COUNT(DISTINCT column_name) COUNT (UNIQUE column_name)

Maximum MAX(expression) MAX(ALL expression) MAX(DISTINCT expression)

MAX(expression) MAX(ALL expression) MAX(DISTINCT column_name) MAX(UNIQUE column_name)

Minimum MIN(expression) MIN(ALL expression) MIN(DISTINCT expression)

MIN(expression) MIN(ALL expression) MIN(DISTINCT column_name) MIN(UNIQUE column_name)

Sum SUM(expression) SUM(ALL expression) SUM(DISTINCT expression)

SUM(expression) SUM(ALL expression) SUM(DISTINCT column_name) SUM(UNIQUE column_name)

Algebraic functions Round ROUND(expressionrounding

factor) ROUND(expressionrounding factor)

Statistical functions Standard Deviation STDEV(expression) STDDEV(expression) Variance VARIANCE(expression) VARIANCE(expression) Range RANGE(expression)

IBM Software Group IBM Information Management

Version 16 83

String functions

Trim LTRIM(expression) RTRIM(expression)

LTRIM(expression) RTRIM(expression)

Length LENGTH(string) LENGTH(string) Like LIKE(string) LIKE(string) Like (single character) _ _ Like (wildcard) String Delimiter lsquo or ldquo lsquo or ldquo Escape Character set within LIKE clause using

ESCAPE ldquordquo to make ldquordquo the escape character

or set within LIKE clause using ESCAPE ldquordquo to make ldquordquo the escape character

Stored procedures Create CREATE OR REPLACE

PROCEDURE procedure_name (var1 IN CHAR(1) var2 OUT DATE var3 IN OUT NUMBER)

DROP PROCEDURE procedure_name CREATE PROCEDURE procedure_name (var1 CHAR(1) var3 INTEGER) RETURNING DATE INTEGER

Arguments EXECUTE PROCEDURE procedure_name (var1 IN var2 OUT var3 IN OUT)

EXECUTE PROCEDURE procedure_name (var1 var3) RETURNING var2 var3

IBM Software Group IBM Information Management

Version 16 84

A P P E N D I X C Database concepts

The table below illustrates the relationship between each database vendorrsquos database objects

Oracle Informix

Database name attached to a group of files Specific database name

Data file Chunk

Tablespace (logical partition) or Segments (Index Segment Table Segment and so on)

Dbspace

Extent Extent

Rollback Segment Physical Log

Redo Log Logical Log

System tablespace Root dbspace

Temporary tablespace Temporary dbspaces dbspacetemp environment variable or dbspacetemp onconfig parameter

Pointer Blobspace Sbspace

Table partitioning table fragmentation

Database link Not supported

Snapshot Not supported

oerr utility finderr utility

sqldba and svrmgrl - monitor utilities onstat and oncheck utilities

SQLPlus utility dbaccess utility

ProC ESQLC

ProCOBOL ESQLCOBOL

SQLNET INet

OCI Like the ESQL function library after pre-compiling if they were publically documented

Read Consistency COMMITTED READ LAST COMMITTED

IBM Software Group IBM Information Management

Version 16 85

A P P E N D I X D Sample code

User defined functions User Defined Routines (UDR) can be developed to extend the capabilities of the database and provides the option to create UDRs to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or rename an Informix function to the corresponding Oracle function name

CONCAT

CREATE PROCEDURE concat (str1 VARCHAR(255) str2 VARCHAR(255)) RETURNING VARCHAR(255) RETURN str1 || str2

END PROCEDURE

INSTR

CREATE PROCEDURE instr( str VARCHAR(255) mask VARCHAR(255) strt SMALLINT DEFAULT 1 occur SMALLINT DEFAULT 1 ) RETURNING INT DEFINE slen SMALLINT DEFINE mlen SMALLINT DEFINE tempstr VARCHAR(255) DEFINE tempmask VARCHAR(255)

DEFINE nomatch SMALLINT DEFINE count SMALLINT DEFINE pos SMALLINT DEFINE retpos SMALLINT DEFINE i SMALLINT DEFINE j SMALLINT DEFINE srchstrt SMALLINT LET slen = LENGTH(str) LET mlen = LENGTH(mask) LET count = 0 LET nomatch = 0 LET pos = 1 LET retpos = 1 LET tempstr = LET tempmask = LET srchstrt = strt

IF (strt lt 0) THEN - reverse the str FOR i = 1 TO slen LET tempstr = str[11] || tempstr LET str = str[2255] END FOR -- reverse the mask FOR i = 1 TO mlen LET tempmask = mask[11] || tempmask LET mask = mask[2255] END FOR

IBM Software Group IBM Information Management

Version 16 86

LET srchstrt = strt -1 LET str = tempstr LET mask = tempmask END IF FOR j = 1 TO slen LET tempstr = str LET tempmask = mask FOR i = 1 TO mlen IF (tempmask[11] = tempstr[11]) THEN LET nomatch = 1 EXIT FOR END IF LET tempmask = tempmask[2255] LET tempstr = tempstr[2255]

END FOR IF (nomatch = 0) THEN IF (pos gt= srchstrt) THEN LET count = count + 1 END IF IF (count = occur) THEN IF (strt lt 0) THEN RETURN slen - pos + 1 ELSE RETURN pos END IF END IF END IF LET str = str[2255] LET nomatch = 0

LET pos = pos + 1 END FOR RETURN 0 END PROCEDURE

YYYYMMDD

CREATE PROCEDURE yyyymmdd (str VARCHAR(10)) RETURNING varchar(8)

DEFINE retstr VARCHAR(8)

IF str IS NULL THEN

RETURN NULL

ELSE

LET retstr = str[710] || str[12] || str[45]

RETURN retstr

END IF

END PROCEDURE

Using EXEC bladelet functions

IBM Software Group IBM Information Management

Version 16 87

Using EXEC

Note the ROW data type variable can be referenced using table and column syntax CREATE PROCEDURE example1() RETURNING INTEGER

DEFINE sql_stmt LVARCHAR(255)

DEFINE rcnt ROW(val INTEGER)

LET sql_stmt = select count() from items where manu_code = lsquoANZrsquo

EXECUTE FUNCTION EXEC(sql_stmt) INTO rcnt

RETURN rcntval

END PROCEDURE

Using EXEC_FOR_ROWS

CREATE PROCEDURE example2() RETURNING INTEGER CHAR(1)

DEFINE rs_rowdata ROW(customer_num INTEGER call_code CHAR(1))

DEFINE sql_stmt LVARCHAR(255)

LET sql_stmt = select customer_num call_code from cust_calls where

customer_num = 106

FOREACH

EXECUTE FUNCTION EXEC_FOR_ROWS(sql_stmt) INTO rs_rowdata

RETURN rs_rowdatacustomer_num rs_rowdatacall_code WITH RESUME

END FOREACH

END PROCEDURE

Using EXEC_FOR_MSET

Note the DEFINE statement for the variable rs_data Collection data types used in a SPL routine cannot be defined using the LIKE attribute in the DEFINE statement CREATE PROCEDURE example3() RETURNING INTEGER VARCHAR(8)

DEFINE v_customer_num LIKE accountscustomer_num

DEFINE v_account_cd LIKE accountsaccount_cd

DEFINE rs_data MULTISET(ROW(

r_customer_num INTEGER

r_account_cd VARCHAR(8)) NOT NULL)

DEFINE sql_stmt LVARCHAR

LET sql_stmt = select customer_num order_num from orders where

company_id = 51155

EXECUTE FUNCTION EXEC_FOR_MSET(sql_stmt) INTO rs_data

FOREACH

SELECT r_customer_num r_account_cd INTO v_customer_num

v_account_cd FROM TABLE(rs_data)

RETURN v_customer_num v_account_cd WITH RESUME

END FOREACH

END PROCEDURE

IBM Software Group IBM Information Management

Version 16 88

Date arithmetic Informix has extensive capabilities for manipulating dates and times You can add or subtract DATE and DATETIME variables from each other You can add or subtract an INTERVAL to a DATE or DATETIME

UNITS Keyword

When working with INTERVAL values sometimes it is necessary to specify the precision with which you are dealing For example suppose you have the following field defined To add 10 days to the lead time you could use a SQL statement like this

SELECT lead_time + INTERVAL(10) DAY to DAY FROM orders

-or- SELECT lead_time + 10 UNITS DAY FROM orders

Using EXTEND function

The EXTEND function allows operations between data types of different precisions SELECT

EXTEND(myvar YEAR to MINUTE) ndash INTERVAL(5) MINUTE to MINUTE

FROM member

Calculate Week Of The Year

SELECT ROUND((TODAY - DATE(0101||YEAR(TODAY))) 7 + 5) FROM DUAL

Number of days difference SELECT DATE(0106||YEAR(TODAY)) - DATE(01062005) FROM DUAL

Number of weeks difference

SELECT ROUND((DATE(0106||YEAR(TODAY)) - DATE(01062005))

7 + 5) FROM DUAL

String representation of date and time

Day and date

SELECT TO_CHAR(TODAY A B d Y) FROM dual

-returns month day and 4 digit year-

Tuesday January 03 2006

Abbreviation of day of week

SELECT SUBSTR(TO_CHAR(TODAY A B d Y R)13) FROM dual

-or-

SELECT TO_CHAR(TODAY a) FROM dual

-returns MON TUE WED THU FRI SAT SUN-

Returning the number of rows affected

IBM Software Group IBM Information Management

Version 16 89

Within SPL routines you can use the DBINFO function to find out the number of rows that have been processed in SELECT INSERT UPDATE DELETE EXECUTE PROCEDURE and EXECUTE FUNCTION statements

CREATE FUNCTION del_rows(pnumb INT) RETURNING INT

DEFINE nrows INT

DELETE FROM sec_tab WHERE part_num = pnumb

LET nrows = DBINFO(sqlcasqlerrd2)

RETURN nrows

END FUNCTION

To ensure valid results use this option after SELECT and EXECUTE PROCEDURE or EXECUTE FUNCTION statements have completed executing If you use the sqlcasqlerrd2 option within cursors make sure that all rows are fetched before the cursors are closed

Using an Informix collection data type

A collection data type as a VARRAY

In the following examples the collection data types of MULTISET and SET are used in a function to hold a collection of values You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value Informix SPL allows you to declare a cursor for a collection variable using the FOREACH statement called a collection cursor

Also demonstrated is how to utilize a variable declared with the keyword COLLECTION A variable declared as type SET MULTISET or LIST is a typed collection variable It can hold a collection of its specified data type only However a COLLECTION is an un-typed (or generic) collection variable that can hold a collection of any data type

This function will build a MULTISET list of values

CREATE FUNCTION func1() RETURNING MULTISET(INTEGER NOT NULL)

DEFINE v_array_of_ints MULTISET(INTEGER NOT NULL)

INSERT INTO TABLE (v_array_of_ints) VALUES(1)

INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(5)

INSERT INTO TABLE (v_array_of_ints) VALUES(4)

RETURN v_array_of_ints

END FUNCTION

This function will receive the COLLECTION list of values from func1

CREATE FUNCTION func2() RETURNING INTEGER

--

-- DEFINE lmset MULTISET(INTEGER NOT NULL)

--

DEFINE lmset COLLECTION

DEFINE v_int INTEGER

--

-- call func1 to populate local multiset variable

--

LET lmset = func1()

--

-- tally a count the number of elements

--

FOREACH

SELECT COUNT() INTO v_int FROM TABLE(lmset)

IBM Software Group IBM Information Management

Version 16 90

RETURN v_int WITH RESUME

END FOREACH

--

-- return the values

--

FOREACH

SELECT INTO v_int FROM TABLE(lmset)

RETURN v_int WITH RESUME

END FOREACH

END FUNCTION

NOTE In the example func2 a duplicate declaration for the ldquolmsetrdquo variable as a MULTISET data type has been commented out by declaring the variable as a COLLECTION it can accept any of the 3 types (MULTISET SET and LIST)

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

4 (row count) 1 2 5 4

By using a SET data type inserts will not permit duplicates

CREATE FUNCTION func1() RETURNING SET(INTEGER NOT NULL) DEFINE v_array_of_ints SET(INTEGER NOT NULL) INSERT INTO TABLE (v_array_of_ints) VALUES(1) INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(2) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) RETURN v_array_of_ints END FUNCTION

NOTE Because func2 is expecting a un-typed COLLECTION variable func1 does not have to be dropped and recreated It can receive a value from any Collection Data Type (MULITSET SET and LIST)

The functionrsquos return values would change to (with duplicates suppressed)

EXECUTE FUNCTION func2()

(expression)

3 (row count) 1 2 5

Using a LIST data type support for assigning values based on ordinal position

IBM Software Group IBM Information Management

Version 16 91

CREATE FUNCTION func1() RETURNING LIST(INTEGER NOT NULL)

DEFINE v_array_of_ints LIST(INTEGER NOT NULL) -- -- first insert no ordinal position can be established By default the -- database server inserts LIST elements at the end of the list -- INSERT AT 5 INTO TABLE (v_array_of_ints) VALUES(5) INSERT AT 1 INTO TABLE (v_array_of_ints) VALUES(1) INSERT AT 2 INTO TABLE (v_array_of_ints) VALUES(2) -- -- Only 3 LIST elements exist position 4 has not been instantiated -- this element will insert at the end of the list -- INSERT AT 4 INTO TABLE (v_array_of_ints) VALUES(4) INSERT AT 3 INTO TABLE (v_array_of_ints) VALUES(3) RETURN v_array_of_ints END FUNCTION

NOTE The elements of a LIST have ordinal positions with a first second and third element in a LIST To support the ordinal position of a LIST the INSERT statement provides the AT clause This clause allows you to specify the position at which you want to insert a list-element value Note the behavior of the ordinal positioning above preceded by a commented explanation

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

5 (row count) 1 2 3 5 4

Using MULTISET and ROW to replace PLSQL TABLE and RECORD types

Creating variables using Informix Collection data types SET MULTISET and LIST in combination with ROW data types can be useful when migrating applications which use Oracle REF CURSORS as arguments to functions as well as Oracle collection data types TABLE and RECORD

Typical Oracle Package specification

CREATE OR REPLACE PACKAGE MyPackage

IS

TYPE recOrders IS RECORD (

order_num ordersorder_numTYPE

order_date ordersorder_dateTYPE

customer_num orderscustomer_numTYPE

po_num orderspo_numTYPE

)

TYPE tabOrders IS TABLE OF recOrders

INDEX BY BINARY_INTEGER

TYPE ref_curtype IS REF CURSOR

Both tabOrders or ref_curtype can be converted to the following Informix SPL definition

DEFINE tabOrders MULTISET(ROW(

IBM Software Group IBM Information Management

Version 16 92

order_num INTEGER

order_date DATETIME YEAR TO FRACTION(3)

customer_num INTEGER

po_num CHAR(10)) NOT NULL)

DEFINE ref_curtype MULTISET(ROW(

define columns based on query result set

) NOT NULL)

IBM Software Group IBM Information Management

Version 16 93

A P P E N D I X E Counting system objects

Using the system catalog

System catalog

Below is a list of SQL statements that will extract most if not all of the counts of system objects owned by user lsquoXXXrsquo

select count(table_name) from all_tables

where owner=rsquoxxxrsquo

select count() from dba_indexes

where owner=rsquoxxxrsquo

select count(synonym_name) from dba_synonyms

where owner=rsquoxxxrsquo

select count() from dba_views

where owner=rsquoxxxrsquo

select count() from dba_tab_columns

where length(column_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

and owner=rsquoxxxrsquo

select count distinct() from dba_tab_columns

and owner=rsquoxxxrsquo

select count() from dba_tables

where length(table_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_synonyms

where length(synonym_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_views

where length(view_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_indexes

where length(index_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and owner=rsquoxxxrsquo

IBM Software Group IBM Information Management

Version 16 94

select data_type count(data_type) from dba_tab_columns

where owner=rsquoxxxrsquo

group by data_type

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and length(data_type)gt254

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquonumberrsquo

and data_scale=0

and owner=rsquoxxxrsquo

Using SQL code

Built-in function references

The following instructions can be used to find references to built-in functions On the UNIX machine or the NT box where your code resides please create the following file as tmpfunctionlist

convert(

hextoint(

inttohex(

getdate(

datename(

datepart(

datediff(

dateadd(

months_between(

char(

char_length(

charindex(

compute(

difference(

length(

lower(

patindex(

replicate(

reverse(

right(

soundex(

space(

str(

stuff(

substring(

upper(

abs(

atn2(

log(

ceiling(

IBM Software Group IBM Information Management

Version 16 95

cot(

degrees(

floor(

radians(

rand(

sign(

to_char(

to_date(

to_number(

exception(

pi(

raise_application_error(

raiserror(

SQLCODE

rollback

savepoint

declare

decode(

nvl(

print(

rowid

waitfor

recompile

bcp

isopen(

notfound(

rowtype(

type(

Then please run the following program with the proper subdirectories

binksh

rm ndashf somehomeoutfile

cd somesourcedatabase

export sourcebase=rdquosomepathrdquo

for functor in `cat tmpfunction_list`

do

echo before find $functor

find $sourcebasedatabase -exec grep -i $functor gtgt

somehome$functoroutfile

find $sourcebaseintfc -exec grep -i $functor gtgt

somehome$functoroutfile

echo after find $functor

done

Object types and counts

This script attempts to count the objects of each type by grepping for CREATE statements containing the object type and counts procedure definitions that are inside package bodies which are not proceeded by a CREATE keyword It is not a sophisticated parser so the results may not be perfect

binbash if [ $1 = ] then

IBM Software Group IBM Information Management

Version 16 96

echo Usage objCountssh ltFilePatterngt return 1 fi declare -a objectTypes=(CLUSTER CONTEXT CONTROLFILE DATABASE DATABASE +LINK DIMENSION DIRECTORY DISKGROUP FUNCTION INDEX INDEXTYPE JAVA LIBRARY MATERIALIZED +VIEW MATERIALIZED +VIEW +LOG OPERATOR OUTLINE PACKAGE PACKAGE +BODY PFILE PROCEDURE PROFILE RESTORE +POINT ROLE ROLLBACK +SEGMENT SCHEMA SEQUENCE SPFILE SYNONYM TABLE TABLESPACE TRIGGER TYPE TYPE +BODY USER VIEW) echo for type in $objectTypes[] do if [ $type = PROCEDURE ] then echo $type object count `cat $1 | grep -icE ^ (|CREATE +|OR REPLACE +)b$typeb` else echo $type object count `cat $1 | grep -icE ^ (CREATE +|OR +REPLACE +)b$typeb` fi done

IBM Software Group IBM Information Management

Version 16 97

A P P E N D I X F Data type mapping

Oracle built-in data types (including ANSI types) can be converted to similar data types in the Informix database according to the mapping described here This table provides default mappings based on most common usage patterns in some cases another mapping may work better

In the following table n is used to indicate length p is used to indicate precision and s is used to indicate scale

Oracle data type Informixreg Server data type

BFILE LONG RAW BLOB

BLOB

BINARY_DOUBLE DOUBLE PRECISION

BINARY_FLOAT DOUBLE PRECISION

BINARY_INTEGER

PLS_INTEGER

NATURAL

NATURALN

POSITIVE

POSITIVEN

32-bit integers only used in PLSQL NATURAL and POSITIVE are unsigned integers

INTEGER

BOOLEAN (PLSQL only) BOOLEAN

CHAR(n) or CHARACTER(n) CHAR(n)

DATE DATETIME YEAR TO SECOND

DOUBLE PRECISION DOUBLE PRECISION

IBM Software Group IBM Information Management

Version 16 98

FLOAT

See note on FLOAT below

FLOAT

INTEGER INT

A 38-digit NUMBER sub-type May want to flag with a warning on possible overflow

INTEGER

INTERVAL DAY(p) TO SECOND(s)

Note Oracle fractional seconds have 9 digits

INTERVAL DAY(p) TO FRACTION(min(5 s))

INTERVAL YEAR(p) TO MONTH

INTERVAL YEAR(p) TO MONTH

LONG CLOB

CLOB

LONG VARCHAR (xxx)

Oracle recommends not using this type

LVARCHAR

NCHAR(n) NATIONAL CHAR(n) or NATIONAL CHARACTER(n)

NCHAR(n)

See National Language Types below

NCLOB CLOB

NUMBER

NUMBER(0)

NUMBER(p) NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s lt 10

NUMBER(3-2) 12300

INTEGER

IBM Software Group IBM Information Management

Version 16 99

NUMBER(p) NUMBER (p0)

Where precision (p) is greater than or equal to 10 and lt= 18

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and 10 lt= p-s lt 19

NUMBER(9-2) 12345678900

BIGINT

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is greater than or equal to s (that is s gt 0 and p gt= s)

NUMERIC (min(p32) min(s32))

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is less than s (that is s gt 0 and p lt s)

NUMBER(35) 000123

NUMERIC (min(s32)min(s32))

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s gt 18 and p-s lt= 32

NUMERIC (min(p-s32)0)

NUMBER(p s)

Where scale (s) is greater than 32 or pInformix-s is greater than 32

NUMERIC (32)

Scale cannot be greater than precision

NUMERIC(3232) would guarantee that digits to the left of the decimal would be lost Using a floating point decimal provides the simplest best way to capture as many digits in a value as possible

IBM Software Group IBM Information Management

Version 16 100

DEC

DECIMAL

NUMERIC

DEC(p)

DECIMAL(p)

NUMERIC(p)

DEC(p s)

DECIMAL(p s) NUMERIC(p s)

There is no difference within Oracle between these types and each other and these types and NUMBER The Oracle system catalogs contain the NUMBER type id for all declarations of these types and the integer types as well Declarations of these types can be mapped using the same rules as those for NUMBER

NVARCHAR2(n) NCHAR VARYING(n) NATIONAL CHAR VARYING(n) NATIONAL CHARACTER VARYING(n)

LVARCHAR(min(n 32767))

RAW(n) BLOB

REAL DOUBLE PRECISION

Record ROWTYPE

Using a CREATE ROWTYPE statement

ROWID INTEGER

SMALLINT SMALLINT

TIMESTAMP(p)

If p is not specified precision defaults to 6

DATETIME YEAR TO FRACTION(min(5 p))

UROWID(n) INTEGER

IBM Software Group IBM Information Management

Version 16 101

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is less than or equal to 255 (that is n lt= 255)

VARCHAR(n)

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is greater than 255 (that is n gt 255)

LVARCHAR(n)

XMLType CLOB

Notes on specific types are below

DOUBLE

The range of values for the DOUBLE PRECISION data type is the same as the range of the C double data type on your computer

VARCHAR

While Oracle VARCHAR data types have a limit of 4000 bytes an Informix Server VARCHAR data types has a limit of 255 bytes An Informix Server LVARCHAR has a limit of 32739 Bytes

NUMBER

Oracle abstracts its numeric types from the hardware and operating system through the use of its NUMBER type Most numeric types like INTEGER are actually NUMBERs internally When porting to a database server like Informix which retains more of a relationship between the operating system types and the database types it is essentially a one-to-many mapping and heuristics have to be used to determine the best-fit target type No single set of type mapping rules will fit all use scenarios The converter has default rules which fit the more common user patterns When considering a number represented as mantissa and exponent

mantissa x 10exponent

precision is the number of digits in the mantissa and scale is the negative exponent how many places to the right of the decimal point the least significant digit is located Oracle NUMBERs have a maximum precision of 38 and the maximum precision available in Informix native types is 32 The first step in a type mapping is to truncate the target type precision to min(precision 32) The scale of a type can be considered its anchor point with respect to the decimal point The most

IBM Software Group IBM Information Management

Version 16 102

significant digit of a numeric type is located precision digits to the left of the decimal point and precision-scale digits to the right of the decimal point The start and end locations of the digits are used to determine the closest fitting Informix type The order of preference is INTEGER BIGINT NUMERIC(p s) and lastly NUMERIC(p) NUMERIC(p) in a non-ANSI mode database is a decimal type with a floating point type In an ANSI mode database the scale is implicitly 0 All Oracle integer declaration types such as INT INTEGER SMALLINT become NUMBER(38) type in the Oracle metadata In Oracle when precision is given but scale is not scale becomes 0 implicitly which makes the type in the set of integral types One exception to the general mapping rules is the NUMBER type specified without precision or scale Strictly speaking this has a floating point scale with 38 digits of precision but most commonly it is used where an integer is more appropriate Even if the user does specify INTEGER in a type definition when it comes out of the Oracle catalogs the type is NUMBER This is one case in particular where one type mapping will not fit well with all usage scenarios

National language types

Oracle Nchar types are allocated by number of characters where Informix is allocated by the number of bytes For Oracle the storage size of the characters varies with the encoding used and is always subject to the standard 32767 limit on maximum bytes but during declarations n always means the number of characters Oracle PLSQL supports explicit and implicit data type conversions These explicit and implicit data types are converted to syntax by using Informix Dynamic Servers explicit and implicit data type conversion mechanism

ROWID

Oracle databases support a pseudo-column named ROWID such that every row in every table is assigned an auto-generated ID Oracle also allows you to define a column of type ROWID which can be used as a foreign key to a ROWID pseudo-column Oracle ROWID columns contain data that if converted to a string are 18 characters long for example lsquoAAAQ+jAAEAAAAAeAANrsquo It is probably not advisable to migrate this data to an Informix database and instead use the Informix type which is an integer If there is a dependency on the values themselves and therefore need migrate the data then an integer type would not hold the values

TYPE

In PLSQL you can refer to the type of an existing variable field or column by using the TYPE attribute The converter replaces this reference directly by the type it refers to

ROWTYPE

In PLSQL you can refer to the record type that represents a row of a table a cursor or a cursor variable PLSQL scripts containing the ROWTYPE attribute are handled in the same way as a record type that has been previously declared

FLOAT

Oracle FLOAT type is a floating point number capable of storing up to 38 decimal digits or 126 binary digits It has a floating point scale that can exist outside the boundaries of what an Informix DECIMAL can represent A C language double or Informix float type is capable of only 16 digits so there is the chance that some data will be lost Using an Informix FLOAT type makes it so that less significant digits are lost in preference to more significant digits

IBM Software Group IBM Information Management

Version 16 103

References to subtypes declared in packages and PLSQL blocks are converted to the Informix Server equivalent base types Variables of type RECORD are not translated by the DDL Converter at the time of this writing They will be handled by the stored procedure converter

XMLType

Informix does not have a built-in type for representing XML The nearest approximation is to store it in a CLOB Another character type like LVARCHAR can be used if it can be determined that the actual data will fit in it

Page 2: Oracle to IBM Informix Server Porting Guide

IBM Software Group IBM Information Management

Version 16 2

copy Copyright IBM Corporation 2012 All Rights Reserved

Trademarks IBM AIX DB2 DB2 Universal Database Informix and iSeries are trademarks of the International Business Machines Corporation in the United States other countries or both UNIX and Unix-based trademarks and logos are trademarks or registered trademarks of The Open Group Intel and Intel-based trademarks and logos are trademarks or registered trademarks of Intel Corporation Windows is a trademark of Microsoft Corporation in the United States and other countries or both Linux is a registered trademark of Linus Torvalds in the United States other countries or both Oracle and Java are registered trademarks of Oracle andor its affiliates Other company product or service names may be the trademarks or service marks of others

Disclaimer References in this publication to IBM products or services do not imply that IBM intends to make them available in all countries in which IBM operates

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

The use of this information or the implementation of any of these techniques is your responsibility and depends on your ability to evaluate and integrate them into your operational environment While each item may have been reviewed by IBM for accuracy in a specific situation there is no guarantee that the same or similar results will be obtained elsewhere Customers attempting to adapt these techniques to their own environments do so at their own risk

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 andor changes in the product(s) andor the program(s) described in this publication at any time without notice

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

The information in this white paper is provided AS IS without warranty Such information was obtained from publicly available sources is current as of December 2011 and is subject to change Any performance data included in the paper was obtained in the specific operating environment and is provided as an illustration Performance in other operating environments may vary More specific information about the capabilities of products described should be obtained from the suppliers of those products

IBM Software Group IBM Information Management

Version 16 3

Document History Revision History

Authoring Original Document (May 2000) Glen Black Frank Martino amp Tim Tobey Informix Software Incorporated Partner Engineering Organization Revisions for Informix Dynamic Server2000 Version 6 (July 2000) Tim Tobey Informix Software Incorporated Partner Engineering Organization Updated to IBM Informix Dynamic Server Database Version 9 Release 4 (February 2004) Christine Normile Informix Dynamic Server Product Manager IBM Software Group Information Management Updated material for Sequence Objects (December 2004) Sam Marino DB2 Business Partner Technical Enablement IBM Information Management Solutions IBM Software Group Updated to IBM Informix Dynamic Server Database Version 1000 (January 2006) Sam Marino Business Partner Technical Enablement ndash Data Services IBM Information Management IBM Software Group Updated to IBM Informix Dynamic Server Database Version 1110 (December 2007) Sam Marino IBM Business Partner Technical Enablement ndash Data Services IBM Information Management IBM Software Group Updated material for delimited identifiers metadata extraction type conversion and miscellaneous (June 2012) Chris Golledge IBM Information Management IBM Software Group

Contributions Technical Reviewers Keshava Murthy IBM Informix Database Server Development IBM Software Group Information Management Lakshman Sakaray IBM Database Migration Toolkit IBM Software Group Information Management

IBM Software Group IBM Information Management

Version 16 4

Table of Contents

C H A P T E R 1 INTRODUCTION 8

PURPOSE 8 PRODUCT OVERVIEW 8 ORGANIZATION 8 CONVENTIONS 9

C H A P T E R 2 DEFINING THE PROBLEM SPACE 11

EXTRACTING THE OBJECTS TO BE MIGRATED 11 Working With Oracle Dump Files 11

C H A P T E R 3 DATA DEFINITION LANGUAGE 15

IDENTIFIERS 15 Delimited identifiers 15 Explicit versus implicit schemaowner names 17 Reserved words or keywords 18 Summary 19

DATABASES 19 Databases database names and instances 19 ANSI vs non-ANSI 20

TABLESPACES AND DBSPACES 20 TABLES 21

Attributes and general syntax 21 Lock mode 21 Storage 21 Constraints 22 ALTER TABLE 22 Data Partitioning 23

DATA TYPES 25 Numeric 25 CHAR VARCHAR and LVARCHAR 26 Date and Time 27 Interval 27 Raw data and Large Objects 28 ROWID 28 User-defined types 29 Complex data types 30

SEQUENCE OBJECTS 30 Oracle sequences 30 Informix sequences 30

INDEXES 30 Composite indexes 30 Maximum key size 31 Index fragmentation 31 General index information 31

VIEWS 32 STORED PROCEDURES AND TRIGGERS 32 ORACLE EXTENSIONS 33

C H A P T E R 4 DATA MANIPULATION LANGUAGE 34

SQL 34 Labels using keywords 34 Inequality operations 34 Selects 34 Optimizer directives 34

IBM Software Group IBM Information Management

Version 16 5

External optimizer directives 35 Inserts 36 Temporary tables 36 Outer joins 36 Sorts 36 Exceptions 37 Correlation names 37 Aliases 37 Hierarchical queries 37 Truncate 39

HOST VARIABLES 40 DATE AND TIME FUNCTIONS 41

SYSDATE 41 Number formats 41 Date formats 42 The RR date format element 43

USER-DEFINED ROUTINES 43 COMPATIBLE SQL FUNCTIONS 43 AGGREGATE FUNCTIONS 43 MATHEMATICAL FUNCTIONS 44 STRING FUNCTIONS 44

LENGTH 44 LTRIM and RTRIM 44 Oracle Extensions 44

OTHER ORACLE FUNCTIONS 44 MACROS 45

ISOPEN and NOT FOUND 45 ROWTYPE 45 TYPE 45

PSEUDO-COLUMNS 45 LEVEL 46 ROWID 46 ROWNUM 46

UPDATE USING CURSORS 49 SYSTEM TABLES 50 STORED PROCEDURES 50

Size limit 50 Parameter limit 50 Packages 51 Routines 51 Exceptions 51 Error handling 52 Cursors 52 Variable declaration and assignment 53 Boolean 53 Binary data types 53 Dynamic SQL 53 Compiler 53

TRIGGERS 54 CONSTRAINTS 55 DUAL TABLE 55

C H A P T E R 5 EMBEDDED SQL 57

HOST VARIABLES 57 Declaration override 57 Arrays 57 Formatting 58

SQL STRUCTURES 59

IBM Software Group IBM Information Management

Version 16 6

SQLCA 59 SQLDA 60 ORACA 61

PRE-COMPILER OPTIONS 61 EMBEDDED PLSQL 61 ORACLE CALL INTERFACE 61

Database library calls 62 Global area processing 62 Fetch cycle 62 RAW binary data type processing 62 Parameter bindings 62

EMBEDDED SQL FOR C 63 VARCHAR 63 Host variables 63

EMBEDDED SQL FOR COBOL 63 VARCHAR 63 Level 88 64 SQLDA 64 REDEFINES 64 Tips 64

ODBC 64

C H A P T E R 6 APPLICATION ARCHITECTURE 65

TRANSACTION PROCESSING 65 Autonomous Transaction 66 Savepoints 67

CONCURRENCY 67 Row Level Locking 67 Transaction Isolation Level 68

C H A P T E R 7 SECURITY 70

USER AUTHENTICATION 70 Operating system security 70 Non-operating system security 70

ROLE BASED AUTHORITY 71 COLUMN-LEVEL ENCRYPTION 71

Passwords and hints 71 Encrypting a column 72 Querying an encrypted column 72 Performance impact of encryption 73 Storage considerations 73 Compliance regulations 73

C H A P T E R 8 ENVIRONMENT 74

SCRIPTS 74 SQL script substitution variables 74

UTILITIES 75 SYSTEM CATALOG 75

C H A P T E R 9 USING BLADELETS 76

WHAT IS A BLADELET 76 INFORMIX EXEC BLADELET FOR DYNAMIC SQL 77 SQLLIB DATABLADE MODULE (SQLLIBC11 SQLLIBJ11) 78

A P P E N D I X A PLANNING GUIDE 79

A P P E N D I X B SYNTAX COMPARISON 82

IBM Software Group IBM Information Management

Version 16 7

A P P E N D I X C DATABASE CONCEPTS 84

A P P E N D I X D SAMPLE CODE 85

DATE ARITHMETIC 88 UNITS Keyword 88 Using EXTEND function 88

STRING REPRESENTATION OF DATE AND TIME 88 Day and date 88 Abbreviation of day of week 88

USING AN INFORMIX COLLECTION DATA TYPE 89 A collection data type as a VARRAY 89 Using MULTISET and ROW to replace PLSQL TABLE and RECORD types 91

A P P E N D I X E COUNTING SYSTEM OBJECTS 93

USING THE SYSTEM CATALOG 93 System catalog 93

USING SQL CODE 94 Built-in function references 94 Object types and counts 95

A P P E N D I X F DATA TYPE MAPPING 97

DOUBLE 101 VARCHAR 101 NUMBER 101 National language types 102 ROWID 102 TYPE 102 ROWTYPE 102 FLOAT 102 XMLType 103

IBM Software Group IBM Information Management

Version 16 8

C H A P T E R 1 Introduction

This document is a technical document describing the differences between Oracle and Informixreg Dynamic Server (IDS) functionality and syntax This porting guide details differences between Oraclersquos 10g release 1 (101) and 10g release 2 (102) and Informix Dynamic Server (version 1110) In addition it can be a useful reference for all migrations between the two database servers regardless of version In addition to DDL DML and overall SQL syntax this document explores the differences between Oracle and Informix with regards to object technology through the use of large objects user defined types and user defined routines It also looks at the differences between Oraclersquos table partitioning and Informixrsquos table fragmentation Part of the explanation is a discussion on what needs to be changed to make an application running on an Oracle database run on an Informix database If there is more than one way to port some piece of functionality alternatives and recommendations are also discussed This document is intended to be a living document Missing items better ways of implementing Oracle functionality in Informix other than what is documented here examples to better illustrate a point and other suggestions should be sent to Chris Golledge (golledgeusibmcom) so they may be included with future revisions

Purpose This document should be used as a guide to assist in porting applications that run on an Oracle database server to run on an Informix database server Regardless of whether a porting effort will be completely manual or if tools will be utilized this document can provide value Obviously if the port is performed manually this guide will provide the most value If the port will utilize tools then analysis can be performed using this guide to determine how much of the application the tools will convert and how much must be converted manually In any case this guide is intended to be used to both visualize the scope of a porting effort and to aid in the porting effort by addressing the technical issues This document will be refined based on usersrsquo experiences to identify as many of the porting issues as possible at the beginning of a project

Product overview IBM Informix Server provides high performance and scalability with legendary reliability and nearly hands-free administration of databases of all size IDS is industry proven on UNIX Linux or Windows platforms with online transaction processing (OLTP) systems data marts data warehouses and e-business applications The IDS 11 release features significant additions over prior versions It supports the services-oriented architecture (SOA) model for application integration and offers many new features for data replication continuous availability and ldquohands freerdquo database administration

Organization This document is broken into sections to logically discuss the different database concepts Some of the sections may contain the same sub-sections for example stored procedures and triggers

IBM Software Group IBM Information Management

Version 16 9

are discussed in the DDL and DML sections This allows separate discussions on the issues facing the same item in each area For example the issues surrounding creating a stored procedure are discussed in the DDL section and the issues surrounding the stored procedure language are discussed in the DML section Among the other references the ldquoPlanning Guiderdquo appendix contains a quick reference of most of the differences between Oracle and Informix along with the degree of difficulty to port each difference This reference is intended for use in the planning process to illustrate the scope and the effort required to perform the porting project Some of the stored procedure logic used to convert Oracle functions is included in the appendix rdquoSample coderdquo

Conventions The conventions used in this document include

Courier Text Distinguishes a logic example

from regular text

Example Illustrates a point In most cases an Oracle example will be followed by an Informix example

Italicized Text Signifies a substitution in other words substitutes for the italicized word the actual object the word is describing for example table_name column_name and so on

UPPER CASE TEXT Signifies database vendor reserved words or statements such as INTEGER CREATE TABLE and so on

Bold example text highlights the item that is being explained

IBM Software Group IBM Information Management

Version 16 10

IBM Software Group IBM Information Management

Version 16 11

C H A P T E R 2 Defining the Problem Space

It is important to define the set of objects to be migrated and it is better if effort is put into this prior to beginning the actual migration This is true if you are the responsible for both the database in general and its migration from one supporting DBMS to another but it is particularly true that there be a clear agreement on the scope of what is to be migrated if the migration is to be performed by a party other than the one with long term responsibility for the database Defining the scope will involve extracting a representation of the objects to be migrated out of the Oracle system catalogs and representing them in some format that can be manipulated into constructs that can be used in Informix

Extracting the objects to be migrated It is possible to represent the objects in more than one language Using the SQL language is the most common method and it will be the only one discussed at length in this document (in its current revision) However it is also possible to express database objects in XML SQL has the advantage that the standard common grammars are widely understood in the context of defining tables indexes etc XML would have an advantage of not requiring parsing that is sensitive to the minor differences in ways of expressing essentially the same object

Working With Oracle Dump Files

There exist 3rd

-party tools for reading system catalogs but it is doubtful that any can read the Oracle catalogs more reliably than Oraclersquos own tools There are two incompatible export and import tool sets used by Oracle The older tools are imp and exp and the newer ones are impdp and expdp where dp stands for Data Pump Oracle has encouraged the use of the newer tools instead of the older ones since the newer ones were introduced at version 10 Nonetheless there are many Oracle users still using imp and exp In the discussions below only the metadata will be extracted into a dump file That is because any data in the dump file will be in a proprietary format and very likely some of the data will have to go through a type conversion process before being loaded into an Informix system Oracle exported data generally cannot be used to load a database in Informix Export and Import

If someone has given you a dump file created with the older export tool there exist tools such as The DDL Wizard by Net 2000 Limited which can be used to extract viable DDL The contents of the dump file contain the SQL for re-creating the database but they are not in a readily usable format The older export and import tools are also more sensitive to the layout of the tablespaces than impdb The ability to extract DDL from the dump file in a usable form segmented by whatever grouping you choose is limited compared to what can be achieved through the Data Pump versions

IBM Software Group IBM Information Management

Version 16 12

It may be tempting to feed the dump file into the IBM Migration Toolkit (MTK) or other tool that works on SQL flat files This will not work MTK works on flat text SQL files and the dump file is binary If you open it up you can see what may be a large number of SQL statements but there are also binary codes within the same file That binary data will prevent MTK from being able to process it Getting SQL statements

If you want to get the SQL statements out of the dump file as they would be executed on the server there is an option available from the import tool itself show=y

imp myIDmyPWD as sysdba file=myFiledmp

full=yes show=y gt dmp_showtxt

This will produce a file which contains the statements but they are wrapped in quotes The contents will look something like

ALTER SESSION SET CURRENT_SCHEMA= SYSTEM CREATE UNDO TABLESPACE TBSPC1 BLOCKSIZE 8192 DATAFILE DORACLEORADA TASCHEMA1CHUNKDBF SIZE 387973120 AUTOEXTEND ON NEXT 5242880 MAXS IZE 32767M EXTENT MANAGEMENT LOCAL

which makes them strings instead of SQL statements Fixing this is a two-step process

-- removes quotes from the start of lines

sed s^ g dmp_showtxt gt step1txt

-- removes quotes from the end of lines

sed s$g step1txt gt dmp_step2sql

The statements are still not correctly formatted because they have been truncated to a fixed length and line-endings inserted However at this point it is possible to get a count of how many of each object type there is using the script in the appendix ldquoGetting an initial count of database objectsrdquo

Data Pump Export and Import

These newer tools provide better performance and more capabilities than their predecessors Please refer to documentation on Oracle for a complete description searches for ldquoData Pump Importrdquo and ldquoData Pump Exportrdquo should return relevant results quickly Below is enough information to get started on defining and extracting the objects to be migrated Metadata can be filtered through the use of the export mode clause and INCLUDE and EXCLUDE parameters However any dependent object of an included or excluded object is likewise included or excluded For example if you include an index then the table associated with the index will also be included and if you exclude a table then any associated indexes will also be excluded The SQL that will generate all the objects in the dump file can be created by the impdp command with the SQLFILE parameter If the output file is very large you might want to break it into smaller pieces There are a couple of ways to do this and the one that is best for you somewhat depends

IBM Software Group IBM Information Management

Version 16 13

on how you intend to proceed with the conversion Data definition language (DDL) SQL for all the objects can be put into one file or the INCLUDE or EXCLUDE parameters can be added to direct Data Pump to filter on the types of objects If you put all the objects into one file then you can break that into smaller files by object type fairly easily because the objects are sorted by type in the SQL file So it is just a matter of cutting the file into smaller pieces This method may be preferred because it allows for you to do things like create all tables load the data and then create the indexes and triggers If the data set is large creating the indexes after loading the data can yield substantial performance improvements However this is less useful if you want to convert sets of objects according to dependencies in which case the filtering option is likely to be more useful Just to illustrate a difference between these two methods in one customer case the metadata dump file was about 18MB and putting all objects in one SQL file resulted in a file that was about 15MB The table definitions occupied a little under 300KB of the 15MB The output file generated by filtering on objects of type TABLE was just over 1MB The addition content was mostly GRANT INDEX and TRIGGER creation statements There were no differences in the CREATE TABLE statements themselves Examples

Prerequisite The Data Pump tools require the use of an Oracle DIRECTORY object This is basically a mapping between a name that exists within the DBMS and a system path It can be a tripping point but it provides an abstraction layer that for instance allows the same commands to work across systems with different disk layouts or different operating systems Creating a DIRECTORY on a Windows system from SQLPlus

SQLgtconnect as sysdba

SQLgtCREATE OR REPLACE DIRECTORY dumpDir AS ctemp

Note Make sure this directory is not read-only There also could be problems if the directory is a network drive on Windows these can be related to there being different users between the Oracle executable and the current user and those users having different permissions on the network drive

SQLgtGRANT read write ON DIRECTORY dumpDir TO userID

Creating a dump file of the entire database

expdp userNameuserPwd as sysdba FULL=Y dumpfile=DB_fulldmp

LOGFILE=LG_expdplog CONTENT=METADATA_ONLY DIRECTORY=dumpDir

Creating a dump file of just one schema

expdp userNameuserPwd as sysdba SCHEMAS=hr DIRECTORY=dumpDir

DUMPFILE=hr dmp LOGFILE=hr log CONTENT=METADATA_ONLY

Creating a dump of just the tables and their dependents

expdp userNameuserPwd as sysdba SCHEMAS=hr INCLUDE=TABLE

DIRECTORY=dumpDir DUMPFILE=hrdmp LOGFILE=hrlog

CONTENT=METADATA_ONLY

Creating a dump of just one table

expdp userNameuserPwd as sysdba SCHEMAS=hr

INCLUDE=TABLELIKE COUNTRIES DIRECTORY=dumpDir

DUMPFILE=hrdmp LOGFILE=hrlog CONTENT=METADATA_ONLY

IBM Software Group IBM Information Management

Version 16 14

Creatinge an SQL file from a dump file

impdp userNameuserPwd as sysdba DIRECTORY=dumpDir

DUMPFILE=hrdmp SQLFILE=dumpDirhrsql

The INCLUDE and EXCLUDE options are also valid when used with impdb so it may be easier to get a complete dump of everything to be migrated then use these options to create subsets of objects it smaller SQL files than it would be to create separate dump files It is easier to divide objects than to merge them together if they are not divided initially as wanted There is a caveat when using this impdp to generate an SQL file the object names will all be delimited identifiers Example

CREATE TABLE HRCOUNTRIES Because of differences between how Informix handles these and how Oracle handles these case-sensitivity issues could occur See the chapter on ldquoDelimited Identifiersrdquo and in particular the description of default shift problems If it can be determined that there are no name collisions if regular identifiers are used removing the quotation marks as part of the conversion might avoid many problems In other words if there are no objects whose names only differ in case like foo and FOO then changing every occurrence of ldquoFOOrdquo to FOO in the DDL could eliminate case-sensitivity issues in the application DML It depends on if the application code uses the delimited form of the name predominantly or not

IBM Software Group IBM Information Management

Version 16 15

C H A P T E R 3 Data Definition Language

Identifiers An identifier specifies the simple name of a database object such as a table name column name index name view name stored procedure name and so on The maximum length of an Oracle identifier is 30 characters and can contain letters numbers ldquo_rdquo ldquo$rdquo and ldquordquo although Oracle highly recommends that ldquo$rdquo and ldquordquo should not be used In contrast Informix identifiers have a maximum length of 128 characters and may contain letters numbers ldquo_rdquo and ldquo$rdquo (as long as ldquo$rdquo is not the first character) See the Delimited Identifiers section below for information This means that all Oracle identifiers containing a ldquordquo anywhere in the identifier or a ldquo$rdquo as the first character must be replaced or modified to remove those characters from the identifier

Delimited identifiers

Delimited identifiers are also known as quoted identifiers and sometimes as escaped identifiers They have been part of the SQL standard since SQL92 but existed in various database management systems (DBMS) prior to that time In a nutshell they are a way to preserve case sensitivity in object names as well as to allow objects to have names outside of the conventions of SQL regular identifiers Prior to the behavior of identifiers in general being standardized different DBMS vendors implemented different means of achieving case-insensitivity for object names some converted all regular identifiers to uppercase and some converted regular identifiers to lowercase By SQL99 the concept of case normal form was standardized to mean simply stated that if there exists an uppercase equivalent of any character in a name then the uppercase version is stored in the system catalogs and used for comparison purposes See the SQL99 standard chapter 5 section 2 and in particular items 21 and 22 for a formal description of case normal form and how it applies to identifier comparisons Delimited identifiers can be used to specify names for database objects that are otherwise identical to SQL reserved keywords such as TABLE WHERE DECLARE and so on The only database object for which delimited identifiers cannot be used is a database name Database administrators and application programmers do not always communicate to each other with 100 efficiency and there is no guarantee that within either of these pools every member codes by the standard practice of the other members After describing how delimited identifiers work in Informix there will be a description of how any inconsistency of usage and the differences between Oracle and Informix can introduce some migration hurdles DELIMIDENT Environment Variable

To use delimited identifiers with Informix you must set the DELIMIDENT environment variable While DELIMIDENT is set strings enclosed in quotation marks ( ldquo ) are treated as identifiers of database objects and strings enclosed in apostrophes ( rsquo ) are treated as literal strings If the

IBM Software Group IBM Information Management

Version 16 16

DELIMIDENT environment variable is not set strings enclosed in quotation marks are also treated as literal strings When you set the DELIMIDENT environment variable you cannot use quotation marks ( rdquo ) to delimit literal strings If DELIMIDENT is set the database server interprets all strings enclosed in quotation marks as SQL identifiers not string literals Commonly within Informix systems DELIMIDENT is set or not on the client side according to the design of the application However if you are converting a database and all applications accessing it from a system where every occurrence of quotation marks (ldquoobjectNamerdquo) indicates an identifier and not a string literal you may want to consider setting it in the server environment in order to avoid any inconsistency between clients where it is set and where it might not be Using Quotes in Strings The apostrophe ( rsquo ) has no special significance in string literals delimited by quotation marks Conversely double quote ( Prime ) has no special significance in strings delimited by apostrophes For example these strings are valid Nancyrsquos puppy jumped the fence

rsquoBilly told his kitten No rsquo A string delimited by quotation marks can include a double quote character by preceding it with another double quote as the following string shows Enter y to

select this row When the DELIMIDENT environment variable is set quotation marks can only delimit identifiers not strings Use of Uppercase Characters You can specify the name of a database object with uppercase characters but the Informix server shifts these to lowercase characters unless the DELIMIDENT environment variable is set and the name of the database object is enclosed in quotation marks In this case the database server treats the name of the database object as a delimited identifier and preserves the uppercase characters in the name Delimited Identifiers By default the character set of a valid SQL identifier is restricted to letters digits underscore and dollar-sign symbols If you set the DELIMIDENT environment variable however SQL identifiers can also include additional characters from the codeset implied by the setting of the DB_LOCALE environment variable See the Identifier section of the Informix Guide to SQL Syntax for more information Storage Object Names In Informix delimited identifiers can be used to specify non-alphanumeric characters in the names of database objects However delimited identifiers can not be used to specify non-alpha characters in the names of storage objects such as dbspaces and blobspaces To use delimited identifiers DELIMIDENT must be set both at compile and run times For example to set DELIMIDENT environment variable with sh or ksh issue the following at the command line prompt

export DELIMIDENT=

Note You do not need to assign a value to the environment variable and counter-intuitively setting DELIMIDENT=n has the same effect as DELIMIDENT=y Also in a Windows environment

set DELIMIDENT=

effectively undefines the variable Default shift problems

Any direct access of system catalog information involving names will cause problems when migrating from a system like Oracle where system catalog names are stored in uppercase to a system like Informix where the catalog names are stored in lowercase For example

CREATE TABLE foo (c1 int)

IBM Software Group IBM Information Management

Version 16 17

Within Oracle the following will return information about the table

select from sysall_objects where object_name = FOO

and the following will not

select from sysall_objects where object_name = foo

Conversely in Informix

select from systables where tabname = foo

will be successful and the same with FOO will not be A similar if not more common problem can occur when the table has been created without the name being delimited but is sometimes delimited when accessed by the application Per the standard foo == FOO == ldquoFOOrdquo but in Informix foo == FOO == ldquofoordquo In Oracle the following SELECT statement will be successful

SELECT FROM ldquoFOOrdquo

but within Informix this will result in an error ldquo206 The specified table (FOO) is not in the databaserdquo Likewise if the name is delimited in its definition such as

CREATE TABLE SCHEMA1TABLE1

this creates a table that can be referenced in Oracle without the name being delimited The statements

SELECT FROM schema1table1

and SELECT FROM SCHEMA1TABLE1

will be successful in the Oracle system but will fail in the Informix one In theory whether on object name is delimited or not should be the same in the database and at every occurrence within the application but this is not always the case It may be beneficial to examine whether delimited identifiers or regular identifiers are most commonly used in application code and use whichever is most common as a naming convention when translating the DDL

Explicit versus implicit schemaowner names

Another complication to keep in mind is that when the log mode is ANSI implicit and explicit owner names are treated differently between the Oracle and Informix servers In Oracle there is no difference in the case handling of an implicit owner name and an explicit one For example if connected to Oracle as scott the following CREATE TABLE statements

create table foo1(c1 int) create table scottfoo2(c1 int) create table SCOTTfoo3(c1 int)

all result in tables owned by SCOTT The following select statements in various forms that may be in application code will all run without error

select from foo1 select from scottfoo1

IBM Software Group IBM Information Management

Version 16 18

select from SCOTTfoo1 select from foo2 select from scottfoo2 select from SCOTTfoo2 select from foo3 select from scottfoo3 select from SCOTTfoo3

These statements will also run without error within a non-ANSI mode Informix database but not all of them will run successfully within an ANSI mode database This is because Informix does not uniformly fold the case of owner names and handles implicit names differently from explicit names so there will always be some combination of DDL and DML usage patterns that work within an Oracle system that do not work in an Informix one You can set ANSIOWNER before starting your Informix server but that will merely change which combinations do not work You may want to examine usage patterns within the applications and choose a naming convention when translating the DDL that matches the most common naming convention used in the applications Note This behavior of Informix forces a tradeoff between using an ANSI mode database which most closely matches the transaction behavior of Oracle and a non-ANSI mode database which has the least mismatch in identifier case sensitivity

Reserved words or keywords

Oracle and Informix both allow identifiers to be reserved words as long as they are delimited However Oracle and Informix reserved words differ In addition both systems have keywords like FROM that are not always reserved in the sense that using them as an identifier will always generate a syntax error There should be few problems with reserved words or keywords if identifiers that are delimited in the original database remain delimited in the destination database The appendix Keywords of SQL for IBM Informix in the Guide to SQL Syntax contains more information about Informix keywords Also one word non-delimited identifiers should be verified against the Informix reserved words list to ensure that they do not need to be delimited or renamed Although almost any word can be used as an identifier in Informix syntactic ambiguities can result from using reserved words as identifiers in SQL statements Delimited identifiers provide a way to use a reserved word as an identifier without causing syntactic ambiguities However doing this changes a case-insensitive name into a case-sensitive one and that means that every reference to the object has to be checked for issues related to case-sensitivity Essentially this is not much less work than changing the name of the object because in essence it is changing the name of the object Examples

The following example shows how to create an Informix table with a case sensitive table name

CREATE TABLE My_Customers (hellip)

The following example shows how to create a table whose name includes a space character If the table name were not in quotation marks () a space character or any other non-alpha character except an underscore ( _ ) or dollar sign ($) (see special conditions above) could be used in the name

CREATE TABLE My Customers (hellip)

IBM Software Group IBM Information Management

Version 16 19

The following example shows how to create a table that uses a keyword as the table name

CREATE TABLE TABLE (hellip)

To include a double-quote () within a delimited identifier the double-quote () must be preceded with another double-quote () as shown in the following example

CREATE TABLE MyGoodData (hellip)

Summary

The main points to keep in mind when deciding about any questions on how identifiers should be translated are

Oracle always has delimited identifiers enabled and Informix does not

Oracle folds regular identifiers to uppercase and Informix folds to lowercase

Informix has behavioral differences between an ANSI mode database and a non-ANSI mode one

It is beneficial to consider the most common usage patterns within the existing application code prior to deciding default identifier translation patterns

Databases

Databases database names and instances

Oracle and Informix implement databases and instances differently Oracle considers a database to be a set of data files control file(s) and log files while an instance is a set of background processes and memory structures accessing database data Oracle instances are also known as servers Each Oracle instance or server runs against one database but through the use of Oracle Parallel Server a database may have multiple instances accessing it An Oracle database is named at initialization and the name has a limit of 8 ASCII characters Informix databases are defined as ldquoa collection of information contained in tables that are useful to a particular organization or used for a specific purposerdquo Informix database names may be up to 128 characters in length An Informix instance is a set of processes memory and disk allocations that manage data and will contain at least two and in most cases many databases Informix instances are also referred to as servers Informix databases may share disk allocations (dbspaces) with other databases within an Informix instance Oracle databases cannot share disk allocations (tablespaces) Informix databases should be created in a dbspace other than the root dbspace The root dbspace holds data for the system configuration information for the engine and so on If user-defined objects are created in this dbspace then the dbspace may become unmanageably large and during backup the system information may also get backed up unnecessarily The CREATE DATABASE statements of Informix and Oracle have differences which may require modification to routines responsible for database creation Informix will accept the same minimal syntax required by Oracle (eg CREATE DATABASE myDB) however issuing the command will implicitly accept the creation of a database without transaction logging enabled and establish the default location for all database objects as the instancersquos default storage location The instancersquos default storage location or ldquorootrdquo dbspace should not contain user-defined objects The root dbspace holds data for the system and some configuration information for the engine If user-

IBM Software Group IBM Information Management

Version 16 20

defined objects are created in this dbspace it may become unmanageable and result in the system contending with user objects for the available space

ANSI vs non-ANSI

Informix supports both ANSI and non-ANSI databases Informix non-ANSI databases are most common but there are some advantages of ANSI databases when porting from Oracle

Oraclersquos transaction behavior is more or less like that of an ANSI database Applications ported on Oracle are always in a transaction In Oracle and ANSI databases transactions begin implicitly with the first of a series of SQL statements and will end immediately after a commit or rollback statement Therefore unlike a non-ANSI database a COMMIT WORK statement does not need to be preceded with a BEGIN WORK statement

In ANSI databases database object references must be prefixed by the ownerrsquos name unless the owner is the one referencing the object If Oracle applications reference database objects with a both parts of the object name prefixing the object name with schema using an ANSI database may ease modifications necessary when porting to Informix

The ldquolsquogrant to PUBLICrdquorsquo concept provide by Informix database security does not apply to ANSI databases Every database object is private and privileges must be explicitly granted to each user

If an Informix ESQLC or 4GL application was developed to run on a non-ANSI Informix database (including BEGIN WORK statements) the application could run on an ANSI Informix database in one of two ways

By placing the BEGIN WORK statement in a pre-processor directive such as IFDEF object_name and omitting the proper preprocessor compile options such as -D object_name

By compiling the application normally and ignoring the resulting warning messages

Additionally the LOG MODE ANSI clause must be added to the CREATE DATABASE statements ANSI mode databases cannot have buffered logging Applications written to use an open API like ODBC or JDBC are compiled without awareness of the database and these APIs are written with the intent to abstract specific database behavior For instance in one of these the application developer would call a function to begin or end a transaction rather than execute a BEGIN and COMMIT or ROLLBACK The API would execute these statements internally or not as necessary for the database connection See the Transaction Processing section in Application Architecture for more information on how an application running on a non-ANSI Informix database can simulate Oracle transaction behavior

Tablespaces and dbspaces Oracle tablespace names need to be replaced with Informix dbspace names Unlike the Oracle tablespace the Informix dbspace cannot be created using DDL (SQL) scripts It must be created using the Informix onspaces utility before any DDL (SQL) scripts are executed Therefore Oraclersquos CREATE TABLESPACE statements should be removed from the DDL (SQL) scripts The user interface for accomplishing these tasks is onmonitor The command line utility is onspaces Therefore the onspaces commands can be placed in shell or batch scripts After successfully executing the onspaces commands the DDL (SQL) scripts may be called through the same shell or batch scripts For example

IBM Software Group IBM Information Management

Version 16 21

onspaces hellip onspaces hellip hellip dbaccess database_name DDL_script_file_name dbaccess database_name DDL_script_file_name hellip

Tables

Attributes and general syntax

When creating tables the Oracle CREATE TABLE statement must be converted to Informix taking advantage of the Informix options IN EXTENT NEXT and LOCK MODE

IN specifies the dbspace in which the table will reside

EXTENT specifies the amount of space that will initially be allocated to the table (16K default on most platforms)

NEXT specifies the amount of space that will be allocated when additional space is needed (16K default on most platforms

Lock mode

LOCK MODE specifies whether to use row or page locks for the table In Oracle the default is row level locking in Informix the default setting is page level locking However it can be changed by using one of the following methods (resolved in the following order of precedence)

1 LOCK MODE specified using an attribute of the CREATE TABLE or ALTER TABLE command syntax

2 IFX_DEF_TABLE_LOCKMODE environment variable setting 3 DEF_TABLE_LOCKMODE parameter setting in the ONCONFIG file

NOTE If the DEF_TABLE_LOCKMODE parameter cannot be found in the ONCONFIG file it can be added to make the specification for every database within the instance The Informix instance must be restarted for this parameter to take effect The new ldquodefaultrdquo LOCK MODE will apply to all tables created after the parameter has been changed To change the LOCK MODE of existing objects use the ALTER TABLE statement

Storage

The Oracle STORAGE INITIAL and STORAGE NEXT clauses must be changed to the Informix EXTENT SIZE and NEXT SIZE clauses respectively In Oracle the STORAGE clause options MINEXTENTS MAXEXTENTS and PCTINCREASE should be removed For example Oracle

CREATE TABLE dept(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13)

)

STORAGE (INITIAL 100K NEXT 50K MINEXTENTS 1 MAXEXTENTS 50

PCTINCREASE 5)

Informix CREATE TABLE dept (

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

IBM Software Group IBM Information Management

Version 16 22

EXTENT SIZE 200 NEXT SIZE 50

When an Oracle CREATE TABLE statement does not include a STORAGE clause the table will be created using the tablespace STORAGE clause by default If an Oracle tablespace is created specifying a STORAGE INITIAL of 100KB and a STORAGE NEXT of 50KB then all tables created within that tablespace will have a default value of STORAGE INITIAL 100KB and STORAGE NEXT 50KB Oracle tables cannot be created with smaller STORAGE clause values than the tablespace default they are created in Informix dbspaces do not have storage clauses attached to them As stated earlier the default Informix EXTENT and NEXT sizes are 16KB on most platforms The minimum EXTENT and NEXT sizes are 4 times the page size

Constraints

The Oracle constraint syntax must be changed to the Informix syntax for primary keys foreign keys unique and so on For example

Oracle CONSTRAINT PK_NUMBER PRIMARY KEY(CUST_NUM)

CONSTRAINT CK_EMP_CODE CHECK (EMP_CODE gt 100)

Informix PRIMARY KEY(CUST_NUM) CONSTRAINT PK_NUMBER

CHECK (EMP_CODE gt 100) CONSTRAINT CK_EMP_CODE

An Oracle check constraint statement may contain functions that are not available in Informix In this circumstance it may be necessary to code the combination of a trigger and a stored procedure to emulate the same functionality A trigger based on an insert or update event can execute a stored procedure which tests the constraint condition and if necessary raise an exception to reject the row data which violates the constraint The Oracle PARALLEL clause which specifies parallel execution of an operation must be removed from any SQL statements (such as CREATE TABLE and ALTER TABLE) In Informix there are ways to accomplish this parallel execution depending on the context in which these SQL statements are called (shell script file batch file and so on)

ALTER TABLE

Informix offers a rich set of ALTER TABLE features adding and dropping columns (rename by using the RENAME statement) changing column data types altering the next size and changing the lock mode Informix will choose one of three algorithms when executing an ALTER TABLE statement depending upon the operation to be performed For certain conditions the database server uses either a ldquoslowrdquo ldquoin-place or ldquofastrdquo alter algorithm to modify the table Informix provides ldquoin-placerdquo alter table support for adding or dropping a column anywhere in the table changing the column length and changing the column data type without an exclusive lock on the table An ldquoin-placerdquo alter will modify the tablersquos definition without changing the existing rows or unloading and reloading the data After the ALTER TABLE operation the database server inserts rows using the latest definition Informix will not change the row structure until a data row is touched by a user operation Once a query accesses a row that is not yet converted there can be a slight degradation in the performance because the database server reformats each row in memory before it is returned Informix uses the ldquoslowrdquo alter algorithm when the ALTER TABLE statement makes column changes that it cannot perform in place This type of alter would be

Adding or drop a column created with the ROWIDS keyword

Dropping a column of the TEXT or BYTE data type

IBM Software Group IBM Information Management

Version 16 23

Converting an INT or a SMALLINT column to SERIAL or SERIAL8

Modifying the data type of a column so that some possible values of the old data type cannot be converted to the new data type

For example if you modify a column of data type INTEGER to CHAR(n) the database server uses the slow ALTER algorithm if the value of n is less than 11 An INTEGER requires 10 characters plus one for the minus sign for the lowest possible negative values

Modifying the data type of a fragmentation column in a way that value conversion might cause rows to move to another fragment

Adding dropping or modifying any column when the table contains user-defined data types or smart large objects

When the database server uses the slow alter algorithm to process an ALTER TABLE statement the table can be unavailable to other users for a long period of time because the database server will lock the table exclusively for the duration of the operation make a copy of the table to convert the table to the new definition and convert the data rows This type of ALTER TABLE processing can encounter the scenario of a statement being a long transaction and abort it if the Long Transaction High Water Mark (LTXHWM) threshold is exceeded Informix will use the ldquofastrdquo alter algorithm when the ALTER TABLE statement changes attributes of the table but does not affect the data The database server uses the fast alter algorithm when you use the ALTER TABLE statement to make the following changes

bull Change the next-extent size

bull Add or drop a constraint

bull Change the lock mode of the table

bull Change the unique index attribute without modifying the column type

With the ldquofastrdquo alter algorithm the database server holds a lock on the table for a very brief period In some cases the database server will lock the system catalog tables but only long enough to change the attribute In either case the table is unavailable for queries for only a short time

Data Partitioning

Informix Table Fragmentation is the counterpart to Oraclersquos Table Partitioning and allows the user to control where data is physically placed at the table level Table Fragmentation or Data Partitioning is typically done to large tables but Informix and Oracle implement fragmentation and partitioning for different reasons and with different results Informix recommends using table fragmentation to improve single-user response time concurrency data availability backup restore characteristics and data-load performance While Oracle does state that table partitioning may improve the performance of queries and that the Oracle optimizer takes partitioning into account the primary goal of partitioning in Oracle is improving database maintenance Partitioning strategies in Oracle include range partitioning as well as hash and composite partitioning Composite partitioning combines range and hash partitions through the use of sub-partitions Tables incorporating Oracle LOBrsquos (large objects) cannot be partitioned Informix fragmentation strategies include expression-based and round robin Basic expression-based fragmentation can replace Oracle range partitioning Unlike Oracle LOBs Informixrsquos Smart Large Objects can be fragmented Examples of creating tables with Oracle range partitioning and Informix fragmentation by expression are shown below Oracle range partitioning

CREATE TABLE dept

IBM Software Group IBM Information Management

Version 16 24

(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13) )

partition by range (deptno)

(partition PART1 values less than (11)

tablespace PART1_TS

partition PART2 values less than (21)

tablespace PART2_TS

partition PART3 values less than (31)

tablespace PART3_TS

partition PART4 values less than (MAXVALUE)

tablespace PART4_TS)

Informix expression based fragmentation CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

deptno lt 11 IN dbspace1

deptno gt= 11 AND deptno lt 21 IN dbspace2

deptno gt= 21 AND deptno lt 31 IN dbspace3

REMAINDER IN dbspace4

Oracle uses MAXVALUE for values not found in the specified range while Informix uses the REMAINDER keyword for values that fall outside the specified expression or expressions Prior to IDS version 1000 each table fragment had to go into a separate dbspace Now tables can be fragmented within a single dbspace You can create partitions within a dbspace that can each support a table fragment It is better to have one chunk per disk drive and now it is not necessary to create a dbspace just to facilitate fragmentation This feature can simplify the management of dbspaces The benefits gained through this new development include

It reduces the total number of dbspaces needed for a fragmented table

Storing multiple table fragments in a single dbspace improves query performance over storing each fragmented expression in a different dbspace

For example Informix partition fragmention in a single dbspace

CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

PARTITION part1 (deptno lt 11) IN dbspace1

PARTITION part2 (deptno lt 21) IN dbspace1

PARTITION part3 (deptno lt 31) IN dbspace1

PARTITION part4 REMAINDER IN dbspace1

Partitions of an Informix fragmented table can be manipulated using the ALTER FRAGMENT statement which supports attaching detaching adding modifying and dropping as well as initializing the distribution strategy

IBM Software Group IBM Information Management

Version 16 25

For example the following SQL removes a partition fragment and places the contents into a new table

ALTER FRAGMENT ON TABLE dept DETACH PARTITION part3 dept_part3

Making use of ALTER FRAGMENT to detach fragments can be an effective way of deleting large quantities of rows from a table quickly and easily After the above statement completes the table will no longer contain rows with a deptno greater than 21 and less than 31 Refer to the Informix Guide to SQL Syntax for a complete description on how to use the ALTER FRAGMENT statement to change the distribution strategy or the storage location of an existing table or index

Data types

Numeric

Oraclersquos NUMBER data type needs to be replaced with one of the following Informix equivalent data types depending on the size of the column The Informix numeric data types are listed below

SMALLINT (-32767 to 32767)

INTEGER (-2147483647 to 2147483647)

BIGINT (-9223372036854775807 to 9223372036854775807)

INT8 (-9223372036854775807 to 9223372036854775807)

The BIGINT type is more efficient in terms of space and speed there are few reasons to use INT8 now that BIGINT is available

DECIMAL (floating point up to 32 significant digits -10-130

to 10124

)

In an ANSI database there is an implied scale of 0 when no scale is given so this is not strictly speaking a floating point type within an ANSI database

NUMERIC (floating point up to 32 significant digits -10-130

to 10124

)

FLOAT (double precision like double data type of C)

SMALLFLOAT (single precision like float data type of C)

REAL (same as SMALLFLOAT)

DOUBLE (same as FLOAT)

LONG (same as long data type of C)

Oraclersquos NUMBER data type is used to store zero positive and negative fixed size and floating point numbers with magnitudes between 10 x 10

-130 and 999 x 10

125 (38 9s followed by 88 0s)

with 38 digits of precision A fixed-point number is specified by NUMBER(p s) where p is the precision or the total number of digits and s is the scale or the number of digits to the right of the decimal point For example a column defined as NUMBER(104) would contain numbers in the format 9999999999 In Oracle the scale can range from -84 to 127 If the scale is 0 or not mentioned then the data type can be converted into Informixrsquos SMALLINT INTEGER or BIGINT depending on the precision or FLOAT SMALLFLOAT DOUBLE or REAL depending on usage in the application When the scale is positive the data type should be converted to Informixrsquos DECIMAL or NUMERIC A floating-point data type in Oracle is declared using the type NUMBER without mentioning scale and precision In Informix this can be replaced with FLOAT SMALLFLOAT REAL DOUBLE PRECISION or DECIMAL(p) in an non-ANSI database

IBM Software Group IBM Information Management

Version 16 26

Oracle allows a negative scale If the scale is negative the actual data is rounded to the specified number of places to the left of the decimal point For example a specification of NUMBER (10 -2) means to round to the hundred If the general form for any number is

mantissa X 10exponent

then precision is the number of digits in the mantissa and scale is the negative exponent Example

select cast( 987654321 AS NUMBER(10-2) ) from dual

returns

987654300

Informix does not support a negative scale If precision - scale is less than the maximum precision of an integer type then that is the most efficient type to use Failing that and if the database is non-ANSI a floating point DECIMAL can be used If that is not sufficient then it may be necessary to define a user type and associated functions Oracle also allows the scale to be greater than the precision Precision is just the number of digits that will be preserved A NUMBER(3 5) might have the value 000123 If the Oracle scale is less than the Informix maximum precision then the Oracle scale can be used for both the Informix precision and scale A NUMERIC(55) column could also store the value 000123 You may need to take into consideration not only the minimum and maximum values but the default size for data types For example when the size of the NUMBER data type is absent Oracle will default to NUMBER(38) while Informix defaults to NUMERIC(16) Oracle and Informix support the ANSI DECIMAL data type Therefore in the case of an ANSI data type the Oracle data type can be converted to the same Informix data type There are differences between conversions based on theory versus those based on practice For instance it is very common to see an undecorated NUMBER declaration where the customer database and applications are using integer data When converting NUMBER declarations it may be necessary to consider how the data is being used in order to determine the best type mapping

CHAR VARCHAR and LVARCHAR

In Oracle the default for a CHAR column is one character and the maximum allowed is 255 characters In Informix the maximum length of CHAR and LVARCHAR columns is 32767 Therefore Oraclersquos CHAR columns can always be converted to an Informix CHAR column The CHAR data type columns can only contain printable characters tabs and spaces The CHAR columns store leading and trailing spaces In Oracle a zero-length string can be inserted into a CHAR column but the column is padded with one blank character when it is used in comparisons Also in Informix a zero-length string can be inserted into a CHAR column however the column is padded with enough spaces to fill the column In the case of inserting NULL into an Informix CHAR column no padding occurs Oraclersquos VARCHAR and VARCHAR2 are currently synonymous and have a maximum data length of 4000 bytes while the maximum length for the Informix VARCHAR data type is 255 Informixrsquos CHAR and LVARCHAR data types have a maximum length of 32767 and 32739 respectively measured in bytes These should be used to replace Oraclersquos VARCHAR VARCHAR2 LONG and LONG VARCHAR if the data length is between 256 and the maximum If the data length exceeds the maximum use Informixrsquos TEXT BYTE BLOB or CLOB data types See the Raw Data section below for more information on TEXT BYTE BLOB and CLOB data types

IBM Software Group IBM Information Management

Version 16 27

Empty Oracle VARCHAR2 strings are considered NULL Empty Informix VARCHAR and LVARCHAR strings are not considered NULL rather they contain at least one space Oracle

compares VARCHAR2 values using non-padded comparison semantics Therefore ldquoBOBrdquo ldquoBOB ldquo Informix ignores trailing blanks Therefore ldquoBOBrdquo = ldquoBOB ldquo or ldquordquo = ldquo rdquo Hence checks for NULL within the application must be replaced with checks for an empty string (such as ldquordquo or ldquo rdquo) whenever an empty string is inserted into the column If NULL is truly inserted into the column checking for NULL is appropriate (for example SELECT FROM hellip WHERE hellip IS NULL) In Oracle LONG columns store variable length character strings containing up to 2 gigabytes or 2

31-1 bytes Informix LONG columns store numeric data Oraclersquos LONG columns have many of

the characteristics of VARCHAR2 columns They can be used in a SELECT list in the SET clause of an UPDATE statement and in an INSERT statement but they cannot be used in a WHERE clause a GROUP BY clause or an ORDER BY clause and they cannot be indexed Oraclersquos LONG columns should be converted to an Informix Smart Large Object or ldquoSLOBrdquo (BLOB CLOB) column

Date and Time

Oraclersquos DATE data type contains date and time components from year down to second It can be to be replaced most directly with Informixrsquos DATETIME YEAR TO SECOND Some analysis may be necessary to determine whether the time is really necessary In other words does the application reference the date and time portions of the values If the application only references the date portion then replace Oraclersquos DATE with Informixrsquos DATE and change the host variable to X(10) or char(10) accordingly The Informix DATE default display format is MM-DD-YYYY although the DATE data type stores the calendar date The Informix DATE data type requires 4 bytes which is stored internally as an integer value equal to the number of days since December 31 1899 The default display format can be changed with the environment variable DBDATE If the application uses different date formats then using DBDATE is not a solution Sometimes it might be necessary to write small subroutines to emulate Oraclersquos DATE representations See the Informix Guide to SQL Reference manual for details on DBDATE and also DBCENTURY If the application only references the time portion of the values replace Oraclersquos DATE with Informixrsquos DATETIME using the EXTEND function to specify precision In addition Informix provides the data type INTERVAL for use while performing DATE and DATETIME calculations In Oracle the DATE data type is used to store date and time information Although date and time information can be represented in both CHAR and NUMBER data types the DATE data type has special associated properties For each DATE value the following information is stored

century

year

month

day

hour

minute

second

Also regarding the Oracle DATE data type if a date value without a time component is specified the default time is 120000am If a DATE value without a date is specified the default date is the first day of the current month

Interval

Within Informix there are two classes of interval types YEAR-MONTH and DAY-FRACTION There are different numbers if days in different months so the MONTH-DAY boundary cannot be crossed without creating ill-defined results Within each of these classes Informix allows you to declare columns or variables as any subset of the start and end fields Oracle has one INTERVAL

IBM Software Group IBM Information Management

Version 16 28

type for each of the two classes YEAR(p) TO MONTH and DAY(p) TO SECOND(s) The Oracle scale on the SECOND field is logically equivalent to the Informix scale on the FRACTION field

Raw data and Large Objects

Oraclersquos support of large blocks of raw unstructured data (such as graphic images video clips and sound waveforms) in binary or character format is provided by the large object (LOB) data types BLOB CLOB NCLOB and BFILE Traditional Oracle data types MLSLABEL (used with Trusted Oracle) RAW and LONG RAW are also used for data that is not to be interpreted by the engine and converted when moving data between different systems Informix supports two types of large objects (LOBs Simple Large Objects and Smart Large Objects Simple LOBs consist of the TEXT and BYTE data types and can be 2

31 bytes or 2

Gigabytes in size Smart LOBs include both Character Large Object (CLOB) and Binary Large Object (BLOB) data types and may be up to 42

40 bytes or 4 Terabytes in size Simple LOBs can

be stored either in-line with table data or in blobspaces while Smart LOBrsquos are stored in sbspaces Oraclersquos CLOB BLOB MLSLABEL RAW and LONG RAW data types should be replaced with Informixrsquos BYTE TEXT CLOB or BLOB depending on the columnrsquos size and usage Informixrsquos Smart BLOB data types CLOB and BLOB should be used under the following conditions and considerations

The large object needs to be referenced by multiple sources

The object size exceeds 2 GB

Fragmentation is required

Byte level locking is available making it possible to lock only a portion of the object

Logging can be specified at the object level

Updates are done in place or moved as needed

Be aware of the following restrictions for Simple Large Objects

Data can only be inserted into a BYTE or TEXT column with the dbload or onload utilities the DBACCESS load statement BYTE or TEXT host variables respectively in ESQLC or declaring a file in ESQLCOBOL

BYTE and TEXT columns cannot be inserted or updated with a literal neither quoted text string nor number

BYTE or TEXT columns cannot be used in string operations with aggregate functions with the GROUP BY ORDER BY IN LIKE or MATCHES clauses

ROWID

The implementation of ROWID differs between Oracle and Informix Oraclersquos ROWID is both a pseudo-column and a data type See the ROWID subsection in the Pseudo-Columns section in CHAPTER 3 Data Manipulation Language for more information Informix implements ROWID as a pseudo-column only Oracle stores the ROWID column and ROWID data type column values in hexadecimal format Informix stores the ROWID column values in INTEGER format The Oracle and Informix engines maintain the values of the ROWID pseudo-column Oraclersquos engine does not maintain the values of other columns of type ROWID In Informix the term rowid refers to an integer that defines the physical location of a row Informix assigns rows in a non-fragmented table a unique rowid which allows applications access to a particular row in a table Rows in fragmented tables in contrast are not assigned a rowid To access data by rowid in a fragmented table a rowid column must be explicitly created as is described in the Informix Guide to SQL Reference manual Creating a Rowid Column If applications attempt to reference a rowid in a fragmented table that does not contain a rowid that was explicitly created Informix displays an appropriate error message and execution of the application is halted

IBM Software Group IBM Information Management

Version 16 29

When used as a data type for a column Oracle does not guarantee that the values are valid ROWIDs For example if the ROWID is used as a data type on a column such as a column in a child table named parent_rowid containing the ROWID of the parent then the values are maintained by the application outside of the engine The application must read the ROWID of the parent and insert it into the parentrsquos corresponding child table rows This is usually done so the two tables can be joined on the parentrsquos ROWID and the childrsquos parent_rowid column This functionality can be duplicated in Informix by using primary and foreign keys Informix recommends that primary keys are used as a method of access in applications rather than rowids because primary keys are defined in the ANSI specification of SQL using them to access data makes applications more portable Refer to the Informix Guide to SQL Reference and the Informix Guide to SQL Syntax for a complete description on how to define and use primary keys to access data

User-defined types

Both Oracle and Informix allow the user to create and define data types Oracle refers to these as abstract data types while Informix refers to these as user-defined types In Oracle all user-defined types are referred to as abstract data types while Informix may refer to user-defined types as COLLECTION types ROW types DISTINCT types and OPAQUE types Currently the Informix ROW type is closest in form and function to the Oracle abstract data type An example of syntax for creating both an Oracle abstract data type and an Informix ROW type is shown below

Oracle abstract data type

CREATE TYPE name_type AS OBJECT

(first_name VARCHAR2(25)

middle_initial CHAR(1)

last_name VARCHAR2(30))

Informix row type

CREATE ROW TYPE name_type

(first_name VARCHAR(25)

middle_initial CHAR(1)

last_name VARCHAR(30))

Both Oracle and Informix support the use of user-defined types for table definition or column definition within a table Building on the example above the following create table example show a table definition and column definition within a table based on user-defined types Oracle table creation

CREATE TABLE name OF name_type

Informix table creation

CREATE TABLE name OF type name_type

Oracle column definition

CREATE TABLE employee

(empno NUMBER(9)

name name_type)

Informix column definition

CREATE TABLE employee

IBM Software Group IBM Information Management

Version 16 30

(empno INTEGER

name name_type)

For more information on User Defined Types see the Informix Guide to SQL Syntax

Complex data types

Informix offers users the ability to create data types from existing built-in types OPAQUE types DISTINCT types and other complex types Complex data types may either be a ROW type or a COLLECTION type Oracle treats complex data types as abstract data types For more information on Oracle abstract data types see the User Defined Types section above For more information on Complex Data Types see the Informix Guide to SQL Syntax For recommended type mappings and additional information see the appendix ldquoData type mappingsrdquo

Sequence objects

Oracle sequences

An Oracle sequence is a database object from which multiple users or transactions may generate unique integers For example sequences can be used to automatically generate primary key values When a sequence object is queried the sequence number is incremented and passed to the query independent of the transaction committing or rolling back If two applications increment the same sequence the sequence numbers each application acquires may not be sequential since sequence numbers are being generated by the other application One user or transaction can never acquire the sequence number generated by another user or transaction Once a user or transaction generates a sequence value that value will never be generated and passed to another user or transaction

Informix sequences

Informix rsquos implementation of sequence objects is identical to that of Oracle Issues regarding syntax compatibility should be negligible with the exception of some keywords which have no effect on the behavior of the sequence Informix supports DML statements (CREATE SEQUENCE ALTER SEQUENCE RENAME SEQUENCE DROP SEQUENCE) for sequence objects that multiple users can access concurrently to generate unique integers in the 8-byte integer range GRANT and REVOKE statements support access privileges on sequence objects and the CREATE SYNONYM and DROP SYNONYM statements can be used to reference synonyms for sequence objects in the local database The operators CURRVAL and NEXTVAL can read or increment the value of an existing synonym with behavior the same as Oracle

Indexes

Composite indexes

A composite index can have up to 16 key parts that are columns or up to 341 key parts that are values returned by a UDR This limit is language-dependent and applies to UDRs written in SPL or Javatrade functional indexes based on C language UDRs can have up to 102 key parts A composite index can have any of the following items as an index key

One or more columns

IBM Software Group IBM Information Management

Version 16 31

One or move values that is returned by a user-defined function (referred to as a functional index)

A combination of columns and user-defined functions

Maximum key size

The total widths of all indexed columns in a single CREATE INDEX statement have a limitation based upon the page size of the dbspace in which the index resides This limitation does not apply to functional indexes An enhancement introduced with Informix Dynamic Server Version 1110 is configurable page sizes for dbspaces Prior to this release the page size of dbspaces were restricted to that of the operating system and could not be changed thus Informix was limited to 390 byte indexes With page sizes configurable from 2K through 16K wider indexes are supported Refer to the table below 16K page sizes raises the limit on index width to over 3000 bytes Lifting the 390 byte limit also permits LVARCHAR columns larger than 387 bytes to be included in an index definition

Page Size Maximum Key Size

2 kilobytes 387 bytes

4 kilobytes 796 bytes

8 kilobytes 1615 bytes

12 kilobytes 2435 bytes

16 kilobytes 3245 bytes

In addition to aiding the porting process wider indexes have satisfied requirements for Unicode data as well as provide performance gains by reducing B-Tree index traversal costs since indexing can be built with more items on an index page and produce fewer levels

Index fragmentation

Just as Oracle and Informix support table fragmentation or partitioning in Oracle both support index fragmentation as well See the Table fragmentation section above for more information regarding Informix table fragmentation and Oracle table partitioning Oracle indexes that are partitioned in the same manner as the table they are indexing are referred to as local indexes Informix refers to these as attached indexes Oracle indexes that span partitions are known as global indexes Informix refers to these as detached indexes Informix detached indexes may also refer to indexes that do not follow the same fragmentation scheme as the table they are indexing Starting with Informix version 1110 indexes can be fragmented similarly to tables on a partition level

General index information

The Informix CLUSTER option should be used when appropriate This option orders the data within the table in the order the index requires It is important to note that the CLUSTER index is not maintained over time The primary factor determining the frequency of CLUSTER index rebuilds is the amount of DML performed against the table Frequent INSERTS UPDATES and DELETES make it necessary to closely monitor CLUSTER indexes There is only one clustered index per table since a tablersquos data can only be stored in one order Oraclersquos INITRANS and PCTFREE functionality is similar to the Informix index FILLFACTOR option of the CREATE INDEX statement or the FILLFACTOR configuration parameter in the ONCONFIG file In either case the functionality is handled by Informixrsquos engine once it is set and can be removed from the application FILLFACTOR specifies the degree of index-page

IBM Software Group IBM Information Management

Version 16 32

compactness A low value provides room for growth in the index A high value compacts the index If an index is fully compacted (100 percent) any new inserts result in splitting nodes The setting on the CREATE INDEX statement overrides the ONCONFIG file value The FILLFACTOR default value for both the CREATE INDEX statement as well as the ONCONFIG is 90 Informix has no support for bitmap indexes

Views Oraclersquos CREATE VIEW statement contains three options FORCE NO FORCE and WITH READ ONLY FORCE creates the view regardless of whether the views base tables exist or the owner of the schema containing the view has privileges on them NO FORCE creates the view only if the base tables exist and the owner of the schema containing the view has privileges on them WITH READ ONLY specifies that no deletes inserts or updates can be performed through the view These options must be removed from the Informix CREATE VIEW statements Because a view is not really a table it cannot be indexed and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE The columns of a view cannot be renamed with RENAME COLUMN To change anything about the definition of a view you must drop the view and re-create it Because it must be merged with the userrsquos query the SELECT statement on which a view is based cannot contain any of the following clauses

INTO TEMP The userrsquos query might contain INTO TEMP if the view also contains it the data would not know where to go

UNION The userrsquos query might contain UNION No meaning has been defined for nested

UNION clauses

ORDER BY The userrsquos query might contain ORDER BY If the view also contains it the choice of columns or sort directions could be in conflict

Stored procedures and triggers The ways stored procedures and triggers are created differ between Oracle and Informix Oracle allows a REPLACE clause in the CREATE statement to handle situations when the object already exists Informix does not support the REPLACE option Instead a DROP PROCEDURE or DROP TRIGGER statement must precede the CREATE PROCEDURE or CREATE TRIGGER statement respectively to handle the situation when the object already exists It should be noted a DROP statement will generate an error when the object does not exist If it is run interactively within the DBACCESS user interface the DROP statement error will terminate processing If it is run using script execution using DBACCESS at the command line processing will continue To run DBACCESS from the command line type

dbaccess db_name

To run the file containing the create statements from the command line type dbaccess db_name sql_file_name

Informix introduced an IF EXISTS clause to most of the CREATE and DROP statements at 117 but the logic is different from Oraclersquos OR REPLACE clause For example these statements

IBM Software Group IBM Information Management

Version 16 33

DROP PROCEDURE IF EXISTS hellip

CREATE PROCEDURE hellip

are logically the same as this Oracle statement

CREATE OR REPLACE PROCEDURE hellip

So it is possible to achieve the same result but not necessarily the same number of statements

Oracle extensions The Oracle CLUSTER option in CREATE statements should be removed These are not to be confused with Informix CLUSTER index statements (See Indexes section above) An Oracle cluster is a database schema object that contains one or more tables that all have one or more columns in common Rows of one or more tables that share the same value in these common columns are physically stored together within the database Removing this Oracle feature will not affect the application Other non-Informix DDL statements like CREATE DATAFILE CREATE CONTROLFILE CREATE ROLLBACK SEGMENT CREATE SNAPSHOT CREATE DATABASE and CREATE DATABASE LINK must be removed or changed (in the case of the CREATE DATABASE statement) The Oracle CREATE PROFILE statement must be removed An Oracle profile is a set of limits on database resources Profiles can be used to limit the database resources available to a user for a single SQL statement or a single session

IBM Software Group IBM Information Management

Version 16 34

C H A P T E R 4 Data Manipulation Language

SQL

Labels using keywords

Oracle displays labels in SQL statements that are Informix reserved words such as UNITS YEAR MONTH DAY HOUR and so on must be converted by using the Informix AS clause between the column name and the display label Otherwise syntactic ambiguities will cause errors

Inequality operations

In addition to the Informix supported ldquonot equal tordquo symbols ldquoltgtrdquo and ldquo=rdquo Oracle supports the symbol ldquo^=rdquo All occurrences of ^= must be replaced with one of the Informix supported symbols

Selects

Queries are executed based on how the optimizer determines the best path to the data Oracle and Informix developed their own query optimizers with their proprietary methods and rules A query that looks exactly the same in both environments may run differently in each following a different path and executing faster or slower Therefore every query in the ported application should be tested for performance regardless of whether a query had to be converted Furthermore Oracle supports optimizer hints within a SELECT statement Prior to IDS 73 and Informix Dynamic Server 92 Informix did not allow optimizer hints See the Optimizer Directives subsection below for more information on porting Oraclersquos optimizer hints to Informixrsquos optimizer directives

Optimizer directives

Informix offers optimizer directives similar to Oraclersquos optimizer hints This feature provides the query developer the flexibility to direct the optimizer to follow specific paths rather than choosing a plan through its analysis A query is processed in two steps First it is optimized and compiled to product a query plan Secondly it is executed to produce a result Optimizer directives are a method for influencing the choice of the optimizer in the creation of the plan

IBM Software Group IBM Information Management

Version 16 35

Optimizer directives address the following key issues

Reduced time for correcting performance problems Rewriting queries can be very time consuming and this allows you to have a quick way to alter a plan

Competitive pressure Users accustomed to this function were looking for it in Informix

Product development tuning This allows product development to alter plans dynamically rather than through code changes to evaluate the effect of different optimization techniques

The syntax and behavior of Informixrsquos implementation is compatible with Oraclersquos optimizer hints which eases the porting of applications from Oracle to Informix Directives are written as a comment whose first character is a lsquo+rsquo (plus sign) An example is

select + ORDERED AVOID_FULL(e) empname deptno

from employee e department d

where edept_no = ddept_no

This above example specifies that the tables should be joined in the order specified in the query and that the employee table (e) should NOT be accessed with a full table scan The Informix implementation differentiates itself significantly from Oraclersquos in one way Informix supports the notion of negative directives whereas Oracle only supports direct hints A directive that tells the optimizer what to avoid rather than what to choose is unique to Informix The query result can be realized by writing a directive to avoid certain actions known to cause performance issues but allow any new indexes or table attributes to be explored by the optimizer as they are added over the life of the table and query This allows a DBA to continue to add indexes to tables and not have to rewrite directives Additionally Informix supports full recognition of directives with SET EXPLAIN output Informix will highlight semantic and syntactic errors which Oracle does not Optimizer directives support control in the following areas of the optimization process

Access methods Index versus scans

Join Methods Forcing hash joins nested loop joins

Join Order Specify which order the tables are joined

Goal Specify first rows or all rows (response time versus throughput) See the Informix Guide to SQL Syntax or Reference for more information

External optimizer directives

External optimizer directives give the DBA the ability to specify query directives and save them in the database These directives are applied automatically to subsequent instances of the same query The SAVE EXTERNAL DIRECTIVES statement associates one or more optimizer directives with a query and stores a record of this association in the sysdirectives system catalog table for subsequent use with queries that match the specified query string The query string must be an exact match that includes case and white space positioning This statement establishes an association between the list of optimizer directives and the text of a query but it does not execute the specified query Only the DBA or user informix can execute SAVE EXTERNAL DIRECTIVES This associates AVOID_INDEX and FULL directives with the specified query

SAVE EXTERNAL DIRECTIVES

+ AVOID_INDEX (table1 index1) + FULL(table1)

ACTIVE FOR

SELECT col1 col2 FROM table1 table2

IBM Software Group IBM Information Management

Version 16 36

WHERE table1col1 = table2col1

These directives are applied automatically to subsequent instances of the same query You must include one of the ACTIVE INACTIVE or TEST ONLY keyword options to enable disable or restrict the scope of external directives When external directives are enabled and the sysdirectives system catalog table is not empty the database server compares every query with the query text of every ACTIVE external directive and for queries executed by the DBA or user informix with every TEST ONLY external directive External directives are ignored if the EXT_DIRECTIVES parameter is set to 0 in the ONCONFIG file In addition the client system can disable this feature for its current session by setting the IFX_EXTDIRECTIVES environment variable to 0 If an external directive has been applied to a query output from the SET EXPLAIN statement indicates ldquoEXTERNAL DIRECTIVES IN EFFECTrdquo for that query Any inline directive is ignored by the optimizer when the external directives are applied to a query that matches the SELECT statement Like inline optimizer directives that are embedded within a query external directives can improve performance in some queries for which the default behavior of the query optimizer is not satisfactory Unlike inline directives external directives can be applied without revising or recompiling existing applications

Inserts

Informix does not support Oraclersquos INSERT with SELECT statement utilizing an UNION clause (although a view with an UNION clause can be referenced resulting in an UNION operation) Additionally Informix does not support an INSERT statement with a VALUE clause with SELECT statements The SELECT statement within a VALUE clause can be rewritten by omitting the VALUE clause and performing an INSERT INTO table_name SELECT hellip FROM other_table_name

Temporary tables

Informix and Oracle implemented the concept of temporary tables differently Oracle implements temporary tables as a work area during batch data loads Informix implements temporary tables just like regular database tables These temporary tables can be created manipulated and dropped only within a session such as stored procedures and ESQL programs Once the session ends any remaining temporary tables are automatically dropped Temporary tables can give an application extra functionality however their use should be limited if reducing database extensions to increase database independence within an application is a priority

Outer joins

Both Oracle (starting with Oracle 9i) and Informix support ANSI standard syntax for outer join specification The syntax for left and right outer join using the plus sign (+) in the WHERE clause is only supported for backward compatibility however it is still in existence The use of ANSI outer join syntax is recommended The Oracle outer join syntax + (placed after the column which has values not matching the corresponding column in the joined table) can be replaced with the Informix equivalent OUTER The OUTER keyword is placed within the SELECT statement before the name of the subservient table Unlike Oracle in Informix multiple outer joins per SELECT statement are allowed grouped with parentheses

Sorts

In Oracle sorts NULL values are considered the highest value and are therefore ordered last in ascending sorts Informix sorts with NULLS as the lowest value ordering them first in ascending sorts First it must be determined whether this sorting difference will affect the outcome enough to warrant a work around In most cases it will not If it does then a stored procedure can be

IBM Software Group IBM Information Management

Version 16 37

written to evaluate whether a column is NULL and if so replace it with a high value so that it will sort last Once the application receives the results it must replace the high values with NULL if the column is going to be displayed or manipulated

Exceptions

Error handling using hard coded Oracle SQL codes must be replaced with the corresponding Informix SQL codes

Correlation names

Informix does not support correlation names with aliases on the main table of an UPDATE or DELETE statement Such cases must be converted For example

Oracle UPDATE customer C

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE Ccreate_date lt= Zeffective_date)

Informix UPDATE customer

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE customercreate_date lt= Zeffective_date)

-and-

Oracle DELETE customer C

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND Cstate = Tstate )

Informix DELETE customer

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND customerstate = Tstate )

Note that Informix allows correlation names with aliases on tables other than the updated or deleted table

Aliases

Unlike Oracle in Informix if an alias is used in the FROM clause of a SELECT statement it must also be used in the SELECT list and WHERE clauses The original table name should be replaced with the alias wherever aliases and original names are used together within a SELECT statement in an Oracle application

Hierarchical queries

Informix does not allow query results to be organized hierarchically in a B-tree fashion Oracle does allow it by using the clauses START WITHhellip and CONNECT BY PRIOR in the SQL

IBM Software Group IBM Information Management

Version 16 38

statement In Oracle if a table contains hierarchical data a bill of materials for example rows can be selected in a hierarchical order using the following clauses START WITH

The START WITH clause identifies the row(s) to be used as the root(s) of a hierarchical query This clause specifies a condition that the root(s) must satisfy If this clause is omitted Oracle uses all rows in the table as root rows A START WITH condition can contain a subquery

CONNECT BY

The CONNECT BY clause specifies the relationship between parent and child rows in a hierarchical query This clause contains a condition that defines this relationship The part of the condition containing the PRIOR operator must have one of the following forms

PRIOR expression comparison_operator expression -or- expression comparison_operator PRIOR expression

To find the children of a parent row Oracle first evaluates the PRIOR expression to identify the parent row(s) and the other expression for each row in the table Rows for which the other expression is true are the children of the parent The CONNECT BY clause can contain other conditions to further filter the rows selected by the query

WHERE

The WHERE clause can restrict the rows returned by the query without affecting other rows of the hierarchy

Oracle uses the information from each of the clauses mentioned above to form the hierarchy using the following steps

1 Oracle selects the root row(s) of the hierarchy These are the rows that satisfy the condition of the START WITH clause

2 Oracle selects the child rows of each root row Each child row must satisfy the condition of the CONNECT BY clause with respect to one of the root rows

3 Oracle selects successive generations of child rows Oracle first selects the children of the rows returned in step 2 and then the children of those children and so on Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row

4 If the query contains a WHERE clause Oracle removes all rows from the hierarchy that do not satisfy the condition of the WHERE clause Oracle evaluates the WHERE condition for each row individually after the row has been fetched rather than only fetching rows that satisfy the WHERE condition

5 Oracle returns the rows in the order of an in-order or left-root-right binary tree traversal

IBM Software Group IBM Information Management

Version 16 39

For example the following SQL statement returns the data in the adjacent table in hierarchical order The root row is defined to be the employee whose job is lsquoPRESIDENTrsquo The child rows of a parent row are defined to be those rows whose manager number is the employee number of the parent row

SELECT ename empno mgr job FROM emp START WITH job = lsquoPRESIDENTrsquo CONNECT BY PRIOR empno = mgr

To duplicate this hierarchical functionality in Informix stored procedures or functions can be written requiring intensive use of cursors and program arrays Informix offers the choice of creating and using a User Defined Routine or ldquoUDRrdquo See User Defined Routines section below Use of Informix global arrays will help considerably To maximize read processing at the expense of insert processing another method is to break the table into two tables one containing the data and the other containing the relationship (foreign keys) between each parent and child A parent row would have an entry in the relationship table for each of its children grandchildren great grandchildren and so on The opposite is true where a child row would have an entry in the relationship table for its parent grandparent great grandparent and so on

Truncate

Informix supports the TRUNCATE statement for deleting all active data rows from a table and associated indexes When using Informixrsquos TRUNCATE you also have the option of releasing the storage space that was occupied by the rows and index extents or keeping the space allocated to be used as the table is repopulated with new data

TRUNCATE [TABLE] table [ [ DROP | REUSE ] STORAGE ]

You may use the commandrsquos simplest usage

TRUNCATE my_table

In the example above the TRUNCATE statement drops all the data for the table and keeps only the initial extents There is a minor difference from Oracle syntax as Informix does not require the keyword TABLE Another example

TRUNCATE my_table REUSE STORAGE

ENAME EMPNO MGR JOB

KING 7839 PRESIDENT

JONES 7566 7839 MANAGER

SCOTT 7788 7566 ANALYST

ADAMS 7876 7788 CLERK

FORD 7902 7566 ANALYST

SMITH 7369 7902 CLERK

BLAKE 7698 7839 MANAGER

ALLEN 7499 7698 SALESMAN

WARD 7521 7698 SALESMAN

MARTIN 7654 7698 SALESMAN

TURNER 7844 7698 SALESMAN

JAMES 7900 7698 CLERK

CLARK 7782 7839 MANAGER

MILLER 7934 7782 CLERK

IBM Software Group IBM Information Management

Version 16 40

This example drops all the data for the table but retains all the space allocated The permissions needed for TRUNCATE TABLE depend on the existence of DELETE triggers on the table For tables with DELETE triggers ALTER permission on the table is required and RESOURCE or DBA privileges because the DELETE triggers will be bypassed For tables without DELETE triggers you need DELETE permission on the table and CONNECT privilege to the database While Oracle does not provide rollback Informix does permit TRUNCATE TABLE to execute within a transaction When you rollback a TRUNCATE statement no rows are removed from the table and the storage extents that hold the data rows and index pages continue to be allocated to the table In a database that supports transaction logging only the COMMIT WORK or ROLLBACK WORK statement is valid after the TRUNCATE statement within a transaction Any other statement will generate an error The TRUNCATE statement does not reset the serial value of SERIAL or SERIAL8 columns To reset the counter of a serial column you must do so explicitly by using the MODIFY clause of the ALTER TABLE statement either before or after you execute the TRUNCATE statement After the TRUNCATE statement successfully executes Informix automatically updates the statistics and distributions for the table and for its indexes in the system catalog to show no rows in the table nor in its dbspace partitions It is not necessary to run the UPDATE STATISTICS statement immediately after you commit the TRUNCATE statement

Host variables Host variable formats should not change during the porting process Instead data types should be converted in a manner to preserve the column and host variablersquos formats However there are times when the database schema changes in a way where the host variable format must change Any column converted to a different format in Informix than that of Oracle requires that its corresponding host variable format be changed to be consistent Alternatively if an Oracle format such as date and numeric variables is not directly supported in Informix then the conversion may require some format processing before or after the SQL statement For example the Oracle function TO_CHAR is used to format both date and numerical values A similar function or at least two functions one to handle date data types and another to handle numeric data types can be declared and used in the Informix application Informix provides two built-in functions TO_DATE which converts a character string to a DATETIME variable and TO_CHAR which converts a DATETIME variable to a character string When converting variables an optional formatting string is allowed which determines how the string is displayed (full day names partial day names full months month number and so on) There is also a function ifx_to_gl_datetime() which takes an Oracle date format and returns the corresponding Informix date format This function is supplied in genlib and is for use in ESQL programs to ease migration efforts from Oracle The syntax is as follows

TO_CHAR (source_date fmt) Returns a character string containing the date specified in source_date in the format specified by fmt if one is provided If fmt is missing the function will use the default date format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

TO_DATE (source_string fmt) Evaluates source_string as a date according to the

format fmt If fmt is missing the function will use the

IBM Software Group IBM Information Management

Version 16 41

default format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

These functions are mainly useful for simplifying migration from Oracle to Informix but are also useful for performing advanced searches on DATETIME data types and for better output presentation

Date and time functions Informix version now has built-in support for most of Oraclersquos date functions so it will not be necessary to modify or replace Oraclersquos SYSDATE or ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat)

SYSDATE

IDS 1110 will support the SYSDATE operator which returns a single value representing the current date and time from the operating system clock SYSDATE is identical to the Informixrsquos CURRENT operator except that the default precision of SYSDATE is YEAR TO FRACTION(5) while the default precision of CURRENT is YEAR TO FRACTION(3) On Windows platforms that do not support a seconds scale greater than FRACTION(3) SYSDATE is effectively a synonym for the CURRENT operator In addition to SYSDATE Informix version 1110 has support for Oraclersquos date functions ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat) Depending on the whether or not the Oracle date_format argument is supported by Informix TO_CHAR(date char_format) and TO_DATE(character_string date_format) may have to be converted to Informix date processing Date processing may be required because the Oracle application may format the date in many different ways unsupported by Informix The formats used in the Oracle functions TO_CHAR TO_NUMBER and TO_DATE are illustrated below These formats should be replaced with Informix formats wherever possible format processing functions or stored procedures written to duplicate the Oracle functionality Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

Number formats

Element Example Description 9 9999 Return value with the specified number of digits with a leading

space if positive Return value with the specified number of digits with a leading minus if negative Leading zeros are blank except for a zero value which returns a zero for the integer part of the fixed-point number

0 09999990 Return leading zeros Return trailing zeros $ $9999 Return value with a leading dollar sign B B9999 Return blanks for the integer part of a fixed-point number

when the integer part is zero (suppress leading zeros regardless of whether zeros are used in the format model ie B00999 )

MI 9999MI Return negative value with a trailing minus sign ldquo-ldquo Return positive value with a trailing blank

S S9999999 Return negative value with a leading minus sign ldquo-ldquo Return

IBM Software Group IBM Information Management

Version 16 42

Element Example Description S positive value with a leading plus sign ldquo+rdquo Return negative

value with a trailing minus sign ldquo-ldquo Return positive value with a trailing plus sign ldquo+rdquo

PR 9999PR Return negative value in ltangle bracketsgt Return positive value with a leading and trailing blank

D 99D99 Return a decimal point ldquordquo In the specified position G 9G999 Return a group separator in the specified position C C999 Return the ISO currency symbol in the specified position L L999 Return the local currency symbol in the specified position 9999 Return a comma in the specified position 9999 Return a decimal point ldquordquo In the specified position V 999V99 Return a value multiplied by 10

n (and if necessary round it

up) where n is the number of ldquo9rdquos after the ldquoVrdquo EEEE 99EEEE Return a value in scientific notation RNrn RN Return a value as Roman numerals in uppercase Return a

value as Roman numerals in lowercase Value can be an integer between 1 and 3999

FM FM909 Return a value with no leading or trailing blanks

Date formats

Element Meaning -rdquotextrdquo Punctuation and quoted text is reproduced in the result AD or AD AD indicator with or without periods AM or AM Meridian indicator with or without periods BC or BC BC indicator with or without periods CC or SCC Century ldquoSrdquo prefixes BC dates with ldquo-ldquo D Day of week (1-7) DAY Name of day padded with blanks to length of 9 characters DD Day of month (1-31) DDD Day of year (1-366) DY Abbreviated name of day IW Week of year (1-52 or 1-53) based on the ISO standard IYY or IY or I Last 3 2 or 1 digit(s) of ISO year IYYY 4-digit year based on the ISO standard HH or HH12 Hour of day (1-12) HH24 Hour of day (0-23) J Julian day the number of days since January 1 4712 BC Number

specified with lsquoJrsquo must be integers MI Minute (0-59) MM Month (01-12 JAN = 01) MONTH Name of month padded with blanks to length of 9 characters MON Abbreviated name of month RM Roman numeral month (I-XII JAN = I) Q Quarter of year (1 2 3 4 JAN-MAR = 1) RR Last 2 digits of year see below for years in other centuries WW Week of year (1-53) where week 1 starts on the first day of the year

and continues to the seventh day of the year W Week of month (1-5) where week 1 starts on the first day of the

month and ends on the seventh PM or PM Meridian indicator with and without periods SS Second (0-59) SSSSS Seconds past midnight (0-86399) YYYY Year with comma in the ldquordquo position YEAR or SYEAR Year spelled out ldquoSrdquo prefixes BC dates with ldquo-ldquo YYYY or SYYYY 4-digit year ldquoSrdquo prefixes BC dates with ldquo-ldquo

IBM Software Group IBM Information Management

Version 16 43

YYY or YY or Y Last 3 2 or 1 digit(s) of year

The RR date format element

The RR date format element is similar to the YY date format element but it provides additional flexibility for storing date values in other centuries The RR date format element allows storing the century even though only two digits are entered for the year The table below illustrates how the year is stored based on only two digits

If the year is entered as

0 ndash 49 50 - 99 If the last two digits of the

0 - 49 The return date is in the current century

The return date is in the century before the current one

current year are

50 - 99 The return date is in the century after the current one

The return date is in the current century

User-defined routines User-defined data types user defined behaviors and user defined access methods add rich functionality to Informix A user-defined routine (UDR) can be developed in C Java or Informix SPL language to vastly extend the capabilities of the database Porting applications to Informix gives the option to create UDRs for aggregate and mathematical functions or to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or you can rename an Informix function to the corresponding Oracle function name

Compatible SQL Functions Informix Dynamic Server version 1110 has added support for a number of built-in SQL functions to ease a migration effort These new functions which perform common operations and data manipulation provide compatibility with Oracle routines thus simplifying the migration of applications that have been developed for an Oracle database

Date and time functions ROUND TRUNC ADD_MONTHS LAST_DAY NEXT_DAY MONTHS_BETWEEN SYSDATE

Conversion functions ASCII TO_CHAR TO_NUMBER

String manipulation LTRIM RTRIM

Number manipulation ROUND TRUNC CEIL FLOOR POWER

Bit manipulation BITAND BITOR BITXOR BITNOT BITANDNOT

Others NULLIF FORMAT_UNITS These functions are documented with examples in the IBM Informix Guide to SQL Syntax

Aggregate functions Like Oracle the result returned by an Informix aggregate function is NULL if all of the column values are NULL with the exception of COUNT which returns 0 (zero) Like Oracle Informix aggregate functions cannot be used in a WHERE clause unless it is on a corresponding column originating from a parent query and the WHERE clause is within a sub-query that is within a HAVING clause or the aggregate function is contained within a sub-query Unlike Oracle in Informix the argument of an aggregate function cannot be another aggregate function Informix supports the SELECT COUNT (column_name) hellip statement where the number of rows containing non-null values in the specified column is returned

IBM Software Group IBM Information Management

Version 16 44

The Oracle aggregate functions STDDEV and VARIANCE are supported however the Informix standard deviation routine is named STDEV thus all references to Oraclersquos STDDEV must be changed to match Informixrsquos STDEV Informix does not support Oraclersquos greatest lower boundary (GLB ) or least upper boundary (LUB) Therefore UDRs must be written to provide equivalent functionality Informix allows users to define their own aggregate functions known as user-defined aggregates (UDA) This extension of existing aggregates can be used for new data types as well as the definition of new aggregates In Informix TEXT and BYTE columns cannot be used in aggregate functions such as COUNT AVG MAX MIN and SUM

Mathematical functions Informix does not support all of Oraclersquos mathematical functions such as SIGN COSH SINH and TANH Therefore functions or UDRs must be written in the Informix application to provide equivalent functionality In Informix the rounding factor within the ROUND function must be a value from -32 to 32 This limitation has seldom been encountered as a migration issue

String functions

LENGTH

Oraclersquos LENGTH function will return different values than Informix for strings stored in CHAR data types The numeric return value representing the string length returned by Oracle will include all trailing spaces Whereas Informixrsquos LENGTH function will ignore trailing blanks regardless of data type For example for the two CHAR strings ldquoBOBrdquo and ldquoBOB ldquo Oraclersquos LENGTH function will return different values for each string 3 and 5 respectively Whereas Informixrsquos LENGTH function will ignore trailing blanks and return the value 3 for both When the input string is NULL both database functions will return a NULL

LTRIM and RTRIM

The SQL Compatibility features of Informx has support for LTRIM and RTRIM and will return identical values to that of Oracle No modifications will be necessary to SQL statements utilizing these functions

Oracle Extensions

Informix does not support all of Oraclersquos string functions such as CHR INSTR SOUNDEX and TRANSLATE Therefore corresponding user-defined routines or UDRs (ie functions or stored procedures) must be written in the Informix application to provide equivalent functionality Please note that the VERITY and EXCALIBUR Datablades included with Informix will work with Oraclersquos string function SOUNDEX

Other Oracle Functions Informix does not support the following Oracle functions Therefore corresponding functions must be written in the Informix application to provide equivalent functionality Alternatives to some of the more common Oracle functions follow this list

CHARTOROWID CONVERT DUMP GREATEST GREATEST_LB

IBM Software Group IBM Information Management

Version 16 45

HEXTORAW LEAST LEAST_UB RAWTOHEX ROWIDTOCHAR TO_LABEL TO_MULTI_BYTE TO_SINGLE_BYTE UID USERENV(OSDBA LABEL LANGUAGE TERMINAL SESSIONID ENTRYID) VSIZE

Macros Oracle contains macros sometimes referred to as language constructs which can determine the status of an object Informix does not support Oraclersquos macros These macros must be removed from the code and the associated logic should be implemented with equivalent Informix logic where applicable

ISOPEN and NOT FOUND

The macro cursor_nameISOPEN returns a Boolean value to indicate whether the cursor is open and cursor_nameNOTFOUND indicates whether there are any more rows yet to be fetched from the cursor cursor_name These macros used in condition statements are followed by some logic to handle the true andor false conditions In the case of ISOPEN this macro and its associated logic can just be omitted since the FOREACH loop processing does not explicitly open a cursor and therefore the condition cannot be checked In the case of NOTFOUND this macro should be omitted and its associated logic converted to Informix logic within an Informix FOREACH loop

ROWTYPE

The Oracle macro prefixROWTYPE is used in the declarative section as a data type to declare variables similar to the structure construct of C or RECORD of INFORMIX The prefix can be either a table name or another structure name Structure names ultimately refer back to a table name This macro may be replaced with the Informix statement LIKE table_name The construct LIKE table_name cannot be used in SPL Instead the construct DEFINE column1 LIKE table_namecolumn1 DEFINE column2 LIKE table_namecolumn2 and so on should be used to declare variables corresponding to all the columns of the table Then operations on the whole or part of the structure should be replaced with operations on single SPL variables

TYPE

The Oracle macro prefixTYPE is used in the declarative section as a data type to declare single variables The prefix is either a table_namecolumn_name or a structure_namevariable_name A structure_namevariable_name ultimately refers back to a table_namecolumn_name This macro can be replaced with the Informix statement LIKE table_namecolumn_name

Pseudo-columns Pseudo-columns are columns that exist in tables but are not displayed from a SELECT FROM table_name query Informix pseudo-columns are generally reserved for the enginersquos use Eliminating the use of such columns increases an applicationrsquos portability and eliminates the need for future modifications if the engine is ever modified to process the column differently or not at all

IBM Software Group IBM Information Management

Version 16 46

LEVEL

In Oracle for each row returned by a hierarchical query the pseudo-column LEVEL returns 1 for a root node 2 for a child of a root 3 for a child whose parent is at level 2 and so on A root node is the highest node within an inverted tree and therefore has no parent A child node is any non-root node A parent node is any node that has children A leaf node is any node without children To define a hierarchical relationship in a query you must use the START WITH and CONNECT BY clauses Informix does not support the LEVEL clause See the Hierarchical Queries subsection in the SQL section in the ldquoData Manipulation Languagerdquo chapter for more information on how to process these queries

ROWID

Oraclersquos ROWID pseudo-column returns the rows address for each row in the database ROWID values contain the following information necessary to locate a row

Which data block in the data file

Which row in the data block (first row is 0)

Which data file (first file is 1)

Usually a ROWID value uniquely identifies a row in the database However rows in different tables that are stored together in the same cluster can have the same ROWID Values of the ROWID pseudo-column have the data type ROWID ROWID values have several important uses

They are the fastest way to access a single row

They can show you how a tables rows are stored

They are unique identifiers for rows in a table

A ROWID does not change during the lifetime of its row However you should not use ROWID as a tables primary key If a row is deleted and re-inserted its ROWID may change even when using the export and import utilities If a row is deleted Oracle may re-assign its ROWID to a new row inserted later Although you can use the ROWID pseudo-column in the SELECT and WHERE clauses of a query these pseudo-column values are not actually stored in the database The value of a ROWID pseudo-column cannot be inserted updated or deleted For example the following Oracle statement selects the address of all rows that contain data for employees in department 20

SELECT ROWID ename FROM emp WHERE deptno = 20

The equivalent pseudo-column in Informix is also known as ROWID and although the behavior is similar the data type is different from Oraclersquos See the ROWID subsection in the Data Types section in the chapter ldquoData definition languagerdquo for more information

ROWNUM

In Oracle for each row returned by a query the ROWNUM pseudo-column returns a number indicating the order in which Oracle selected the row from a table or set of joined rows The first row selected has a ROWNUM of 1 the second has 2 and so on ROWNUM can be used to limit the number of rows returned by a query as in this example to read 9 rows

SELECT

FROM emp

WHERE ROWNUM lt 10

ROWID ENAME 0000000F00000002 SMITH 0000000F00030002 JONES 0000000F00070002 SCOTT 0000000F000A0002 ADAMS 0000000F000C0002 FORD

IBM Software Group IBM Information Management

Version 16 47

You can also use ROWNUM to assign unique values to each row of a table as in this example

UPDATE tabx

SET col1 = ROWNUM

Oracle assigns a ROWNUM value to each row as it is retrieved before the rows are sorted by an ORDER BY clause Therefore the final order of the rows is in ORDER BY order not in ROWNUM order An ORDER BY clause does not affect the ROWNUM values except in the case where the ORDER BY clause causes Oracle to use an index In that case the ROWNUM values are set in the order the rows are retrieved using the index and hence in ORDER BY order This order is different than if the rows were retrieved without the index So in this case the ORDER BY can affect the ROWNUM values Conditions which test for ROWNUM values greater than zero are always false For example this query returns no rows

SELECT FROM employee WHERE ROWNUM gt 1

The first row fetched is assigned a ROWNUM of 1 thus making the condition false The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 making the condition false All rows subsequently fail to satisfy the condition so no rows are returned Although there is no ROWNUM equivalent in Informix there are solutions Beginning with IDS 73 and in Informix Dynamic Server 2000 Informix provides a feature which allows the user to limit the results of a query to the first N rows This was implemented for TPC-D compliance and to support ldquorankrdquo queries Rank queries can be assembled by using FIRST N with the ORDER BY clause Informix will return the top N rows according to some ordering criteria Therefore the following Oracle SELECT utilizing ROWNUM

SELECT FROM emp WHERE ROWNUM lt 10

can be ported to Informix as follows

SELECT FIRST 9 FROM emp

Informix does not support SELECT FIRST N in complex cases as the following

Sub-queries (SELECT within a SELECT)

View definitions (Cannot be used by a SELECT statement which references a view)

UNION queries The behavior of SELECT FIRST N depends on the presence of an ORDER BY clause If no order by clause is specified the first N rows returned may be in any order Examples are as follows

find 10 highest paid employees

SELECT FIRST 10 name salary

FROM emp

ORDER BY salary

find 10 highest salary values

SELECT FIRST 10 DISTINCT salary

FROM emp

ORDER BY salary

IBM Software Group IBM Information Management

Version 16 48

Informix supports column names of ldquofirstrdquo Thus without a positive integer following the word ldquofirstrdquo the token is parsed as a column name rather than a keyword The value of N may be between 1 and (2

31-1)

When ROWNUM is used in a WHERE clause the same results can be obtained through the use of the FIRST N and SKIP clauses but if ROWNUM is used in the select list the solution is a little more complicated Simply stated you can construct a query where the ROWNUM column in any row is the count of the rows that came before This involves creating a correlated subquery where the subquery contains a self-join This can be done for any table or set of tables which has a unique key defined on it Here is an example using the customer table of the stores7 database

select

counterrownum

basecustomer_num

basefname

baselname

from

-- There can be more than one table here and the result

-- set should thought of as a table (just not a base table)

-- The result table has to be joined to itself in the

-- subquery so if there are multiple tables in this FROM

-- clause the expansion can get messy You have to have a

-- set of columns that uniquely identify each row in the

-- result table and join across them ROWID would

-- likely work if the table is not fragmented but if it is

-- there is no guarantee the final results would be accurate

-- because ROWID is not guaranteed to be unique across

-- fragments

customer base

(select

count() as rownum

acustomer_num -- any unique key possibly multiple

-- columns

from

customer a

customer b

where

-- This is where the rownum is determined the relationship

-- here has to match the outer order-by where the rows

-- are sorted and has to create a unique sort order

--

-- Any columns to be ordered by go here

-- Also the unique key has to be used to keep rows

-- that do not have a unique sort order from being merged

(alname gt blname) -- example sorting by last name

or

(alname = blname and afname gt bfname)

-- sorting by fname where lname is equal

or

(alname = blname and afname = bfname

and acustomer_num gt= bcustomer_num)

-- sorting by unique key where all the

-- other sort columns are equal

-- The expansion above is logically the same as

-- alname || afname || to_char(acustomer_num) gt=

-- blname || bfname || to_char(bcustomer_num)

-- but it allows the server to utilize any indexes that

-- may exist

group by

-- unique key columns go here

IBM Software Group IBM Information Management

Version 16 49

acustomer_num

) counter

where

-- key columns in the base tables go here

basecustomer_num = countercustomer_num

-- if you want to limit on rownum it goes here

-- and rownum lt= 10

order by

counterrownum

If using ROWNUM as an assignment as in

UPDATE tabx

SET col1 = ROWNUM

The following Informix-ESQLC pseudo-code example would have to be used

int counter = 0

EXEC SQL declare c1 cursor for

SELECT col1 col2

INTO col1 col2

FROM table 1

WHERE col1 = XX

EXEC SQL open c1

while (SQLCODE == 0)

EXEC SQL fetch c1

counter++ Increment counter for each row

fetched

if (counter gt= 5)

break

logic

End if

End while

Update using cursors There are slight differences between the ways Informix and Oracle process cursors Unlike Oracle in Informix the WHERE CURRENT OF clause cannot be used to update tables in a SELECT statement joining multiple tables since the WHERE CURRENT OF clause requires a FOR UPDATE cursor and Informix does not support the FOR UPDATE clause in SELECT statements that join multiple tables Therefore in the multi-table join statements the Oracle options FOR UPDATE and WHERE CURRENT OF should be removed and the update of the rows should be done using a separate UPDATE statement in the same cursor loop

IBM Software Group IBM Information Management

Version 16 50

In Informix a commit or rollback statement closes all cursors open in a given transaction boundary See the Transaction Processing section in CHAPTER 5 Application Architecture for more information In situations where the intention is to commit or rollback without closing the cursor in other words where the commit or rollback is executed within a cursor fetch loop the cursor can be declared as a HOLD cursor This requires that a BEGIN WORK is issued before the cursor loop starts A HOLD cursor is not closed when a commit or rollback statement is issued In Informix the FOR UPDATE clause cannot be used when declaring a HOLD cursor Thus where an Oracle application updates a table from which it fetches data in the fetch loop or issues a commit work in the fetch loop it must be converted to Informix The cursor can be declared with HOLD and then an UPDATE statement can be issued without the WHERE CURRENT OF clause In order to uniquely identify the row to be updated in the table in other words in order to simulate the WHERE CURRENT OF clause the ROWID or unique primary key columns of the table(s) to be updated must also be fetched and the WHERE CURRENT OF clause can be replaced with WHERE ROWID = fetched rowid or WHERE unique primary key column(s) = fetched unique primary key column(s) A BEGIN WORK must follow immediately after a COMMIT WORK or ROLLBACK WORK in the fetch loops to simulate Oracle implied transaction boundaries These transaction control statements work for either Informix logged databases or Informix ANSI mode databases however ANSI mode database processing with these statements will set certain warning flags after executing the BEGIN WORK statement and continue processing without failure See the ANSI vs Non-ANSI subsection in the Databases section in the chapter ldquoData Manipulation Languagerdquo for more information

System tables References to Oracle system tables should be replaced with corresponding references to Informix system tables The information schema views provided by Informix can be used These views are created after the database is installed They are populated by data in the system catalog tables and are used for easier porting

Stored procedures Informix procedures and functions are considered to be user-defined routines (UDR) A UDR can be written in Informixrsquos Stored Procedure Language (SPL) or an external language such as C or Java A procedure is a routine written that does not return a value A function is a routine written that returns a single value a value with a complex data type or multiple values Informix SPL is an extension to Informix SQL and provides procedural flow control such as looping and branching A SPL routine is a generic term that includes both SPL procedures and SPL

functions You use SQL and SPL statements to write an SPL routine SPL statements can be used only inside the CREATE PROCEDURE CREATE PROCEDURE FROM CREATE FUNCTION and CREATE FUNCTION FROM statements SPL routines are parsed optimized and stored in the system catalog tables in executable format Like Oracle Informix stored procedures support input output and inputoutput parameters and can be used in SQL statements wherever expressions are allowed

Size limit

Informix stored procedures have a size limit of approximately 64K Oracle stored procedures greater than 64K in size can be broken into smaller Informix stored procedures communicating with each other as though they were one by passing and returning the necessary values

Parameter limit

IBM Software Group IBM Information Management

Version 16 51

Informix has a limit of 341 parameters for each stored procedure This limit also applies to UDRs written in the Java language UDRs written in the C language can have no more than 102 parameters You can define any number of SPL routine parameters but the total length of all parameters passed to an SPL routine must be less than 64 kilobytes No more than nine arguments to a UDR written in the Java language can be DECIMAL data types of SQL that the UDR declares as BigDecimal data types of the Java language Any C language UDR that returns an opaque data type must specify opaque_type in the var binary declaration of the C host variable

Packages

An Oracle package is a collection of functions procedures and variables that can be enabled and accessed as a unit There is no direct equivalent within Informix but there are ways of achieving similar capabilities Within Oracle a procedure within a package can be accessed through grammar such as package_nameprocedure_name If you create an owner or schema name within the Informix system the same as the package name then it will be easier to migrate calls to that procedure because the grammar is effectively the same although the meaning changes somewhat Using this practice a call to a migrated procedure would be ownerprocedure_name where the owner name is the same as the package name Translating package names as owner names is a way to maintain the scoping of the objects within the package Maintaining the aspect of being able to enable use of or upgrade the collection of package objects can be done by creating a datablade that contains all the objects that used to be part of the package Datablade routines can be procedures or functions written in Stored Procedure Language (SPL) C and Java In addition routines can be written in C++ on Windows platforms

Routines

Oraclersquos stored functions and stored procedures are similar in concept to Informixrsquos stored procedures Oraclersquos user defined database level functions such as stored functions stored procedures all need to be converted to Informix stored procedures using the Informix SPL C or Java Routines written in SPL have the advantage of being maintained and backed up with database backups Routines written in C are fast but are not automatically backed up when the database is and need to be compiled specifically for the operating system on which it will run Routines written in Java also not backed up by the DBMS itself but they are platform independent However probably as a result of having to convert between system memory where the objects have C structures and Java virtual machine memory where the objects have Java structures the performance of Java routines can be slow compared with the C equivalent All procedures written in an Oracle package body must be rewritten as separate Informix procedures When rewriting package bodies into separate procedures Oraclersquos variable declarations can be replaced at the package level (global) with Informixrsquos global variables The Informix global variables must be defined in the first stored procedure of the logical group

Exceptions

The method of handling exceptions is different between Informix and Oracle Oracle has many predefined and user defined exception labels such as CURSOR_ALREADY_OPEN NO_DATA_FOUND ZERO_DIVIDE and so on The labels can be used in the logic to identify errors Only one exception check is allowed per BEGIN and END block using the EXCEPTION construct and it is normally placed just before the END statement Informix also supports predefined and user defined exceptions however they are represented numerically not with labels In Informix all the exceptions checked in the stored procedure control blocks delimited with BEGIN and END statements must be declared explicitly at the top of each

IBM Software Group IBM Information Management

Version 16 52

control block with the Informix EXCEPTION construct Therefore Oracle procedure code must be restructured to manipulate these exceptions In Oracle an exception can be raised globally and acted upon globally In Informix the scope of an exception mechanism is always restricted to the block in which it is located This leads to the addition of multiple Informix exception handling mechanisms for each Oracle exception raised as well as a redesign of the overall stored procedure to a more blocked format

Error handling

In Oracle errors are processed as part of a function call return value In Informix errors are retrieved as a separate function call that has multiple structures that have to be created in order to retrieve error and status The SQLCA structure is not fully available in Informix stored procedures It is not possible to check the SQLCODE variable in the stored procedure body Instead the function DBINFO can be used to extract the value of two members of the SQLCA structure sqlcasqlerrd1 and sqlcasqlerrd2 This function should be used inside the FOREACH construct while the cursor is open Once the cursor is closed the DBINFO function cannot return proper values The sqlcasqlerrd1 option returns different values depending on the type of SQL statement For INSERT statements if the table contains a serial column then the sqlcasqlerrd1 option will return the serial value of the last row inserted into the table For SELECT DELETE and UPDATE statements the sqlcasqlerrd1 option will return the number of rows processed by the query In these cases upon each pass through the FOREACH loop sqlcasqlerrd1 is the same value the number of rows the FOREACH loop will process The sqlcasqlerrd1 value can still be interrogated during each pass through the FOREACH loop The sqlcasqlerrd2 option returns the number of rows processed by a SELECT INSERT UPDATE DELETE or EXECUTE PROCEDURE statement It should not be interrogated until after the cursor has finished processing In other words within the FOREACH loop the sqlcasqlerrd2 value can be moved to a variable which is then interrogated outside of the FOREACH loop

Cursors

Unlike Informix in Oracle cursors can be global to a package In Informix Oraclersquos global cursors can be replaced with temporary tables A temporary table can be created and populated in place of where the cursor is opened The temporary table can then be processed the same way the cursor is processed Finally the temporary table should be dropped in place of where the cursor is closed Cursors are explicitly declared opened and fetched in Oracle stored procedures In Informix cursors do not need to be explicitly declared opened and fetched in stored procedures Instead Oracle stored procedure cursors can be replaced with Informixrsquos FOREACH construct The Oracle cursor name should be used in the FOREACH statement for example FOREACH cursor_name SELECT hellip END FOREACH In order to update a cursor row in Oracle the cursor must be declared with the FOR UPDATE clause In Informix if the SELECT statement in the FOREACH construct is not a multi-table join then each fetched row can be updated using the UPDATE lttable_namegt WHERE CURRENT OF ltcursor_namegt statement See the Update Using Cursors section in ldquoData Manipulation Languagerdquo for more information Informix does not support the SELECT FOR UPDATE statement in a stored procedure Therefore the SELECT FOR UPDATE clause cannot be used in the FOREACH construct

IBM Software Group IBM Information Management

Version 16 53

Variable declaration and assignment

Oracle allows implicit variable definitions within a FOR loop The variables are defined using an assignment operator and a column name For example

out_customer_name = customername

The variable out_customer_name is defined as the same type as the column name in the customer table Informix requires that all variables be defined at the beginning of each stored procedure control block For example

DEFINE out_customer_name LIKE customername

DEFINE counter INTEGER

Therefore Oraclersquos implicit variable declaration must be replaced with Informixrsquos explicit variable declaration before the control block Additionally assignment operations will need to be ported Oracle uses a colon and an equal sign (=) for assignment while Informix utilizes the LET keyword in combination with an equal sign (=) (ie LET var = 1) Therefore assignment statements must be modified with the LET keyword and an equal sign

Boolean

Oraclersquos BOOLEAN variable type can be replaced with Informixrsquos BOOLEAN data type

Binary data types

Binary data types are very different between Oracle and Informix In Oracle the binary type is defined as a type RAW and is explicitly defined with a maximum length as part of the declaration In Informix the binary type is defined as REFERENCES BYTE which deals only with pointers to BLOBs It implicitly defines a maximum length as part of the function call in which the pointer to the BLOB and maximum length (as used in the function call) was passed as values As a result the binary type cannot be assigned a binary value in a stored procedure nor can it be inserted into a table via the SQL INSERT statement in a stored procedure These operations that initialize a binary type must be performed outside of stored procedures

Dynamic SQL

Unlike Oracle Informix does not support dynamic SQL within the Stored Procedure Language In other words a statement such as SELECT variable_name FROM variable_name WHERE variable_name is not supported This kind of processing can be achieved in Informix within an embedded SQL program This requires that either the Oracle stored procedure be converted to an embedded SQL program or just the Dynamic SQL portion be placed in an embedded SQL program and then called from within the stored procedure The latter option will have performance implications since calling an embedded SQL program from a stored procedure requires an operating system call Another option is to use the Informix EXEC Bladelet The EXEC Bladelet consists of user-defined functions that take a SQL query as an argument execute it and return a result (the format of which varies depending on the function and the kind of query) The EXEC Bladelet functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries Further details can be found in Chapter 7 Using Bladelets

Compiler

Unlike Oracle the Informix compiler was developed with the concept that developers can create stored procedures independently of the database Therefore Informixrsquos stored procedure

IBM Software Group IBM Information Management

Version 16 54

compiler has a limited set of errors that it checks compared to Oraclersquos For example the Informix stored procedure compiler does not validate database object names such as table column and view names Therefore database object naming errors will occur at runtime not compile time Additionally the error messages generated from the compiler are not very specific Identifying a problem in a stored procedure may require breaking it apart and recompiling the pieces until the problem is found This may impact the time necessary to unit test the stored procedures

Triggers Oracle supports the use of multiple trigger events for example insert update and delete within the same trigger Informix only supports one trigger event per trigger In Informix the Oracle trigger body in this example must be copied into three different triggers each with only one event Informix triggers have some constraints Oraclersquos do not In Informix if a trigger is fired due to inserting a row into a table a trigger can only act on any rows or columns within that table using the EXECUTE PROCEDURE hellip INTO syntax Similarly if a trigger is fired due to updating a row then the trigger can only act on the column that caused the trigger to fire using the EXECUTE PROCEDURE hellip INTO syntax Like Oracle if a trigger is fired due to deleting a row there are no restrictions Prior to IDS 73 when a trigger was fired on an INSERTUPDATE action no modification could be done to the columns (in the row) which just fired the trigger The reentrant UPDATEINSERT triggers feature introduced with IDS 1110 enables users to update the triggering columns by using the EXECUTE PROCEDURE INTO syntax Additionally the feature enforce that this action will not cause any additional triggers to be fired (same or different trigger) causing a cascading of triggers and potentially an infinite loop The following example demonstrates how the reentrant UPDATEINSERT trigger feature is used

create table foo

(

x int default NULL

y int default NULL

z int default NULL

)

create procedure reentrant()

returning int

return 56

end procedure

create trigger reentrant_trigger insert on foo for each row

(

execute procedure reentrant() into z

)

insert into foo values

(

1

2

3

)

The following SELECT will result in the following returned data

select from foo

x y z

1 2 56

IBM Software Group IBM Information Management

Version 16 55

Oracle allows SQL statements logical statements and stored procedure calls within a trigger body Informix allows only SQL statements and stored procedure calls within a trigger body Oracle triggers containing logical statements must be converted to Informix by moving their contents into a stored procedure The stored procedure should then be executed from the trigger

Constraints Constraints in both Oracle and Informix can be enabled and disabled within an application transaction however there are behavioral differences In Oracle the application is always executing within a transaction In Informix transaction boundaries are explicitly declared and care should be taken to ensure that this functionality is performed within the boundaries of a transaction See the Transaction Processing section in CHAPTER 5 Application Architecture for more information The constraint syntax available in Informix is

SET CONSTRAINTSINDEXESTRIGGERS FOR table_name

ENABLED|DISABLED

SET CONSTRAINTS comma_separated_constraint_names

ENABLED|DISABLED

SET INDEXES comma_separated_index_names ENABLED|DISABLED

SET TRIGGERS comma_triggers_constraint_names ENABLED|DISABLED

SET CONSTRAINTS ALLconstraint_name IMMEDIATE|DEFERRED

The first four statements must be executed with DBA privileges if placed in the application Therefore care should be taken when using them Note that the last statement contains a DEFERRED clause This is the statement used if the users of the application do not have DBA privileges When the constraint is set with the DEFERRED clause the specified constraints are not checked until the transaction is committed If a constraint violation occurs while the transaction is being committed the transaction is rolled back

DUAL table Oraclersquos DUAL table is a system table with only one row containing one column named DUMMY This table is used to complete the syntax of an SQL statement that does not involve an existing table such as

A SELECT statement which assigns some constant value (which can only be derived in an SQL statement) to a host variable

SELECT TO_CHAR(SYSDATE) INTO date_var FROM DUAL

A SELECT statement which assigns a value of another variable to a variable

SELECT source_var INTO dest_var FROM DUAL

A SELECT statement which unions application host variable values with another SELECT statement to return a result containing a row of application variable values

SELECT col1 col2 col3 FROM table_name

UNION

SELECT host_var1 host_var2 host_var3 FROM DUAL

Converting Oraclersquos DUAL table functionality to Informix depends on the way it is used Converting statements that just assign constants is as simple as replacing the DUAL statement with an Informix assignment statement The solutions below apply to Informix versions prior to 11 At 11 and above the concept of a DUAL table as well as sysdate is supported

IBM Software Group IBM Information Management

Version 16 56

SELECT sysdate FROM sysmastersysdual

If you want a dual table in your local database then create the following synonym The sysmastersysdual table is much faster than a physical table in your database because it is an in- memory pseudo table

CREATE SYNONYM dual FOR sysmastersysdual

If you are restricted to using a version of Informix prior to 11 then the following solutions can be used A dummy table can be created to mimic the behavior of simple SELECT INTO statements used to assign values to variables

CREATE TABLE dual (dummy VARCHAR(1))

INSERT INTO dual VALUES(lsquoXrsquo)

An alternate solution to widespread use of the DUAL table could be creating a permanent view that is generally accessible

CREATE VIEW dual (d) as SELECT X

FROM systables WHERE tabid = 1

The exact definition could be used or modified as needed but this would solve the problem of having DUAL be permanent usable by anyone and not modifiable

IBM Software Group IBM Information Management

Version 16 57

C H A P T E R 5 Embedded SQL

Oraclersquos embedded SQL products are ProC and ProCOBOL Informixrsquos corresponding embedded SQL products are ESQLC and ESQLCOBOL

Host variables

Declaration override

The Oracle EXEC SQL VAR declarative statement (host variable equivalency of Oracle external data types by overriding the default assignment) can be converted to an Informix explicit declaration statement For example

Oracle char char_var[20]

EXEC SQL VAR char_var IS STRING(11)

Informix

char char_var[11]

Note that the size and type used in the EXEC SQL VAR section is the final information required to declare the host variable in Informix

Arrays

Oracle arrays are not subscripted in SQL statements since it is not required to process the host arrays in a loop in the SQL statement In Informix subscripting is mandatory In Oracle if an array is defined of size 200 then an SQL statement would be

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A

VAR-B

VAR-C

END-EXEC

-or- EXEC SQL SELECT COL1 COL2 COL3

INTO VAR-A

VAR-B

VAR-C

FROM TABLE1

WHERE COL2 gt 100

END-EXEC

where VAR-A VAR-B and VAR-C are each an array of say 200

IBM Software Group IBM Information Management

Version 16 58

In Informix the first example would be converted to

PERFORM VARYING LOOP-CTR FROM 1 BY 1 UNTIL

LOOP-CTR IS GREATER THAN 200

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A(LOOP-CTR)

VAR-B(LOOP-CTR)

VAR-C(LOOP-CTR)

END-EXEC

IF SQLCODE = 100

GO TO EXIT-PERFORM

END-IF

END-PERFORM

EXIT-PERFORM

For the second Oracle example given above a cursor must be declared in Informix opened and fetched for 200 rows or less (less because there may be less than 200 qualifying rows) into the host array and then should be closed If the number of qualifying rows is more than 200 then the extra rows must be ignored to duplicate the Oracle functionality But for the first example each fetch in Oracle will return the next 200 or less number of rows Therefore each Oracle fetch needs to be replaced by another call to the Informix fetch loop Oracle also uses this method for inserts deletes and updates These array techniques are mainly used in batch SQL processing

Formatting

In Informix when a DECIMAL MONEY DATE or DATETIME value is selected into a host variable of the same data type the value must be formatted using the available Informix formatting routines before they can be printed or displayed For example

hellip

dec_t dec_host_var

char formatted_dec[40]

EXEC SQL SELECT DEC_COLUMN INTO dec_host_var FROM TABLE_NAME

rfmtdec(ampdec_host_var ldquoampampampampampampampampampamprdquo formatted_dec)

printf(ldquoThe Decimal Value is snrdquo formatted_dec)

hellip

IBM Software Group IBM Information Management

Version 16 59

Informix supplies many formatting functions and formatting strings The names of these functions are different in Informix ESQLC and ESQLCOBOL but the functionality is the same Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

SQL structures

SQLCA

Oraclersquos SQLCA structure is different from that of Informix However the components of both structures are logically the same Oraclersquos SQLCA components can be replaced with the corresponding Informix components Oraclersquos SQLCA structure

SQLCAID string containing ldquoSQLCArdquo SQLCABC length of SQLCA data structure SQLCODE Oracle error message code SQLERRM sub-record for error message

SQLERRML length of error message SQLERRMC text of error message SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) reserved for future use SQLERRD(1) reserved for future use SQLERRD(2) number of rows processed SQLERRD(3) reserved for future use SQLERRD(4) parse error offset SQLERRD(5) reserved for future use

SQLWARN array of eight warning flags SQLWARN(0) another warning flag set SQLWARN(1) character string truncated SQLWARN(2) no longer in use SQLWARN(3) SELECT list not equal to INTO list SQLWARN(4) DELETE or UPDATE without WHERE clause SQLWARN(5) reserved for future use SQLWARN(6) no longer in use SQLWARN(7) no longer in use

SQLTEXT reserved for future use

IBM Software Group IBM Information Management

Version 16 60

Informixrsquos SQLCA structure

SQLCODE Informix error code SQLERRM error message parameter SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) estimated number of rows returned SQLERRD(1) serial value of INSERT or ISAM error code SQLERRD(2) number of rows processed SQLERRD(3) estimated cost SQLERRD(4) parse error offset SQLERRD(5) ROWID after INSERT

SQLWARN structure of eight warning flags SQLWARN0 another warning flag set SQLWARN1 character string truncated or no privileges revoked SQLWARN2 NULL value returned or ANSI database SQLWARN3 SELECT list not equal to INTO list or turbo back-end SQLWARN4 DELETE or UPDATE without WHERE clause SQLWARN5 if non-ANSI statement SQLWARN6 if server is in data replication secondary mode SQLWARN7 reserved

In order to get Oracle error messages an application normally uses the SQLCA element SQLERRMC The Informix equivalent is SQLERRM On the HPUX and Solaris platforms the Informix function rgetmsg should be used instead of the element SQLERRM At the time of this writing using SQLERRM would cause an error on the HPUX and Solaris platforms

SQLDA

The implementation of Oraclersquos SQLDA structure is very different from that of Informix Significant changes are necessary to convert Oraclersquos functionality to Informix Oraclersquos sqlald function can be replaced with Informixrsquos ALLOCATE DESCRIPTOR statement Since Oraclersquos and Informixrsquos SQLDA structures are so different Oraclersquos SQLDA logic must be rewritten with the more powerful Informix SQLDA logic or alternatively the Informix system-descriptor area logic Oraclersquos SQLDA Structure

N maximum number of SELECT list items or placeholders V pointer to array of address of SELECT list items or bind variables L pointer to array of lengths of SELECT list items or bind variables T pointer to array of data types of SELECT list items or bind variables I pointer to array of addresses of indicator variable values F actual number of SELECT list items or placeholders S pointer to array of addresses of SELECT list items or placeholder names M pointer to array of max lengths of SELECT list items or placeholder names C pointer to array of current lengths of SELECT list items or placeholder names X pointer to array of addresses of indicator variable names Y pointer to array of maximum lengths of indicator variable names Z pointer to array of current lengths of indicator variable names

IBM Software Group IBM Information Management

Version 16 61

Informixrsquos SQLDA Structure SQLD count of the following SQLVAR members SQLVAR pointer to array of structures

SQLDATA pointer to actual data SQLTYPE data type of placeholder or SELECT item SQLLEN length of the placeholder or SELECT item SQLIND pointer to the indicator SQLNAME pointer to placeholder or SELECT item name SQLFORMAT reserved SQLIDATA indicator data pointer SQLITYPE indicator variable type SQLILEN length of indicator variable

If an Oracle application uses the simple dynamic SQL method using macros only not the SQLDA structure directly the value indicatorsplaceholders can be replaced with a lsquorsquo in Informix For example Oracle sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES (v1 v2)rdquo) Informix sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES ( )rdquo)

ORACA

Oraclersquos ORACA structure is not supported by Informix This structure is used to handle Oracle specific communication and more runtime information than SQLCA Oracle statements containing references to this structure should be removed from the application

Pre-compiler options The Oracle options beginning with the EXEC ORACLE OPTION statement can be removed from the application The options set after this statement do not affect the application logic They may affect some application performance only

Embedded PLSQL Oracle allows procedure language (PLSQL) blocks inside ProC and ProCOBOL code delimited by the EXEC SQL EXECUTE and END-EXEC statements In Informix these blocks must be replaced with the equivalent ESQLC or ESQLCOBOL code

Oracle Call Interface Oracle call interface (OCI) is the base layer for a variety of other application programming interfaces such as JDBC-OCI Oracle Precompilers and Oracle ODBC It is also used directly by customers who are willing to develop their code using a lower level proprietary API From a high level it can be thought of as if IBM Informix had standardized and published the function calls in the ESQLC library Although some customers have reverse engineered these calls and developed applications using them this is generally discouraged because there is no guarantee that the library of calls will not change There is no direct equivalent to this Oracle API in Informix Migrating applications written using Oracle Call Interface (OCI) will require rewriting the code from scratch OCI is native to the C language and so it should be less effort to migrate the application to an Informix API that is also native to C This could be ESQLC or CLI The following information explains differences between Oracle OCI and Informix ODBC

IBM Software Group IBM Information Management

Version 16 62

The following table is an approximate mapping of the differences between the Informix CLI and Oracle OCI function calls in which there is not a direct one-to-one mapping

Oracle Informix Buffer Areas HAD LDA CDA HENV HDBC HSTMT

Connect and allocate resources

OLOG OOPEN SQLConnect SQLAllocEnv SQLAllocConnect SQLAllocStmt

Update delete insert select OPARSE OBNDRV OEXEC SQLPrepare SQLBindParameter SQLExecute

Select ODEFIN OFETCH SQLBindCol SQLFetch

Commit Rollback OCOM OROL SQLTransact

Disconnect OLOGOF OCLOSE SQLDisconnect SQLFreeStmt SQLFreeConnect SQLFreeEnv

Database library calls

One of the first main differences between Informix CLI and Oracle OCI calls is the overall data structures and mechanisms used to process database library calls Oracle uses direct connections to the database server Informix uses an ODBC connection to the database server As a result the Informix calls will be implemented as ODBC SQL calls utilizing three tiers of increasing SQL levels of complexity

Global area processing

Another main difference between Informix CLI and Oracle OCI is Informixrsquos use of pointers to three global areas versus Oraclersquos use of pointers to three different but similar global areas Hence the Oracle OCI calls that utilize HAD (Handle Data Area) LDA (Logon Data Area) and CDA (Cursor Data Area) pointers must be translated over to Informix CLI calls that utilize HENV (Environment Area) HDBC (Database Connection Area) and HSTMT (Statement Area) pointers respectively in conjunction with an ODBC interface

Fetch cycle

Another difference between Informix CLI and Oracle OCI calls is that the overall fetch cycle is different for each and must be modified accordingly In Oracle the fetch cycle for selecting multiple rows utilizing a cursor area involves parsing binding defining fetching and then executing into a cursor data area These must be translated to a cycle that involves preparing binding executing binding and then fetching via the ldquoFor Eachrdquo cycle

RAW binary data type processing

RAW binary data types in Oracle will need to be translated to a pointer-to-BLOB REFERENCES BYTE type in Informix See the Binary Data Types subsection of the Stored Procedures section in CHAPTER 3

Parameter bindings

In Oracle multiple output bindings of parameters are declared as type ldquoOUTPUTrdquo in the ODEFIN() calls In Informix convert the calls to Informix SQLBindCol() calls and bind the output parameters as columns Differences also exist between Informix CLI and Oracle OCI in the use of inputoutput bindings In Oracle these bindings are declared as type ldquoINPUTOUTPUTrdquo in the ODEFIN() calls In Informix a ldquoround robinrdquo approach is used using three variables in the following manner A=B B=C C=A A variable (A) is declared before the SQL bindings as an input variable The function is called

IBM Software Group IBM Information Management

Version 16 63

using a second input variable (B) that is set to the first input variable (A) The function returns a third variable (C) that is bound as an output column Finally the first variable (A) is now set to the returned third variable (C) that made the first variable (A) appear as an ldquoinputoutputrdquo variable to the rest of the program

Embedded SQL for C

VARCHAR

Oraclersquos ProC VARCHAR data type is expanded after pre-compiling into a structure with two elements one is unsigned short len and the other is unsigned char arr[size] The name of the expanded structure is the same name as the VARCHAR variable and size is replaced with the size of the VARCHAR variable In Informix the VARCHAR data type is just a synonym for the C languagersquos char data type Therefore statements that use variable_namelen can be removed from the application and all occurrences of variable_namearr can be replaced with variable_name For example

Oracle VARCHAR vName[40]

strcpy(vNamearr ldquoCompany Namerdquo)

vNamelen = strlen(vNamearr)

Informix VARCHAR vName[40]

strcpy(vName ldquoCompany Namerdquo)

Host variables

The Oracle statement EXEC SQL TYPE is synonymous with the C languagersquos typedef declarative instruction It can be easily replaced with the Informix declarative instruction typedef

Embedded SQL for COBOL

VARCHAR

Oraclersquos ProCOBOL character host variable declaration statementrsquos VARYING clause is expanded after pre-compiling into a group with two elements one is variable-name-LEN PIC S9(4) COMP and the other is variable-name-ARR PIC X(size) The group name is the same as the host variable name and size is replaced with the size of the VARYING variable Informix does not support this concept Therefore statements that use variable-name-LEN must be removed from the application and all occurrences of variable-name-ARR must be replaced with variable-name Also the VARYING clause must be removed from the declarative statement For example

Oracle

05 vName PIC X(40) VARYING

hellip

MOVE ldquoCompany Namerdquo TO vName-ARR

MOVE 12 TO vName-LEN

Informix

05 vName PIC X(40)

hellip

MOVE ldquoCompany Namerdquo TO vName

IBM Software Group IBM Information Management

Version 16 64

Level 88

COBOLrsquos level 88 functionality is not supported within an Informix ESQLCOBOL host variable declaration section in versions prior to 72 Level 88 functionality is supported in Informix ESQLCOBOL 72

SQLDA

In Informix ESQLCOBOL the SQLDA structure is not available The Informix macros such as ALLOCATE DESCRIPTOR DESCRIBE GET DESCRIPTOR and SET DESCRIPTOR must be used to retrieve and manipulate the SQLDA data

REDEFINES

Oracle supports the use of the REDEFINES clause at the elementary level in the host variable declaration section In other words the redefined item cannot be a group item but the redefining item may be a group item Informix does not support the use of the REDEFINES clause in the host variable declaration section in versions prior to 72 The REDEFINES clause is supported in Informix ESQLCOBOL 72

Tips

If the Informix pre-compiler finds an SQL statement within an IF [ELSE IF hellip ] END-IF or EVALUATE END-EVALUATE or PERFORM END-PERFORM block then the pre-compiler adds a period after the generated COBOL statements regardless of whether there is a period at the end of the SQL statement This is a violation of COBOL rules for such blocks and the code may cause syntax errors during compilation or may behave unexpectedly To avoid these problems each SQL statement group should be moved to a new paragraph and these paragraphs should be performed from the block from which they were moved

ODBC Although the Open Database Connectivity (ODBC) API is designed to make it possible to write and compile an application once and use it with any ODBC driver on the same platform there are frequently differences between the underlying DBMSs that can expose problems to the applications For instance there can be differences between how unspecified parts of a date-time value are filled Most of these kinds of differences that get exposed through ODBC have their origins in the differences between the DBMSs themselves There are also cases where there are gaps in the ODBC standard for example there is a standard ODBC call that allows the application to ask the driver if it can support scrollable cursors and there is another call to ask if it can support updateable cursors There is no call to ask if it can support both at the same time With Informix you can have a scrollable cursor and you can have an updateable cursor but you can not have one cursor that is both scrollable and updateable A more complete description of ODBC application migration issues is beyond the scope of this article

IBM Software Group IBM Information Management

Version 16 65

C H A P T E R 6 Application Architecture

Transaction processing Transaction boundaries are defined differently in Oracle and Informix Oraclersquos transactions begin implicitly in one of two ways either by issuing a CONNECT statement or issuing a COMMIT or ROLLBACK statement A CONNECT statement marks the beginning of a transaction and a COMMIT or ROLLBACK statement commits or rolls back the previous transaction respectively and then implicitly begins a new transaction CONNECT statements are usually issued once at the beginning of a program however they may be nested or issued more than once serially to connect to the same or a different database When using more than one CONNECT statement within a program each CONNECT statement must be named This marks the beginning of named transactions Every SQL statement within a named transaction must also be named with the same transaction name as the CONNECT statement at where the SQL is to be executed SQL is named using the EXEC SQL statementrsquos AT clause Informixrsquos transaction boundaries are explicitly marked with the reserved words BEGIN WORK and COMMIT WORK or ROLLBACK WORK Note that once a transaction has begun for a given connection it stays open until a COMMIT or ROLLBACK is executed In other words if an ESQL program begins a transaction and then calls a stored procedure the stored procedure executes within the same transaction If the stored procedure issues a COMMIT then the whole transaction is committed and the calling ESQL program should not issue a COMMIT or ROLLBACK Informix transactions can be written to behave the same way as Oraclersquos To simulate Oraclersquos CONNECT statement behavior an Informix CONNECT should also be issued followed by a BEGIN WORK statement If more than one CONNECT statement is used in a program Informix also requires that the CONNECT and SQL statements be named To simulate Oraclersquos COMMIT and ROLLBACK statement behavior an Informix COMMIT WORK or ROLLBACK WORK statement should be issued followed by a BEGIN WORK statement Nested transactions can be simulated in Informix with the CONNECT statement and naming the transactions Then the Informix SET CONNECTION connection_name statement can be used to switch between transactions Committing or rolling back each named transaction does not commit or roll back other active transactions The Oracle statement EXEC SQL COMMITROLLBACK RELEASE should be replaced with the Informix statements EXEC SQL COMMITROLLBACK [WORK] followed by EXEC SQL DISCONNECT CURRENT In the following examples ws-dbenviron is the database name ws-connect-nm is the user name and ws-identity-nm is the password set in the program enp and connection-name are the connection names For Informix the user name and password information should correspond to the entries in the etcpasswd file on the UNIX system See the User Authentication section later in this chapter for more information The default server name is automatically obtained from the environment variable INFORMIXSERVER The following examples illustrate how Oracle and Informix implement the CONNECT functionality

IBM Software Group IBM Information Management

Version 16 66

Simple Connect

Oracle

CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm

Informix

CONNECT ws-dbenviron USER ws-connect-nm USING ws-identity-nm

Named Connect with Literal

Oracle

DECLARE enp DATABASE hellip CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm AT enp USING ws-dbenviron hellip AT enp SELECT col1 col2 INTO var1 var2

FROM table_name

Informix

CONNECT TO ws-dbenviron AS ldquoenprdquo USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION ldquoenprdquo hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Named Connect with Variable

Oracle

CONNECT ws-connect-nm

IDENTIFIED BY ws-identity-nm AT connection-name USING ws-dbenviron hellip AT connection-name SELECT col1 col2 INTO var1 var2 FROM table_name

Informix

CONNECT TO ws-dbenviron AS connection-name USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION connection-name hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Autonomous Transaction

An autonomous transaction is an independent transaction that is initiated by another transaction (the parent transaction) An autonomous transaction can modify data and commit or rollback independent of the state of the parent transaction The autonomous transaction must commit or roll back before the autonomous transaction is ended and the parent transaction continues

IBM Software Group IBM Information Management

Version 16 67

An autonomous transactions has been available since the release of Oracle 8i An autonomous transaction is defined in the declaration of a PLSQL block This can be an anonymous block function procedure object method or triggerThis is done by adding the statement PRAGMA AUTONOMOUS_TRANSACTION anywhere in the declaration block There isnt much involved in defining a PLSQL block as an autonomous transaction You simply include the following statement in your declaration section PRAGMA AUTONOMOUS_TRANSACTION Sample code

PROCEDURE test_autonomous

IS

PRAGMA AUTONOMOUS_TRANSACTION

BEGIN

insert

commit

END test_autonomous

Autonomous transactions can be used for logging in the database independent of the rollbackcommit of the parent transaction

Savepoints

Oracle allows savepoints within its PLSQL For example a PLSQL block can be structured so that SAVEPOINT A is issued upon entry and SAVEPOINT B is issued after some processing Then after some more processing a COMMIT or ROLLBACK can be issued against all the logic since the last COMMIT point which is before the PLSQL block or up to any of the savepoints by naming the COMMIT or ROLLBACK with the savepoint name In other words a savepoint can be issued at the beginning of a stored procedure and then only the stored procedure logic can be committed without committing the changes pending before the stored procedure was executed Those changes can be committed or rolled back once processing is returned from the stored procedure Informix does not support savepoint processing within a stored procedure

Concurrency Database concurrency can be managed through the combination of two configurable settings one specifies the lock granularity on database objects while the other influences how the application behaves in regards to the presence and placement of locks using a transaction isolation level

Row Level Locking

Oracle and Informix implement locking differently on database objects Oracle defaults to row level locking whereas Informix defaults to page level In most cases row level locking is preferred to improve concurrency Informix supports row level locking however it must be either explicitly requested specified by an environment variable or permanently changed in the instancersquos configuration Having three methods for establishing the lock level there is an order of precedence

1 To be explicitly requested the CREATE TABLE statement must include the specification of the LOCK MODE attribute

CREATE TABLE emp (

name CHAR(40)

salary MONEY

ssn LVARCHAR(64)

) LOCK MODE ROW

IBM Software Group IBM Information Management

Version 16 68

2 The environment variable IFX_DEF_TABLE_LOCKMODE will establish the default for CREATE TABLE statements issued without the LOCK MODE attribute and will override the Instancersquos configuration setting The variable setting on the client will override the server environment setting

set IFX_DEF_TABLE_LOCKMODE=ROW -or- export IFX_DEF_TABLE_LOCKMODE=ROW

3 Informix allows the instancersquos lock level default to be changed using a configuration parameter Row level locking can be as the default by adding the parameter DEF_TABLE_LOCKMODE to the instancersquos ONCONFIG file This parameter may not be found in the existing file and if not present can be added using an editor and establish a new default setting of ROW

DEF_TABLE_LOCKMODE ROW

None of the steps will apply a change to existing tables only establish the lock level for the CREATE TABLE statement

Transaction Isolation Level

Oracle databases incorporate a feature known as ldquoread consistencyrdquo which allows a query return a result based on the state of the data when the query started regardless of other processes updating or deleting the same data while the query is running Informix facilitates this type of behavior differently by providing control of the applicationrsquos placement of locks as well as how it reacts to those placed by other processes through the use of the transactionrsquos isolation level If Oraclersquos technique of ldquoreaders not blocking writersrdquo is a requirement then in many circumstance Informixrsquos DIRTY READ isolation level can be used The readers will not block the writers with dirty read processing however the query result may contain updates performed while the query was running which may be uncommitted If the emulation of Oraclersquos ldquoread consistencyrdquo is desired the LAST COMMITTED option of Informixrsquos COMMITTED READ isolation level can reduce the risk of locking conflicts when two or more sessions attempt to access the same row in a table whose locking granularity is row-level When an application attempts to read a row on which another session holds an exclusive lock these keywords instruct the database server to return the most recently committed version of the row rather than wait for the lock to be released This isolation level attribute could be preferable to executing queries using DIRTY READ since it will return only the most recently committed versions of the data The LAST COMMITTED option can be enabled in the following ways

1 Setting the USELASTCOMMITTED parameter in the Instancersquos configuration (ONCONFIG) will apply this feature as the default isolation level to all database transactions The parameterlsquos values will designate the scope of applying the LAST COMMITED option to either ALL NONE or only COMMITED READ and DIRTY READ isolation levels

USELASTCOMMITTED [ALL | NONE | COMMITTED READ | DIRTY READ]

2 The SET ENVIRONMENT statement can override the USELASTCOMMITTED configuration parameter setting for the duration of the current session The same semantics apply as the parameter within the ONCONFIG file with the setting value enclosed in quotes (lsquo)

SET ENVIRONMENT USELASTCOMMITTED lsquoALLrsquo

IBM Software Group IBM Information Management

Version 16 69

3 The SET ISOLATION statement can be used to override the instance configuration and session environment setting The SET ISOLATION statement is an Informix extension to the ANSI SQL-92 standard and provides the same functionality as the ISOANSI-compliant SET TRANSACTION statement There is no support for the LAST COMMITTED option with the SET TRANSACTION statement SET TRANSACTION complies with ANSI SQL-92 and only ANSI supported isolation levels are supported

SET ISOLATION TO COMMITTED READ LAST COMMITTED

4 PREPARE statements in ODBCJDBC applications

This feature is primarily documented in the Guide to SQL Syntax Guide to SQL Reference Administrators Reference and Administrators Guide

IBM Software Group IBM Information Management

Version 16 70

C H A P T E R 7 Security

User authentication In Oracle security information is stored in the database Up until recently Informix has used only the operating system security subsystem to check security For security purposes Oracle connects to the server and passes the user ID and password information to the database for verification

Operating system security

Informix does not store user ID and password information in the database Instead they are validated against the operating systemrsquos security mechanism on the server for example the etcpasswd file in UNIX Therefore either every database user must have an entry in the serverrsquos password file or the application must handle a level of security where user IDs are converted into a group id based on database permissions and only those group IDs are entered into the password file Note that if the second alternative is chosen then auditing capabilities based on user ID are lost Also if the application performs security functions then those functions are not applicable to third party applications such as report writers application development tools and so on when they access the database The home directory of all the users should point to the same physical directory where the application executable resides The Informix method of using the operating system for security checking allows external programs to be called from within stored procedures This capability is not allowed in Oracle In Oracle the OPS$User_name is sometimes used to connect to the database where OPS$User_name is a valid Oracle user and User_name is a valid operating system level user In this case the connection is made to the database using just the lsquorsquo character without the user id and password Informixrsquos technique of using the etcpasswd file for security works fine for this type of connection

Non-operating system security

In previous releases each user who needed to access the database server also needed an operating system account on the host computer Now you can configure Informix so that users who are authenticated by an external authentication service (such as Kerberos or Microsoft Active Directory) can connect to Informix The new USERMAPPING configuration parameter specifies whether or not such users can access the database server and whether any of those users can have administrative privileges When Informix is configured to allow user mapping you can still control which externally authenticated users are allowed to connect to Informix and their privileges Please refer to the IBM Informix documentation on connection security for more information

IBM Software Group IBM Information Management

Version 16 71

Informix supports for the pluggable authentication module (PAM) framework which lets an administrator customize authentication for individual applications and permits column-level encryption

Role based authority Role based authority can help you manage your database permissions As of version 1110 you can create a role and assign that as a default role for individual users (or to PUBLIC) A role is a work-task classification such as ldquopayrollrdquo or ldquomanagerrdquo Each defined role has privileges on the database object granted to the role You use the CREATE ROLE statement to define a role and GRANT DEFAULT ROLE to establish the userrsquos initial setting when connecting to the database A userrsquos role can be changed after connecting by using the SET ROLE statement

Column-level encryption You can use column-level encryption to improve the confidentiality of your data IDS Version 1110 has new built-in SQL scalar functions provide methods for data in columns to be stored in an encrypted format Use the ENCRYPT_AES or the ENCRYPT_TDES function to define encrypted data Use the DECRYPT_BINARY() and DECRYPT_CHAR() functions to query encrypted data When using the routines the encryption of data is under application control and the DBMS is not aware that data is encrypted Informixrsquos support of column level encryption is analogous to Oraclersquos DBMS Obfuscation Tool Kit Built-in ENCRYPT functions provide methods for encrypting and decrypting the following character data types or smart large object data types

CHAR

NCHAR

VARCHAR

NVARCHAR

LVARCHAR

BLOB

CLOB

Passwords and hints

Passwords are necessary when using the encryption functions Only users who can provide a secret password can view copy or modify encrypted data The password must be a minimum of 6 bytes and can be a maximum of 128 bytes When you set an encryption password you have the option of specifying a password hint Hints can be up to 32 bytes of text If you specify a hint you can store the hint with the encrypted password or in another location Passwords (and hints) to be used by default can be set for a session using the SET ENCRYPTION PASSWORD statement

SET ENCRYPTION PASSWORD lsquopasswordrsquo [ WITH HINT lsquohint stringrsquo ]

Hence the password and hint parameters can be optional when calling the encryption function Explicit values override the session default values The password or hint can be a single word or several words The hint should be a word or phrase that helps you to remember the password but does not include the password You can subsequently execute the built-in GETHINT function (with an encrypted value as its argument) to return the plain text of hint Calling the GETHINT function with an argument of encrypted data will return the hint (if any) from the encrypted data or an empty string (NULL) is no hint was provided There is no privilege needed anybody can get any hint at any time When you set a password Informix transfers the password and any hint to 128-bit key that is used to encrypt the password and hint Passwords and hints are not stored as plain text any table of the system catalog The key is a time-based random value per instance The database server

IBM Software Group IBM Information Management

Version 16 72

initializes the key when the server starts the key is destroyed when the database server shuts down

Encrypting a column

Column data can be encrypted through the use of two functions ENCRYPT_TDES and ENCRYPT_AES corresponding to the two data encryption standards Triple Data Encryption Standard (Triple-DES) and Advanced Encryption Standard (AES) which describes the cipher algorithm used to protect data from unauthorized viewing AES encryption (also known as Rijndael) uses a 128-bit key size and Triple-DES encryption uses two 56-bit keys for 112-bits overall Both functions are variant functions and will return a different result every time it is used The following example demonstrates how to use the encryption functions with a column that contains a social security number

CREATE TABLE emp (name CHAR (40) salary MONEY ssn LVARCHAR(64))

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890one two

three 123))

-or-

CREATE TABLE emp (name CHAR(40) salary MONEY ssn LVARCHAR(64))

SET ENCRYPTION PASSWORD one two three 123

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890))

Querying an encrypted column

Encrypted data can be translated using Informixrsquos DECRYPT_CHAR and DECRYPT_BINARY scalar functions Encrypted data contains information about the encryption method and all the other data needed to decrypt it except the password The encrypted data value is passed as the first argument and a password as the second unless the SET ENCRYPTION statement has specified for this session with the same session password by which the first argument was encrypted If the data is not encrypted the function call will return an error The DECRYPT_CHAR function is used to invoke a decryption routine on character data types (ie CHAR LVARCHAR NCHAR NVARCHAR and VARCHAR) while the DECRYPT_BINARY function accepts an encrypted large object of type BLOB or CLOB If the first argument to DECRYPT_CHAR or DECRYPT_BINARY is not an encrypted value or if the second argument (or the default password specified by SET ENCRYPTION) is not the password that was used when the first argument was encrypted Informix will issue an error and the call fails If the call to the decryption function is successful it returns the plain text version of the encrypted data argument The following example demonstrates how to use the decrypt function to query encrypted data

SELECT name salary DECRYPT_CHAR(ssn lsquoone two three 123rsquo)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

-or-

SET ENCRYPTION PASSWORD lsquoone two three 123rsquo

SELECT name salary DECRYPT_CHAR(ssn)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

The first argument to DECRYPT_BINARY is expected to be an encrypted value of a large object data type however if it is called with a character data type Informix invokes the DECRYPT_CHAR function and attempts to decrypt the specified value

IBM Software Group IBM Information Management

Version 16 73

Do not use either decryption function to create a functional index on an encrypted column This would store the decrypted values as plain text data in the database defeating the purpose of encryption

Performance impact of encryption

The performance impact of encryption is significant Encryption by its nature will slow down most SQL statements If some care and discretion are used the amount of extra overhead should be minimal Also encrypted data will have a significant impact on your database design In general you want to encrypt a few very sensitive data elements in a schema like social security numbers credit card numbers patient names and so on The effect on performance depends on direction encrypting is slower than decrypting It does not depend measurably on which algorithm is used AES performs at the same speed as Triple-DES It does depend on data size the relative overhead is less when there is more data to encrypt

Storage considerations

An encrypted value uses more storage space than the corresponding plain text value Data encrypted using AES can be bigger than Triple-DES but not by a significant amount This occurs because all of the information needed to decrypt the value except the encryption key is stored with the value Therefore before you set the encryption password and encrypt the data you must be sure the encrypted data can fit in the column A chart of the expected sizes can be found in the IBM Informix Administrator Guide

Compliance regulations

Informixrsquos encryption routines comply with the United Statesrsquo regulations of Health Insurance Portability and Accountability Act (HIPAA) Sarbanes-Oxley Gramm-Leach-Bliley and California Personal Information Privacy (SB 1386) as well as the international requirements of Basel II Also they comply with the latest cryptographic standards (OpenSSL 097c)

IBM Software Group IBM Information Management

Version 16 74

C H A P T E R 8 Environment

Scripts Oracle make files used to build the application should be modified to invoke the appropriate Informix ESQLCOBOL ESQLC MF COBOL and other application language commands The shell scripts shell startup scripts and command files should be modified for Informix compliant statements

SQL script substitution variables

In Oracle a substitution variable is a user variable name preceded by one or two ampersands (amp) When Oracle (SQLPlus) encounters a substitution variable in a command Oracle executes the command as though it contained the value of the substitution variable rather than the variable itself In Oracle the substitution variables can be used anywhere in SQL and SQLPlus commands except as the first word entered at the command prompt When SQLPlus encounters an undefined substitution variable in a command SQLPlus prompts the user for the value SQLPlus reads the responses from the keyboard even if terminal input or output has been redirected to a file If a terminal is not available (if for example the command file is run in batch mode) SQLPlus uses the redirected file Informixrsquos dbaccess does not provide this functionality however a work-around for the redirected file type of substitution is a follows (no user prompting) Create the following shell script (named subvalsksh in this case)

binkshif [[ $ -ne 2 ]]

then

echo nUsage $0 ltdfilegt ltcfilegtn

echo Desc This script accepts two files - dfile the decode

file

echo and cfile the change file It modifies the

change file

echo using the values listed in the decode file

echo The decode file should contain two columns - old

value

echo and new value

echo Ex

echo changethis tothis

echo

echo In this case every occurance of changethis

would be

echo replaced with tothisn

exit 1

fi

IBM Software Group IBM Information Management

Version 16 75

-----------------------

Declare variables

-----------------------

dfile=$1

cfile=$2

awk print s$1$2 $dfile gt $dfile_sed

sed -f $dfile_sed $cfile

The preceding script is used by creating a ldquodecoderdquo file (named decodefile in this case) which holds two columns in the form which may contain multiple rows

oldval newval

Executing the following command

subvalsksh decodefile chgfile

will replace every occurrence of oldval with newval in the file chgfile The shell script (subvalsksh) writes to standard output therefore the output should be redirected The redirected file will then be able to run with dbaccess

Utilities To improve performance the Informix EXPLAIN utility should be used by executing the SET EXPLAIN ON command to see how an SQL statement accesses the database From that point forward the access path for every SQL statement is written in the SQEXPLAINOUT file in the current working directory or the home directory of the process that initiated the request on the host machine The Informix SET EXPLAIN OFF should be executed to turn off this feature when finished The overall system performance should be monitored using the Informix ONSTAT utility

System catalog The following items discuss how Informix implements the system catalog differently than Oracle Each item refers to the Informix implementation only Object names are stored in lower case The system catalog tables are owned by lsquoinformixrsquo To query the systables table use SELECT from lsquoinformixrsquosystables Each table in systables is assigned a tabid by the system It is used as the primary key and therefore the foreign key for the other catalog tables The identifier information is stored in sysindexes Columns part1 - part16 each contain a column component of a composite index They are integers positive for ascending order negative for descending order In syscolumns collength and coltype have special meanings depending on the data type of the column See the Informix Guide to SQL Reference Version for details

IBM Software Group IBM Information Management

Version 16 76

C H A P T E R 9 Using Bladelets

What is a Bladelet

A Bladelet is a small informal Informix Datablade module Its meant to be useful out of the box and is offered complete with source code at no cost -- and no support or warranty In the context of this document the term Datablade refers to an extension to the standard IBM Informix database engine These generally take the form of new data types (for example timeseries or video) andor new routines that execute inside the server The new routines might operate on new data types or on existing ones A Datablade module is usually a formal product available for sale In addition a Datablade is

Developed either by IBM Informix or by a third-party developer

Rigorously tested

Packaged and sold for profit

May or may not be formally certified by IBM Informix as having been developed according to approved Datablade coding practices

In contrast a Bladelet is

Not rigorously tested

Not sold for profit

Not certified by IBM Informix A Bladelet is an extension to the database engine that is narrow in scope and thought to be generally useful being offered at no cost complete with source Just remember before you use any of this code in mission-critical applications its up to you to thoroughly test it and fix any problems you find Please review the disclaimer which applies to any sample code you find on this site httpwwwibmcomdeveloperworksdb2zonesinformixlibrarysamplesdb_downloadshtml Note The bladelets at this link have not been updated for some time (at the time of this writing) some of the capabilities especially simple function call that increase compatibility may have been introduced into the Informix server itself since they were written

Useful Bladelets

Bladelet Description

Exec Defines two user-defined functions that provide dynamic SQL functionality within a SPL procedure

Flat File Access Method A complete access method that lets you build virtual tables based on operating system files

IUtil Implements a collection of other database vendor functions for Informix

IBM Software Group IBM Information Management

Version 16 77

JPEG Image Bladelet Provides a user-defined type for JPEG images that allows you to manipulate images and to extract and search on image properties

Multirepresentational lvarchar Opaque Type

Creates the idn_mrLvarchar opaque type which stores character data up to 2 gigabytes

Node Datablade Module Creates the node opaque type which is intended to solve one of the hardest problems in relational databases transitive closure

Regexp Creates routines that let you manipulate character and clob data using regular expressions

Shapes DataBlade Module Creates several opaque types for managing spatial data including R-tree index support

Smart Blob Information DataBlade Module

Includes a variety of useful routines for working with smart blobs

SqlLib C SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

SqlLib Java SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

Versioning Table Access Method

Permits users to create and manage versioned tables

We will look closer at two bladelets which could assist with migration the Exec datablade and SQLLib

Informix Exec bladelet for Dynamic SQL Often it is desirable to execute a SQL query that is generated at run-time within the RDBMS For example a developer may not know the name of the temporary table they wish to run the query against or they might want to append predicates to a query In external programs this can be accomplished using the ESQLC SQLCA and DESCRIPTOR facilities Unfortunately the INFORMIX Stored Procedure Language (SPL) does not support Dynamic SQL Queries must be hard-coded into the SPL logic The objective of the Exec bladelet is to remedy this situation Exec consists of user-defined functions that take an SQL query as an argument execute it and return the result (the format of which varies depending on which function is called and the kind of query) The Exec functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries For more details and download refer to

httpwwwibmcomdeveloperworksdb2zonesinformixlibrarydemoids_exechtml

There are three User Defined Routines (UDRs) in the Exec bladelet Two of them are external C functions that use the Server API (SAPI) These must be compiled into shared libraries on the target machine and you need to declare them to the server using CREATE FUNCTION statements The third UDR is a routine written in Informix Stored Procedure Language (SPL) that uses the first two UDRs to return a collection of items The Exec bladelet module consists of the following

1 EXEC The EXEC() function takes an LVARCHAR that it treats as a SQL query executes the query and returns a single LVARCHAR result string Depending on what kind of SQL statement is submitted Exec() returns a different result format

IBM Software Group IBM Information Management

Version 16 78

2 EXEC_FOR_ROWS The EXEC_FOR_ROWS() UDR is an iterator function which means it can return more than one result row Of course it only does so when it is asked to execute a SELECT Otherwise it behaves exactly as the EXEC() UDR Being an iterator function limits the ways in which such a UDR can be used It cannot be used in another SQL query The only place it can be used effectively is inside a SPL routine

3 EXEC_FOR_MSET EXEC_FOR_MSET() is a SPL routine that uses the EXEC_FOR_ROWS() routine introduced above Instead of returning a set of rows as an iterator or a single row as the EXEC() UDF does this UDR collects the results of the SQL query together into a single object a multi-set

Refer to Appendix E Sample Code for examples on using the EXEC bladelet functions

SqlLib DataBlade module (SqlLibC11 SqlLibJ11) The SqlLib DataBlade module implements SQL routines that the Informix does not support natively but that are supported by some other database vendors Source code is freely available for download and includes two implementations one in C (SqlLibC) and the other in Java (SqlLibJ)

The following routines are included

ascii - takes a single character as input and returns the ASCII value in decimal that corresponds to that character

ceil - takes a single numeric value as input and returns the smallest integer that is either equal to or greater than the input value

chr - takes an integer value and returns the character that is represented by the ASCII value (in decimal) of that integer

instr - searches for a value in a string and returns the position where it was found It

returns 0 if the search value was not found instrb - provides the exact same functionality as instr() but for single-byte character sets

sign - takes a numeric argument and returns an integer that indicates if the input value is

positive (1) negative (-1) or zero (0) to_decimal - converts the input character argument into a decimal type

to_float - converts the input character argument into a float type

to_integer - converts the input character argument into an integer type For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

IBM Software Group IBM Information Management

Version 16 79

A P P E N D I X A Planning guide

The checklist below will help an analyst determine which Oracle features which need to be converted to Informix and give some guidance on the effort involved Each porting task is listed They are followed by a quantity field used to determine how prevalent the item the difficulty or amount of effort involved 1 (low) to 5 (high) is used to estimate the amount of time needed to perform the task when the associated item exists in the application a moderate number of times What is moderate depends on the size of the application If there are an unusually large number of occurrences of an item then the effort should be increased Conversely if there are a small number of occurrences of an item then the effort should be decreased Each of these items is discussed in detail within this document Each heading corresponds to a section heading within the document

Tasks Quantity Effort

DDL

Identifiers Delimit identifiers named with Informix reserved words 2 Databases Determine database names and create databases 3 Replace Oracle tablespace names with Informix dbspace names 1 ANSI vs Non-ANSI considerations 3 Tables Convert create table statements 2 Convert DDL syntax 3 Reduce primary key length to 390 bytes 5 Data Types Convert Oraclersquos NUMBER data type 3 Convert VARCHAR columns 2 Convert Oraclersquos DATE data type 5 Convert raw data types 2 Convert Rowids 2 Indexes Convert Indexes 2 Views Remove CREATE VIEW statement options 1 Stored Procedures and Triggers Convert CREATE and REPLACE Stored Procedure and Trigger syntax 1 Oracle Extensions Remove non-supported Oracle extensions from DDL 1

Tasks Quantity Effort

DML

SQL Add the Informix AS clause to display labels 1 Replace non-supported DML syntax ^= hellip = ELSE IF 2 Convert Optimizer DirectiveHints 2 Convert InsertSelectUnion and InsertValueSelect statements 3

IBM Software Group IBM Information Management

Version 16 80

Convert Delete statement syntax 1 Convert temporary table processing 2 Convert Join statements + MINUS INTERSECT different data types 2 Convert sorts 4 Convert hard coded SQL error messages 3 Remove correlation names on the main table of Update and Delete statements

2

Replace original table names in SELECT statements using aliases 1 Convert hierarchical implementation (CONNECT BY PRIOR) 5 Host Variables Convert host variable format or add conversion processing 5 Functions Convert date and time functions 5 Convert aggregate functions 3 Convert mathematical functions 5 Convert string function syntax 1 Convert other unsupported Oracle functions 5 Macros Convert ISOPEN NOT FOUND ROWTYPE and TYPE macros 3 Pseudo-Columns Convert Level processing 3 Convert Rownum processing 2 Update Using Cursors Convert WHERE CURRENT OF processing for multiple table joins 5 Convert FOR UPDATE with a HOLD cursor processing 2 Convert concurrency processing from Oraclersquos implicit to Informixrsquos explicit

4

System Tables Convert system table references 1

Tasks Quantity Effort

Stored procedures Break stored procedures greater than 64K in size into smaller ones 2 Convert Oraclersquos stored procedure packages 3 Convert exception processing 5 Convert error handling (SQLCA) 2 Convert Oraclersquos global cursor processing 5 Convert Oraclersquos explicit cursor processing 2 Convert flow control processing 5 Convert Oraclersquos implicit variable declaration and assignment 3 Convert Oraclersquos BOOLEAN variable type 1 Convert binary data type processing Convert Oraclersquos dynamic SQL processing 5 Triggers Convert multi-functional triggers 3 Convert Insert and Update triggers which are not supported in Informix 5 Place logical statements in a stored procedure 5 Constraints Convert constraint enabling and disabling processing 5 DUAL table Convert Dual table processing 4

Embedded SQL

Host variables

IBM Software Group IBM Information Management

Version 16 81

Convert declaration overrides 1 Convert array processing 5 Convert Oraclersquos formatting functions 4 SQL structures Convert SQLDA processing 5 Convert ORACA processing 1 Pre-compiler options Convert Oracle pre-compiler options 1 Embedded PLSQL Convert Oraclersquos Embedded PLSQL 5 ODBC Convert Oraclersquos OCI 5 Convert database library calls Convert global area processing Convert fetch cycle Convert RAW data type processing Convert parameter bindings Embedded SQL for C Convert VARCHAR processing 2 Embedded SQL for COBOL Convert VARCHAR processing 2 Convert 88 Level processing in COBOL 2 Convert Redefine processing in COBOL 4

Tasks Quantity Effort

Application architecture

Transaction processing Convert application to Informix transaction processing 5 Convert multiple connect processing 5 Convert savepoints Concurrency Address Informix locking processing na 2 User authentication Address Informix security processing na 4

Environment

Convert make files 2 Convert shell scripts shell startup scripts and command files 2 Convert script substitution variables

IBM Software Group IBM Information Management

Version 16 82

A P P E N D I X B Syntax comparison

See the Informix Guide to SQL Syntax for more information on each item

Oracle Informix Boolean AND AND AND NOT NOT NOT OR OR OR Greater Than or Equal To gt= gt= Less Than or Equal TO lt= lt= Not Equal ltgt = or ^= ltgt or = Identifiers letters numbersrdquo_rdquordquo$rdquordquordquo letters numbers and ldquo_rdquo Data types Character CHAR CHAR Long Character VARCHAR (2000) if lt= 2000

LONG VARCHAR if gt 2000 CHAR or TEXT

Number (2 bytes) NUMBER SMALLINT Number (4 bytes) NUMBER INTEGER Number (gt 4 bytes) NUMBER DECIMAL Image LONG RAW CLOB BLOB BYTE TEXT CLOB BLOB DML Comments -- hellip -- hellip Assignment var1 = expression LET var1 = expression Condition ELSE IF ELSE or ELIF

IF Aggregate functions Average AVG(expression) AVG(ALL

expression) AVG(DISTINCT expression)

AVG(expression) AVG(ALL expression) AVG(DISTINCT column_name) AVG(UNIQUE column_name)

Count COUNT() COUNT (expression) COUNT(ALL expression) COUNT (DISTINCT expression)

COUNT() COUNT(DISTINCT column_name) COUNT (UNIQUE column_name)

Maximum MAX(expression) MAX(ALL expression) MAX(DISTINCT expression)

MAX(expression) MAX(ALL expression) MAX(DISTINCT column_name) MAX(UNIQUE column_name)

Minimum MIN(expression) MIN(ALL expression) MIN(DISTINCT expression)

MIN(expression) MIN(ALL expression) MIN(DISTINCT column_name) MIN(UNIQUE column_name)

Sum SUM(expression) SUM(ALL expression) SUM(DISTINCT expression)

SUM(expression) SUM(ALL expression) SUM(DISTINCT column_name) SUM(UNIQUE column_name)

Algebraic functions Round ROUND(expressionrounding

factor) ROUND(expressionrounding factor)

Statistical functions Standard Deviation STDEV(expression) STDDEV(expression) Variance VARIANCE(expression) VARIANCE(expression) Range RANGE(expression)

IBM Software Group IBM Information Management

Version 16 83

String functions

Trim LTRIM(expression) RTRIM(expression)

LTRIM(expression) RTRIM(expression)

Length LENGTH(string) LENGTH(string) Like LIKE(string) LIKE(string) Like (single character) _ _ Like (wildcard) String Delimiter lsquo or ldquo lsquo or ldquo Escape Character set within LIKE clause using

ESCAPE ldquordquo to make ldquordquo the escape character

or set within LIKE clause using ESCAPE ldquordquo to make ldquordquo the escape character

Stored procedures Create CREATE OR REPLACE

PROCEDURE procedure_name (var1 IN CHAR(1) var2 OUT DATE var3 IN OUT NUMBER)

DROP PROCEDURE procedure_name CREATE PROCEDURE procedure_name (var1 CHAR(1) var3 INTEGER) RETURNING DATE INTEGER

Arguments EXECUTE PROCEDURE procedure_name (var1 IN var2 OUT var3 IN OUT)

EXECUTE PROCEDURE procedure_name (var1 var3) RETURNING var2 var3

IBM Software Group IBM Information Management

Version 16 84

A P P E N D I X C Database concepts

The table below illustrates the relationship between each database vendorrsquos database objects

Oracle Informix

Database name attached to a group of files Specific database name

Data file Chunk

Tablespace (logical partition) or Segments (Index Segment Table Segment and so on)

Dbspace

Extent Extent

Rollback Segment Physical Log

Redo Log Logical Log

System tablespace Root dbspace

Temporary tablespace Temporary dbspaces dbspacetemp environment variable or dbspacetemp onconfig parameter

Pointer Blobspace Sbspace

Table partitioning table fragmentation

Database link Not supported

Snapshot Not supported

oerr utility finderr utility

sqldba and svrmgrl - monitor utilities onstat and oncheck utilities

SQLPlus utility dbaccess utility

ProC ESQLC

ProCOBOL ESQLCOBOL

SQLNET INet

OCI Like the ESQL function library after pre-compiling if they were publically documented

Read Consistency COMMITTED READ LAST COMMITTED

IBM Software Group IBM Information Management

Version 16 85

A P P E N D I X D Sample code

User defined functions User Defined Routines (UDR) can be developed to extend the capabilities of the database and provides the option to create UDRs to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or rename an Informix function to the corresponding Oracle function name

CONCAT

CREATE PROCEDURE concat (str1 VARCHAR(255) str2 VARCHAR(255)) RETURNING VARCHAR(255) RETURN str1 || str2

END PROCEDURE

INSTR

CREATE PROCEDURE instr( str VARCHAR(255) mask VARCHAR(255) strt SMALLINT DEFAULT 1 occur SMALLINT DEFAULT 1 ) RETURNING INT DEFINE slen SMALLINT DEFINE mlen SMALLINT DEFINE tempstr VARCHAR(255) DEFINE tempmask VARCHAR(255)

DEFINE nomatch SMALLINT DEFINE count SMALLINT DEFINE pos SMALLINT DEFINE retpos SMALLINT DEFINE i SMALLINT DEFINE j SMALLINT DEFINE srchstrt SMALLINT LET slen = LENGTH(str) LET mlen = LENGTH(mask) LET count = 0 LET nomatch = 0 LET pos = 1 LET retpos = 1 LET tempstr = LET tempmask = LET srchstrt = strt

IF (strt lt 0) THEN - reverse the str FOR i = 1 TO slen LET tempstr = str[11] || tempstr LET str = str[2255] END FOR -- reverse the mask FOR i = 1 TO mlen LET tempmask = mask[11] || tempmask LET mask = mask[2255] END FOR

IBM Software Group IBM Information Management

Version 16 86

LET srchstrt = strt -1 LET str = tempstr LET mask = tempmask END IF FOR j = 1 TO slen LET tempstr = str LET tempmask = mask FOR i = 1 TO mlen IF (tempmask[11] = tempstr[11]) THEN LET nomatch = 1 EXIT FOR END IF LET tempmask = tempmask[2255] LET tempstr = tempstr[2255]

END FOR IF (nomatch = 0) THEN IF (pos gt= srchstrt) THEN LET count = count + 1 END IF IF (count = occur) THEN IF (strt lt 0) THEN RETURN slen - pos + 1 ELSE RETURN pos END IF END IF END IF LET str = str[2255] LET nomatch = 0

LET pos = pos + 1 END FOR RETURN 0 END PROCEDURE

YYYYMMDD

CREATE PROCEDURE yyyymmdd (str VARCHAR(10)) RETURNING varchar(8)

DEFINE retstr VARCHAR(8)

IF str IS NULL THEN

RETURN NULL

ELSE

LET retstr = str[710] || str[12] || str[45]

RETURN retstr

END IF

END PROCEDURE

Using EXEC bladelet functions

IBM Software Group IBM Information Management

Version 16 87

Using EXEC

Note the ROW data type variable can be referenced using table and column syntax CREATE PROCEDURE example1() RETURNING INTEGER

DEFINE sql_stmt LVARCHAR(255)

DEFINE rcnt ROW(val INTEGER)

LET sql_stmt = select count() from items where manu_code = lsquoANZrsquo

EXECUTE FUNCTION EXEC(sql_stmt) INTO rcnt

RETURN rcntval

END PROCEDURE

Using EXEC_FOR_ROWS

CREATE PROCEDURE example2() RETURNING INTEGER CHAR(1)

DEFINE rs_rowdata ROW(customer_num INTEGER call_code CHAR(1))

DEFINE sql_stmt LVARCHAR(255)

LET sql_stmt = select customer_num call_code from cust_calls where

customer_num = 106

FOREACH

EXECUTE FUNCTION EXEC_FOR_ROWS(sql_stmt) INTO rs_rowdata

RETURN rs_rowdatacustomer_num rs_rowdatacall_code WITH RESUME

END FOREACH

END PROCEDURE

Using EXEC_FOR_MSET

Note the DEFINE statement for the variable rs_data Collection data types used in a SPL routine cannot be defined using the LIKE attribute in the DEFINE statement CREATE PROCEDURE example3() RETURNING INTEGER VARCHAR(8)

DEFINE v_customer_num LIKE accountscustomer_num

DEFINE v_account_cd LIKE accountsaccount_cd

DEFINE rs_data MULTISET(ROW(

r_customer_num INTEGER

r_account_cd VARCHAR(8)) NOT NULL)

DEFINE sql_stmt LVARCHAR

LET sql_stmt = select customer_num order_num from orders where

company_id = 51155

EXECUTE FUNCTION EXEC_FOR_MSET(sql_stmt) INTO rs_data

FOREACH

SELECT r_customer_num r_account_cd INTO v_customer_num

v_account_cd FROM TABLE(rs_data)

RETURN v_customer_num v_account_cd WITH RESUME

END FOREACH

END PROCEDURE

IBM Software Group IBM Information Management

Version 16 88

Date arithmetic Informix has extensive capabilities for manipulating dates and times You can add or subtract DATE and DATETIME variables from each other You can add or subtract an INTERVAL to a DATE or DATETIME

UNITS Keyword

When working with INTERVAL values sometimes it is necessary to specify the precision with which you are dealing For example suppose you have the following field defined To add 10 days to the lead time you could use a SQL statement like this

SELECT lead_time + INTERVAL(10) DAY to DAY FROM orders

-or- SELECT lead_time + 10 UNITS DAY FROM orders

Using EXTEND function

The EXTEND function allows operations between data types of different precisions SELECT

EXTEND(myvar YEAR to MINUTE) ndash INTERVAL(5) MINUTE to MINUTE

FROM member

Calculate Week Of The Year

SELECT ROUND((TODAY - DATE(0101||YEAR(TODAY))) 7 + 5) FROM DUAL

Number of days difference SELECT DATE(0106||YEAR(TODAY)) - DATE(01062005) FROM DUAL

Number of weeks difference

SELECT ROUND((DATE(0106||YEAR(TODAY)) - DATE(01062005))

7 + 5) FROM DUAL

String representation of date and time

Day and date

SELECT TO_CHAR(TODAY A B d Y) FROM dual

-returns month day and 4 digit year-

Tuesday January 03 2006

Abbreviation of day of week

SELECT SUBSTR(TO_CHAR(TODAY A B d Y R)13) FROM dual

-or-

SELECT TO_CHAR(TODAY a) FROM dual

-returns MON TUE WED THU FRI SAT SUN-

Returning the number of rows affected

IBM Software Group IBM Information Management

Version 16 89

Within SPL routines you can use the DBINFO function to find out the number of rows that have been processed in SELECT INSERT UPDATE DELETE EXECUTE PROCEDURE and EXECUTE FUNCTION statements

CREATE FUNCTION del_rows(pnumb INT) RETURNING INT

DEFINE nrows INT

DELETE FROM sec_tab WHERE part_num = pnumb

LET nrows = DBINFO(sqlcasqlerrd2)

RETURN nrows

END FUNCTION

To ensure valid results use this option after SELECT and EXECUTE PROCEDURE or EXECUTE FUNCTION statements have completed executing If you use the sqlcasqlerrd2 option within cursors make sure that all rows are fetched before the cursors are closed

Using an Informix collection data type

A collection data type as a VARRAY

In the following examples the collection data types of MULTISET and SET are used in a function to hold a collection of values You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value Informix SPL allows you to declare a cursor for a collection variable using the FOREACH statement called a collection cursor

Also demonstrated is how to utilize a variable declared with the keyword COLLECTION A variable declared as type SET MULTISET or LIST is a typed collection variable It can hold a collection of its specified data type only However a COLLECTION is an un-typed (or generic) collection variable that can hold a collection of any data type

This function will build a MULTISET list of values

CREATE FUNCTION func1() RETURNING MULTISET(INTEGER NOT NULL)

DEFINE v_array_of_ints MULTISET(INTEGER NOT NULL)

INSERT INTO TABLE (v_array_of_ints) VALUES(1)

INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(5)

INSERT INTO TABLE (v_array_of_ints) VALUES(4)

RETURN v_array_of_ints

END FUNCTION

This function will receive the COLLECTION list of values from func1

CREATE FUNCTION func2() RETURNING INTEGER

--

-- DEFINE lmset MULTISET(INTEGER NOT NULL)

--

DEFINE lmset COLLECTION

DEFINE v_int INTEGER

--

-- call func1 to populate local multiset variable

--

LET lmset = func1()

--

-- tally a count the number of elements

--

FOREACH

SELECT COUNT() INTO v_int FROM TABLE(lmset)

IBM Software Group IBM Information Management

Version 16 90

RETURN v_int WITH RESUME

END FOREACH

--

-- return the values

--

FOREACH

SELECT INTO v_int FROM TABLE(lmset)

RETURN v_int WITH RESUME

END FOREACH

END FUNCTION

NOTE In the example func2 a duplicate declaration for the ldquolmsetrdquo variable as a MULTISET data type has been commented out by declaring the variable as a COLLECTION it can accept any of the 3 types (MULTISET SET and LIST)

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

4 (row count) 1 2 5 4

By using a SET data type inserts will not permit duplicates

CREATE FUNCTION func1() RETURNING SET(INTEGER NOT NULL) DEFINE v_array_of_ints SET(INTEGER NOT NULL) INSERT INTO TABLE (v_array_of_ints) VALUES(1) INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(2) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) RETURN v_array_of_ints END FUNCTION

NOTE Because func2 is expecting a un-typed COLLECTION variable func1 does not have to be dropped and recreated It can receive a value from any Collection Data Type (MULITSET SET and LIST)

The functionrsquos return values would change to (with duplicates suppressed)

EXECUTE FUNCTION func2()

(expression)

3 (row count) 1 2 5

Using a LIST data type support for assigning values based on ordinal position

IBM Software Group IBM Information Management

Version 16 91

CREATE FUNCTION func1() RETURNING LIST(INTEGER NOT NULL)

DEFINE v_array_of_ints LIST(INTEGER NOT NULL) -- -- first insert no ordinal position can be established By default the -- database server inserts LIST elements at the end of the list -- INSERT AT 5 INTO TABLE (v_array_of_ints) VALUES(5) INSERT AT 1 INTO TABLE (v_array_of_ints) VALUES(1) INSERT AT 2 INTO TABLE (v_array_of_ints) VALUES(2) -- -- Only 3 LIST elements exist position 4 has not been instantiated -- this element will insert at the end of the list -- INSERT AT 4 INTO TABLE (v_array_of_ints) VALUES(4) INSERT AT 3 INTO TABLE (v_array_of_ints) VALUES(3) RETURN v_array_of_ints END FUNCTION

NOTE The elements of a LIST have ordinal positions with a first second and third element in a LIST To support the ordinal position of a LIST the INSERT statement provides the AT clause This clause allows you to specify the position at which you want to insert a list-element value Note the behavior of the ordinal positioning above preceded by a commented explanation

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

5 (row count) 1 2 3 5 4

Using MULTISET and ROW to replace PLSQL TABLE and RECORD types

Creating variables using Informix Collection data types SET MULTISET and LIST in combination with ROW data types can be useful when migrating applications which use Oracle REF CURSORS as arguments to functions as well as Oracle collection data types TABLE and RECORD

Typical Oracle Package specification

CREATE OR REPLACE PACKAGE MyPackage

IS

TYPE recOrders IS RECORD (

order_num ordersorder_numTYPE

order_date ordersorder_dateTYPE

customer_num orderscustomer_numTYPE

po_num orderspo_numTYPE

)

TYPE tabOrders IS TABLE OF recOrders

INDEX BY BINARY_INTEGER

TYPE ref_curtype IS REF CURSOR

Both tabOrders or ref_curtype can be converted to the following Informix SPL definition

DEFINE tabOrders MULTISET(ROW(

IBM Software Group IBM Information Management

Version 16 92

order_num INTEGER

order_date DATETIME YEAR TO FRACTION(3)

customer_num INTEGER

po_num CHAR(10)) NOT NULL)

DEFINE ref_curtype MULTISET(ROW(

define columns based on query result set

) NOT NULL)

IBM Software Group IBM Information Management

Version 16 93

A P P E N D I X E Counting system objects

Using the system catalog

System catalog

Below is a list of SQL statements that will extract most if not all of the counts of system objects owned by user lsquoXXXrsquo

select count(table_name) from all_tables

where owner=rsquoxxxrsquo

select count() from dba_indexes

where owner=rsquoxxxrsquo

select count(synonym_name) from dba_synonyms

where owner=rsquoxxxrsquo

select count() from dba_views

where owner=rsquoxxxrsquo

select count() from dba_tab_columns

where length(column_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

and owner=rsquoxxxrsquo

select count distinct() from dba_tab_columns

and owner=rsquoxxxrsquo

select count() from dba_tables

where length(table_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_synonyms

where length(synonym_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_views

where length(view_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_indexes

where length(index_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and owner=rsquoxxxrsquo

IBM Software Group IBM Information Management

Version 16 94

select data_type count(data_type) from dba_tab_columns

where owner=rsquoxxxrsquo

group by data_type

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and length(data_type)gt254

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquonumberrsquo

and data_scale=0

and owner=rsquoxxxrsquo

Using SQL code

Built-in function references

The following instructions can be used to find references to built-in functions On the UNIX machine or the NT box where your code resides please create the following file as tmpfunctionlist

convert(

hextoint(

inttohex(

getdate(

datename(

datepart(

datediff(

dateadd(

months_between(

char(

char_length(

charindex(

compute(

difference(

length(

lower(

patindex(

replicate(

reverse(

right(

soundex(

space(

str(

stuff(

substring(

upper(

abs(

atn2(

log(

ceiling(

IBM Software Group IBM Information Management

Version 16 95

cot(

degrees(

floor(

radians(

rand(

sign(

to_char(

to_date(

to_number(

exception(

pi(

raise_application_error(

raiserror(

SQLCODE

rollback

savepoint

declare

decode(

nvl(

print(

rowid

waitfor

recompile

bcp

isopen(

notfound(

rowtype(

type(

Then please run the following program with the proper subdirectories

binksh

rm ndashf somehomeoutfile

cd somesourcedatabase

export sourcebase=rdquosomepathrdquo

for functor in `cat tmpfunction_list`

do

echo before find $functor

find $sourcebasedatabase -exec grep -i $functor gtgt

somehome$functoroutfile

find $sourcebaseintfc -exec grep -i $functor gtgt

somehome$functoroutfile

echo after find $functor

done

Object types and counts

This script attempts to count the objects of each type by grepping for CREATE statements containing the object type and counts procedure definitions that are inside package bodies which are not proceeded by a CREATE keyword It is not a sophisticated parser so the results may not be perfect

binbash if [ $1 = ] then

IBM Software Group IBM Information Management

Version 16 96

echo Usage objCountssh ltFilePatterngt return 1 fi declare -a objectTypes=(CLUSTER CONTEXT CONTROLFILE DATABASE DATABASE +LINK DIMENSION DIRECTORY DISKGROUP FUNCTION INDEX INDEXTYPE JAVA LIBRARY MATERIALIZED +VIEW MATERIALIZED +VIEW +LOG OPERATOR OUTLINE PACKAGE PACKAGE +BODY PFILE PROCEDURE PROFILE RESTORE +POINT ROLE ROLLBACK +SEGMENT SCHEMA SEQUENCE SPFILE SYNONYM TABLE TABLESPACE TRIGGER TYPE TYPE +BODY USER VIEW) echo for type in $objectTypes[] do if [ $type = PROCEDURE ] then echo $type object count `cat $1 | grep -icE ^ (|CREATE +|OR REPLACE +)b$typeb` else echo $type object count `cat $1 | grep -icE ^ (CREATE +|OR +REPLACE +)b$typeb` fi done

IBM Software Group IBM Information Management

Version 16 97

A P P E N D I X F Data type mapping

Oracle built-in data types (including ANSI types) can be converted to similar data types in the Informix database according to the mapping described here This table provides default mappings based on most common usage patterns in some cases another mapping may work better

In the following table n is used to indicate length p is used to indicate precision and s is used to indicate scale

Oracle data type Informixreg Server data type

BFILE LONG RAW BLOB

BLOB

BINARY_DOUBLE DOUBLE PRECISION

BINARY_FLOAT DOUBLE PRECISION

BINARY_INTEGER

PLS_INTEGER

NATURAL

NATURALN

POSITIVE

POSITIVEN

32-bit integers only used in PLSQL NATURAL and POSITIVE are unsigned integers

INTEGER

BOOLEAN (PLSQL only) BOOLEAN

CHAR(n) or CHARACTER(n) CHAR(n)

DATE DATETIME YEAR TO SECOND

DOUBLE PRECISION DOUBLE PRECISION

IBM Software Group IBM Information Management

Version 16 98

FLOAT

See note on FLOAT below

FLOAT

INTEGER INT

A 38-digit NUMBER sub-type May want to flag with a warning on possible overflow

INTEGER

INTERVAL DAY(p) TO SECOND(s)

Note Oracle fractional seconds have 9 digits

INTERVAL DAY(p) TO FRACTION(min(5 s))

INTERVAL YEAR(p) TO MONTH

INTERVAL YEAR(p) TO MONTH

LONG CLOB

CLOB

LONG VARCHAR (xxx)

Oracle recommends not using this type

LVARCHAR

NCHAR(n) NATIONAL CHAR(n) or NATIONAL CHARACTER(n)

NCHAR(n)

See National Language Types below

NCLOB CLOB

NUMBER

NUMBER(0)

NUMBER(p) NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s lt 10

NUMBER(3-2) 12300

INTEGER

IBM Software Group IBM Information Management

Version 16 99

NUMBER(p) NUMBER (p0)

Where precision (p) is greater than or equal to 10 and lt= 18

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and 10 lt= p-s lt 19

NUMBER(9-2) 12345678900

BIGINT

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is greater than or equal to s (that is s gt 0 and p gt= s)

NUMERIC (min(p32) min(s32))

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is less than s (that is s gt 0 and p lt s)

NUMBER(35) 000123

NUMERIC (min(s32)min(s32))

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s gt 18 and p-s lt= 32

NUMERIC (min(p-s32)0)

NUMBER(p s)

Where scale (s) is greater than 32 or pInformix-s is greater than 32

NUMERIC (32)

Scale cannot be greater than precision

NUMERIC(3232) would guarantee that digits to the left of the decimal would be lost Using a floating point decimal provides the simplest best way to capture as many digits in a value as possible

IBM Software Group IBM Information Management

Version 16 100

DEC

DECIMAL

NUMERIC

DEC(p)

DECIMAL(p)

NUMERIC(p)

DEC(p s)

DECIMAL(p s) NUMERIC(p s)

There is no difference within Oracle between these types and each other and these types and NUMBER The Oracle system catalogs contain the NUMBER type id for all declarations of these types and the integer types as well Declarations of these types can be mapped using the same rules as those for NUMBER

NVARCHAR2(n) NCHAR VARYING(n) NATIONAL CHAR VARYING(n) NATIONAL CHARACTER VARYING(n)

LVARCHAR(min(n 32767))

RAW(n) BLOB

REAL DOUBLE PRECISION

Record ROWTYPE

Using a CREATE ROWTYPE statement

ROWID INTEGER

SMALLINT SMALLINT

TIMESTAMP(p)

If p is not specified precision defaults to 6

DATETIME YEAR TO FRACTION(min(5 p))

UROWID(n) INTEGER

IBM Software Group IBM Information Management

Version 16 101

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is less than or equal to 255 (that is n lt= 255)

VARCHAR(n)

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is greater than 255 (that is n gt 255)

LVARCHAR(n)

XMLType CLOB

Notes on specific types are below

DOUBLE

The range of values for the DOUBLE PRECISION data type is the same as the range of the C double data type on your computer

VARCHAR

While Oracle VARCHAR data types have a limit of 4000 bytes an Informix Server VARCHAR data types has a limit of 255 bytes An Informix Server LVARCHAR has a limit of 32739 Bytes

NUMBER

Oracle abstracts its numeric types from the hardware and operating system through the use of its NUMBER type Most numeric types like INTEGER are actually NUMBERs internally When porting to a database server like Informix which retains more of a relationship between the operating system types and the database types it is essentially a one-to-many mapping and heuristics have to be used to determine the best-fit target type No single set of type mapping rules will fit all use scenarios The converter has default rules which fit the more common user patterns When considering a number represented as mantissa and exponent

mantissa x 10exponent

precision is the number of digits in the mantissa and scale is the negative exponent how many places to the right of the decimal point the least significant digit is located Oracle NUMBERs have a maximum precision of 38 and the maximum precision available in Informix native types is 32 The first step in a type mapping is to truncate the target type precision to min(precision 32) The scale of a type can be considered its anchor point with respect to the decimal point The most

IBM Software Group IBM Information Management

Version 16 102

significant digit of a numeric type is located precision digits to the left of the decimal point and precision-scale digits to the right of the decimal point The start and end locations of the digits are used to determine the closest fitting Informix type The order of preference is INTEGER BIGINT NUMERIC(p s) and lastly NUMERIC(p) NUMERIC(p) in a non-ANSI mode database is a decimal type with a floating point type In an ANSI mode database the scale is implicitly 0 All Oracle integer declaration types such as INT INTEGER SMALLINT become NUMBER(38) type in the Oracle metadata In Oracle when precision is given but scale is not scale becomes 0 implicitly which makes the type in the set of integral types One exception to the general mapping rules is the NUMBER type specified without precision or scale Strictly speaking this has a floating point scale with 38 digits of precision but most commonly it is used where an integer is more appropriate Even if the user does specify INTEGER in a type definition when it comes out of the Oracle catalogs the type is NUMBER This is one case in particular where one type mapping will not fit well with all usage scenarios

National language types

Oracle Nchar types are allocated by number of characters where Informix is allocated by the number of bytes For Oracle the storage size of the characters varies with the encoding used and is always subject to the standard 32767 limit on maximum bytes but during declarations n always means the number of characters Oracle PLSQL supports explicit and implicit data type conversions These explicit and implicit data types are converted to syntax by using Informix Dynamic Servers explicit and implicit data type conversion mechanism

ROWID

Oracle databases support a pseudo-column named ROWID such that every row in every table is assigned an auto-generated ID Oracle also allows you to define a column of type ROWID which can be used as a foreign key to a ROWID pseudo-column Oracle ROWID columns contain data that if converted to a string are 18 characters long for example lsquoAAAQ+jAAEAAAAAeAANrsquo It is probably not advisable to migrate this data to an Informix database and instead use the Informix type which is an integer If there is a dependency on the values themselves and therefore need migrate the data then an integer type would not hold the values

TYPE

In PLSQL you can refer to the type of an existing variable field or column by using the TYPE attribute The converter replaces this reference directly by the type it refers to

ROWTYPE

In PLSQL you can refer to the record type that represents a row of a table a cursor or a cursor variable PLSQL scripts containing the ROWTYPE attribute are handled in the same way as a record type that has been previously declared

FLOAT

Oracle FLOAT type is a floating point number capable of storing up to 38 decimal digits or 126 binary digits It has a floating point scale that can exist outside the boundaries of what an Informix DECIMAL can represent A C language double or Informix float type is capable of only 16 digits so there is the chance that some data will be lost Using an Informix FLOAT type makes it so that less significant digits are lost in preference to more significant digits

IBM Software Group IBM Information Management

Version 16 103

References to subtypes declared in packages and PLSQL blocks are converted to the Informix Server equivalent base types Variables of type RECORD are not translated by the DDL Converter at the time of this writing They will be handled by the stored procedure converter

XMLType

Informix does not have a built-in type for representing XML The nearest approximation is to store it in a CLOB Another character type like LVARCHAR can be used if it can be determined that the actual data will fit in it

Page 3: Oracle to IBM Informix Server Porting Guide

IBM Software Group IBM Information Management

Version 16 3

Document History Revision History

Authoring Original Document (May 2000) Glen Black Frank Martino amp Tim Tobey Informix Software Incorporated Partner Engineering Organization Revisions for Informix Dynamic Server2000 Version 6 (July 2000) Tim Tobey Informix Software Incorporated Partner Engineering Organization Updated to IBM Informix Dynamic Server Database Version 9 Release 4 (February 2004) Christine Normile Informix Dynamic Server Product Manager IBM Software Group Information Management Updated material for Sequence Objects (December 2004) Sam Marino DB2 Business Partner Technical Enablement IBM Information Management Solutions IBM Software Group Updated to IBM Informix Dynamic Server Database Version 1000 (January 2006) Sam Marino Business Partner Technical Enablement ndash Data Services IBM Information Management IBM Software Group Updated to IBM Informix Dynamic Server Database Version 1110 (December 2007) Sam Marino IBM Business Partner Technical Enablement ndash Data Services IBM Information Management IBM Software Group Updated material for delimited identifiers metadata extraction type conversion and miscellaneous (June 2012) Chris Golledge IBM Information Management IBM Software Group

Contributions Technical Reviewers Keshava Murthy IBM Informix Database Server Development IBM Software Group Information Management Lakshman Sakaray IBM Database Migration Toolkit IBM Software Group Information Management

IBM Software Group IBM Information Management

Version 16 4

Table of Contents

C H A P T E R 1 INTRODUCTION 8

PURPOSE 8 PRODUCT OVERVIEW 8 ORGANIZATION 8 CONVENTIONS 9

C H A P T E R 2 DEFINING THE PROBLEM SPACE 11

EXTRACTING THE OBJECTS TO BE MIGRATED 11 Working With Oracle Dump Files 11

C H A P T E R 3 DATA DEFINITION LANGUAGE 15

IDENTIFIERS 15 Delimited identifiers 15 Explicit versus implicit schemaowner names 17 Reserved words or keywords 18 Summary 19

DATABASES 19 Databases database names and instances 19 ANSI vs non-ANSI 20

TABLESPACES AND DBSPACES 20 TABLES 21

Attributes and general syntax 21 Lock mode 21 Storage 21 Constraints 22 ALTER TABLE 22 Data Partitioning 23

DATA TYPES 25 Numeric 25 CHAR VARCHAR and LVARCHAR 26 Date and Time 27 Interval 27 Raw data and Large Objects 28 ROWID 28 User-defined types 29 Complex data types 30

SEQUENCE OBJECTS 30 Oracle sequences 30 Informix sequences 30

INDEXES 30 Composite indexes 30 Maximum key size 31 Index fragmentation 31 General index information 31

VIEWS 32 STORED PROCEDURES AND TRIGGERS 32 ORACLE EXTENSIONS 33

C H A P T E R 4 DATA MANIPULATION LANGUAGE 34

SQL 34 Labels using keywords 34 Inequality operations 34 Selects 34 Optimizer directives 34

IBM Software Group IBM Information Management

Version 16 5

External optimizer directives 35 Inserts 36 Temporary tables 36 Outer joins 36 Sorts 36 Exceptions 37 Correlation names 37 Aliases 37 Hierarchical queries 37 Truncate 39

HOST VARIABLES 40 DATE AND TIME FUNCTIONS 41

SYSDATE 41 Number formats 41 Date formats 42 The RR date format element 43

USER-DEFINED ROUTINES 43 COMPATIBLE SQL FUNCTIONS 43 AGGREGATE FUNCTIONS 43 MATHEMATICAL FUNCTIONS 44 STRING FUNCTIONS 44

LENGTH 44 LTRIM and RTRIM 44 Oracle Extensions 44

OTHER ORACLE FUNCTIONS 44 MACROS 45

ISOPEN and NOT FOUND 45 ROWTYPE 45 TYPE 45

PSEUDO-COLUMNS 45 LEVEL 46 ROWID 46 ROWNUM 46

UPDATE USING CURSORS 49 SYSTEM TABLES 50 STORED PROCEDURES 50

Size limit 50 Parameter limit 50 Packages 51 Routines 51 Exceptions 51 Error handling 52 Cursors 52 Variable declaration and assignment 53 Boolean 53 Binary data types 53 Dynamic SQL 53 Compiler 53

TRIGGERS 54 CONSTRAINTS 55 DUAL TABLE 55

C H A P T E R 5 EMBEDDED SQL 57

HOST VARIABLES 57 Declaration override 57 Arrays 57 Formatting 58

SQL STRUCTURES 59

IBM Software Group IBM Information Management

Version 16 6

SQLCA 59 SQLDA 60 ORACA 61

PRE-COMPILER OPTIONS 61 EMBEDDED PLSQL 61 ORACLE CALL INTERFACE 61

Database library calls 62 Global area processing 62 Fetch cycle 62 RAW binary data type processing 62 Parameter bindings 62

EMBEDDED SQL FOR C 63 VARCHAR 63 Host variables 63

EMBEDDED SQL FOR COBOL 63 VARCHAR 63 Level 88 64 SQLDA 64 REDEFINES 64 Tips 64

ODBC 64

C H A P T E R 6 APPLICATION ARCHITECTURE 65

TRANSACTION PROCESSING 65 Autonomous Transaction 66 Savepoints 67

CONCURRENCY 67 Row Level Locking 67 Transaction Isolation Level 68

C H A P T E R 7 SECURITY 70

USER AUTHENTICATION 70 Operating system security 70 Non-operating system security 70

ROLE BASED AUTHORITY 71 COLUMN-LEVEL ENCRYPTION 71

Passwords and hints 71 Encrypting a column 72 Querying an encrypted column 72 Performance impact of encryption 73 Storage considerations 73 Compliance regulations 73

C H A P T E R 8 ENVIRONMENT 74

SCRIPTS 74 SQL script substitution variables 74

UTILITIES 75 SYSTEM CATALOG 75

C H A P T E R 9 USING BLADELETS 76

WHAT IS A BLADELET 76 INFORMIX EXEC BLADELET FOR DYNAMIC SQL 77 SQLLIB DATABLADE MODULE (SQLLIBC11 SQLLIBJ11) 78

A P P E N D I X A PLANNING GUIDE 79

A P P E N D I X B SYNTAX COMPARISON 82

IBM Software Group IBM Information Management

Version 16 7

A P P E N D I X C DATABASE CONCEPTS 84

A P P E N D I X D SAMPLE CODE 85

DATE ARITHMETIC 88 UNITS Keyword 88 Using EXTEND function 88

STRING REPRESENTATION OF DATE AND TIME 88 Day and date 88 Abbreviation of day of week 88

USING AN INFORMIX COLLECTION DATA TYPE 89 A collection data type as a VARRAY 89 Using MULTISET and ROW to replace PLSQL TABLE and RECORD types 91

A P P E N D I X E COUNTING SYSTEM OBJECTS 93

USING THE SYSTEM CATALOG 93 System catalog 93

USING SQL CODE 94 Built-in function references 94 Object types and counts 95

A P P E N D I X F DATA TYPE MAPPING 97

DOUBLE 101 VARCHAR 101 NUMBER 101 National language types 102 ROWID 102 TYPE 102 ROWTYPE 102 FLOAT 102 XMLType 103

IBM Software Group IBM Information Management

Version 16 8

C H A P T E R 1 Introduction

This document is a technical document describing the differences between Oracle and Informixreg Dynamic Server (IDS) functionality and syntax This porting guide details differences between Oraclersquos 10g release 1 (101) and 10g release 2 (102) and Informix Dynamic Server (version 1110) In addition it can be a useful reference for all migrations between the two database servers regardless of version In addition to DDL DML and overall SQL syntax this document explores the differences between Oracle and Informix with regards to object technology through the use of large objects user defined types and user defined routines It also looks at the differences between Oraclersquos table partitioning and Informixrsquos table fragmentation Part of the explanation is a discussion on what needs to be changed to make an application running on an Oracle database run on an Informix database If there is more than one way to port some piece of functionality alternatives and recommendations are also discussed This document is intended to be a living document Missing items better ways of implementing Oracle functionality in Informix other than what is documented here examples to better illustrate a point and other suggestions should be sent to Chris Golledge (golledgeusibmcom) so they may be included with future revisions

Purpose This document should be used as a guide to assist in porting applications that run on an Oracle database server to run on an Informix database server Regardless of whether a porting effort will be completely manual or if tools will be utilized this document can provide value Obviously if the port is performed manually this guide will provide the most value If the port will utilize tools then analysis can be performed using this guide to determine how much of the application the tools will convert and how much must be converted manually In any case this guide is intended to be used to both visualize the scope of a porting effort and to aid in the porting effort by addressing the technical issues This document will be refined based on usersrsquo experiences to identify as many of the porting issues as possible at the beginning of a project

Product overview IBM Informix Server provides high performance and scalability with legendary reliability and nearly hands-free administration of databases of all size IDS is industry proven on UNIX Linux or Windows platforms with online transaction processing (OLTP) systems data marts data warehouses and e-business applications The IDS 11 release features significant additions over prior versions It supports the services-oriented architecture (SOA) model for application integration and offers many new features for data replication continuous availability and ldquohands freerdquo database administration

Organization This document is broken into sections to logically discuss the different database concepts Some of the sections may contain the same sub-sections for example stored procedures and triggers

IBM Software Group IBM Information Management

Version 16 9

are discussed in the DDL and DML sections This allows separate discussions on the issues facing the same item in each area For example the issues surrounding creating a stored procedure are discussed in the DDL section and the issues surrounding the stored procedure language are discussed in the DML section Among the other references the ldquoPlanning Guiderdquo appendix contains a quick reference of most of the differences between Oracle and Informix along with the degree of difficulty to port each difference This reference is intended for use in the planning process to illustrate the scope and the effort required to perform the porting project Some of the stored procedure logic used to convert Oracle functions is included in the appendix rdquoSample coderdquo

Conventions The conventions used in this document include

Courier Text Distinguishes a logic example

from regular text

Example Illustrates a point In most cases an Oracle example will be followed by an Informix example

Italicized Text Signifies a substitution in other words substitutes for the italicized word the actual object the word is describing for example table_name column_name and so on

UPPER CASE TEXT Signifies database vendor reserved words or statements such as INTEGER CREATE TABLE and so on

Bold example text highlights the item that is being explained

IBM Software Group IBM Information Management

Version 16 10

IBM Software Group IBM Information Management

Version 16 11

C H A P T E R 2 Defining the Problem Space

It is important to define the set of objects to be migrated and it is better if effort is put into this prior to beginning the actual migration This is true if you are the responsible for both the database in general and its migration from one supporting DBMS to another but it is particularly true that there be a clear agreement on the scope of what is to be migrated if the migration is to be performed by a party other than the one with long term responsibility for the database Defining the scope will involve extracting a representation of the objects to be migrated out of the Oracle system catalogs and representing them in some format that can be manipulated into constructs that can be used in Informix

Extracting the objects to be migrated It is possible to represent the objects in more than one language Using the SQL language is the most common method and it will be the only one discussed at length in this document (in its current revision) However it is also possible to express database objects in XML SQL has the advantage that the standard common grammars are widely understood in the context of defining tables indexes etc XML would have an advantage of not requiring parsing that is sensitive to the minor differences in ways of expressing essentially the same object

Working With Oracle Dump Files

There exist 3rd

-party tools for reading system catalogs but it is doubtful that any can read the Oracle catalogs more reliably than Oraclersquos own tools There are two incompatible export and import tool sets used by Oracle The older tools are imp and exp and the newer ones are impdp and expdp where dp stands for Data Pump Oracle has encouraged the use of the newer tools instead of the older ones since the newer ones were introduced at version 10 Nonetheless there are many Oracle users still using imp and exp In the discussions below only the metadata will be extracted into a dump file That is because any data in the dump file will be in a proprietary format and very likely some of the data will have to go through a type conversion process before being loaded into an Informix system Oracle exported data generally cannot be used to load a database in Informix Export and Import

If someone has given you a dump file created with the older export tool there exist tools such as The DDL Wizard by Net 2000 Limited which can be used to extract viable DDL The contents of the dump file contain the SQL for re-creating the database but they are not in a readily usable format The older export and import tools are also more sensitive to the layout of the tablespaces than impdb The ability to extract DDL from the dump file in a usable form segmented by whatever grouping you choose is limited compared to what can be achieved through the Data Pump versions

IBM Software Group IBM Information Management

Version 16 12

It may be tempting to feed the dump file into the IBM Migration Toolkit (MTK) or other tool that works on SQL flat files This will not work MTK works on flat text SQL files and the dump file is binary If you open it up you can see what may be a large number of SQL statements but there are also binary codes within the same file That binary data will prevent MTK from being able to process it Getting SQL statements

If you want to get the SQL statements out of the dump file as they would be executed on the server there is an option available from the import tool itself show=y

imp myIDmyPWD as sysdba file=myFiledmp

full=yes show=y gt dmp_showtxt

This will produce a file which contains the statements but they are wrapped in quotes The contents will look something like

ALTER SESSION SET CURRENT_SCHEMA= SYSTEM CREATE UNDO TABLESPACE TBSPC1 BLOCKSIZE 8192 DATAFILE DORACLEORADA TASCHEMA1CHUNKDBF SIZE 387973120 AUTOEXTEND ON NEXT 5242880 MAXS IZE 32767M EXTENT MANAGEMENT LOCAL

which makes them strings instead of SQL statements Fixing this is a two-step process

-- removes quotes from the start of lines

sed s^ g dmp_showtxt gt step1txt

-- removes quotes from the end of lines

sed s$g step1txt gt dmp_step2sql

The statements are still not correctly formatted because they have been truncated to a fixed length and line-endings inserted However at this point it is possible to get a count of how many of each object type there is using the script in the appendix ldquoGetting an initial count of database objectsrdquo

Data Pump Export and Import

These newer tools provide better performance and more capabilities than their predecessors Please refer to documentation on Oracle for a complete description searches for ldquoData Pump Importrdquo and ldquoData Pump Exportrdquo should return relevant results quickly Below is enough information to get started on defining and extracting the objects to be migrated Metadata can be filtered through the use of the export mode clause and INCLUDE and EXCLUDE parameters However any dependent object of an included or excluded object is likewise included or excluded For example if you include an index then the table associated with the index will also be included and if you exclude a table then any associated indexes will also be excluded The SQL that will generate all the objects in the dump file can be created by the impdp command with the SQLFILE parameter If the output file is very large you might want to break it into smaller pieces There are a couple of ways to do this and the one that is best for you somewhat depends

IBM Software Group IBM Information Management

Version 16 13

on how you intend to proceed with the conversion Data definition language (DDL) SQL for all the objects can be put into one file or the INCLUDE or EXCLUDE parameters can be added to direct Data Pump to filter on the types of objects If you put all the objects into one file then you can break that into smaller files by object type fairly easily because the objects are sorted by type in the SQL file So it is just a matter of cutting the file into smaller pieces This method may be preferred because it allows for you to do things like create all tables load the data and then create the indexes and triggers If the data set is large creating the indexes after loading the data can yield substantial performance improvements However this is less useful if you want to convert sets of objects according to dependencies in which case the filtering option is likely to be more useful Just to illustrate a difference between these two methods in one customer case the metadata dump file was about 18MB and putting all objects in one SQL file resulted in a file that was about 15MB The table definitions occupied a little under 300KB of the 15MB The output file generated by filtering on objects of type TABLE was just over 1MB The addition content was mostly GRANT INDEX and TRIGGER creation statements There were no differences in the CREATE TABLE statements themselves Examples

Prerequisite The Data Pump tools require the use of an Oracle DIRECTORY object This is basically a mapping between a name that exists within the DBMS and a system path It can be a tripping point but it provides an abstraction layer that for instance allows the same commands to work across systems with different disk layouts or different operating systems Creating a DIRECTORY on a Windows system from SQLPlus

SQLgtconnect as sysdba

SQLgtCREATE OR REPLACE DIRECTORY dumpDir AS ctemp

Note Make sure this directory is not read-only There also could be problems if the directory is a network drive on Windows these can be related to there being different users between the Oracle executable and the current user and those users having different permissions on the network drive

SQLgtGRANT read write ON DIRECTORY dumpDir TO userID

Creating a dump file of the entire database

expdp userNameuserPwd as sysdba FULL=Y dumpfile=DB_fulldmp

LOGFILE=LG_expdplog CONTENT=METADATA_ONLY DIRECTORY=dumpDir

Creating a dump file of just one schema

expdp userNameuserPwd as sysdba SCHEMAS=hr DIRECTORY=dumpDir

DUMPFILE=hr dmp LOGFILE=hr log CONTENT=METADATA_ONLY

Creating a dump of just the tables and their dependents

expdp userNameuserPwd as sysdba SCHEMAS=hr INCLUDE=TABLE

DIRECTORY=dumpDir DUMPFILE=hrdmp LOGFILE=hrlog

CONTENT=METADATA_ONLY

Creating a dump of just one table

expdp userNameuserPwd as sysdba SCHEMAS=hr

INCLUDE=TABLELIKE COUNTRIES DIRECTORY=dumpDir

DUMPFILE=hrdmp LOGFILE=hrlog CONTENT=METADATA_ONLY

IBM Software Group IBM Information Management

Version 16 14

Creatinge an SQL file from a dump file

impdp userNameuserPwd as sysdba DIRECTORY=dumpDir

DUMPFILE=hrdmp SQLFILE=dumpDirhrsql

The INCLUDE and EXCLUDE options are also valid when used with impdb so it may be easier to get a complete dump of everything to be migrated then use these options to create subsets of objects it smaller SQL files than it would be to create separate dump files It is easier to divide objects than to merge them together if they are not divided initially as wanted There is a caveat when using this impdp to generate an SQL file the object names will all be delimited identifiers Example

CREATE TABLE HRCOUNTRIES Because of differences between how Informix handles these and how Oracle handles these case-sensitivity issues could occur See the chapter on ldquoDelimited Identifiersrdquo and in particular the description of default shift problems If it can be determined that there are no name collisions if regular identifiers are used removing the quotation marks as part of the conversion might avoid many problems In other words if there are no objects whose names only differ in case like foo and FOO then changing every occurrence of ldquoFOOrdquo to FOO in the DDL could eliminate case-sensitivity issues in the application DML It depends on if the application code uses the delimited form of the name predominantly or not

IBM Software Group IBM Information Management

Version 16 15

C H A P T E R 3 Data Definition Language

Identifiers An identifier specifies the simple name of a database object such as a table name column name index name view name stored procedure name and so on The maximum length of an Oracle identifier is 30 characters and can contain letters numbers ldquo_rdquo ldquo$rdquo and ldquordquo although Oracle highly recommends that ldquo$rdquo and ldquordquo should not be used In contrast Informix identifiers have a maximum length of 128 characters and may contain letters numbers ldquo_rdquo and ldquo$rdquo (as long as ldquo$rdquo is not the first character) See the Delimited Identifiers section below for information This means that all Oracle identifiers containing a ldquordquo anywhere in the identifier or a ldquo$rdquo as the first character must be replaced or modified to remove those characters from the identifier

Delimited identifiers

Delimited identifiers are also known as quoted identifiers and sometimes as escaped identifiers They have been part of the SQL standard since SQL92 but existed in various database management systems (DBMS) prior to that time In a nutshell they are a way to preserve case sensitivity in object names as well as to allow objects to have names outside of the conventions of SQL regular identifiers Prior to the behavior of identifiers in general being standardized different DBMS vendors implemented different means of achieving case-insensitivity for object names some converted all regular identifiers to uppercase and some converted regular identifiers to lowercase By SQL99 the concept of case normal form was standardized to mean simply stated that if there exists an uppercase equivalent of any character in a name then the uppercase version is stored in the system catalogs and used for comparison purposes See the SQL99 standard chapter 5 section 2 and in particular items 21 and 22 for a formal description of case normal form and how it applies to identifier comparisons Delimited identifiers can be used to specify names for database objects that are otherwise identical to SQL reserved keywords such as TABLE WHERE DECLARE and so on The only database object for which delimited identifiers cannot be used is a database name Database administrators and application programmers do not always communicate to each other with 100 efficiency and there is no guarantee that within either of these pools every member codes by the standard practice of the other members After describing how delimited identifiers work in Informix there will be a description of how any inconsistency of usage and the differences between Oracle and Informix can introduce some migration hurdles DELIMIDENT Environment Variable

To use delimited identifiers with Informix you must set the DELIMIDENT environment variable While DELIMIDENT is set strings enclosed in quotation marks ( ldquo ) are treated as identifiers of database objects and strings enclosed in apostrophes ( rsquo ) are treated as literal strings If the

IBM Software Group IBM Information Management

Version 16 16

DELIMIDENT environment variable is not set strings enclosed in quotation marks are also treated as literal strings When you set the DELIMIDENT environment variable you cannot use quotation marks ( rdquo ) to delimit literal strings If DELIMIDENT is set the database server interprets all strings enclosed in quotation marks as SQL identifiers not string literals Commonly within Informix systems DELIMIDENT is set or not on the client side according to the design of the application However if you are converting a database and all applications accessing it from a system where every occurrence of quotation marks (ldquoobjectNamerdquo) indicates an identifier and not a string literal you may want to consider setting it in the server environment in order to avoid any inconsistency between clients where it is set and where it might not be Using Quotes in Strings The apostrophe ( rsquo ) has no special significance in string literals delimited by quotation marks Conversely double quote ( Prime ) has no special significance in strings delimited by apostrophes For example these strings are valid Nancyrsquos puppy jumped the fence

rsquoBilly told his kitten No rsquo A string delimited by quotation marks can include a double quote character by preceding it with another double quote as the following string shows Enter y to

select this row When the DELIMIDENT environment variable is set quotation marks can only delimit identifiers not strings Use of Uppercase Characters You can specify the name of a database object with uppercase characters but the Informix server shifts these to lowercase characters unless the DELIMIDENT environment variable is set and the name of the database object is enclosed in quotation marks In this case the database server treats the name of the database object as a delimited identifier and preserves the uppercase characters in the name Delimited Identifiers By default the character set of a valid SQL identifier is restricted to letters digits underscore and dollar-sign symbols If you set the DELIMIDENT environment variable however SQL identifiers can also include additional characters from the codeset implied by the setting of the DB_LOCALE environment variable See the Identifier section of the Informix Guide to SQL Syntax for more information Storage Object Names In Informix delimited identifiers can be used to specify non-alphanumeric characters in the names of database objects However delimited identifiers can not be used to specify non-alpha characters in the names of storage objects such as dbspaces and blobspaces To use delimited identifiers DELIMIDENT must be set both at compile and run times For example to set DELIMIDENT environment variable with sh or ksh issue the following at the command line prompt

export DELIMIDENT=

Note You do not need to assign a value to the environment variable and counter-intuitively setting DELIMIDENT=n has the same effect as DELIMIDENT=y Also in a Windows environment

set DELIMIDENT=

effectively undefines the variable Default shift problems

Any direct access of system catalog information involving names will cause problems when migrating from a system like Oracle where system catalog names are stored in uppercase to a system like Informix where the catalog names are stored in lowercase For example

CREATE TABLE foo (c1 int)

IBM Software Group IBM Information Management

Version 16 17

Within Oracle the following will return information about the table

select from sysall_objects where object_name = FOO

and the following will not

select from sysall_objects where object_name = foo

Conversely in Informix

select from systables where tabname = foo

will be successful and the same with FOO will not be A similar if not more common problem can occur when the table has been created without the name being delimited but is sometimes delimited when accessed by the application Per the standard foo == FOO == ldquoFOOrdquo but in Informix foo == FOO == ldquofoordquo In Oracle the following SELECT statement will be successful

SELECT FROM ldquoFOOrdquo

but within Informix this will result in an error ldquo206 The specified table (FOO) is not in the databaserdquo Likewise if the name is delimited in its definition such as

CREATE TABLE SCHEMA1TABLE1

this creates a table that can be referenced in Oracle without the name being delimited The statements

SELECT FROM schema1table1

and SELECT FROM SCHEMA1TABLE1

will be successful in the Oracle system but will fail in the Informix one In theory whether on object name is delimited or not should be the same in the database and at every occurrence within the application but this is not always the case It may be beneficial to examine whether delimited identifiers or regular identifiers are most commonly used in application code and use whichever is most common as a naming convention when translating the DDL

Explicit versus implicit schemaowner names

Another complication to keep in mind is that when the log mode is ANSI implicit and explicit owner names are treated differently between the Oracle and Informix servers In Oracle there is no difference in the case handling of an implicit owner name and an explicit one For example if connected to Oracle as scott the following CREATE TABLE statements

create table foo1(c1 int) create table scottfoo2(c1 int) create table SCOTTfoo3(c1 int)

all result in tables owned by SCOTT The following select statements in various forms that may be in application code will all run without error

select from foo1 select from scottfoo1

IBM Software Group IBM Information Management

Version 16 18

select from SCOTTfoo1 select from foo2 select from scottfoo2 select from SCOTTfoo2 select from foo3 select from scottfoo3 select from SCOTTfoo3

These statements will also run without error within a non-ANSI mode Informix database but not all of them will run successfully within an ANSI mode database This is because Informix does not uniformly fold the case of owner names and handles implicit names differently from explicit names so there will always be some combination of DDL and DML usage patterns that work within an Oracle system that do not work in an Informix one You can set ANSIOWNER before starting your Informix server but that will merely change which combinations do not work You may want to examine usage patterns within the applications and choose a naming convention when translating the DDL that matches the most common naming convention used in the applications Note This behavior of Informix forces a tradeoff between using an ANSI mode database which most closely matches the transaction behavior of Oracle and a non-ANSI mode database which has the least mismatch in identifier case sensitivity

Reserved words or keywords

Oracle and Informix both allow identifiers to be reserved words as long as they are delimited However Oracle and Informix reserved words differ In addition both systems have keywords like FROM that are not always reserved in the sense that using them as an identifier will always generate a syntax error There should be few problems with reserved words or keywords if identifiers that are delimited in the original database remain delimited in the destination database The appendix Keywords of SQL for IBM Informix in the Guide to SQL Syntax contains more information about Informix keywords Also one word non-delimited identifiers should be verified against the Informix reserved words list to ensure that they do not need to be delimited or renamed Although almost any word can be used as an identifier in Informix syntactic ambiguities can result from using reserved words as identifiers in SQL statements Delimited identifiers provide a way to use a reserved word as an identifier without causing syntactic ambiguities However doing this changes a case-insensitive name into a case-sensitive one and that means that every reference to the object has to be checked for issues related to case-sensitivity Essentially this is not much less work than changing the name of the object because in essence it is changing the name of the object Examples

The following example shows how to create an Informix table with a case sensitive table name

CREATE TABLE My_Customers (hellip)

The following example shows how to create a table whose name includes a space character If the table name were not in quotation marks () a space character or any other non-alpha character except an underscore ( _ ) or dollar sign ($) (see special conditions above) could be used in the name

CREATE TABLE My Customers (hellip)

IBM Software Group IBM Information Management

Version 16 19

The following example shows how to create a table that uses a keyword as the table name

CREATE TABLE TABLE (hellip)

To include a double-quote () within a delimited identifier the double-quote () must be preceded with another double-quote () as shown in the following example

CREATE TABLE MyGoodData (hellip)

Summary

The main points to keep in mind when deciding about any questions on how identifiers should be translated are

Oracle always has delimited identifiers enabled and Informix does not

Oracle folds regular identifiers to uppercase and Informix folds to lowercase

Informix has behavioral differences between an ANSI mode database and a non-ANSI mode one

It is beneficial to consider the most common usage patterns within the existing application code prior to deciding default identifier translation patterns

Databases

Databases database names and instances

Oracle and Informix implement databases and instances differently Oracle considers a database to be a set of data files control file(s) and log files while an instance is a set of background processes and memory structures accessing database data Oracle instances are also known as servers Each Oracle instance or server runs against one database but through the use of Oracle Parallel Server a database may have multiple instances accessing it An Oracle database is named at initialization and the name has a limit of 8 ASCII characters Informix databases are defined as ldquoa collection of information contained in tables that are useful to a particular organization or used for a specific purposerdquo Informix database names may be up to 128 characters in length An Informix instance is a set of processes memory and disk allocations that manage data and will contain at least two and in most cases many databases Informix instances are also referred to as servers Informix databases may share disk allocations (dbspaces) with other databases within an Informix instance Oracle databases cannot share disk allocations (tablespaces) Informix databases should be created in a dbspace other than the root dbspace The root dbspace holds data for the system configuration information for the engine and so on If user-defined objects are created in this dbspace then the dbspace may become unmanageably large and during backup the system information may also get backed up unnecessarily The CREATE DATABASE statements of Informix and Oracle have differences which may require modification to routines responsible for database creation Informix will accept the same minimal syntax required by Oracle (eg CREATE DATABASE myDB) however issuing the command will implicitly accept the creation of a database without transaction logging enabled and establish the default location for all database objects as the instancersquos default storage location The instancersquos default storage location or ldquorootrdquo dbspace should not contain user-defined objects The root dbspace holds data for the system and some configuration information for the engine If user-

IBM Software Group IBM Information Management

Version 16 20

defined objects are created in this dbspace it may become unmanageable and result in the system contending with user objects for the available space

ANSI vs non-ANSI

Informix supports both ANSI and non-ANSI databases Informix non-ANSI databases are most common but there are some advantages of ANSI databases when porting from Oracle

Oraclersquos transaction behavior is more or less like that of an ANSI database Applications ported on Oracle are always in a transaction In Oracle and ANSI databases transactions begin implicitly with the first of a series of SQL statements and will end immediately after a commit or rollback statement Therefore unlike a non-ANSI database a COMMIT WORK statement does not need to be preceded with a BEGIN WORK statement

In ANSI databases database object references must be prefixed by the ownerrsquos name unless the owner is the one referencing the object If Oracle applications reference database objects with a both parts of the object name prefixing the object name with schema using an ANSI database may ease modifications necessary when porting to Informix

The ldquolsquogrant to PUBLICrdquorsquo concept provide by Informix database security does not apply to ANSI databases Every database object is private and privileges must be explicitly granted to each user

If an Informix ESQLC or 4GL application was developed to run on a non-ANSI Informix database (including BEGIN WORK statements) the application could run on an ANSI Informix database in one of two ways

By placing the BEGIN WORK statement in a pre-processor directive such as IFDEF object_name and omitting the proper preprocessor compile options such as -D object_name

By compiling the application normally and ignoring the resulting warning messages

Additionally the LOG MODE ANSI clause must be added to the CREATE DATABASE statements ANSI mode databases cannot have buffered logging Applications written to use an open API like ODBC or JDBC are compiled without awareness of the database and these APIs are written with the intent to abstract specific database behavior For instance in one of these the application developer would call a function to begin or end a transaction rather than execute a BEGIN and COMMIT or ROLLBACK The API would execute these statements internally or not as necessary for the database connection See the Transaction Processing section in Application Architecture for more information on how an application running on a non-ANSI Informix database can simulate Oracle transaction behavior

Tablespaces and dbspaces Oracle tablespace names need to be replaced with Informix dbspace names Unlike the Oracle tablespace the Informix dbspace cannot be created using DDL (SQL) scripts It must be created using the Informix onspaces utility before any DDL (SQL) scripts are executed Therefore Oraclersquos CREATE TABLESPACE statements should be removed from the DDL (SQL) scripts The user interface for accomplishing these tasks is onmonitor The command line utility is onspaces Therefore the onspaces commands can be placed in shell or batch scripts After successfully executing the onspaces commands the DDL (SQL) scripts may be called through the same shell or batch scripts For example

IBM Software Group IBM Information Management

Version 16 21

onspaces hellip onspaces hellip hellip dbaccess database_name DDL_script_file_name dbaccess database_name DDL_script_file_name hellip

Tables

Attributes and general syntax

When creating tables the Oracle CREATE TABLE statement must be converted to Informix taking advantage of the Informix options IN EXTENT NEXT and LOCK MODE

IN specifies the dbspace in which the table will reside

EXTENT specifies the amount of space that will initially be allocated to the table (16K default on most platforms)

NEXT specifies the amount of space that will be allocated when additional space is needed (16K default on most platforms

Lock mode

LOCK MODE specifies whether to use row or page locks for the table In Oracle the default is row level locking in Informix the default setting is page level locking However it can be changed by using one of the following methods (resolved in the following order of precedence)

1 LOCK MODE specified using an attribute of the CREATE TABLE or ALTER TABLE command syntax

2 IFX_DEF_TABLE_LOCKMODE environment variable setting 3 DEF_TABLE_LOCKMODE parameter setting in the ONCONFIG file

NOTE If the DEF_TABLE_LOCKMODE parameter cannot be found in the ONCONFIG file it can be added to make the specification for every database within the instance The Informix instance must be restarted for this parameter to take effect The new ldquodefaultrdquo LOCK MODE will apply to all tables created after the parameter has been changed To change the LOCK MODE of existing objects use the ALTER TABLE statement

Storage

The Oracle STORAGE INITIAL and STORAGE NEXT clauses must be changed to the Informix EXTENT SIZE and NEXT SIZE clauses respectively In Oracle the STORAGE clause options MINEXTENTS MAXEXTENTS and PCTINCREASE should be removed For example Oracle

CREATE TABLE dept(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13)

)

STORAGE (INITIAL 100K NEXT 50K MINEXTENTS 1 MAXEXTENTS 50

PCTINCREASE 5)

Informix CREATE TABLE dept (

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

IBM Software Group IBM Information Management

Version 16 22

EXTENT SIZE 200 NEXT SIZE 50

When an Oracle CREATE TABLE statement does not include a STORAGE clause the table will be created using the tablespace STORAGE clause by default If an Oracle tablespace is created specifying a STORAGE INITIAL of 100KB and a STORAGE NEXT of 50KB then all tables created within that tablespace will have a default value of STORAGE INITIAL 100KB and STORAGE NEXT 50KB Oracle tables cannot be created with smaller STORAGE clause values than the tablespace default they are created in Informix dbspaces do not have storage clauses attached to them As stated earlier the default Informix EXTENT and NEXT sizes are 16KB on most platforms The minimum EXTENT and NEXT sizes are 4 times the page size

Constraints

The Oracle constraint syntax must be changed to the Informix syntax for primary keys foreign keys unique and so on For example

Oracle CONSTRAINT PK_NUMBER PRIMARY KEY(CUST_NUM)

CONSTRAINT CK_EMP_CODE CHECK (EMP_CODE gt 100)

Informix PRIMARY KEY(CUST_NUM) CONSTRAINT PK_NUMBER

CHECK (EMP_CODE gt 100) CONSTRAINT CK_EMP_CODE

An Oracle check constraint statement may contain functions that are not available in Informix In this circumstance it may be necessary to code the combination of a trigger and a stored procedure to emulate the same functionality A trigger based on an insert or update event can execute a stored procedure which tests the constraint condition and if necessary raise an exception to reject the row data which violates the constraint The Oracle PARALLEL clause which specifies parallel execution of an operation must be removed from any SQL statements (such as CREATE TABLE and ALTER TABLE) In Informix there are ways to accomplish this parallel execution depending on the context in which these SQL statements are called (shell script file batch file and so on)

ALTER TABLE

Informix offers a rich set of ALTER TABLE features adding and dropping columns (rename by using the RENAME statement) changing column data types altering the next size and changing the lock mode Informix will choose one of three algorithms when executing an ALTER TABLE statement depending upon the operation to be performed For certain conditions the database server uses either a ldquoslowrdquo ldquoin-place or ldquofastrdquo alter algorithm to modify the table Informix provides ldquoin-placerdquo alter table support for adding or dropping a column anywhere in the table changing the column length and changing the column data type without an exclusive lock on the table An ldquoin-placerdquo alter will modify the tablersquos definition without changing the existing rows or unloading and reloading the data After the ALTER TABLE operation the database server inserts rows using the latest definition Informix will not change the row structure until a data row is touched by a user operation Once a query accesses a row that is not yet converted there can be a slight degradation in the performance because the database server reformats each row in memory before it is returned Informix uses the ldquoslowrdquo alter algorithm when the ALTER TABLE statement makes column changes that it cannot perform in place This type of alter would be

Adding or drop a column created with the ROWIDS keyword

Dropping a column of the TEXT or BYTE data type

IBM Software Group IBM Information Management

Version 16 23

Converting an INT or a SMALLINT column to SERIAL or SERIAL8

Modifying the data type of a column so that some possible values of the old data type cannot be converted to the new data type

For example if you modify a column of data type INTEGER to CHAR(n) the database server uses the slow ALTER algorithm if the value of n is less than 11 An INTEGER requires 10 characters plus one for the minus sign for the lowest possible negative values

Modifying the data type of a fragmentation column in a way that value conversion might cause rows to move to another fragment

Adding dropping or modifying any column when the table contains user-defined data types or smart large objects

When the database server uses the slow alter algorithm to process an ALTER TABLE statement the table can be unavailable to other users for a long period of time because the database server will lock the table exclusively for the duration of the operation make a copy of the table to convert the table to the new definition and convert the data rows This type of ALTER TABLE processing can encounter the scenario of a statement being a long transaction and abort it if the Long Transaction High Water Mark (LTXHWM) threshold is exceeded Informix will use the ldquofastrdquo alter algorithm when the ALTER TABLE statement changes attributes of the table but does not affect the data The database server uses the fast alter algorithm when you use the ALTER TABLE statement to make the following changes

bull Change the next-extent size

bull Add or drop a constraint

bull Change the lock mode of the table

bull Change the unique index attribute without modifying the column type

With the ldquofastrdquo alter algorithm the database server holds a lock on the table for a very brief period In some cases the database server will lock the system catalog tables but only long enough to change the attribute In either case the table is unavailable for queries for only a short time

Data Partitioning

Informix Table Fragmentation is the counterpart to Oraclersquos Table Partitioning and allows the user to control where data is physically placed at the table level Table Fragmentation or Data Partitioning is typically done to large tables but Informix and Oracle implement fragmentation and partitioning for different reasons and with different results Informix recommends using table fragmentation to improve single-user response time concurrency data availability backup restore characteristics and data-load performance While Oracle does state that table partitioning may improve the performance of queries and that the Oracle optimizer takes partitioning into account the primary goal of partitioning in Oracle is improving database maintenance Partitioning strategies in Oracle include range partitioning as well as hash and composite partitioning Composite partitioning combines range and hash partitions through the use of sub-partitions Tables incorporating Oracle LOBrsquos (large objects) cannot be partitioned Informix fragmentation strategies include expression-based and round robin Basic expression-based fragmentation can replace Oracle range partitioning Unlike Oracle LOBs Informixrsquos Smart Large Objects can be fragmented Examples of creating tables with Oracle range partitioning and Informix fragmentation by expression are shown below Oracle range partitioning

CREATE TABLE dept

IBM Software Group IBM Information Management

Version 16 24

(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13) )

partition by range (deptno)

(partition PART1 values less than (11)

tablespace PART1_TS

partition PART2 values less than (21)

tablespace PART2_TS

partition PART3 values less than (31)

tablespace PART3_TS

partition PART4 values less than (MAXVALUE)

tablespace PART4_TS)

Informix expression based fragmentation CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

deptno lt 11 IN dbspace1

deptno gt= 11 AND deptno lt 21 IN dbspace2

deptno gt= 21 AND deptno lt 31 IN dbspace3

REMAINDER IN dbspace4

Oracle uses MAXVALUE for values not found in the specified range while Informix uses the REMAINDER keyword for values that fall outside the specified expression or expressions Prior to IDS version 1000 each table fragment had to go into a separate dbspace Now tables can be fragmented within a single dbspace You can create partitions within a dbspace that can each support a table fragment It is better to have one chunk per disk drive and now it is not necessary to create a dbspace just to facilitate fragmentation This feature can simplify the management of dbspaces The benefits gained through this new development include

It reduces the total number of dbspaces needed for a fragmented table

Storing multiple table fragments in a single dbspace improves query performance over storing each fragmented expression in a different dbspace

For example Informix partition fragmention in a single dbspace

CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

PARTITION part1 (deptno lt 11) IN dbspace1

PARTITION part2 (deptno lt 21) IN dbspace1

PARTITION part3 (deptno lt 31) IN dbspace1

PARTITION part4 REMAINDER IN dbspace1

Partitions of an Informix fragmented table can be manipulated using the ALTER FRAGMENT statement which supports attaching detaching adding modifying and dropping as well as initializing the distribution strategy

IBM Software Group IBM Information Management

Version 16 25

For example the following SQL removes a partition fragment and places the contents into a new table

ALTER FRAGMENT ON TABLE dept DETACH PARTITION part3 dept_part3

Making use of ALTER FRAGMENT to detach fragments can be an effective way of deleting large quantities of rows from a table quickly and easily After the above statement completes the table will no longer contain rows with a deptno greater than 21 and less than 31 Refer to the Informix Guide to SQL Syntax for a complete description on how to use the ALTER FRAGMENT statement to change the distribution strategy or the storage location of an existing table or index

Data types

Numeric

Oraclersquos NUMBER data type needs to be replaced with one of the following Informix equivalent data types depending on the size of the column The Informix numeric data types are listed below

SMALLINT (-32767 to 32767)

INTEGER (-2147483647 to 2147483647)

BIGINT (-9223372036854775807 to 9223372036854775807)

INT8 (-9223372036854775807 to 9223372036854775807)

The BIGINT type is more efficient in terms of space and speed there are few reasons to use INT8 now that BIGINT is available

DECIMAL (floating point up to 32 significant digits -10-130

to 10124

)

In an ANSI database there is an implied scale of 0 when no scale is given so this is not strictly speaking a floating point type within an ANSI database

NUMERIC (floating point up to 32 significant digits -10-130

to 10124

)

FLOAT (double precision like double data type of C)

SMALLFLOAT (single precision like float data type of C)

REAL (same as SMALLFLOAT)

DOUBLE (same as FLOAT)

LONG (same as long data type of C)

Oraclersquos NUMBER data type is used to store zero positive and negative fixed size and floating point numbers with magnitudes between 10 x 10

-130 and 999 x 10

125 (38 9s followed by 88 0s)

with 38 digits of precision A fixed-point number is specified by NUMBER(p s) where p is the precision or the total number of digits and s is the scale or the number of digits to the right of the decimal point For example a column defined as NUMBER(104) would contain numbers in the format 9999999999 In Oracle the scale can range from -84 to 127 If the scale is 0 or not mentioned then the data type can be converted into Informixrsquos SMALLINT INTEGER or BIGINT depending on the precision or FLOAT SMALLFLOAT DOUBLE or REAL depending on usage in the application When the scale is positive the data type should be converted to Informixrsquos DECIMAL or NUMERIC A floating-point data type in Oracle is declared using the type NUMBER without mentioning scale and precision In Informix this can be replaced with FLOAT SMALLFLOAT REAL DOUBLE PRECISION or DECIMAL(p) in an non-ANSI database

IBM Software Group IBM Information Management

Version 16 26

Oracle allows a negative scale If the scale is negative the actual data is rounded to the specified number of places to the left of the decimal point For example a specification of NUMBER (10 -2) means to round to the hundred If the general form for any number is

mantissa X 10exponent

then precision is the number of digits in the mantissa and scale is the negative exponent Example

select cast( 987654321 AS NUMBER(10-2) ) from dual

returns

987654300

Informix does not support a negative scale If precision - scale is less than the maximum precision of an integer type then that is the most efficient type to use Failing that and if the database is non-ANSI a floating point DECIMAL can be used If that is not sufficient then it may be necessary to define a user type and associated functions Oracle also allows the scale to be greater than the precision Precision is just the number of digits that will be preserved A NUMBER(3 5) might have the value 000123 If the Oracle scale is less than the Informix maximum precision then the Oracle scale can be used for both the Informix precision and scale A NUMERIC(55) column could also store the value 000123 You may need to take into consideration not only the minimum and maximum values but the default size for data types For example when the size of the NUMBER data type is absent Oracle will default to NUMBER(38) while Informix defaults to NUMERIC(16) Oracle and Informix support the ANSI DECIMAL data type Therefore in the case of an ANSI data type the Oracle data type can be converted to the same Informix data type There are differences between conversions based on theory versus those based on practice For instance it is very common to see an undecorated NUMBER declaration where the customer database and applications are using integer data When converting NUMBER declarations it may be necessary to consider how the data is being used in order to determine the best type mapping

CHAR VARCHAR and LVARCHAR

In Oracle the default for a CHAR column is one character and the maximum allowed is 255 characters In Informix the maximum length of CHAR and LVARCHAR columns is 32767 Therefore Oraclersquos CHAR columns can always be converted to an Informix CHAR column The CHAR data type columns can only contain printable characters tabs and spaces The CHAR columns store leading and trailing spaces In Oracle a zero-length string can be inserted into a CHAR column but the column is padded with one blank character when it is used in comparisons Also in Informix a zero-length string can be inserted into a CHAR column however the column is padded with enough spaces to fill the column In the case of inserting NULL into an Informix CHAR column no padding occurs Oraclersquos VARCHAR and VARCHAR2 are currently synonymous and have a maximum data length of 4000 bytes while the maximum length for the Informix VARCHAR data type is 255 Informixrsquos CHAR and LVARCHAR data types have a maximum length of 32767 and 32739 respectively measured in bytes These should be used to replace Oraclersquos VARCHAR VARCHAR2 LONG and LONG VARCHAR if the data length is between 256 and the maximum If the data length exceeds the maximum use Informixrsquos TEXT BYTE BLOB or CLOB data types See the Raw Data section below for more information on TEXT BYTE BLOB and CLOB data types

IBM Software Group IBM Information Management

Version 16 27

Empty Oracle VARCHAR2 strings are considered NULL Empty Informix VARCHAR and LVARCHAR strings are not considered NULL rather they contain at least one space Oracle

compares VARCHAR2 values using non-padded comparison semantics Therefore ldquoBOBrdquo ldquoBOB ldquo Informix ignores trailing blanks Therefore ldquoBOBrdquo = ldquoBOB ldquo or ldquordquo = ldquo rdquo Hence checks for NULL within the application must be replaced with checks for an empty string (such as ldquordquo or ldquo rdquo) whenever an empty string is inserted into the column If NULL is truly inserted into the column checking for NULL is appropriate (for example SELECT FROM hellip WHERE hellip IS NULL) In Oracle LONG columns store variable length character strings containing up to 2 gigabytes or 2

31-1 bytes Informix LONG columns store numeric data Oraclersquos LONG columns have many of

the characteristics of VARCHAR2 columns They can be used in a SELECT list in the SET clause of an UPDATE statement and in an INSERT statement but they cannot be used in a WHERE clause a GROUP BY clause or an ORDER BY clause and they cannot be indexed Oraclersquos LONG columns should be converted to an Informix Smart Large Object or ldquoSLOBrdquo (BLOB CLOB) column

Date and Time

Oraclersquos DATE data type contains date and time components from year down to second It can be to be replaced most directly with Informixrsquos DATETIME YEAR TO SECOND Some analysis may be necessary to determine whether the time is really necessary In other words does the application reference the date and time portions of the values If the application only references the date portion then replace Oraclersquos DATE with Informixrsquos DATE and change the host variable to X(10) or char(10) accordingly The Informix DATE default display format is MM-DD-YYYY although the DATE data type stores the calendar date The Informix DATE data type requires 4 bytes which is stored internally as an integer value equal to the number of days since December 31 1899 The default display format can be changed with the environment variable DBDATE If the application uses different date formats then using DBDATE is not a solution Sometimes it might be necessary to write small subroutines to emulate Oraclersquos DATE representations See the Informix Guide to SQL Reference manual for details on DBDATE and also DBCENTURY If the application only references the time portion of the values replace Oraclersquos DATE with Informixrsquos DATETIME using the EXTEND function to specify precision In addition Informix provides the data type INTERVAL for use while performing DATE and DATETIME calculations In Oracle the DATE data type is used to store date and time information Although date and time information can be represented in both CHAR and NUMBER data types the DATE data type has special associated properties For each DATE value the following information is stored

century

year

month

day

hour

minute

second

Also regarding the Oracle DATE data type if a date value without a time component is specified the default time is 120000am If a DATE value without a date is specified the default date is the first day of the current month

Interval

Within Informix there are two classes of interval types YEAR-MONTH and DAY-FRACTION There are different numbers if days in different months so the MONTH-DAY boundary cannot be crossed without creating ill-defined results Within each of these classes Informix allows you to declare columns or variables as any subset of the start and end fields Oracle has one INTERVAL

IBM Software Group IBM Information Management

Version 16 28

type for each of the two classes YEAR(p) TO MONTH and DAY(p) TO SECOND(s) The Oracle scale on the SECOND field is logically equivalent to the Informix scale on the FRACTION field

Raw data and Large Objects

Oraclersquos support of large blocks of raw unstructured data (such as graphic images video clips and sound waveforms) in binary or character format is provided by the large object (LOB) data types BLOB CLOB NCLOB and BFILE Traditional Oracle data types MLSLABEL (used with Trusted Oracle) RAW and LONG RAW are also used for data that is not to be interpreted by the engine and converted when moving data between different systems Informix supports two types of large objects (LOBs Simple Large Objects and Smart Large Objects Simple LOBs consist of the TEXT and BYTE data types and can be 2

31 bytes or 2

Gigabytes in size Smart LOBs include both Character Large Object (CLOB) and Binary Large Object (BLOB) data types and may be up to 42

40 bytes or 4 Terabytes in size Simple LOBs can

be stored either in-line with table data or in blobspaces while Smart LOBrsquos are stored in sbspaces Oraclersquos CLOB BLOB MLSLABEL RAW and LONG RAW data types should be replaced with Informixrsquos BYTE TEXT CLOB or BLOB depending on the columnrsquos size and usage Informixrsquos Smart BLOB data types CLOB and BLOB should be used under the following conditions and considerations

The large object needs to be referenced by multiple sources

The object size exceeds 2 GB

Fragmentation is required

Byte level locking is available making it possible to lock only a portion of the object

Logging can be specified at the object level

Updates are done in place or moved as needed

Be aware of the following restrictions for Simple Large Objects

Data can only be inserted into a BYTE or TEXT column with the dbload or onload utilities the DBACCESS load statement BYTE or TEXT host variables respectively in ESQLC or declaring a file in ESQLCOBOL

BYTE and TEXT columns cannot be inserted or updated with a literal neither quoted text string nor number

BYTE or TEXT columns cannot be used in string operations with aggregate functions with the GROUP BY ORDER BY IN LIKE or MATCHES clauses

ROWID

The implementation of ROWID differs between Oracle and Informix Oraclersquos ROWID is both a pseudo-column and a data type See the ROWID subsection in the Pseudo-Columns section in CHAPTER 3 Data Manipulation Language for more information Informix implements ROWID as a pseudo-column only Oracle stores the ROWID column and ROWID data type column values in hexadecimal format Informix stores the ROWID column values in INTEGER format The Oracle and Informix engines maintain the values of the ROWID pseudo-column Oraclersquos engine does not maintain the values of other columns of type ROWID In Informix the term rowid refers to an integer that defines the physical location of a row Informix assigns rows in a non-fragmented table a unique rowid which allows applications access to a particular row in a table Rows in fragmented tables in contrast are not assigned a rowid To access data by rowid in a fragmented table a rowid column must be explicitly created as is described in the Informix Guide to SQL Reference manual Creating a Rowid Column If applications attempt to reference a rowid in a fragmented table that does not contain a rowid that was explicitly created Informix displays an appropriate error message and execution of the application is halted

IBM Software Group IBM Information Management

Version 16 29

When used as a data type for a column Oracle does not guarantee that the values are valid ROWIDs For example if the ROWID is used as a data type on a column such as a column in a child table named parent_rowid containing the ROWID of the parent then the values are maintained by the application outside of the engine The application must read the ROWID of the parent and insert it into the parentrsquos corresponding child table rows This is usually done so the two tables can be joined on the parentrsquos ROWID and the childrsquos parent_rowid column This functionality can be duplicated in Informix by using primary and foreign keys Informix recommends that primary keys are used as a method of access in applications rather than rowids because primary keys are defined in the ANSI specification of SQL using them to access data makes applications more portable Refer to the Informix Guide to SQL Reference and the Informix Guide to SQL Syntax for a complete description on how to define and use primary keys to access data

User-defined types

Both Oracle and Informix allow the user to create and define data types Oracle refers to these as abstract data types while Informix refers to these as user-defined types In Oracle all user-defined types are referred to as abstract data types while Informix may refer to user-defined types as COLLECTION types ROW types DISTINCT types and OPAQUE types Currently the Informix ROW type is closest in form and function to the Oracle abstract data type An example of syntax for creating both an Oracle abstract data type and an Informix ROW type is shown below

Oracle abstract data type

CREATE TYPE name_type AS OBJECT

(first_name VARCHAR2(25)

middle_initial CHAR(1)

last_name VARCHAR2(30))

Informix row type

CREATE ROW TYPE name_type

(first_name VARCHAR(25)

middle_initial CHAR(1)

last_name VARCHAR(30))

Both Oracle and Informix support the use of user-defined types for table definition or column definition within a table Building on the example above the following create table example show a table definition and column definition within a table based on user-defined types Oracle table creation

CREATE TABLE name OF name_type

Informix table creation

CREATE TABLE name OF type name_type

Oracle column definition

CREATE TABLE employee

(empno NUMBER(9)

name name_type)

Informix column definition

CREATE TABLE employee

IBM Software Group IBM Information Management

Version 16 30

(empno INTEGER

name name_type)

For more information on User Defined Types see the Informix Guide to SQL Syntax

Complex data types

Informix offers users the ability to create data types from existing built-in types OPAQUE types DISTINCT types and other complex types Complex data types may either be a ROW type or a COLLECTION type Oracle treats complex data types as abstract data types For more information on Oracle abstract data types see the User Defined Types section above For more information on Complex Data Types see the Informix Guide to SQL Syntax For recommended type mappings and additional information see the appendix ldquoData type mappingsrdquo

Sequence objects

Oracle sequences

An Oracle sequence is a database object from which multiple users or transactions may generate unique integers For example sequences can be used to automatically generate primary key values When a sequence object is queried the sequence number is incremented and passed to the query independent of the transaction committing or rolling back If two applications increment the same sequence the sequence numbers each application acquires may not be sequential since sequence numbers are being generated by the other application One user or transaction can never acquire the sequence number generated by another user or transaction Once a user or transaction generates a sequence value that value will never be generated and passed to another user or transaction

Informix sequences

Informix rsquos implementation of sequence objects is identical to that of Oracle Issues regarding syntax compatibility should be negligible with the exception of some keywords which have no effect on the behavior of the sequence Informix supports DML statements (CREATE SEQUENCE ALTER SEQUENCE RENAME SEQUENCE DROP SEQUENCE) for sequence objects that multiple users can access concurrently to generate unique integers in the 8-byte integer range GRANT and REVOKE statements support access privileges on sequence objects and the CREATE SYNONYM and DROP SYNONYM statements can be used to reference synonyms for sequence objects in the local database The operators CURRVAL and NEXTVAL can read or increment the value of an existing synonym with behavior the same as Oracle

Indexes

Composite indexes

A composite index can have up to 16 key parts that are columns or up to 341 key parts that are values returned by a UDR This limit is language-dependent and applies to UDRs written in SPL or Javatrade functional indexes based on C language UDRs can have up to 102 key parts A composite index can have any of the following items as an index key

One or more columns

IBM Software Group IBM Information Management

Version 16 31

One or move values that is returned by a user-defined function (referred to as a functional index)

A combination of columns and user-defined functions

Maximum key size

The total widths of all indexed columns in a single CREATE INDEX statement have a limitation based upon the page size of the dbspace in which the index resides This limitation does not apply to functional indexes An enhancement introduced with Informix Dynamic Server Version 1110 is configurable page sizes for dbspaces Prior to this release the page size of dbspaces were restricted to that of the operating system and could not be changed thus Informix was limited to 390 byte indexes With page sizes configurable from 2K through 16K wider indexes are supported Refer to the table below 16K page sizes raises the limit on index width to over 3000 bytes Lifting the 390 byte limit also permits LVARCHAR columns larger than 387 bytes to be included in an index definition

Page Size Maximum Key Size

2 kilobytes 387 bytes

4 kilobytes 796 bytes

8 kilobytes 1615 bytes

12 kilobytes 2435 bytes

16 kilobytes 3245 bytes

In addition to aiding the porting process wider indexes have satisfied requirements for Unicode data as well as provide performance gains by reducing B-Tree index traversal costs since indexing can be built with more items on an index page and produce fewer levels

Index fragmentation

Just as Oracle and Informix support table fragmentation or partitioning in Oracle both support index fragmentation as well See the Table fragmentation section above for more information regarding Informix table fragmentation and Oracle table partitioning Oracle indexes that are partitioned in the same manner as the table they are indexing are referred to as local indexes Informix refers to these as attached indexes Oracle indexes that span partitions are known as global indexes Informix refers to these as detached indexes Informix detached indexes may also refer to indexes that do not follow the same fragmentation scheme as the table they are indexing Starting with Informix version 1110 indexes can be fragmented similarly to tables on a partition level

General index information

The Informix CLUSTER option should be used when appropriate This option orders the data within the table in the order the index requires It is important to note that the CLUSTER index is not maintained over time The primary factor determining the frequency of CLUSTER index rebuilds is the amount of DML performed against the table Frequent INSERTS UPDATES and DELETES make it necessary to closely monitor CLUSTER indexes There is only one clustered index per table since a tablersquos data can only be stored in one order Oraclersquos INITRANS and PCTFREE functionality is similar to the Informix index FILLFACTOR option of the CREATE INDEX statement or the FILLFACTOR configuration parameter in the ONCONFIG file In either case the functionality is handled by Informixrsquos engine once it is set and can be removed from the application FILLFACTOR specifies the degree of index-page

IBM Software Group IBM Information Management

Version 16 32

compactness A low value provides room for growth in the index A high value compacts the index If an index is fully compacted (100 percent) any new inserts result in splitting nodes The setting on the CREATE INDEX statement overrides the ONCONFIG file value The FILLFACTOR default value for both the CREATE INDEX statement as well as the ONCONFIG is 90 Informix has no support for bitmap indexes

Views Oraclersquos CREATE VIEW statement contains three options FORCE NO FORCE and WITH READ ONLY FORCE creates the view regardless of whether the views base tables exist or the owner of the schema containing the view has privileges on them NO FORCE creates the view only if the base tables exist and the owner of the schema containing the view has privileges on them WITH READ ONLY specifies that no deletes inserts or updates can be performed through the view These options must be removed from the Informix CREATE VIEW statements Because a view is not really a table it cannot be indexed and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE The columns of a view cannot be renamed with RENAME COLUMN To change anything about the definition of a view you must drop the view and re-create it Because it must be merged with the userrsquos query the SELECT statement on which a view is based cannot contain any of the following clauses

INTO TEMP The userrsquos query might contain INTO TEMP if the view also contains it the data would not know where to go

UNION The userrsquos query might contain UNION No meaning has been defined for nested

UNION clauses

ORDER BY The userrsquos query might contain ORDER BY If the view also contains it the choice of columns or sort directions could be in conflict

Stored procedures and triggers The ways stored procedures and triggers are created differ between Oracle and Informix Oracle allows a REPLACE clause in the CREATE statement to handle situations when the object already exists Informix does not support the REPLACE option Instead a DROP PROCEDURE or DROP TRIGGER statement must precede the CREATE PROCEDURE or CREATE TRIGGER statement respectively to handle the situation when the object already exists It should be noted a DROP statement will generate an error when the object does not exist If it is run interactively within the DBACCESS user interface the DROP statement error will terminate processing If it is run using script execution using DBACCESS at the command line processing will continue To run DBACCESS from the command line type

dbaccess db_name

To run the file containing the create statements from the command line type dbaccess db_name sql_file_name

Informix introduced an IF EXISTS clause to most of the CREATE and DROP statements at 117 but the logic is different from Oraclersquos OR REPLACE clause For example these statements

IBM Software Group IBM Information Management

Version 16 33

DROP PROCEDURE IF EXISTS hellip

CREATE PROCEDURE hellip

are logically the same as this Oracle statement

CREATE OR REPLACE PROCEDURE hellip

So it is possible to achieve the same result but not necessarily the same number of statements

Oracle extensions The Oracle CLUSTER option in CREATE statements should be removed These are not to be confused with Informix CLUSTER index statements (See Indexes section above) An Oracle cluster is a database schema object that contains one or more tables that all have one or more columns in common Rows of one or more tables that share the same value in these common columns are physically stored together within the database Removing this Oracle feature will not affect the application Other non-Informix DDL statements like CREATE DATAFILE CREATE CONTROLFILE CREATE ROLLBACK SEGMENT CREATE SNAPSHOT CREATE DATABASE and CREATE DATABASE LINK must be removed or changed (in the case of the CREATE DATABASE statement) The Oracle CREATE PROFILE statement must be removed An Oracle profile is a set of limits on database resources Profiles can be used to limit the database resources available to a user for a single SQL statement or a single session

IBM Software Group IBM Information Management

Version 16 34

C H A P T E R 4 Data Manipulation Language

SQL

Labels using keywords

Oracle displays labels in SQL statements that are Informix reserved words such as UNITS YEAR MONTH DAY HOUR and so on must be converted by using the Informix AS clause between the column name and the display label Otherwise syntactic ambiguities will cause errors

Inequality operations

In addition to the Informix supported ldquonot equal tordquo symbols ldquoltgtrdquo and ldquo=rdquo Oracle supports the symbol ldquo^=rdquo All occurrences of ^= must be replaced with one of the Informix supported symbols

Selects

Queries are executed based on how the optimizer determines the best path to the data Oracle and Informix developed their own query optimizers with their proprietary methods and rules A query that looks exactly the same in both environments may run differently in each following a different path and executing faster or slower Therefore every query in the ported application should be tested for performance regardless of whether a query had to be converted Furthermore Oracle supports optimizer hints within a SELECT statement Prior to IDS 73 and Informix Dynamic Server 92 Informix did not allow optimizer hints See the Optimizer Directives subsection below for more information on porting Oraclersquos optimizer hints to Informixrsquos optimizer directives

Optimizer directives

Informix offers optimizer directives similar to Oraclersquos optimizer hints This feature provides the query developer the flexibility to direct the optimizer to follow specific paths rather than choosing a plan through its analysis A query is processed in two steps First it is optimized and compiled to product a query plan Secondly it is executed to produce a result Optimizer directives are a method for influencing the choice of the optimizer in the creation of the plan

IBM Software Group IBM Information Management

Version 16 35

Optimizer directives address the following key issues

Reduced time for correcting performance problems Rewriting queries can be very time consuming and this allows you to have a quick way to alter a plan

Competitive pressure Users accustomed to this function were looking for it in Informix

Product development tuning This allows product development to alter plans dynamically rather than through code changes to evaluate the effect of different optimization techniques

The syntax and behavior of Informixrsquos implementation is compatible with Oraclersquos optimizer hints which eases the porting of applications from Oracle to Informix Directives are written as a comment whose first character is a lsquo+rsquo (plus sign) An example is

select + ORDERED AVOID_FULL(e) empname deptno

from employee e department d

where edept_no = ddept_no

This above example specifies that the tables should be joined in the order specified in the query and that the employee table (e) should NOT be accessed with a full table scan The Informix implementation differentiates itself significantly from Oraclersquos in one way Informix supports the notion of negative directives whereas Oracle only supports direct hints A directive that tells the optimizer what to avoid rather than what to choose is unique to Informix The query result can be realized by writing a directive to avoid certain actions known to cause performance issues but allow any new indexes or table attributes to be explored by the optimizer as they are added over the life of the table and query This allows a DBA to continue to add indexes to tables and not have to rewrite directives Additionally Informix supports full recognition of directives with SET EXPLAIN output Informix will highlight semantic and syntactic errors which Oracle does not Optimizer directives support control in the following areas of the optimization process

Access methods Index versus scans

Join Methods Forcing hash joins nested loop joins

Join Order Specify which order the tables are joined

Goal Specify first rows or all rows (response time versus throughput) See the Informix Guide to SQL Syntax or Reference for more information

External optimizer directives

External optimizer directives give the DBA the ability to specify query directives and save them in the database These directives are applied automatically to subsequent instances of the same query The SAVE EXTERNAL DIRECTIVES statement associates one or more optimizer directives with a query and stores a record of this association in the sysdirectives system catalog table for subsequent use with queries that match the specified query string The query string must be an exact match that includes case and white space positioning This statement establishes an association between the list of optimizer directives and the text of a query but it does not execute the specified query Only the DBA or user informix can execute SAVE EXTERNAL DIRECTIVES This associates AVOID_INDEX and FULL directives with the specified query

SAVE EXTERNAL DIRECTIVES

+ AVOID_INDEX (table1 index1) + FULL(table1)

ACTIVE FOR

SELECT col1 col2 FROM table1 table2

IBM Software Group IBM Information Management

Version 16 36

WHERE table1col1 = table2col1

These directives are applied automatically to subsequent instances of the same query You must include one of the ACTIVE INACTIVE or TEST ONLY keyword options to enable disable or restrict the scope of external directives When external directives are enabled and the sysdirectives system catalog table is not empty the database server compares every query with the query text of every ACTIVE external directive and for queries executed by the DBA or user informix with every TEST ONLY external directive External directives are ignored if the EXT_DIRECTIVES parameter is set to 0 in the ONCONFIG file In addition the client system can disable this feature for its current session by setting the IFX_EXTDIRECTIVES environment variable to 0 If an external directive has been applied to a query output from the SET EXPLAIN statement indicates ldquoEXTERNAL DIRECTIVES IN EFFECTrdquo for that query Any inline directive is ignored by the optimizer when the external directives are applied to a query that matches the SELECT statement Like inline optimizer directives that are embedded within a query external directives can improve performance in some queries for which the default behavior of the query optimizer is not satisfactory Unlike inline directives external directives can be applied without revising or recompiling existing applications

Inserts

Informix does not support Oraclersquos INSERT with SELECT statement utilizing an UNION clause (although a view with an UNION clause can be referenced resulting in an UNION operation) Additionally Informix does not support an INSERT statement with a VALUE clause with SELECT statements The SELECT statement within a VALUE clause can be rewritten by omitting the VALUE clause and performing an INSERT INTO table_name SELECT hellip FROM other_table_name

Temporary tables

Informix and Oracle implemented the concept of temporary tables differently Oracle implements temporary tables as a work area during batch data loads Informix implements temporary tables just like regular database tables These temporary tables can be created manipulated and dropped only within a session such as stored procedures and ESQL programs Once the session ends any remaining temporary tables are automatically dropped Temporary tables can give an application extra functionality however their use should be limited if reducing database extensions to increase database independence within an application is a priority

Outer joins

Both Oracle (starting with Oracle 9i) and Informix support ANSI standard syntax for outer join specification The syntax for left and right outer join using the plus sign (+) in the WHERE clause is only supported for backward compatibility however it is still in existence The use of ANSI outer join syntax is recommended The Oracle outer join syntax + (placed after the column which has values not matching the corresponding column in the joined table) can be replaced with the Informix equivalent OUTER The OUTER keyword is placed within the SELECT statement before the name of the subservient table Unlike Oracle in Informix multiple outer joins per SELECT statement are allowed grouped with parentheses

Sorts

In Oracle sorts NULL values are considered the highest value and are therefore ordered last in ascending sorts Informix sorts with NULLS as the lowest value ordering them first in ascending sorts First it must be determined whether this sorting difference will affect the outcome enough to warrant a work around In most cases it will not If it does then a stored procedure can be

IBM Software Group IBM Information Management

Version 16 37

written to evaluate whether a column is NULL and if so replace it with a high value so that it will sort last Once the application receives the results it must replace the high values with NULL if the column is going to be displayed or manipulated

Exceptions

Error handling using hard coded Oracle SQL codes must be replaced with the corresponding Informix SQL codes

Correlation names

Informix does not support correlation names with aliases on the main table of an UPDATE or DELETE statement Such cases must be converted For example

Oracle UPDATE customer C

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE Ccreate_date lt= Zeffective_date)

Informix UPDATE customer

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE customercreate_date lt= Zeffective_date)

-and-

Oracle DELETE customer C

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND Cstate = Tstate )

Informix DELETE customer

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND customerstate = Tstate )

Note that Informix allows correlation names with aliases on tables other than the updated or deleted table

Aliases

Unlike Oracle in Informix if an alias is used in the FROM clause of a SELECT statement it must also be used in the SELECT list and WHERE clauses The original table name should be replaced with the alias wherever aliases and original names are used together within a SELECT statement in an Oracle application

Hierarchical queries

Informix does not allow query results to be organized hierarchically in a B-tree fashion Oracle does allow it by using the clauses START WITHhellip and CONNECT BY PRIOR in the SQL

IBM Software Group IBM Information Management

Version 16 38

statement In Oracle if a table contains hierarchical data a bill of materials for example rows can be selected in a hierarchical order using the following clauses START WITH

The START WITH clause identifies the row(s) to be used as the root(s) of a hierarchical query This clause specifies a condition that the root(s) must satisfy If this clause is omitted Oracle uses all rows in the table as root rows A START WITH condition can contain a subquery

CONNECT BY

The CONNECT BY clause specifies the relationship between parent and child rows in a hierarchical query This clause contains a condition that defines this relationship The part of the condition containing the PRIOR operator must have one of the following forms

PRIOR expression comparison_operator expression -or- expression comparison_operator PRIOR expression

To find the children of a parent row Oracle first evaluates the PRIOR expression to identify the parent row(s) and the other expression for each row in the table Rows for which the other expression is true are the children of the parent The CONNECT BY clause can contain other conditions to further filter the rows selected by the query

WHERE

The WHERE clause can restrict the rows returned by the query without affecting other rows of the hierarchy

Oracle uses the information from each of the clauses mentioned above to form the hierarchy using the following steps

1 Oracle selects the root row(s) of the hierarchy These are the rows that satisfy the condition of the START WITH clause

2 Oracle selects the child rows of each root row Each child row must satisfy the condition of the CONNECT BY clause with respect to one of the root rows

3 Oracle selects successive generations of child rows Oracle first selects the children of the rows returned in step 2 and then the children of those children and so on Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row

4 If the query contains a WHERE clause Oracle removes all rows from the hierarchy that do not satisfy the condition of the WHERE clause Oracle evaluates the WHERE condition for each row individually after the row has been fetched rather than only fetching rows that satisfy the WHERE condition

5 Oracle returns the rows in the order of an in-order or left-root-right binary tree traversal

IBM Software Group IBM Information Management

Version 16 39

For example the following SQL statement returns the data in the adjacent table in hierarchical order The root row is defined to be the employee whose job is lsquoPRESIDENTrsquo The child rows of a parent row are defined to be those rows whose manager number is the employee number of the parent row

SELECT ename empno mgr job FROM emp START WITH job = lsquoPRESIDENTrsquo CONNECT BY PRIOR empno = mgr

To duplicate this hierarchical functionality in Informix stored procedures or functions can be written requiring intensive use of cursors and program arrays Informix offers the choice of creating and using a User Defined Routine or ldquoUDRrdquo See User Defined Routines section below Use of Informix global arrays will help considerably To maximize read processing at the expense of insert processing another method is to break the table into two tables one containing the data and the other containing the relationship (foreign keys) between each parent and child A parent row would have an entry in the relationship table for each of its children grandchildren great grandchildren and so on The opposite is true where a child row would have an entry in the relationship table for its parent grandparent great grandparent and so on

Truncate

Informix supports the TRUNCATE statement for deleting all active data rows from a table and associated indexes When using Informixrsquos TRUNCATE you also have the option of releasing the storage space that was occupied by the rows and index extents or keeping the space allocated to be used as the table is repopulated with new data

TRUNCATE [TABLE] table [ [ DROP | REUSE ] STORAGE ]

You may use the commandrsquos simplest usage

TRUNCATE my_table

In the example above the TRUNCATE statement drops all the data for the table and keeps only the initial extents There is a minor difference from Oracle syntax as Informix does not require the keyword TABLE Another example

TRUNCATE my_table REUSE STORAGE

ENAME EMPNO MGR JOB

KING 7839 PRESIDENT

JONES 7566 7839 MANAGER

SCOTT 7788 7566 ANALYST

ADAMS 7876 7788 CLERK

FORD 7902 7566 ANALYST

SMITH 7369 7902 CLERK

BLAKE 7698 7839 MANAGER

ALLEN 7499 7698 SALESMAN

WARD 7521 7698 SALESMAN

MARTIN 7654 7698 SALESMAN

TURNER 7844 7698 SALESMAN

JAMES 7900 7698 CLERK

CLARK 7782 7839 MANAGER

MILLER 7934 7782 CLERK

IBM Software Group IBM Information Management

Version 16 40

This example drops all the data for the table but retains all the space allocated The permissions needed for TRUNCATE TABLE depend on the existence of DELETE triggers on the table For tables with DELETE triggers ALTER permission on the table is required and RESOURCE or DBA privileges because the DELETE triggers will be bypassed For tables without DELETE triggers you need DELETE permission on the table and CONNECT privilege to the database While Oracle does not provide rollback Informix does permit TRUNCATE TABLE to execute within a transaction When you rollback a TRUNCATE statement no rows are removed from the table and the storage extents that hold the data rows and index pages continue to be allocated to the table In a database that supports transaction logging only the COMMIT WORK or ROLLBACK WORK statement is valid after the TRUNCATE statement within a transaction Any other statement will generate an error The TRUNCATE statement does not reset the serial value of SERIAL or SERIAL8 columns To reset the counter of a serial column you must do so explicitly by using the MODIFY clause of the ALTER TABLE statement either before or after you execute the TRUNCATE statement After the TRUNCATE statement successfully executes Informix automatically updates the statistics and distributions for the table and for its indexes in the system catalog to show no rows in the table nor in its dbspace partitions It is not necessary to run the UPDATE STATISTICS statement immediately after you commit the TRUNCATE statement

Host variables Host variable formats should not change during the porting process Instead data types should be converted in a manner to preserve the column and host variablersquos formats However there are times when the database schema changes in a way where the host variable format must change Any column converted to a different format in Informix than that of Oracle requires that its corresponding host variable format be changed to be consistent Alternatively if an Oracle format such as date and numeric variables is not directly supported in Informix then the conversion may require some format processing before or after the SQL statement For example the Oracle function TO_CHAR is used to format both date and numerical values A similar function or at least two functions one to handle date data types and another to handle numeric data types can be declared and used in the Informix application Informix provides two built-in functions TO_DATE which converts a character string to a DATETIME variable and TO_CHAR which converts a DATETIME variable to a character string When converting variables an optional formatting string is allowed which determines how the string is displayed (full day names partial day names full months month number and so on) There is also a function ifx_to_gl_datetime() which takes an Oracle date format and returns the corresponding Informix date format This function is supplied in genlib and is for use in ESQL programs to ease migration efforts from Oracle The syntax is as follows

TO_CHAR (source_date fmt) Returns a character string containing the date specified in source_date in the format specified by fmt if one is provided If fmt is missing the function will use the default date format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

TO_DATE (source_string fmt) Evaluates source_string as a date according to the

format fmt If fmt is missing the function will use the

IBM Software Group IBM Information Management

Version 16 41

default format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

These functions are mainly useful for simplifying migration from Oracle to Informix but are also useful for performing advanced searches on DATETIME data types and for better output presentation

Date and time functions Informix version now has built-in support for most of Oraclersquos date functions so it will not be necessary to modify or replace Oraclersquos SYSDATE or ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat)

SYSDATE

IDS 1110 will support the SYSDATE operator which returns a single value representing the current date and time from the operating system clock SYSDATE is identical to the Informixrsquos CURRENT operator except that the default precision of SYSDATE is YEAR TO FRACTION(5) while the default precision of CURRENT is YEAR TO FRACTION(3) On Windows platforms that do not support a seconds scale greater than FRACTION(3) SYSDATE is effectively a synonym for the CURRENT operator In addition to SYSDATE Informix version 1110 has support for Oraclersquos date functions ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat) Depending on the whether or not the Oracle date_format argument is supported by Informix TO_CHAR(date char_format) and TO_DATE(character_string date_format) may have to be converted to Informix date processing Date processing may be required because the Oracle application may format the date in many different ways unsupported by Informix The formats used in the Oracle functions TO_CHAR TO_NUMBER and TO_DATE are illustrated below These formats should be replaced with Informix formats wherever possible format processing functions or stored procedures written to duplicate the Oracle functionality Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

Number formats

Element Example Description 9 9999 Return value with the specified number of digits with a leading

space if positive Return value with the specified number of digits with a leading minus if negative Leading zeros are blank except for a zero value which returns a zero for the integer part of the fixed-point number

0 09999990 Return leading zeros Return trailing zeros $ $9999 Return value with a leading dollar sign B B9999 Return blanks for the integer part of a fixed-point number

when the integer part is zero (suppress leading zeros regardless of whether zeros are used in the format model ie B00999 )

MI 9999MI Return negative value with a trailing minus sign ldquo-ldquo Return positive value with a trailing blank

S S9999999 Return negative value with a leading minus sign ldquo-ldquo Return

IBM Software Group IBM Information Management

Version 16 42

Element Example Description S positive value with a leading plus sign ldquo+rdquo Return negative

value with a trailing minus sign ldquo-ldquo Return positive value with a trailing plus sign ldquo+rdquo

PR 9999PR Return negative value in ltangle bracketsgt Return positive value with a leading and trailing blank

D 99D99 Return a decimal point ldquordquo In the specified position G 9G999 Return a group separator in the specified position C C999 Return the ISO currency symbol in the specified position L L999 Return the local currency symbol in the specified position 9999 Return a comma in the specified position 9999 Return a decimal point ldquordquo In the specified position V 999V99 Return a value multiplied by 10

n (and if necessary round it

up) where n is the number of ldquo9rdquos after the ldquoVrdquo EEEE 99EEEE Return a value in scientific notation RNrn RN Return a value as Roman numerals in uppercase Return a

value as Roman numerals in lowercase Value can be an integer between 1 and 3999

FM FM909 Return a value with no leading or trailing blanks

Date formats

Element Meaning -rdquotextrdquo Punctuation and quoted text is reproduced in the result AD or AD AD indicator with or without periods AM or AM Meridian indicator with or without periods BC or BC BC indicator with or without periods CC or SCC Century ldquoSrdquo prefixes BC dates with ldquo-ldquo D Day of week (1-7) DAY Name of day padded with blanks to length of 9 characters DD Day of month (1-31) DDD Day of year (1-366) DY Abbreviated name of day IW Week of year (1-52 or 1-53) based on the ISO standard IYY or IY or I Last 3 2 or 1 digit(s) of ISO year IYYY 4-digit year based on the ISO standard HH or HH12 Hour of day (1-12) HH24 Hour of day (0-23) J Julian day the number of days since January 1 4712 BC Number

specified with lsquoJrsquo must be integers MI Minute (0-59) MM Month (01-12 JAN = 01) MONTH Name of month padded with blanks to length of 9 characters MON Abbreviated name of month RM Roman numeral month (I-XII JAN = I) Q Quarter of year (1 2 3 4 JAN-MAR = 1) RR Last 2 digits of year see below for years in other centuries WW Week of year (1-53) where week 1 starts on the first day of the year

and continues to the seventh day of the year W Week of month (1-5) where week 1 starts on the first day of the

month and ends on the seventh PM or PM Meridian indicator with and without periods SS Second (0-59) SSSSS Seconds past midnight (0-86399) YYYY Year with comma in the ldquordquo position YEAR or SYEAR Year spelled out ldquoSrdquo prefixes BC dates with ldquo-ldquo YYYY or SYYYY 4-digit year ldquoSrdquo prefixes BC dates with ldquo-ldquo

IBM Software Group IBM Information Management

Version 16 43

YYY or YY or Y Last 3 2 or 1 digit(s) of year

The RR date format element

The RR date format element is similar to the YY date format element but it provides additional flexibility for storing date values in other centuries The RR date format element allows storing the century even though only two digits are entered for the year The table below illustrates how the year is stored based on only two digits

If the year is entered as

0 ndash 49 50 - 99 If the last two digits of the

0 - 49 The return date is in the current century

The return date is in the century before the current one

current year are

50 - 99 The return date is in the century after the current one

The return date is in the current century

User-defined routines User-defined data types user defined behaviors and user defined access methods add rich functionality to Informix A user-defined routine (UDR) can be developed in C Java or Informix SPL language to vastly extend the capabilities of the database Porting applications to Informix gives the option to create UDRs for aggregate and mathematical functions or to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or you can rename an Informix function to the corresponding Oracle function name

Compatible SQL Functions Informix Dynamic Server version 1110 has added support for a number of built-in SQL functions to ease a migration effort These new functions which perform common operations and data manipulation provide compatibility with Oracle routines thus simplifying the migration of applications that have been developed for an Oracle database

Date and time functions ROUND TRUNC ADD_MONTHS LAST_DAY NEXT_DAY MONTHS_BETWEEN SYSDATE

Conversion functions ASCII TO_CHAR TO_NUMBER

String manipulation LTRIM RTRIM

Number manipulation ROUND TRUNC CEIL FLOOR POWER

Bit manipulation BITAND BITOR BITXOR BITNOT BITANDNOT

Others NULLIF FORMAT_UNITS These functions are documented with examples in the IBM Informix Guide to SQL Syntax

Aggregate functions Like Oracle the result returned by an Informix aggregate function is NULL if all of the column values are NULL with the exception of COUNT which returns 0 (zero) Like Oracle Informix aggregate functions cannot be used in a WHERE clause unless it is on a corresponding column originating from a parent query and the WHERE clause is within a sub-query that is within a HAVING clause or the aggregate function is contained within a sub-query Unlike Oracle in Informix the argument of an aggregate function cannot be another aggregate function Informix supports the SELECT COUNT (column_name) hellip statement where the number of rows containing non-null values in the specified column is returned

IBM Software Group IBM Information Management

Version 16 44

The Oracle aggregate functions STDDEV and VARIANCE are supported however the Informix standard deviation routine is named STDEV thus all references to Oraclersquos STDDEV must be changed to match Informixrsquos STDEV Informix does not support Oraclersquos greatest lower boundary (GLB ) or least upper boundary (LUB) Therefore UDRs must be written to provide equivalent functionality Informix allows users to define their own aggregate functions known as user-defined aggregates (UDA) This extension of existing aggregates can be used for new data types as well as the definition of new aggregates In Informix TEXT and BYTE columns cannot be used in aggregate functions such as COUNT AVG MAX MIN and SUM

Mathematical functions Informix does not support all of Oraclersquos mathematical functions such as SIGN COSH SINH and TANH Therefore functions or UDRs must be written in the Informix application to provide equivalent functionality In Informix the rounding factor within the ROUND function must be a value from -32 to 32 This limitation has seldom been encountered as a migration issue

String functions

LENGTH

Oraclersquos LENGTH function will return different values than Informix for strings stored in CHAR data types The numeric return value representing the string length returned by Oracle will include all trailing spaces Whereas Informixrsquos LENGTH function will ignore trailing blanks regardless of data type For example for the two CHAR strings ldquoBOBrdquo and ldquoBOB ldquo Oraclersquos LENGTH function will return different values for each string 3 and 5 respectively Whereas Informixrsquos LENGTH function will ignore trailing blanks and return the value 3 for both When the input string is NULL both database functions will return a NULL

LTRIM and RTRIM

The SQL Compatibility features of Informx has support for LTRIM and RTRIM and will return identical values to that of Oracle No modifications will be necessary to SQL statements utilizing these functions

Oracle Extensions

Informix does not support all of Oraclersquos string functions such as CHR INSTR SOUNDEX and TRANSLATE Therefore corresponding user-defined routines or UDRs (ie functions or stored procedures) must be written in the Informix application to provide equivalent functionality Please note that the VERITY and EXCALIBUR Datablades included with Informix will work with Oraclersquos string function SOUNDEX

Other Oracle Functions Informix does not support the following Oracle functions Therefore corresponding functions must be written in the Informix application to provide equivalent functionality Alternatives to some of the more common Oracle functions follow this list

CHARTOROWID CONVERT DUMP GREATEST GREATEST_LB

IBM Software Group IBM Information Management

Version 16 45

HEXTORAW LEAST LEAST_UB RAWTOHEX ROWIDTOCHAR TO_LABEL TO_MULTI_BYTE TO_SINGLE_BYTE UID USERENV(OSDBA LABEL LANGUAGE TERMINAL SESSIONID ENTRYID) VSIZE

Macros Oracle contains macros sometimes referred to as language constructs which can determine the status of an object Informix does not support Oraclersquos macros These macros must be removed from the code and the associated logic should be implemented with equivalent Informix logic where applicable

ISOPEN and NOT FOUND

The macro cursor_nameISOPEN returns a Boolean value to indicate whether the cursor is open and cursor_nameNOTFOUND indicates whether there are any more rows yet to be fetched from the cursor cursor_name These macros used in condition statements are followed by some logic to handle the true andor false conditions In the case of ISOPEN this macro and its associated logic can just be omitted since the FOREACH loop processing does not explicitly open a cursor and therefore the condition cannot be checked In the case of NOTFOUND this macro should be omitted and its associated logic converted to Informix logic within an Informix FOREACH loop

ROWTYPE

The Oracle macro prefixROWTYPE is used in the declarative section as a data type to declare variables similar to the structure construct of C or RECORD of INFORMIX The prefix can be either a table name or another structure name Structure names ultimately refer back to a table name This macro may be replaced with the Informix statement LIKE table_name The construct LIKE table_name cannot be used in SPL Instead the construct DEFINE column1 LIKE table_namecolumn1 DEFINE column2 LIKE table_namecolumn2 and so on should be used to declare variables corresponding to all the columns of the table Then operations on the whole or part of the structure should be replaced with operations on single SPL variables

TYPE

The Oracle macro prefixTYPE is used in the declarative section as a data type to declare single variables The prefix is either a table_namecolumn_name or a structure_namevariable_name A structure_namevariable_name ultimately refers back to a table_namecolumn_name This macro can be replaced with the Informix statement LIKE table_namecolumn_name

Pseudo-columns Pseudo-columns are columns that exist in tables but are not displayed from a SELECT FROM table_name query Informix pseudo-columns are generally reserved for the enginersquos use Eliminating the use of such columns increases an applicationrsquos portability and eliminates the need for future modifications if the engine is ever modified to process the column differently or not at all

IBM Software Group IBM Information Management

Version 16 46

LEVEL

In Oracle for each row returned by a hierarchical query the pseudo-column LEVEL returns 1 for a root node 2 for a child of a root 3 for a child whose parent is at level 2 and so on A root node is the highest node within an inverted tree and therefore has no parent A child node is any non-root node A parent node is any node that has children A leaf node is any node without children To define a hierarchical relationship in a query you must use the START WITH and CONNECT BY clauses Informix does not support the LEVEL clause See the Hierarchical Queries subsection in the SQL section in the ldquoData Manipulation Languagerdquo chapter for more information on how to process these queries

ROWID

Oraclersquos ROWID pseudo-column returns the rows address for each row in the database ROWID values contain the following information necessary to locate a row

Which data block in the data file

Which row in the data block (first row is 0)

Which data file (first file is 1)

Usually a ROWID value uniquely identifies a row in the database However rows in different tables that are stored together in the same cluster can have the same ROWID Values of the ROWID pseudo-column have the data type ROWID ROWID values have several important uses

They are the fastest way to access a single row

They can show you how a tables rows are stored

They are unique identifiers for rows in a table

A ROWID does not change during the lifetime of its row However you should not use ROWID as a tables primary key If a row is deleted and re-inserted its ROWID may change even when using the export and import utilities If a row is deleted Oracle may re-assign its ROWID to a new row inserted later Although you can use the ROWID pseudo-column in the SELECT and WHERE clauses of a query these pseudo-column values are not actually stored in the database The value of a ROWID pseudo-column cannot be inserted updated or deleted For example the following Oracle statement selects the address of all rows that contain data for employees in department 20

SELECT ROWID ename FROM emp WHERE deptno = 20

The equivalent pseudo-column in Informix is also known as ROWID and although the behavior is similar the data type is different from Oraclersquos See the ROWID subsection in the Data Types section in the chapter ldquoData definition languagerdquo for more information

ROWNUM

In Oracle for each row returned by a query the ROWNUM pseudo-column returns a number indicating the order in which Oracle selected the row from a table or set of joined rows The first row selected has a ROWNUM of 1 the second has 2 and so on ROWNUM can be used to limit the number of rows returned by a query as in this example to read 9 rows

SELECT

FROM emp

WHERE ROWNUM lt 10

ROWID ENAME 0000000F00000002 SMITH 0000000F00030002 JONES 0000000F00070002 SCOTT 0000000F000A0002 ADAMS 0000000F000C0002 FORD

IBM Software Group IBM Information Management

Version 16 47

You can also use ROWNUM to assign unique values to each row of a table as in this example

UPDATE tabx

SET col1 = ROWNUM

Oracle assigns a ROWNUM value to each row as it is retrieved before the rows are sorted by an ORDER BY clause Therefore the final order of the rows is in ORDER BY order not in ROWNUM order An ORDER BY clause does not affect the ROWNUM values except in the case where the ORDER BY clause causes Oracle to use an index In that case the ROWNUM values are set in the order the rows are retrieved using the index and hence in ORDER BY order This order is different than if the rows were retrieved without the index So in this case the ORDER BY can affect the ROWNUM values Conditions which test for ROWNUM values greater than zero are always false For example this query returns no rows

SELECT FROM employee WHERE ROWNUM gt 1

The first row fetched is assigned a ROWNUM of 1 thus making the condition false The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 making the condition false All rows subsequently fail to satisfy the condition so no rows are returned Although there is no ROWNUM equivalent in Informix there are solutions Beginning with IDS 73 and in Informix Dynamic Server 2000 Informix provides a feature which allows the user to limit the results of a query to the first N rows This was implemented for TPC-D compliance and to support ldquorankrdquo queries Rank queries can be assembled by using FIRST N with the ORDER BY clause Informix will return the top N rows according to some ordering criteria Therefore the following Oracle SELECT utilizing ROWNUM

SELECT FROM emp WHERE ROWNUM lt 10

can be ported to Informix as follows

SELECT FIRST 9 FROM emp

Informix does not support SELECT FIRST N in complex cases as the following

Sub-queries (SELECT within a SELECT)

View definitions (Cannot be used by a SELECT statement which references a view)

UNION queries The behavior of SELECT FIRST N depends on the presence of an ORDER BY clause If no order by clause is specified the first N rows returned may be in any order Examples are as follows

find 10 highest paid employees

SELECT FIRST 10 name salary

FROM emp

ORDER BY salary

find 10 highest salary values

SELECT FIRST 10 DISTINCT salary

FROM emp

ORDER BY salary

IBM Software Group IBM Information Management

Version 16 48

Informix supports column names of ldquofirstrdquo Thus without a positive integer following the word ldquofirstrdquo the token is parsed as a column name rather than a keyword The value of N may be between 1 and (2

31-1)

When ROWNUM is used in a WHERE clause the same results can be obtained through the use of the FIRST N and SKIP clauses but if ROWNUM is used in the select list the solution is a little more complicated Simply stated you can construct a query where the ROWNUM column in any row is the count of the rows that came before This involves creating a correlated subquery where the subquery contains a self-join This can be done for any table or set of tables which has a unique key defined on it Here is an example using the customer table of the stores7 database

select

counterrownum

basecustomer_num

basefname

baselname

from

-- There can be more than one table here and the result

-- set should thought of as a table (just not a base table)

-- The result table has to be joined to itself in the

-- subquery so if there are multiple tables in this FROM

-- clause the expansion can get messy You have to have a

-- set of columns that uniquely identify each row in the

-- result table and join across them ROWID would

-- likely work if the table is not fragmented but if it is

-- there is no guarantee the final results would be accurate

-- because ROWID is not guaranteed to be unique across

-- fragments

customer base

(select

count() as rownum

acustomer_num -- any unique key possibly multiple

-- columns

from

customer a

customer b

where

-- This is where the rownum is determined the relationship

-- here has to match the outer order-by where the rows

-- are sorted and has to create a unique sort order

--

-- Any columns to be ordered by go here

-- Also the unique key has to be used to keep rows

-- that do not have a unique sort order from being merged

(alname gt blname) -- example sorting by last name

or

(alname = blname and afname gt bfname)

-- sorting by fname where lname is equal

or

(alname = blname and afname = bfname

and acustomer_num gt= bcustomer_num)

-- sorting by unique key where all the

-- other sort columns are equal

-- The expansion above is logically the same as

-- alname || afname || to_char(acustomer_num) gt=

-- blname || bfname || to_char(bcustomer_num)

-- but it allows the server to utilize any indexes that

-- may exist

group by

-- unique key columns go here

IBM Software Group IBM Information Management

Version 16 49

acustomer_num

) counter

where

-- key columns in the base tables go here

basecustomer_num = countercustomer_num

-- if you want to limit on rownum it goes here

-- and rownum lt= 10

order by

counterrownum

If using ROWNUM as an assignment as in

UPDATE tabx

SET col1 = ROWNUM

The following Informix-ESQLC pseudo-code example would have to be used

int counter = 0

EXEC SQL declare c1 cursor for

SELECT col1 col2

INTO col1 col2

FROM table 1

WHERE col1 = XX

EXEC SQL open c1

while (SQLCODE == 0)

EXEC SQL fetch c1

counter++ Increment counter for each row

fetched

if (counter gt= 5)

break

logic

End if

End while

Update using cursors There are slight differences between the ways Informix and Oracle process cursors Unlike Oracle in Informix the WHERE CURRENT OF clause cannot be used to update tables in a SELECT statement joining multiple tables since the WHERE CURRENT OF clause requires a FOR UPDATE cursor and Informix does not support the FOR UPDATE clause in SELECT statements that join multiple tables Therefore in the multi-table join statements the Oracle options FOR UPDATE and WHERE CURRENT OF should be removed and the update of the rows should be done using a separate UPDATE statement in the same cursor loop

IBM Software Group IBM Information Management

Version 16 50

In Informix a commit or rollback statement closes all cursors open in a given transaction boundary See the Transaction Processing section in CHAPTER 5 Application Architecture for more information In situations where the intention is to commit or rollback without closing the cursor in other words where the commit or rollback is executed within a cursor fetch loop the cursor can be declared as a HOLD cursor This requires that a BEGIN WORK is issued before the cursor loop starts A HOLD cursor is not closed when a commit or rollback statement is issued In Informix the FOR UPDATE clause cannot be used when declaring a HOLD cursor Thus where an Oracle application updates a table from which it fetches data in the fetch loop or issues a commit work in the fetch loop it must be converted to Informix The cursor can be declared with HOLD and then an UPDATE statement can be issued without the WHERE CURRENT OF clause In order to uniquely identify the row to be updated in the table in other words in order to simulate the WHERE CURRENT OF clause the ROWID or unique primary key columns of the table(s) to be updated must also be fetched and the WHERE CURRENT OF clause can be replaced with WHERE ROWID = fetched rowid or WHERE unique primary key column(s) = fetched unique primary key column(s) A BEGIN WORK must follow immediately after a COMMIT WORK or ROLLBACK WORK in the fetch loops to simulate Oracle implied transaction boundaries These transaction control statements work for either Informix logged databases or Informix ANSI mode databases however ANSI mode database processing with these statements will set certain warning flags after executing the BEGIN WORK statement and continue processing without failure See the ANSI vs Non-ANSI subsection in the Databases section in the chapter ldquoData Manipulation Languagerdquo for more information

System tables References to Oracle system tables should be replaced with corresponding references to Informix system tables The information schema views provided by Informix can be used These views are created after the database is installed They are populated by data in the system catalog tables and are used for easier porting

Stored procedures Informix procedures and functions are considered to be user-defined routines (UDR) A UDR can be written in Informixrsquos Stored Procedure Language (SPL) or an external language such as C or Java A procedure is a routine written that does not return a value A function is a routine written that returns a single value a value with a complex data type or multiple values Informix SPL is an extension to Informix SQL and provides procedural flow control such as looping and branching A SPL routine is a generic term that includes both SPL procedures and SPL

functions You use SQL and SPL statements to write an SPL routine SPL statements can be used only inside the CREATE PROCEDURE CREATE PROCEDURE FROM CREATE FUNCTION and CREATE FUNCTION FROM statements SPL routines are parsed optimized and stored in the system catalog tables in executable format Like Oracle Informix stored procedures support input output and inputoutput parameters and can be used in SQL statements wherever expressions are allowed

Size limit

Informix stored procedures have a size limit of approximately 64K Oracle stored procedures greater than 64K in size can be broken into smaller Informix stored procedures communicating with each other as though they were one by passing and returning the necessary values

Parameter limit

IBM Software Group IBM Information Management

Version 16 51

Informix has a limit of 341 parameters for each stored procedure This limit also applies to UDRs written in the Java language UDRs written in the C language can have no more than 102 parameters You can define any number of SPL routine parameters but the total length of all parameters passed to an SPL routine must be less than 64 kilobytes No more than nine arguments to a UDR written in the Java language can be DECIMAL data types of SQL that the UDR declares as BigDecimal data types of the Java language Any C language UDR that returns an opaque data type must specify opaque_type in the var binary declaration of the C host variable

Packages

An Oracle package is a collection of functions procedures and variables that can be enabled and accessed as a unit There is no direct equivalent within Informix but there are ways of achieving similar capabilities Within Oracle a procedure within a package can be accessed through grammar such as package_nameprocedure_name If you create an owner or schema name within the Informix system the same as the package name then it will be easier to migrate calls to that procedure because the grammar is effectively the same although the meaning changes somewhat Using this practice a call to a migrated procedure would be ownerprocedure_name where the owner name is the same as the package name Translating package names as owner names is a way to maintain the scoping of the objects within the package Maintaining the aspect of being able to enable use of or upgrade the collection of package objects can be done by creating a datablade that contains all the objects that used to be part of the package Datablade routines can be procedures or functions written in Stored Procedure Language (SPL) C and Java In addition routines can be written in C++ on Windows platforms

Routines

Oraclersquos stored functions and stored procedures are similar in concept to Informixrsquos stored procedures Oraclersquos user defined database level functions such as stored functions stored procedures all need to be converted to Informix stored procedures using the Informix SPL C or Java Routines written in SPL have the advantage of being maintained and backed up with database backups Routines written in C are fast but are not automatically backed up when the database is and need to be compiled specifically for the operating system on which it will run Routines written in Java also not backed up by the DBMS itself but they are platform independent However probably as a result of having to convert between system memory where the objects have C structures and Java virtual machine memory where the objects have Java structures the performance of Java routines can be slow compared with the C equivalent All procedures written in an Oracle package body must be rewritten as separate Informix procedures When rewriting package bodies into separate procedures Oraclersquos variable declarations can be replaced at the package level (global) with Informixrsquos global variables The Informix global variables must be defined in the first stored procedure of the logical group

Exceptions

The method of handling exceptions is different between Informix and Oracle Oracle has many predefined and user defined exception labels such as CURSOR_ALREADY_OPEN NO_DATA_FOUND ZERO_DIVIDE and so on The labels can be used in the logic to identify errors Only one exception check is allowed per BEGIN and END block using the EXCEPTION construct and it is normally placed just before the END statement Informix also supports predefined and user defined exceptions however they are represented numerically not with labels In Informix all the exceptions checked in the stored procedure control blocks delimited with BEGIN and END statements must be declared explicitly at the top of each

IBM Software Group IBM Information Management

Version 16 52

control block with the Informix EXCEPTION construct Therefore Oracle procedure code must be restructured to manipulate these exceptions In Oracle an exception can be raised globally and acted upon globally In Informix the scope of an exception mechanism is always restricted to the block in which it is located This leads to the addition of multiple Informix exception handling mechanisms for each Oracle exception raised as well as a redesign of the overall stored procedure to a more blocked format

Error handling

In Oracle errors are processed as part of a function call return value In Informix errors are retrieved as a separate function call that has multiple structures that have to be created in order to retrieve error and status The SQLCA structure is not fully available in Informix stored procedures It is not possible to check the SQLCODE variable in the stored procedure body Instead the function DBINFO can be used to extract the value of two members of the SQLCA structure sqlcasqlerrd1 and sqlcasqlerrd2 This function should be used inside the FOREACH construct while the cursor is open Once the cursor is closed the DBINFO function cannot return proper values The sqlcasqlerrd1 option returns different values depending on the type of SQL statement For INSERT statements if the table contains a serial column then the sqlcasqlerrd1 option will return the serial value of the last row inserted into the table For SELECT DELETE and UPDATE statements the sqlcasqlerrd1 option will return the number of rows processed by the query In these cases upon each pass through the FOREACH loop sqlcasqlerrd1 is the same value the number of rows the FOREACH loop will process The sqlcasqlerrd1 value can still be interrogated during each pass through the FOREACH loop The sqlcasqlerrd2 option returns the number of rows processed by a SELECT INSERT UPDATE DELETE or EXECUTE PROCEDURE statement It should not be interrogated until after the cursor has finished processing In other words within the FOREACH loop the sqlcasqlerrd2 value can be moved to a variable which is then interrogated outside of the FOREACH loop

Cursors

Unlike Informix in Oracle cursors can be global to a package In Informix Oraclersquos global cursors can be replaced with temporary tables A temporary table can be created and populated in place of where the cursor is opened The temporary table can then be processed the same way the cursor is processed Finally the temporary table should be dropped in place of where the cursor is closed Cursors are explicitly declared opened and fetched in Oracle stored procedures In Informix cursors do not need to be explicitly declared opened and fetched in stored procedures Instead Oracle stored procedure cursors can be replaced with Informixrsquos FOREACH construct The Oracle cursor name should be used in the FOREACH statement for example FOREACH cursor_name SELECT hellip END FOREACH In order to update a cursor row in Oracle the cursor must be declared with the FOR UPDATE clause In Informix if the SELECT statement in the FOREACH construct is not a multi-table join then each fetched row can be updated using the UPDATE lttable_namegt WHERE CURRENT OF ltcursor_namegt statement See the Update Using Cursors section in ldquoData Manipulation Languagerdquo for more information Informix does not support the SELECT FOR UPDATE statement in a stored procedure Therefore the SELECT FOR UPDATE clause cannot be used in the FOREACH construct

IBM Software Group IBM Information Management

Version 16 53

Variable declaration and assignment

Oracle allows implicit variable definitions within a FOR loop The variables are defined using an assignment operator and a column name For example

out_customer_name = customername

The variable out_customer_name is defined as the same type as the column name in the customer table Informix requires that all variables be defined at the beginning of each stored procedure control block For example

DEFINE out_customer_name LIKE customername

DEFINE counter INTEGER

Therefore Oraclersquos implicit variable declaration must be replaced with Informixrsquos explicit variable declaration before the control block Additionally assignment operations will need to be ported Oracle uses a colon and an equal sign (=) for assignment while Informix utilizes the LET keyword in combination with an equal sign (=) (ie LET var = 1) Therefore assignment statements must be modified with the LET keyword and an equal sign

Boolean

Oraclersquos BOOLEAN variable type can be replaced with Informixrsquos BOOLEAN data type

Binary data types

Binary data types are very different between Oracle and Informix In Oracle the binary type is defined as a type RAW and is explicitly defined with a maximum length as part of the declaration In Informix the binary type is defined as REFERENCES BYTE which deals only with pointers to BLOBs It implicitly defines a maximum length as part of the function call in which the pointer to the BLOB and maximum length (as used in the function call) was passed as values As a result the binary type cannot be assigned a binary value in a stored procedure nor can it be inserted into a table via the SQL INSERT statement in a stored procedure These operations that initialize a binary type must be performed outside of stored procedures

Dynamic SQL

Unlike Oracle Informix does not support dynamic SQL within the Stored Procedure Language In other words a statement such as SELECT variable_name FROM variable_name WHERE variable_name is not supported This kind of processing can be achieved in Informix within an embedded SQL program This requires that either the Oracle stored procedure be converted to an embedded SQL program or just the Dynamic SQL portion be placed in an embedded SQL program and then called from within the stored procedure The latter option will have performance implications since calling an embedded SQL program from a stored procedure requires an operating system call Another option is to use the Informix EXEC Bladelet The EXEC Bladelet consists of user-defined functions that take a SQL query as an argument execute it and return a result (the format of which varies depending on the function and the kind of query) The EXEC Bladelet functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries Further details can be found in Chapter 7 Using Bladelets

Compiler

Unlike Oracle the Informix compiler was developed with the concept that developers can create stored procedures independently of the database Therefore Informixrsquos stored procedure

IBM Software Group IBM Information Management

Version 16 54

compiler has a limited set of errors that it checks compared to Oraclersquos For example the Informix stored procedure compiler does not validate database object names such as table column and view names Therefore database object naming errors will occur at runtime not compile time Additionally the error messages generated from the compiler are not very specific Identifying a problem in a stored procedure may require breaking it apart and recompiling the pieces until the problem is found This may impact the time necessary to unit test the stored procedures

Triggers Oracle supports the use of multiple trigger events for example insert update and delete within the same trigger Informix only supports one trigger event per trigger In Informix the Oracle trigger body in this example must be copied into three different triggers each with only one event Informix triggers have some constraints Oraclersquos do not In Informix if a trigger is fired due to inserting a row into a table a trigger can only act on any rows or columns within that table using the EXECUTE PROCEDURE hellip INTO syntax Similarly if a trigger is fired due to updating a row then the trigger can only act on the column that caused the trigger to fire using the EXECUTE PROCEDURE hellip INTO syntax Like Oracle if a trigger is fired due to deleting a row there are no restrictions Prior to IDS 73 when a trigger was fired on an INSERTUPDATE action no modification could be done to the columns (in the row) which just fired the trigger The reentrant UPDATEINSERT triggers feature introduced with IDS 1110 enables users to update the triggering columns by using the EXECUTE PROCEDURE INTO syntax Additionally the feature enforce that this action will not cause any additional triggers to be fired (same or different trigger) causing a cascading of triggers and potentially an infinite loop The following example demonstrates how the reentrant UPDATEINSERT trigger feature is used

create table foo

(

x int default NULL

y int default NULL

z int default NULL

)

create procedure reentrant()

returning int

return 56

end procedure

create trigger reentrant_trigger insert on foo for each row

(

execute procedure reentrant() into z

)

insert into foo values

(

1

2

3

)

The following SELECT will result in the following returned data

select from foo

x y z

1 2 56

IBM Software Group IBM Information Management

Version 16 55

Oracle allows SQL statements logical statements and stored procedure calls within a trigger body Informix allows only SQL statements and stored procedure calls within a trigger body Oracle triggers containing logical statements must be converted to Informix by moving their contents into a stored procedure The stored procedure should then be executed from the trigger

Constraints Constraints in both Oracle and Informix can be enabled and disabled within an application transaction however there are behavioral differences In Oracle the application is always executing within a transaction In Informix transaction boundaries are explicitly declared and care should be taken to ensure that this functionality is performed within the boundaries of a transaction See the Transaction Processing section in CHAPTER 5 Application Architecture for more information The constraint syntax available in Informix is

SET CONSTRAINTSINDEXESTRIGGERS FOR table_name

ENABLED|DISABLED

SET CONSTRAINTS comma_separated_constraint_names

ENABLED|DISABLED

SET INDEXES comma_separated_index_names ENABLED|DISABLED

SET TRIGGERS comma_triggers_constraint_names ENABLED|DISABLED

SET CONSTRAINTS ALLconstraint_name IMMEDIATE|DEFERRED

The first four statements must be executed with DBA privileges if placed in the application Therefore care should be taken when using them Note that the last statement contains a DEFERRED clause This is the statement used if the users of the application do not have DBA privileges When the constraint is set with the DEFERRED clause the specified constraints are not checked until the transaction is committed If a constraint violation occurs while the transaction is being committed the transaction is rolled back

DUAL table Oraclersquos DUAL table is a system table with only one row containing one column named DUMMY This table is used to complete the syntax of an SQL statement that does not involve an existing table such as

A SELECT statement which assigns some constant value (which can only be derived in an SQL statement) to a host variable

SELECT TO_CHAR(SYSDATE) INTO date_var FROM DUAL

A SELECT statement which assigns a value of another variable to a variable

SELECT source_var INTO dest_var FROM DUAL

A SELECT statement which unions application host variable values with another SELECT statement to return a result containing a row of application variable values

SELECT col1 col2 col3 FROM table_name

UNION

SELECT host_var1 host_var2 host_var3 FROM DUAL

Converting Oraclersquos DUAL table functionality to Informix depends on the way it is used Converting statements that just assign constants is as simple as replacing the DUAL statement with an Informix assignment statement The solutions below apply to Informix versions prior to 11 At 11 and above the concept of a DUAL table as well as sysdate is supported

IBM Software Group IBM Information Management

Version 16 56

SELECT sysdate FROM sysmastersysdual

If you want a dual table in your local database then create the following synonym The sysmastersysdual table is much faster than a physical table in your database because it is an in- memory pseudo table

CREATE SYNONYM dual FOR sysmastersysdual

If you are restricted to using a version of Informix prior to 11 then the following solutions can be used A dummy table can be created to mimic the behavior of simple SELECT INTO statements used to assign values to variables

CREATE TABLE dual (dummy VARCHAR(1))

INSERT INTO dual VALUES(lsquoXrsquo)

An alternate solution to widespread use of the DUAL table could be creating a permanent view that is generally accessible

CREATE VIEW dual (d) as SELECT X

FROM systables WHERE tabid = 1

The exact definition could be used or modified as needed but this would solve the problem of having DUAL be permanent usable by anyone and not modifiable

IBM Software Group IBM Information Management

Version 16 57

C H A P T E R 5 Embedded SQL

Oraclersquos embedded SQL products are ProC and ProCOBOL Informixrsquos corresponding embedded SQL products are ESQLC and ESQLCOBOL

Host variables

Declaration override

The Oracle EXEC SQL VAR declarative statement (host variable equivalency of Oracle external data types by overriding the default assignment) can be converted to an Informix explicit declaration statement For example

Oracle char char_var[20]

EXEC SQL VAR char_var IS STRING(11)

Informix

char char_var[11]

Note that the size and type used in the EXEC SQL VAR section is the final information required to declare the host variable in Informix

Arrays

Oracle arrays are not subscripted in SQL statements since it is not required to process the host arrays in a loop in the SQL statement In Informix subscripting is mandatory In Oracle if an array is defined of size 200 then an SQL statement would be

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A

VAR-B

VAR-C

END-EXEC

-or- EXEC SQL SELECT COL1 COL2 COL3

INTO VAR-A

VAR-B

VAR-C

FROM TABLE1

WHERE COL2 gt 100

END-EXEC

where VAR-A VAR-B and VAR-C are each an array of say 200

IBM Software Group IBM Information Management

Version 16 58

In Informix the first example would be converted to

PERFORM VARYING LOOP-CTR FROM 1 BY 1 UNTIL

LOOP-CTR IS GREATER THAN 200

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A(LOOP-CTR)

VAR-B(LOOP-CTR)

VAR-C(LOOP-CTR)

END-EXEC

IF SQLCODE = 100

GO TO EXIT-PERFORM

END-IF

END-PERFORM

EXIT-PERFORM

For the second Oracle example given above a cursor must be declared in Informix opened and fetched for 200 rows or less (less because there may be less than 200 qualifying rows) into the host array and then should be closed If the number of qualifying rows is more than 200 then the extra rows must be ignored to duplicate the Oracle functionality But for the first example each fetch in Oracle will return the next 200 or less number of rows Therefore each Oracle fetch needs to be replaced by another call to the Informix fetch loop Oracle also uses this method for inserts deletes and updates These array techniques are mainly used in batch SQL processing

Formatting

In Informix when a DECIMAL MONEY DATE or DATETIME value is selected into a host variable of the same data type the value must be formatted using the available Informix formatting routines before they can be printed or displayed For example

hellip

dec_t dec_host_var

char formatted_dec[40]

EXEC SQL SELECT DEC_COLUMN INTO dec_host_var FROM TABLE_NAME

rfmtdec(ampdec_host_var ldquoampampampampampampampampampamprdquo formatted_dec)

printf(ldquoThe Decimal Value is snrdquo formatted_dec)

hellip

IBM Software Group IBM Information Management

Version 16 59

Informix supplies many formatting functions and formatting strings The names of these functions are different in Informix ESQLC and ESQLCOBOL but the functionality is the same Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

SQL structures

SQLCA

Oraclersquos SQLCA structure is different from that of Informix However the components of both structures are logically the same Oraclersquos SQLCA components can be replaced with the corresponding Informix components Oraclersquos SQLCA structure

SQLCAID string containing ldquoSQLCArdquo SQLCABC length of SQLCA data structure SQLCODE Oracle error message code SQLERRM sub-record for error message

SQLERRML length of error message SQLERRMC text of error message SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) reserved for future use SQLERRD(1) reserved for future use SQLERRD(2) number of rows processed SQLERRD(3) reserved for future use SQLERRD(4) parse error offset SQLERRD(5) reserved for future use

SQLWARN array of eight warning flags SQLWARN(0) another warning flag set SQLWARN(1) character string truncated SQLWARN(2) no longer in use SQLWARN(3) SELECT list not equal to INTO list SQLWARN(4) DELETE or UPDATE without WHERE clause SQLWARN(5) reserved for future use SQLWARN(6) no longer in use SQLWARN(7) no longer in use

SQLTEXT reserved for future use

IBM Software Group IBM Information Management

Version 16 60

Informixrsquos SQLCA structure

SQLCODE Informix error code SQLERRM error message parameter SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) estimated number of rows returned SQLERRD(1) serial value of INSERT or ISAM error code SQLERRD(2) number of rows processed SQLERRD(3) estimated cost SQLERRD(4) parse error offset SQLERRD(5) ROWID after INSERT

SQLWARN structure of eight warning flags SQLWARN0 another warning flag set SQLWARN1 character string truncated or no privileges revoked SQLWARN2 NULL value returned or ANSI database SQLWARN3 SELECT list not equal to INTO list or turbo back-end SQLWARN4 DELETE or UPDATE without WHERE clause SQLWARN5 if non-ANSI statement SQLWARN6 if server is in data replication secondary mode SQLWARN7 reserved

In order to get Oracle error messages an application normally uses the SQLCA element SQLERRMC The Informix equivalent is SQLERRM On the HPUX and Solaris platforms the Informix function rgetmsg should be used instead of the element SQLERRM At the time of this writing using SQLERRM would cause an error on the HPUX and Solaris platforms

SQLDA

The implementation of Oraclersquos SQLDA structure is very different from that of Informix Significant changes are necessary to convert Oraclersquos functionality to Informix Oraclersquos sqlald function can be replaced with Informixrsquos ALLOCATE DESCRIPTOR statement Since Oraclersquos and Informixrsquos SQLDA structures are so different Oraclersquos SQLDA logic must be rewritten with the more powerful Informix SQLDA logic or alternatively the Informix system-descriptor area logic Oraclersquos SQLDA Structure

N maximum number of SELECT list items or placeholders V pointer to array of address of SELECT list items or bind variables L pointer to array of lengths of SELECT list items or bind variables T pointer to array of data types of SELECT list items or bind variables I pointer to array of addresses of indicator variable values F actual number of SELECT list items or placeholders S pointer to array of addresses of SELECT list items or placeholder names M pointer to array of max lengths of SELECT list items or placeholder names C pointer to array of current lengths of SELECT list items or placeholder names X pointer to array of addresses of indicator variable names Y pointer to array of maximum lengths of indicator variable names Z pointer to array of current lengths of indicator variable names

IBM Software Group IBM Information Management

Version 16 61

Informixrsquos SQLDA Structure SQLD count of the following SQLVAR members SQLVAR pointer to array of structures

SQLDATA pointer to actual data SQLTYPE data type of placeholder or SELECT item SQLLEN length of the placeholder or SELECT item SQLIND pointer to the indicator SQLNAME pointer to placeholder or SELECT item name SQLFORMAT reserved SQLIDATA indicator data pointer SQLITYPE indicator variable type SQLILEN length of indicator variable

If an Oracle application uses the simple dynamic SQL method using macros only not the SQLDA structure directly the value indicatorsplaceholders can be replaced with a lsquorsquo in Informix For example Oracle sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES (v1 v2)rdquo) Informix sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES ( )rdquo)

ORACA

Oraclersquos ORACA structure is not supported by Informix This structure is used to handle Oracle specific communication and more runtime information than SQLCA Oracle statements containing references to this structure should be removed from the application

Pre-compiler options The Oracle options beginning with the EXEC ORACLE OPTION statement can be removed from the application The options set after this statement do not affect the application logic They may affect some application performance only

Embedded PLSQL Oracle allows procedure language (PLSQL) blocks inside ProC and ProCOBOL code delimited by the EXEC SQL EXECUTE and END-EXEC statements In Informix these blocks must be replaced with the equivalent ESQLC or ESQLCOBOL code

Oracle Call Interface Oracle call interface (OCI) is the base layer for a variety of other application programming interfaces such as JDBC-OCI Oracle Precompilers and Oracle ODBC It is also used directly by customers who are willing to develop their code using a lower level proprietary API From a high level it can be thought of as if IBM Informix had standardized and published the function calls in the ESQLC library Although some customers have reverse engineered these calls and developed applications using them this is generally discouraged because there is no guarantee that the library of calls will not change There is no direct equivalent to this Oracle API in Informix Migrating applications written using Oracle Call Interface (OCI) will require rewriting the code from scratch OCI is native to the C language and so it should be less effort to migrate the application to an Informix API that is also native to C This could be ESQLC or CLI The following information explains differences between Oracle OCI and Informix ODBC

IBM Software Group IBM Information Management

Version 16 62

The following table is an approximate mapping of the differences between the Informix CLI and Oracle OCI function calls in which there is not a direct one-to-one mapping

Oracle Informix Buffer Areas HAD LDA CDA HENV HDBC HSTMT

Connect and allocate resources

OLOG OOPEN SQLConnect SQLAllocEnv SQLAllocConnect SQLAllocStmt

Update delete insert select OPARSE OBNDRV OEXEC SQLPrepare SQLBindParameter SQLExecute

Select ODEFIN OFETCH SQLBindCol SQLFetch

Commit Rollback OCOM OROL SQLTransact

Disconnect OLOGOF OCLOSE SQLDisconnect SQLFreeStmt SQLFreeConnect SQLFreeEnv

Database library calls

One of the first main differences between Informix CLI and Oracle OCI calls is the overall data structures and mechanisms used to process database library calls Oracle uses direct connections to the database server Informix uses an ODBC connection to the database server As a result the Informix calls will be implemented as ODBC SQL calls utilizing three tiers of increasing SQL levels of complexity

Global area processing

Another main difference between Informix CLI and Oracle OCI is Informixrsquos use of pointers to three global areas versus Oraclersquos use of pointers to three different but similar global areas Hence the Oracle OCI calls that utilize HAD (Handle Data Area) LDA (Logon Data Area) and CDA (Cursor Data Area) pointers must be translated over to Informix CLI calls that utilize HENV (Environment Area) HDBC (Database Connection Area) and HSTMT (Statement Area) pointers respectively in conjunction with an ODBC interface

Fetch cycle

Another difference between Informix CLI and Oracle OCI calls is that the overall fetch cycle is different for each and must be modified accordingly In Oracle the fetch cycle for selecting multiple rows utilizing a cursor area involves parsing binding defining fetching and then executing into a cursor data area These must be translated to a cycle that involves preparing binding executing binding and then fetching via the ldquoFor Eachrdquo cycle

RAW binary data type processing

RAW binary data types in Oracle will need to be translated to a pointer-to-BLOB REFERENCES BYTE type in Informix See the Binary Data Types subsection of the Stored Procedures section in CHAPTER 3

Parameter bindings

In Oracle multiple output bindings of parameters are declared as type ldquoOUTPUTrdquo in the ODEFIN() calls In Informix convert the calls to Informix SQLBindCol() calls and bind the output parameters as columns Differences also exist between Informix CLI and Oracle OCI in the use of inputoutput bindings In Oracle these bindings are declared as type ldquoINPUTOUTPUTrdquo in the ODEFIN() calls In Informix a ldquoround robinrdquo approach is used using three variables in the following manner A=B B=C C=A A variable (A) is declared before the SQL bindings as an input variable The function is called

IBM Software Group IBM Information Management

Version 16 63

using a second input variable (B) that is set to the first input variable (A) The function returns a third variable (C) that is bound as an output column Finally the first variable (A) is now set to the returned third variable (C) that made the first variable (A) appear as an ldquoinputoutputrdquo variable to the rest of the program

Embedded SQL for C

VARCHAR

Oraclersquos ProC VARCHAR data type is expanded after pre-compiling into a structure with two elements one is unsigned short len and the other is unsigned char arr[size] The name of the expanded structure is the same name as the VARCHAR variable and size is replaced with the size of the VARCHAR variable In Informix the VARCHAR data type is just a synonym for the C languagersquos char data type Therefore statements that use variable_namelen can be removed from the application and all occurrences of variable_namearr can be replaced with variable_name For example

Oracle VARCHAR vName[40]

strcpy(vNamearr ldquoCompany Namerdquo)

vNamelen = strlen(vNamearr)

Informix VARCHAR vName[40]

strcpy(vName ldquoCompany Namerdquo)

Host variables

The Oracle statement EXEC SQL TYPE is synonymous with the C languagersquos typedef declarative instruction It can be easily replaced with the Informix declarative instruction typedef

Embedded SQL for COBOL

VARCHAR

Oraclersquos ProCOBOL character host variable declaration statementrsquos VARYING clause is expanded after pre-compiling into a group with two elements one is variable-name-LEN PIC S9(4) COMP and the other is variable-name-ARR PIC X(size) The group name is the same as the host variable name and size is replaced with the size of the VARYING variable Informix does not support this concept Therefore statements that use variable-name-LEN must be removed from the application and all occurrences of variable-name-ARR must be replaced with variable-name Also the VARYING clause must be removed from the declarative statement For example

Oracle

05 vName PIC X(40) VARYING

hellip

MOVE ldquoCompany Namerdquo TO vName-ARR

MOVE 12 TO vName-LEN

Informix

05 vName PIC X(40)

hellip

MOVE ldquoCompany Namerdquo TO vName

IBM Software Group IBM Information Management

Version 16 64

Level 88

COBOLrsquos level 88 functionality is not supported within an Informix ESQLCOBOL host variable declaration section in versions prior to 72 Level 88 functionality is supported in Informix ESQLCOBOL 72

SQLDA

In Informix ESQLCOBOL the SQLDA structure is not available The Informix macros such as ALLOCATE DESCRIPTOR DESCRIBE GET DESCRIPTOR and SET DESCRIPTOR must be used to retrieve and manipulate the SQLDA data

REDEFINES

Oracle supports the use of the REDEFINES clause at the elementary level in the host variable declaration section In other words the redefined item cannot be a group item but the redefining item may be a group item Informix does not support the use of the REDEFINES clause in the host variable declaration section in versions prior to 72 The REDEFINES clause is supported in Informix ESQLCOBOL 72

Tips

If the Informix pre-compiler finds an SQL statement within an IF [ELSE IF hellip ] END-IF or EVALUATE END-EVALUATE or PERFORM END-PERFORM block then the pre-compiler adds a period after the generated COBOL statements regardless of whether there is a period at the end of the SQL statement This is a violation of COBOL rules for such blocks and the code may cause syntax errors during compilation or may behave unexpectedly To avoid these problems each SQL statement group should be moved to a new paragraph and these paragraphs should be performed from the block from which they were moved

ODBC Although the Open Database Connectivity (ODBC) API is designed to make it possible to write and compile an application once and use it with any ODBC driver on the same platform there are frequently differences between the underlying DBMSs that can expose problems to the applications For instance there can be differences between how unspecified parts of a date-time value are filled Most of these kinds of differences that get exposed through ODBC have their origins in the differences between the DBMSs themselves There are also cases where there are gaps in the ODBC standard for example there is a standard ODBC call that allows the application to ask the driver if it can support scrollable cursors and there is another call to ask if it can support updateable cursors There is no call to ask if it can support both at the same time With Informix you can have a scrollable cursor and you can have an updateable cursor but you can not have one cursor that is both scrollable and updateable A more complete description of ODBC application migration issues is beyond the scope of this article

IBM Software Group IBM Information Management

Version 16 65

C H A P T E R 6 Application Architecture

Transaction processing Transaction boundaries are defined differently in Oracle and Informix Oraclersquos transactions begin implicitly in one of two ways either by issuing a CONNECT statement or issuing a COMMIT or ROLLBACK statement A CONNECT statement marks the beginning of a transaction and a COMMIT or ROLLBACK statement commits or rolls back the previous transaction respectively and then implicitly begins a new transaction CONNECT statements are usually issued once at the beginning of a program however they may be nested or issued more than once serially to connect to the same or a different database When using more than one CONNECT statement within a program each CONNECT statement must be named This marks the beginning of named transactions Every SQL statement within a named transaction must also be named with the same transaction name as the CONNECT statement at where the SQL is to be executed SQL is named using the EXEC SQL statementrsquos AT clause Informixrsquos transaction boundaries are explicitly marked with the reserved words BEGIN WORK and COMMIT WORK or ROLLBACK WORK Note that once a transaction has begun for a given connection it stays open until a COMMIT or ROLLBACK is executed In other words if an ESQL program begins a transaction and then calls a stored procedure the stored procedure executes within the same transaction If the stored procedure issues a COMMIT then the whole transaction is committed and the calling ESQL program should not issue a COMMIT or ROLLBACK Informix transactions can be written to behave the same way as Oraclersquos To simulate Oraclersquos CONNECT statement behavior an Informix CONNECT should also be issued followed by a BEGIN WORK statement If more than one CONNECT statement is used in a program Informix also requires that the CONNECT and SQL statements be named To simulate Oraclersquos COMMIT and ROLLBACK statement behavior an Informix COMMIT WORK or ROLLBACK WORK statement should be issued followed by a BEGIN WORK statement Nested transactions can be simulated in Informix with the CONNECT statement and naming the transactions Then the Informix SET CONNECTION connection_name statement can be used to switch between transactions Committing or rolling back each named transaction does not commit or roll back other active transactions The Oracle statement EXEC SQL COMMITROLLBACK RELEASE should be replaced with the Informix statements EXEC SQL COMMITROLLBACK [WORK] followed by EXEC SQL DISCONNECT CURRENT In the following examples ws-dbenviron is the database name ws-connect-nm is the user name and ws-identity-nm is the password set in the program enp and connection-name are the connection names For Informix the user name and password information should correspond to the entries in the etcpasswd file on the UNIX system See the User Authentication section later in this chapter for more information The default server name is automatically obtained from the environment variable INFORMIXSERVER The following examples illustrate how Oracle and Informix implement the CONNECT functionality

IBM Software Group IBM Information Management

Version 16 66

Simple Connect

Oracle

CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm

Informix

CONNECT ws-dbenviron USER ws-connect-nm USING ws-identity-nm

Named Connect with Literal

Oracle

DECLARE enp DATABASE hellip CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm AT enp USING ws-dbenviron hellip AT enp SELECT col1 col2 INTO var1 var2

FROM table_name

Informix

CONNECT TO ws-dbenviron AS ldquoenprdquo USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION ldquoenprdquo hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Named Connect with Variable

Oracle

CONNECT ws-connect-nm

IDENTIFIED BY ws-identity-nm AT connection-name USING ws-dbenviron hellip AT connection-name SELECT col1 col2 INTO var1 var2 FROM table_name

Informix

CONNECT TO ws-dbenviron AS connection-name USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION connection-name hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Autonomous Transaction

An autonomous transaction is an independent transaction that is initiated by another transaction (the parent transaction) An autonomous transaction can modify data and commit or rollback independent of the state of the parent transaction The autonomous transaction must commit or roll back before the autonomous transaction is ended and the parent transaction continues

IBM Software Group IBM Information Management

Version 16 67

An autonomous transactions has been available since the release of Oracle 8i An autonomous transaction is defined in the declaration of a PLSQL block This can be an anonymous block function procedure object method or triggerThis is done by adding the statement PRAGMA AUTONOMOUS_TRANSACTION anywhere in the declaration block There isnt much involved in defining a PLSQL block as an autonomous transaction You simply include the following statement in your declaration section PRAGMA AUTONOMOUS_TRANSACTION Sample code

PROCEDURE test_autonomous

IS

PRAGMA AUTONOMOUS_TRANSACTION

BEGIN

insert

commit

END test_autonomous

Autonomous transactions can be used for logging in the database independent of the rollbackcommit of the parent transaction

Savepoints

Oracle allows savepoints within its PLSQL For example a PLSQL block can be structured so that SAVEPOINT A is issued upon entry and SAVEPOINT B is issued after some processing Then after some more processing a COMMIT or ROLLBACK can be issued against all the logic since the last COMMIT point which is before the PLSQL block or up to any of the savepoints by naming the COMMIT or ROLLBACK with the savepoint name In other words a savepoint can be issued at the beginning of a stored procedure and then only the stored procedure logic can be committed without committing the changes pending before the stored procedure was executed Those changes can be committed or rolled back once processing is returned from the stored procedure Informix does not support savepoint processing within a stored procedure

Concurrency Database concurrency can be managed through the combination of two configurable settings one specifies the lock granularity on database objects while the other influences how the application behaves in regards to the presence and placement of locks using a transaction isolation level

Row Level Locking

Oracle and Informix implement locking differently on database objects Oracle defaults to row level locking whereas Informix defaults to page level In most cases row level locking is preferred to improve concurrency Informix supports row level locking however it must be either explicitly requested specified by an environment variable or permanently changed in the instancersquos configuration Having three methods for establishing the lock level there is an order of precedence

1 To be explicitly requested the CREATE TABLE statement must include the specification of the LOCK MODE attribute

CREATE TABLE emp (

name CHAR(40)

salary MONEY

ssn LVARCHAR(64)

) LOCK MODE ROW

IBM Software Group IBM Information Management

Version 16 68

2 The environment variable IFX_DEF_TABLE_LOCKMODE will establish the default for CREATE TABLE statements issued without the LOCK MODE attribute and will override the Instancersquos configuration setting The variable setting on the client will override the server environment setting

set IFX_DEF_TABLE_LOCKMODE=ROW -or- export IFX_DEF_TABLE_LOCKMODE=ROW

3 Informix allows the instancersquos lock level default to be changed using a configuration parameter Row level locking can be as the default by adding the parameter DEF_TABLE_LOCKMODE to the instancersquos ONCONFIG file This parameter may not be found in the existing file and if not present can be added using an editor and establish a new default setting of ROW

DEF_TABLE_LOCKMODE ROW

None of the steps will apply a change to existing tables only establish the lock level for the CREATE TABLE statement

Transaction Isolation Level

Oracle databases incorporate a feature known as ldquoread consistencyrdquo which allows a query return a result based on the state of the data when the query started regardless of other processes updating or deleting the same data while the query is running Informix facilitates this type of behavior differently by providing control of the applicationrsquos placement of locks as well as how it reacts to those placed by other processes through the use of the transactionrsquos isolation level If Oraclersquos technique of ldquoreaders not blocking writersrdquo is a requirement then in many circumstance Informixrsquos DIRTY READ isolation level can be used The readers will not block the writers with dirty read processing however the query result may contain updates performed while the query was running which may be uncommitted If the emulation of Oraclersquos ldquoread consistencyrdquo is desired the LAST COMMITTED option of Informixrsquos COMMITTED READ isolation level can reduce the risk of locking conflicts when two or more sessions attempt to access the same row in a table whose locking granularity is row-level When an application attempts to read a row on which another session holds an exclusive lock these keywords instruct the database server to return the most recently committed version of the row rather than wait for the lock to be released This isolation level attribute could be preferable to executing queries using DIRTY READ since it will return only the most recently committed versions of the data The LAST COMMITTED option can be enabled in the following ways

1 Setting the USELASTCOMMITTED parameter in the Instancersquos configuration (ONCONFIG) will apply this feature as the default isolation level to all database transactions The parameterlsquos values will designate the scope of applying the LAST COMMITED option to either ALL NONE or only COMMITED READ and DIRTY READ isolation levels

USELASTCOMMITTED [ALL | NONE | COMMITTED READ | DIRTY READ]

2 The SET ENVIRONMENT statement can override the USELASTCOMMITTED configuration parameter setting for the duration of the current session The same semantics apply as the parameter within the ONCONFIG file with the setting value enclosed in quotes (lsquo)

SET ENVIRONMENT USELASTCOMMITTED lsquoALLrsquo

IBM Software Group IBM Information Management

Version 16 69

3 The SET ISOLATION statement can be used to override the instance configuration and session environment setting The SET ISOLATION statement is an Informix extension to the ANSI SQL-92 standard and provides the same functionality as the ISOANSI-compliant SET TRANSACTION statement There is no support for the LAST COMMITTED option with the SET TRANSACTION statement SET TRANSACTION complies with ANSI SQL-92 and only ANSI supported isolation levels are supported

SET ISOLATION TO COMMITTED READ LAST COMMITTED

4 PREPARE statements in ODBCJDBC applications

This feature is primarily documented in the Guide to SQL Syntax Guide to SQL Reference Administrators Reference and Administrators Guide

IBM Software Group IBM Information Management

Version 16 70

C H A P T E R 7 Security

User authentication In Oracle security information is stored in the database Up until recently Informix has used only the operating system security subsystem to check security For security purposes Oracle connects to the server and passes the user ID and password information to the database for verification

Operating system security

Informix does not store user ID and password information in the database Instead they are validated against the operating systemrsquos security mechanism on the server for example the etcpasswd file in UNIX Therefore either every database user must have an entry in the serverrsquos password file or the application must handle a level of security where user IDs are converted into a group id based on database permissions and only those group IDs are entered into the password file Note that if the second alternative is chosen then auditing capabilities based on user ID are lost Also if the application performs security functions then those functions are not applicable to third party applications such as report writers application development tools and so on when they access the database The home directory of all the users should point to the same physical directory where the application executable resides The Informix method of using the operating system for security checking allows external programs to be called from within stored procedures This capability is not allowed in Oracle In Oracle the OPS$User_name is sometimes used to connect to the database where OPS$User_name is a valid Oracle user and User_name is a valid operating system level user In this case the connection is made to the database using just the lsquorsquo character without the user id and password Informixrsquos technique of using the etcpasswd file for security works fine for this type of connection

Non-operating system security

In previous releases each user who needed to access the database server also needed an operating system account on the host computer Now you can configure Informix so that users who are authenticated by an external authentication service (such as Kerberos or Microsoft Active Directory) can connect to Informix The new USERMAPPING configuration parameter specifies whether or not such users can access the database server and whether any of those users can have administrative privileges When Informix is configured to allow user mapping you can still control which externally authenticated users are allowed to connect to Informix and their privileges Please refer to the IBM Informix documentation on connection security for more information

IBM Software Group IBM Information Management

Version 16 71

Informix supports for the pluggable authentication module (PAM) framework which lets an administrator customize authentication for individual applications and permits column-level encryption

Role based authority Role based authority can help you manage your database permissions As of version 1110 you can create a role and assign that as a default role for individual users (or to PUBLIC) A role is a work-task classification such as ldquopayrollrdquo or ldquomanagerrdquo Each defined role has privileges on the database object granted to the role You use the CREATE ROLE statement to define a role and GRANT DEFAULT ROLE to establish the userrsquos initial setting when connecting to the database A userrsquos role can be changed after connecting by using the SET ROLE statement

Column-level encryption You can use column-level encryption to improve the confidentiality of your data IDS Version 1110 has new built-in SQL scalar functions provide methods for data in columns to be stored in an encrypted format Use the ENCRYPT_AES or the ENCRYPT_TDES function to define encrypted data Use the DECRYPT_BINARY() and DECRYPT_CHAR() functions to query encrypted data When using the routines the encryption of data is under application control and the DBMS is not aware that data is encrypted Informixrsquos support of column level encryption is analogous to Oraclersquos DBMS Obfuscation Tool Kit Built-in ENCRYPT functions provide methods for encrypting and decrypting the following character data types or smart large object data types

CHAR

NCHAR

VARCHAR

NVARCHAR

LVARCHAR

BLOB

CLOB

Passwords and hints

Passwords are necessary when using the encryption functions Only users who can provide a secret password can view copy or modify encrypted data The password must be a minimum of 6 bytes and can be a maximum of 128 bytes When you set an encryption password you have the option of specifying a password hint Hints can be up to 32 bytes of text If you specify a hint you can store the hint with the encrypted password or in another location Passwords (and hints) to be used by default can be set for a session using the SET ENCRYPTION PASSWORD statement

SET ENCRYPTION PASSWORD lsquopasswordrsquo [ WITH HINT lsquohint stringrsquo ]

Hence the password and hint parameters can be optional when calling the encryption function Explicit values override the session default values The password or hint can be a single word or several words The hint should be a word or phrase that helps you to remember the password but does not include the password You can subsequently execute the built-in GETHINT function (with an encrypted value as its argument) to return the plain text of hint Calling the GETHINT function with an argument of encrypted data will return the hint (if any) from the encrypted data or an empty string (NULL) is no hint was provided There is no privilege needed anybody can get any hint at any time When you set a password Informix transfers the password and any hint to 128-bit key that is used to encrypt the password and hint Passwords and hints are not stored as plain text any table of the system catalog The key is a time-based random value per instance The database server

IBM Software Group IBM Information Management

Version 16 72

initializes the key when the server starts the key is destroyed when the database server shuts down

Encrypting a column

Column data can be encrypted through the use of two functions ENCRYPT_TDES and ENCRYPT_AES corresponding to the two data encryption standards Triple Data Encryption Standard (Triple-DES) and Advanced Encryption Standard (AES) which describes the cipher algorithm used to protect data from unauthorized viewing AES encryption (also known as Rijndael) uses a 128-bit key size and Triple-DES encryption uses two 56-bit keys for 112-bits overall Both functions are variant functions and will return a different result every time it is used The following example demonstrates how to use the encryption functions with a column that contains a social security number

CREATE TABLE emp (name CHAR (40) salary MONEY ssn LVARCHAR(64))

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890one two

three 123))

-or-

CREATE TABLE emp (name CHAR(40) salary MONEY ssn LVARCHAR(64))

SET ENCRYPTION PASSWORD one two three 123

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890))

Querying an encrypted column

Encrypted data can be translated using Informixrsquos DECRYPT_CHAR and DECRYPT_BINARY scalar functions Encrypted data contains information about the encryption method and all the other data needed to decrypt it except the password The encrypted data value is passed as the first argument and a password as the second unless the SET ENCRYPTION statement has specified for this session with the same session password by which the first argument was encrypted If the data is not encrypted the function call will return an error The DECRYPT_CHAR function is used to invoke a decryption routine on character data types (ie CHAR LVARCHAR NCHAR NVARCHAR and VARCHAR) while the DECRYPT_BINARY function accepts an encrypted large object of type BLOB or CLOB If the first argument to DECRYPT_CHAR or DECRYPT_BINARY is not an encrypted value or if the second argument (or the default password specified by SET ENCRYPTION) is not the password that was used when the first argument was encrypted Informix will issue an error and the call fails If the call to the decryption function is successful it returns the plain text version of the encrypted data argument The following example demonstrates how to use the decrypt function to query encrypted data

SELECT name salary DECRYPT_CHAR(ssn lsquoone two three 123rsquo)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

-or-

SET ENCRYPTION PASSWORD lsquoone two three 123rsquo

SELECT name salary DECRYPT_CHAR(ssn)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

The first argument to DECRYPT_BINARY is expected to be an encrypted value of a large object data type however if it is called with a character data type Informix invokes the DECRYPT_CHAR function and attempts to decrypt the specified value

IBM Software Group IBM Information Management

Version 16 73

Do not use either decryption function to create a functional index on an encrypted column This would store the decrypted values as plain text data in the database defeating the purpose of encryption

Performance impact of encryption

The performance impact of encryption is significant Encryption by its nature will slow down most SQL statements If some care and discretion are used the amount of extra overhead should be minimal Also encrypted data will have a significant impact on your database design In general you want to encrypt a few very sensitive data elements in a schema like social security numbers credit card numbers patient names and so on The effect on performance depends on direction encrypting is slower than decrypting It does not depend measurably on which algorithm is used AES performs at the same speed as Triple-DES It does depend on data size the relative overhead is less when there is more data to encrypt

Storage considerations

An encrypted value uses more storage space than the corresponding plain text value Data encrypted using AES can be bigger than Triple-DES but not by a significant amount This occurs because all of the information needed to decrypt the value except the encryption key is stored with the value Therefore before you set the encryption password and encrypt the data you must be sure the encrypted data can fit in the column A chart of the expected sizes can be found in the IBM Informix Administrator Guide

Compliance regulations

Informixrsquos encryption routines comply with the United Statesrsquo regulations of Health Insurance Portability and Accountability Act (HIPAA) Sarbanes-Oxley Gramm-Leach-Bliley and California Personal Information Privacy (SB 1386) as well as the international requirements of Basel II Also they comply with the latest cryptographic standards (OpenSSL 097c)

IBM Software Group IBM Information Management

Version 16 74

C H A P T E R 8 Environment

Scripts Oracle make files used to build the application should be modified to invoke the appropriate Informix ESQLCOBOL ESQLC MF COBOL and other application language commands The shell scripts shell startup scripts and command files should be modified for Informix compliant statements

SQL script substitution variables

In Oracle a substitution variable is a user variable name preceded by one or two ampersands (amp) When Oracle (SQLPlus) encounters a substitution variable in a command Oracle executes the command as though it contained the value of the substitution variable rather than the variable itself In Oracle the substitution variables can be used anywhere in SQL and SQLPlus commands except as the first word entered at the command prompt When SQLPlus encounters an undefined substitution variable in a command SQLPlus prompts the user for the value SQLPlus reads the responses from the keyboard even if terminal input or output has been redirected to a file If a terminal is not available (if for example the command file is run in batch mode) SQLPlus uses the redirected file Informixrsquos dbaccess does not provide this functionality however a work-around for the redirected file type of substitution is a follows (no user prompting) Create the following shell script (named subvalsksh in this case)

binkshif [[ $ -ne 2 ]]

then

echo nUsage $0 ltdfilegt ltcfilegtn

echo Desc This script accepts two files - dfile the decode

file

echo and cfile the change file It modifies the

change file

echo using the values listed in the decode file

echo The decode file should contain two columns - old

value

echo and new value

echo Ex

echo changethis tothis

echo

echo In this case every occurance of changethis

would be

echo replaced with tothisn

exit 1

fi

IBM Software Group IBM Information Management

Version 16 75

-----------------------

Declare variables

-----------------------

dfile=$1

cfile=$2

awk print s$1$2 $dfile gt $dfile_sed

sed -f $dfile_sed $cfile

The preceding script is used by creating a ldquodecoderdquo file (named decodefile in this case) which holds two columns in the form which may contain multiple rows

oldval newval

Executing the following command

subvalsksh decodefile chgfile

will replace every occurrence of oldval with newval in the file chgfile The shell script (subvalsksh) writes to standard output therefore the output should be redirected The redirected file will then be able to run with dbaccess

Utilities To improve performance the Informix EXPLAIN utility should be used by executing the SET EXPLAIN ON command to see how an SQL statement accesses the database From that point forward the access path for every SQL statement is written in the SQEXPLAINOUT file in the current working directory or the home directory of the process that initiated the request on the host machine The Informix SET EXPLAIN OFF should be executed to turn off this feature when finished The overall system performance should be monitored using the Informix ONSTAT utility

System catalog The following items discuss how Informix implements the system catalog differently than Oracle Each item refers to the Informix implementation only Object names are stored in lower case The system catalog tables are owned by lsquoinformixrsquo To query the systables table use SELECT from lsquoinformixrsquosystables Each table in systables is assigned a tabid by the system It is used as the primary key and therefore the foreign key for the other catalog tables The identifier information is stored in sysindexes Columns part1 - part16 each contain a column component of a composite index They are integers positive for ascending order negative for descending order In syscolumns collength and coltype have special meanings depending on the data type of the column See the Informix Guide to SQL Reference Version for details

IBM Software Group IBM Information Management

Version 16 76

C H A P T E R 9 Using Bladelets

What is a Bladelet

A Bladelet is a small informal Informix Datablade module Its meant to be useful out of the box and is offered complete with source code at no cost -- and no support or warranty In the context of this document the term Datablade refers to an extension to the standard IBM Informix database engine These generally take the form of new data types (for example timeseries or video) andor new routines that execute inside the server The new routines might operate on new data types or on existing ones A Datablade module is usually a formal product available for sale In addition a Datablade is

Developed either by IBM Informix or by a third-party developer

Rigorously tested

Packaged and sold for profit

May or may not be formally certified by IBM Informix as having been developed according to approved Datablade coding practices

In contrast a Bladelet is

Not rigorously tested

Not sold for profit

Not certified by IBM Informix A Bladelet is an extension to the database engine that is narrow in scope and thought to be generally useful being offered at no cost complete with source Just remember before you use any of this code in mission-critical applications its up to you to thoroughly test it and fix any problems you find Please review the disclaimer which applies to any sample code you find on this site httpwwwibmcomdeveloperworksdb2zonesinformixlibrarysamplesdb_downloadshtml Note The bladelets at this link have not been updated for some time (at the time of this writing) some of the capabilities especially simple function call that increase compatibility may have been introduced into the Informix server itself since they were written

Useful Bladelets

Bladelet Description

Exec Defines two user-defined functions that provide dynamic SQL functionality within a SPL procedure

Flat File Access Method A complete access method that lets you build virtual tables based on operating system files

IUtil Implements a collection of other database vendor functions for Informix

IBM Software Group IBM Information Management

Version 16 77

JPEG Image Bladelet Provides a user-defined type for JPEG images that allows you to manipulate images and to extract and search on image properties

Multirepresentational lvarchar Opaque Type

Creates the idn_mrLvarchar opaque type which stores character data up to 2 gigabytes

Node Datablade Module Creates the node opaque type which is intended to solve one of the hardest problems in relational databases transitive closure

Regexp Creates routines that let you manipulate character and clob data using regular expressions

Shapes DataBlade Module Creates several opaque types for managing spatial data including R-tree index support

Smart Blob Information DataBlade Module

Includes a variety of useful routines for working with smart blobs

SqlLib C SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

SqlLib Java SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

Versioning Table Access Method

Permits users to create and manage versioned tables

We will look closer at two bladelets which could assist with migration the Exec datablade and SQLLib

Informix Exec bladelet for Dynamic SQL Often it is desirable to execute a SQL query that is generated at run-time within the RDBMS For example a developer may not know the name of the temporary table they wish to run the query against or they might want to append predicates to a query In external programs this can be accomplished using the ESQLC SQLCA and DESCRIPTOR facilities Unfortunately the INFORMIX Stored Procedure Language (SPL) does not support Dynamic SQL Queries must be hard-coded into the SPL logic The objective of the Exec bladelet is to remedy this situation Exec consists of user-defined functions that take an SQL query as an argument execute it and return the result (the format of which varies depending on which function is called and the kind of query) The Exec functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries For more details and download refer to

httpwwwibmcomdeveloperworksdb2zonesinformixlibrarydemoids_exechtml

There are three User Defined Routines (UDRs) in the Exec bladelet Two of them are external C functions that use the Server API (SAPI) These must be compiled into shared libraries on the target machine and you need to declare them to the server using CREATE FUNCTION statements The third UDR is a routine written in Informix Stored Procedure Language (SPL) that uses the first two UDRs to return a collection of items The Exec bladelet module consists of the following

1 EXEC The EXEC() function takes an LVARCHAR that it treats as a SQL query executes the query and returns a single LVARCHAR result string Depending on what kind of SQL statement is submitted Exec() returns a different result format

IBM Software Group IBM Information Management

Version 16 78

2 EXEC_FOR_ROWS The EXEC_FOR_ROWS() UDR is an iterator function which means it can return more than one result row Of course it only does so when it is asked to execute a SELECT Otherwise it behaves exactly as the EXEC() UDR Being an iterator function limits the ways in which such a UDR can be used It cannot be used in another SQL query The only place it can be used effectively is inside a SPL routine

3 EXEC_FOR_MSET EXEC_FOR_MSET() is a SPL routine that uses the EXEC_FOR_ROWS() routine introduced above Instead of returning a set of rows as an iterator or a single row as the EXEC() UDF does this UDR collects the results of the SQL query together into a single object a multi-set

Refer to Appendix E Sample Code for examples on using the EXEC bladelet functions

SqlLib DataBlade module (SqlLibC11 SqlLibJ11) The SqlLib DataBlade module implements SQL routines that the Informix does not support natively but that are supported by some other database vendors Source code is freely available for download and includes two implementations one in C (SqlLibC) and the other in Java (SqlLibJ)

The following routines are included

ascii - takes a single character as input and returns the ASCII value in decimal that corresponds to that character

ceil - takes a single numeric value as input and returns the smallest integer that is either equal to or greater than the input value

chr - takes an integer value and returns the character that is represented by the ASCII value (in decimal) of that integer

instr - searches for a value in a string and returns the position where it was found It

returns 0 if the search value was not found instrb - provides the exact same functionality as instr() but for single-byte character sets

sign - takes a numeric argument and returns an integer that indicates if the input value is

positive (1) negative (-1) or zero (0) to_decimal - converts the input character argument into a decimal type

to_float - converts the input character argument into a float type

to_integer - converts the input character argument into an integer type For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

IBM Software Group IBM Information Management

Version 16 79

A P P E N D I X A Planning guide

The checklist below will help an analyst determine which Oracle features which need to be converted to Informix and give some guidance on the effort involved Each porting task is listed They are followed by a quantity field used to determine how prevalent the item the difficulty or amount of effort involved 1 (low) to 5 (high) is used to estimate the amount of time needed to perform the task when the associated item exists in the application a moderate number of times What is moderate depends on the size of the application If there are an unusually large number of occurrences of an item then the effort should be increased Conversely if there are a small number of occurrences of an item then the effort should be decreased Each of these items is discussed in detail within this document Each heading corresponds to a section heading within the document

Tasks Quantity Effort

DDL

Identifiers Delimit identifiers named with Informix reserved words 2 Databases Determine database names and create databases 3 Replace Oracle tablespace names with Informix dbspace names 1 ANSI vs Non-ANSI considerations 3 Tables Convert create table statements 2 Convert DDL syntax 3 Reduce primary key length to 390 bytes 5 Data Types Convert Oraclersquos NUMBER data type 3 Convert VARCHAR columns 2 Convert Oraclersquos DATE data type 5 Convert raw data types 2 Convert Rowids 2 Indexes Convert Indexes 2 Views Remove CREATE VIEW statement options 1 Stored Procedures and Triggers Convert CREATE and REPLACE Stored Procedure and Trigger syntax 1 Oracle Extensions Remove non-supported Oracle extensions from DDL 1

Tasks Quantity Effort

DML

SQL Add the Informix AS clause to display labels 1 Replace non-supported DML syntax ^= hellip = ELSE IF 2 Convert Optimizer DirectiveHints 2 Convert InsertSelectUnion and InsertValueSelect statements 3

IBM Software Group IBM Information Management

Version 16 80

Convert Delete statement syntax 1 Convert temporary table processing 2 Convert Join statements + MINUS INTERSECT different data types 2 Convert sorts 4 Convert hard coded SQL error messages 3 Remove correlation names on the main table of Update and Delete statements

2

Replace original table names in SELECT statements using aliases 1 Convert hierarchical implementation (CONNECT BY PRIOR) 5 Host Variables Convert host variable format or add conversion processing 5 Functions Convert date and time functions 5 Convert aggregate functions 3 Convert mathematical functions 5 Convert string function syntax 1 Convert other unsupported Oracle functions 5 Macros Convert ISOPEN NOT FOUND ROWTYPE and TYPE macros 3 Pseudo-Columns Convert Level processing 3 Convert Rownum processing 2 Update Using Cursors Convert WHERE CURRENT OF processing for multiple table joins 5 Convert FOR UPDATE with a HOLD cursor processing 2 Convert concurrency processing from Oraclersquos implicit to Informixrsquos explicit

4

System Tables Convert system table references 1

Tasks Quantity Effort

Stored procedures Break stored procedures greater than 64K in size into smaller ones 2 Convert Oraclersquos stored procedure packages 3 Convert exception processing 5 Convert error handling (SQLCA) 2 Convert Oraclersquos global cursor processing 5 Convert Oraclersquos explicit cursor processing 2 Convert flow control processing 5 Convert Oraclersquos implicit variable declaration and assignment 3 Convert Oraclersquos BOOLEAN variable type 1 Convert binary data type processing Convert Oraclersquos dynamic SQL processing 5 Triggers Convert multi-functional triggers 3 Convert Insert and Update triggers which are not supported in Informix 5 Place logical statements in a stored procedure 5 Constraints Convert constraint enabling and disabling processing 5 DUAL table Convert Dual table processing 4

Embedded SQL

Host variables

IBM Software Group IBM Information Management

Version 16 81

Convert declaration overrides 1 Convert array processing 5 Convert Oraclersquos formatting functions 4 SQL structures Convert SQLDA processing 5 Convert ORACA processing 1 Pre-compiler options Convert Oracle pre-compiler options 1 Embedded PLSQL Convert Oraclersquos Embedded PLSQL 5 ODBC Convert Oraclersquos OCI 5 Convert database library calls Convert global area processing Convert fetch cycle Convert RAW data type processing Convert parameter bindings Embedded SQL for C Convert VARCHAR processing 2 Embedded SQL for COBOL Convert VARCHAR processing 2 Convert 88 Level processing in COBOL 2 Convert Redefine processing in COBOL 4

Tasks Quantity Effort

Application architecture

Transaction processing Convert application to Informix transaction processing 5 Convert multiple connect processing 5 Convert savepoints Concurrency Address Informix locking processing na 2 User authentication Address Informix security processing na 4

Environment

Convert make files 2 Convert shell scripts shell startup scripts and command files 2 Convert script substitution variables

IBM Software Group IBM Information Management

Version 16 82

A P P E N D I X B Syntax comparison

See the Informix Guide to SQL Syntax for more information on each item

Oracle Informix Boolean AND AND AND NOT NOT NOT OR OR OR Greater Than or Equal To gt= gt= Less Than or Equal TO lt= lt= Not Equal ltgt = or ^= ltgt or = Identifiers letters numbersrdquo_rdquordquo$rdquordquordquo letters numbers and ldquo_rdquo Data types Character CHAR CHAR Long Character VARCHAR (2000) if lt= 2000

LONG VARCHAR if gt 2000 CHAR or TEXT

Number (2 bytes) NUMBER SMALLINT Number (4 bytes) NUMBER INTEGER Number (gt 4 bytes) NUMBER DECIMAL Image LONG RAW CLOB BLOB BYTE TEXT CLOB BLOB DML Comments -- hellip -- hellip Assignment var1 = expression LET var1 = expression Condition ELSE IF ELSE or ELIF

IF Aggregate functions Average AVG(expression) AVG(ALL

expression) AVG(DISTINCT expression)

AVG(expression) AVG(ALL expression) AVG(DISTINCT column_name) AVG(UNIQUE column_name)

Count COUNT() COUNT (expression) COUNT(ALL expression) COUNT (DISTINCT expression)

COUNT() COUNT(DISTINCT column_name) COUNT (UNIQUE column_name)

Maximum MAX(expression) MAX(ALL expression) MAX(DISTINCT expression)

MAX(expression) MAX(ALL expression) MAX(DISTINCT column_name) MAX(UNIQUE column_name)

Minimum MIN(expression) MIN(ALL expression) MIN(DISTINCT expression)

MIN(expression) MIN(ALL expression) MIN(DISTINCT column_name) MIN(UNIQUE column_name)

Sum SUM(expression) SUM(ALL expression) SUM(DISTINCT expression)

SUM(expression) SUM(ALL expression) SUM(DISTINCT column_name) SUM(UNIQUE column_name)

Algebraic functions Round ROUND(expressionrounding

factor) ROUND(expressionrounding factor)

Statistical functions Standard Deviation STDEV(expression) STDDEV(expression) Variance VARIANCE(expression) VARIANCE(expression) Range RANGE(expression)

IBM Software Group IBM Information Management

Version 16 83

String functions

Trim LTRIM(expression) RTRIM(expression)

LTRIM(expression) RTRIM(expression)

Length LENGTH(string) LENGTH(string) Like LIKE(string) LIKE(string) Like (single character) _ _ Like (wildcard) String Delimiter lsquo or ldquo lsquo or ldquo Escape Character set within LIKE clause using

ESCAPE ldquordquo to make ldquordquo the escape character

or set within LIKE clause using ESCAPE ldquordquo to make ldquordquo the escape character

Stored procedures Create CREATE OR REPLACE

PROCEDURE procedure_name (var1 IN CHAR(1) var2 OUT DATE var3 IN OUT NUMBER)

DROP PROCEDURE procedure_name CREATE PROCEDURE procedure_name (var1 CHAR(1) var3 INTEGER) RETURNING DATE INTEGER

Arguments EXECUTE PROCEDURE procedure_name (var1 IN var2 OUT var3 IN OUT)

EXECUTE PROCEDURE procedure_name (var1 var3) RETURNING var2 var3

IBM Software Group IBM Information Management

Version 16 84

A P P E N D I X C Database concepts

The table below illustrates the relationship between each database vendorrsquos database objects

Oracle Informix

Database name attached to a group of files Specific database name

Data file Chunk

Tablespace (logical partition) or Segments (Index Segment Table Segment and so on)

Dbspace

Extent Extent

Rollback Segment Physical Log

Redo Log Logical Log

System tablespace Root dbspace

Temporary tablespace Temporary dbspaces dbspacetemp environment variable or dbspacetemp onconfig parameter

Pointer Blobspace Sbspace

Table partitioning table fragmentation

Database link Not supported

Snapshot Not supported

oerr utility finderr utility

sqldba and svrmgrl - monitor utilities onstat and oncheck utilities

SQLPlus utility dbaccess utility

ProC ESQLC

ProCOBOL ESQLCOBOL

SQLNET INet

OCI Like the ESQL function library after pre-compiling if they were publically documented

Read Consistency COMMITTED READ LAST COMMITTED

IBM Software Group IBM Information Management

Version 16 85

A P P E N D I X D Sample code

User defined functions User Defined Routines (UDR) can be developed to extend the capabilities of the database and provides the option to create UDRs to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or rename an Informix function to the corresponding Oracle function name

CONCAT

CREATE PROCEDURE concat (str1 VARCHAR(255) str2 VARCHAR(255)) RETURNING VARCHAR(255) RETURN str1 || str2

END PROCEDURE

INSTR

CREATE PROCEDURE instr( str VARCHAR(255) mask VARCHAR(255) strt SMALLINT DEFAULT 1 occur SMALLINT DEFAULT 1 ) RETURNING INT DEFINE slen SMALLINT DEFINE mlen SMALLINT DEFINE tempstr VARCHAR(255) DEFINE tempmask VARCHAR(255)

DEFINE nomatch SMALLINT DEFINE count SMALLINT DEFINE pos SMALLINT DEFINE retpos SMALLINT DEFINE i SMALLINT DEFINE j SMALLINT DEFINE srchstrt SMALLINT LET slen = LENGTH(str) LET mlen = LENGTH(mask) LET count = 0 LET nomatch = 0 LET pos = 1 LET retpos = 1 LET tempstr = LET tempmask = LET srchstrt = strt

IF (strt lt 0) THEN - reverse the str FOR i = 1 TO slen LET tempstr = str[11] || tempstr LET str = str[2255] END FOR -- reverse the mask FOR i = 1 TO mlen LET tempmask = mask[11] || tempmask LET mask = mask[2255] END FOR

IBM Software Group IBM Information Management

Version 16 86

LET srchstrt = strt -1 LET str = tempstr LET mask = tempmask END IF FOR j = 1 TO slen LET tempstr = str LET tempmask = mask FOR i = 1 TO mlen IF (tempmask[11] = tempstr[11]) THEN LET nomatch = 1 EXIT FOR END IF LET tempmask = tempmask[2255] LET tempstr = tempstr[2255]

END FOR IF (nomatch = 0) THEN IF (pos gt= srchstrt) THEN LET count = count + 1 END IF IF (count = occur) THEN IF (strt lt 0) THEN RETURN slen - pos + 1 ELSE RETURN pos END IF END IF END IF LET str = str[2255] LET nomatch = 0

LET pos = pos + 1 END FOR RETURN 0 END PROCEDURE

YYYYMMDD

CREATE PROCEDURE yyyymmdd (str VARCHAR(10)) RETURNING varchar(8)

DEFINE retstr VARCHAR(8)

IF str IS NULL THEN

RETURN NULL

ELSE

LET retstr = str[710] || str[12] || str[45]

RETURN retstr

END IF

END PROCEDURE

Using EXEC bladelet functions

IBM Software Group IBM Information Management

Version 16 87

Using EXEC

Note the ROW data type variable can be referenced using table and column syntax CREATE PROCEDURE example1() RETURNING INTEGER

DEFINE sql_stmt LVARCHAR(255)

DEFINE rcnt ROW(val INTEGER)

LET sql_stmt = select count() from items where manu_code = lsquoANZrsquo

EXECUTE FUNCTION EXEC(sql_stmt) INTO rcnt

RETURN rcntval

END PROCEDURE

Using EXEC_FOR_ROWS

CREATE PROCEDURE example2() RETURNING INTEGER CHAR(1)

DEFINE rs_rowdata ROW(customer_num INTEGER call_code CHAR(1))

DEFINE sql_stmt LVARCHAR(255)

LET sql_stmt = select customer_num call_code from cust_calls where

customer_num = 106

FOREACH

EXECUTE FUNCTION EXEC_FOR_ROWS(sql_stmt) INTO rs_rowdata

RETURN rs_rowdatacustomer_num rs_rowdatacall_code WITH RESUME

END FOREACH

END PROCEDURE

Using EXEC_FOR_MSET

Note the DEFINE statement for the variable rs_data Collection data types used in a SPL routine cannot be defined using the LIKE attribute in the DEFINE statement CREATE PROCEDURE example3() RETURNING INTEGER VARCHAR(8)

DEFINE v_customer_num LIKE accountscustomer_num

DEFINE v_account_cd LIKE accountsaccount_cd

DEFINE rs_data MULTISET(ROW(

r_customer_num INTEGER

r_account_cd VARCHAR(8)) NOT NULL)

DEFINE sql_stmt LVARCHAR

LET sql_stmt = select customer_num order_num from orders where

company_id = 51155

EXECUTE FUNCTION EXEC_FOR_MSET(sql_stmt) INTO rs_data

FOREACH

SELECT r_customer_num r_account_cd INTO v_customer_num

v_account_cd FROM TABLE(rs_data)

RETURN v_customer_num v_account_cd WITH RESUME

END FOREACH

END PROCEDURE

IBM Software Group IBM Information Management

Version 16 88

Date arithmetic Informix has extensive capabilities for manipulating dates and times You can add or subtract DATE and DATETIME variables from each other You can add or subtract an INTERVAL to a DATE or DATETIME

UNITS Keyword

When working with INTERVAL values sometimes it is necessary to specify the precision with which you are dealing For example suppose you have the following field defined To add 10 days to the lead time you could use a SQL statement like this

SELECT lead_time + INTERVAL(10) DAY to DAY FROM orders

-or- SELECT lead_time + 10 UNITS DAY FROM orders

Using EXTEND function

The EXTEND function allows operations between data types of different precisions SELECT

EXTEND(myvar YEAR to MINUTE) ndash INTERVAL(5) MINUTE to MINUTE

FROM member

Calculate Week Of The Year

SELECT ROUND((TODAY - DATE(0101||YEAR(TODAY))) 7 + 5) FROM DUAL

Number of days difference SELECT DATE(0106||YEAR(TODAY)) - DATE(01062005) FROM DUAL

Number of weeks difference

SELECT ROUND((DATE(0106||YEAR(TODAY)) - DATE(01062005))

7 + 5) FROM DUAL

String representation of date and time

Day and date

SELECT TO_CHAR(TODAY A B d Y) FROM dual

-returns month day and 4 digit year-

Tuesday January 03 2006

Abbreviation of day of week

SELECT SUBSTR(TO_CHAR(TODAY A B d Y R)13) FROM dual

-or-

SELECT TO_CHAR(TODAY a) FROM dual

-returns MON TUE WED THU FRI SAT SUN-

Returning the number of rows affected

IBM Software Group IBM Information Management

Version 16 89

Within SPL routines you can use the DBINFO function to find out the number of rows that have been processed in SELECT INSERT UPDATE DELETE EXECUTE PROCEDURE and EXECUTE FUNCTION statements

CREATE FUNCTION del_rows(pnumb INT) RETURNING INT

DEFINE nrows INT

DELETE FROM sec_tab WHERE part_num = pnumb

LET nrows = DBINFO(sqlcasqlerrd2)

RETURN nrows

END FUNCTION

To ensure valid results use this option after SELECT and EXECUTE PROCEDURE or EXECUTE FUNCTION statements have completed executing If you use the sqlcasqlerrd2 option within cursors make sure that all rows are fetched before the cursors are closed

Using an Informix collection data type

A collection data type as a VARRAY

In the following examples the collection data types of MULTISET and SET are used in a function to hold a collection of values You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value Informix SPL allows you to declare a cursor for a collection variable using the FOREACH statement called a collection cursor

Also demonstrated is how to utilize a variable declared with the keyword COLLECTION A variable declared as type SET MULTISET or LIST is a typed collection variable It can hold a collection of its specified data type only However a COLLECTION is an un-typed (or generic) collection variable that can hold a collection of any data type

This function will build a MULTISET list of values

CREATE FUNCTION func1() RETURNING MULTISET(INTEGER NOT NULL)

DEFINE v_array_of_ints MULTISET(INTEGER NOT NULL)

INSERT INTO TABLE (v_array_of_ints) VALUES(1)

INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(5)

INSERT INTO TABLE (v_array_of_ints) VALUES(4)

RETURN v_array_of_ints

END FUNCTION

This function will receive the COLLECTION list of values from func1

CREATE FUNCTION func2() RETURNING INTEGER

--

-- DEFINE lmset MULTISET(INTEGER NOT NULL)

--

DEFINE lmset COLLECTION

DEFINE v_int INTEGER

--

-- call func1 to populate local multiset variable

--

LET lmset = func1()

--

-- tally a count the number of elements

--

FOREACH

SELECT COUNT() INTO v_int FROM TABLE(lmset)

IBM Software Group IBM Information Management

Version 16 90

RETURN v_int WITH RESUME

END FOREACH

--

-- return the values

--

FOREACH

SELECT INTO v_int FROM TABLE(lmset)

RETURN v_int WITH RESUME

END FOREACH

END FUNCTION

NOTE In the example func2 a duplicate declaration for the ldquolmsetrdquo variable as a MULTISET data type has been commented out by declaring the variable as a COLLECTION it can accept any of the 3 types (MULTISET SET and LIST)

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

4 (row count) 1 2 5 4

By using a SET data type inserts will not permit duplicates

CREATE FUNCTION func1() RETURNING SET(INTEGER NOT NULL) DEFINE v_array_of_ints SET(INTEGER NOT NULL) INSERT INTO TABLE (v_array_of_ints) VALUES(1) INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(2) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) RETURN v_array_of_ints END FUNCTION

NOTE Because func2 is expecting a un-typed COLLECTION variable func1 does not have to be dropped and recreated It can receive a value from any Collection Data Type (MULITSET SET and LIST)

The functionrsquos return values would change to (with duplicates suppressed)

EXECUTE FUNCTION func2()

(expression)

3 (row count) 1 2 5

Using a LIST data type support for assigning values based on ordinal position

IBM Software Group IBM Information Management

Version 16 91

CREATE FUNCTION func1() RETURNING LIST(INTEGER NOT NULL)

DEFINE v_array_of_ints LIST(INTEGER NOT NULL) -- -- first insert no ordinal position can be established By default the -- database server inserts LIST elements at the end of the list -- INSERT AT 5 INTO TABLE (v_array_of_ints) VALUES(5) INSERT AT 1 INTO TABLE (v_array_of_ints) VALUES(1) INSERT AT 2 INTO TABLE (v_array_of_ints) VALUES(2) -- -- Only 3 LIST elements exist position 4 has not been instantiated -- this element will insert at the end of the list -- INSERT AT 4 INTO TABLE (v_array_of_ints) VALUES(4) INSERT AT 3 INTO TABLE (v_array_of_ints) VALUES(3) RETURN v_array_of_ints END FUNCTION

NOTE The elements of a LIST have ordinal positions with a first second and third element in a LIST To support the ordinal position of a LIST the INSERT statement provides the AT clause This clause allows you to specify the position at which you want to insert a list-element value Note the behavior of the ordinal positioning above preceded by a commented explanation

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

5 (row count) 1 2 3 5 4

Using MULTISET and ROW to replace PLSQL TABLE and RECORD types

Creating variables using Informix Collection data types SET MULTISET and LIST in combination with ROW data types can be useful when migrating applications which use Oracle REF CURSORS as arguments to functions as well as Oracle collection data types TABLE and RECORD

Typical Oracle Package specification

CREATE OR REPLACE PACKAGE MyPackage

IS

TYPE recOrders IS RECORD (

order_num ordersorder_numTYPE

order_date ordersorder_dateTYPE

customer_num orderscustomer_numTYPE

po_num orderspo_numTYPE

)

TYPE tabOrders IS TABLE OF recOrders

INDEX BY BINARY_INTEGER

TYPE ref_curtype IS REF CURSOR

Both tabOrders or ref_curtype can be converted to the following Informix SPL definition

DEFINE tabOrders MULTISET(ROW(

IBM Software Group IBM Information Management

Version 16 92

order_num INTEGER

order_date DATETIME YEAR TO FRACTION(3)

customer_num INTEGER

po_num CHAR(10)) NOT NULL)

DEFINE ref_curtype MULTISET(ROW(

define columns based on query result set

) NOT NULL)

IBM Software Group IBM Information Management

Version 16 93

A P P E N D I X E Counting system objects

Using the system catalog

System catalog

Below is a list of SQL statements that will extract most if not all of the counts of system objects owned by user lsquoXXXrsquo

select count(table_name) from all_tables

where owner=rsquoxxxrsquo

select count() from dba_indexes

where owner=rsquoxxxrsquo

select count(synonym_name) from dba_synonyms

where owner=rsquoxxxrsquo

select count() from dba_views

where owner=rsquoxxxrsquo

select count() from dba_tab_columns

where length(column_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

and owner=rsquoxxxrsquo

select count distinct() from dba_tab_columns

and owner=rsquoxxxrsquo

select count() from dba_tables

where length(table_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_synonyms

where length(synonym_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_views

where length(view_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_indexes

where length(index_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and owner=rsquoxxxrsquo

IBM Software Group IBM Information Management

Version 16 94

select data_type count(data_type) from dba_tab_columns

where owner=rsquoxxxrsquo

group by data_type

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and length(data_type)gt254

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquonumberrsquo

and data_scale=0

and owner=rsquoxxxrsquo

Using SQL code

Built-in function references

The following instructions can be used to find references to built-in functions On the UNIX machine or the NT box where your code resides please create the following file as tmpfunctionlist

convert(

hextoint(

inttohex(

getdate(

datename(

datepart(

datediff(

dateadd(

months_between(

char(

char_length(

charindex(

compute(

difference(

length(

lower(

patindex(

replicate(

reverse(

right(

soundex(

space(

str(

stuff(

substring(

upper(

abs(

atn2(

log(

ceiling(

IBM Software Group IBM Information Management

Version 16 95

cot(

degrees(

floor(

radians(

rand(

sign(

to_char(

to_date(

to_number(

exception(

pi(

raise_application_error(

raiserror(

SQLCODE

rollback

savepoint

declare

decode(

nvl(

print(

rowid

waitfor

recompile

bcp

isopen(

notfound(

rowtype(

type(

Then please run the following program with the proper subdirectories

binksh

rm ndashf somehomeoutfile

cd somesourcedatabase

export sourcebase=rdquosomepathrdquo

for functor in `cat tmpfunction_list`

do

echo before find $functor

find $sourcebasedatabase -exec grep -i $functor gtgt

somehome$functoroutfile

find $sourcebaseintfc -exec grep -i $functor gtgt

somehome$functoroutfile

echo after find $functor

done

Object types and counts

This script attempts to count the objects of each type by grepping for CREATE statements containing the object type and counts procedure definitions that are inside package bodies which are not proceeded by a CREATE keyword It is not a sophisticated parser so the results may not be perfect

binbash if [ $1 = ] then

IBM Software Group IBM Information Management

Version 16 96

echo Usage objCountssh ltFilePatterngt return 1 fi declare -a objectTypes=(CLUSTER CONTEXT CONTROLFILE DATABASE DATABASE +LINK DIMENSION DIRECTORY DISKGROUP FUNCTION INDEX INDEXTYPE JAVA LIBRARY MATERIALIZED +VIEW MATERIALIZED +VIEW +LOG OPERATOR OUTLINE PACKAGE PACKAGE +BODY PFILE PROCEDURE PROFILE RESTORE +POINT ROLE ROLLBACK +SEGMENT SCHEMA SEQUENCE SPFILE SYNONYM TABLE TABLESPACE TRIGGER TYPE TYPE +BODY USER VIEW) echo for type in $objectTypes[] do if [ $type = PROCEDURE ] then echo $type object count `cat $1 | grep -icE ^ (|CREATE +|OR REPLACE +)b$typeb` else echo $type object count `cat $1 | grep -icE ^ (CREATE +|OR +REPLACE +)b$typeb` fi done

IBM Software Group IBM Information Management

Version 16 97

A P P E N D I X F Data type mapping

Oracle built-in data types (including ANSI types) can be converted to similar data types in the Informix database according to the mapping described here This table provides default mappings based on most common usage patterns in some cases another mapping may work better

In the following table n is used to indicate length p is used to indicate precision and s is used to indicate scale

Oracle data type Informixreg Server data type

BFILE LONG RAW BLOB

BLOB

BINARY_DOUBLE DOUBLE PRECISION

BINARY_FLOAT DOUBLE PRECISION

BINARY_INTEGER

PLS_INTEGER

NATURAL

NATURALN

POSITIVE

POSITIVEN

32-bit integers only used in PLSQL NATURAL and POSITIVE are unsigned integers

INTEGER

BOOLEAN (PLSQL only) BOOLEAN

CHAR(n) or CHARACTER(n) CHAR(n)

DATE DATETIME YEAR TO SECOND

DOUBLE PRECISION DOUBLE PRECISION

IBM Software Group IBM Information Management

Version 16 98

FLOAT

See note on FLOAT below

FLOAT

INTEGER INT

A 38-digit NUMBER sub-type May want to flag with a warning on possible overflow

INTEGER

INTERVAL DAY(p) TO SECOND(s)

Note Oracle fractional seconds have 9 digits

INTERVAL DAY(p) TO FRACTION(min(5 s))

INTERVAL YEAR(p) TO MONTH

INTERVAL YEAR(p) TO MONTH

LONG CLOB

CLOB

LONG VARCHAR (xxx)

Oracle recommends not using this type

LVARCHAR

NCHAR(n) NATIONAL CHAR(n) or NATIONAL CHARACTER(n)

NCHAR(n)

See National Language Types below

NCLOB CLOB

NUMBER

NUMBER(0)

NUMBER(p) NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s lt 10

NUMBER(3-2) 12300

INTEGER

IBM Software Group IBM Information Management

Version 16 99

NUMBER(p) NUMBER (p0)

Where precision (p) is greater than or equal to 10 and lt= 18

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and 10 lt= p-s lt 19

NUMBER(9-2) 12345678900

BIGINT

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is greater than or equal to s (that is s gt 0 and p gt= s)

NUMERIC (min(p32) min(s32))

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is less than s (that is s gt 0 and p lt s)

NUMBER(35) 000123

NUMERIC (min(s32)min(s32))

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s gt 18 and p-s lt= 32

NUMERIC (min(p-s32)0)

NUMBER(p s)

Where scale (s) is greater than 32 or pInformix-s is greater than 32

NUMERIC (32)

Scale cannot be greater than precision

NUMERIC(3232) would guarantee that digits to the left of the decimal would be lost Using a floating point decimal provides the simplest best way to capture as many digits in a value as possible

IBM Software Group IBM Information Management

Version 16 100

DEC

DECIMAL

NUMERIC

DEC(p)

DECIMAL(p)

NUMERIC(p)

DEC(p s)

DECIMAL(p s) NUMERIC(p s)

There is no difference within Oracle between these types and each other and these types and NUMBER The Oracle system catalogs contain the NUMBER type id for all declarations of these types and the integer types as well Declarations of these types can be mapped using the same rules as those for NUMBER

NVARCHAR2(n) NCHAR VARYING(n) NATIONAL CHAR VARYING(n) NATIONAL CHARACTER VARYING(n)

LVARCHAR(min(n 32767))

RAW(n) BLOB

REAL DOUBLE PRECISION

Record ROWTYPE

Using a CREATE ROWTYPE statement

ROWID INTEGER

SMALLINT SMALLINT

TIMESTAMP(p)

If p is not specified precision defaults to 6

DATETIME YEAR TO FRACTION(min(5 p))

UROWID(n) INTEGER

IBM Software Group IBM Information Management

Version 16 101

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is less than or equal to 255 (that is n lt= 255)

VARCHAR(n)

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is greater than 255 (that is n gt 255)

LVARCHAR(n)

XMLType CLOB

Notes on specific types are below

DOUBLE

The range of values for the DOUBLE PRECISION data type is the same as the range of the C double data type on your computer

VARCHAR

While Oracle VARCHAR data types have a limit of 4000 bytes an Informix Server VARCHAR data types has a limit of 255 bytes An Informix Server LVARCHAR has a limit of 32739 Bytes

NUMBER

Oracle abstracts its numeric types from the hardware and operating system through the use of its NUMBER type Most numeric types like INTEGER are actually NUMBERs internally When porting to a database server like Informix which retains more of a relationship between the operating system types and the database types it is essentially a one-to-many mapping and heuristics have to be used to determine the best-fit target type No single set of type mapping rules will fit all use scenarios The converter has default rules which fit the more common user patterns When considering a number represented as mantissa and exponent

mantissa x 10exponent

precision is the number of digits in the mantissa and scale is the negative exponent how many places to the right of the decimal point the least significant digit is located Oracle NUMBERs have a maximum precision of 38 and the maximum precision available in Informix native types is 32 The first step in a type mapping is to truncate the target type precision to min(precision 32) The scale of a type can be considered its anchor point with respect to the decimal point The most

IBM Software Group IBM Information Management

Version 16 102

significant digit of a numeric type is located precision digits to the left of the decimal point and precision-scale digits to the right of the decimal point The start and end locations of the digits are used to determine the closest fitting Informix type The order of preference is INTEGER BIGINT NUMERIC(p s) and lastly NUMERIC(p) NUMERIC(p) in a non-ANSI mode database is a decimal type with a floating point type In an ANSI mode database the scale is implicitly 0 All Oracle integer declaration types such as INT INTEGER SMALLINT become NUMBER(38) type in the Oracle metadata In Oracle when precision is given but scale is not scale becomes 0 implicitly which makes the type in the set of integral types One exception to the general mapping rules is the NUMBER type specified without precision or scale Strictly speaking this has a floating point scale with 38 digits of precision but most commonly it is used where an integer is more appropriate Even if the user does specify INTEGER in a type definition when it comes out of the Oracle catalogs the type is NUMBER This is one case in particular where one type mapping will not fit well with all usage scenarios

National language types

Oracle Nchar types are allocated by number of characters where Informix is allocated by the number of bytes For Oracle the storage size of the characters varies with the encoding used and is always subject to the standard 32767 limit on maximum bytes but during declarations n always means the number of characters Oracle PLSQL supports explicit and implicit data type conversions These explicit and implicit data types are converted to syntax by using Informix Dynamic Servers explicit and implicit data type conversion mechanism

ROWID

Oracle databases support a pseudo-column named ROWID such that every row in every table is assigned an auto-generated ID Oracle also allows you to define a column of type ROWID which can be used as a foreign key to a ROWID pseudo-column Oracle ROWID columns contain data that if converted to a string are 18 characters long for example lsquoAAAQ+jAAEAAAAAeAANrsquo It is probably not advisable to migrate this data to an Informix database and instead use the Informix type which is an integer If there is a dependency on the values themselves and therefore need migrate the data then an integer type would not hold the values

TYPE

In PLSQL you can refer to the type of an existing variable field or column by using the TYPE attribute The converter replaces this reference directly by the type it refers to

ROWTYPE

In PLSQL you can refer to the record type that represents a row of a table a cursor or a cursor variable PLSQL scripts containing the ROWTYPE attribute are handled in the same way as a record type that has been previously declared

FLOAT

Oracle FLOAT type is a floating point number capable of storing up to 38 decimal digits or 126 binary digits It has a floating point scale that can exist outside the boundaries of what an Informix DECIMAL can represent A C language double or Informix float type is capable of only 16 digits so there is the chance that some data will be lost Using an Informix FLOAT type makes it so that less significant digits are lost in preference to more significant digits

IBM Software Group IBM Information Management

Version 16 103

References to subtypes declared in packages and PLSQL blocks are converted to the Informix Server equivalent base types Variables of type RECORD are not translated by the DDL Converter at the time of this writing They will be handled by the stored procedure converter

XMLType

Informix does not have a built-in type for representing XML The nearest approximation is to store it in a CLOB Another character type like LVARCHAR can be used if it can be determined that the actual data will fit in it

Page 4: Oracle to IBM Informix Server Porting Guide

IBM Software Group IBM Information Management

Version 16 4

Table of Contents

C H A P T E R 1 INTRODUCTION 8

PURPOSE 8 PRODUCT OVERVIEW 8 ORGANIZATION 8 CONVENTIONS 9

C H A P T E R 2 DEFINING THE PROBLEM SPACE 11

EXTRACTING THE OBJECTS TO BE MIGRATED 11 Working With Oracle Dump Files 11

C H A P T E R 3 DATA DEFINITION LANGUAGE 15

IDENTIFIERS 15 Delimited identifiers 15 Explicit versus implicit schemaowner names 17 Reserved words or keywords 18 Summary 19

DATABASES 19 Databases database names and instances 19 ANSI vs non-ANSI 20

TABLESPACES AND DBSPACES 20 TABLES 21

Attributes and general syntax 21 Lock mode 21 Storage 21 Constraints 22 ALTER TABLE 22 Data Partitioning 23

DATA TYPES 25 Numeric 25 CHAR VARCHAR and LVARCHAR 26 Date and Time 27 Interval 27 Raw data and Large Objects 28 ROWID 28 User-defined types 29 Complex data types 30

SEQUENCE OBJECTS 30 Oracle sequences 30 Informix sequences 30

INDEXES 30 Composite indexes 30 Maximum key size 31 Index fragmentation 31 General index information 31

VIEWS 32 STORED PROCEDURES AND TRIGGERS 32 ORACLE EXTENSIONS 33

C H A P T E R 4 DATA MANIPULATION LANGUAGE 34

SQL 34 Labels using keywords 34 Inequality operations 34 Selects 34 Optimizer directives 34

IBM Software Group IBM Information Management

Version 16 5

External optimizer directives 35 Inserts 36 Temporary tables 36 Outer joins 36 Sorts 36 Exceptions 37 Correlation names 37 Aliases 37 Hierarchical queries 37 Truncate 39

HOST VARIABLES 40 DATE AND TIME FUNCTIONS 41

SYSDATE 41 Number formats 41 Date formats 42 The RR date format element 43

USER-DEFINED ROUTINES 43 COMPATIBLE SQL FUNCTIONS 43 AGGREGATE FUNCTIONS 43 MATHEMATICAL FUNCTIONS 44 STRING FUNCTIONS 44

LENGTH 44 LTRIM and RTRIM 44 Oracle Extensions 44

OTHER ORACLE FUNCTIONS 44 MACROS 45

ISOPEN and NOT FOUND 45 ROWTYPE 45 TYPE 45

PSEUDO-COLUMNS 45 LEVEL 46 ROWID 46 ROWNUM 46

UPDATE USING CURSORS 49 SYSTEM TABLES 50 STORED PROCEDURES 50

Size limit 50 Parameter limit 50 Packages 51 Routines 51 Exceptions 51 Error handling 52 Cursors 52 Variable declaration and assignment 53 Boolean 53 Binary data types 53 Dynamic SQL 53 Compiler 53

TRIGGERS 54 CONSTRAINTS 55 DUAL TABLE 55

C H A P T E R 5 EMBEDDED SQL 57

HOST VARIABLES 57 Declaration override 57 Arrays 57 Formatting 58

SQL STRUCTURES 59

IBM Software Group IBM Information Management

Version 16 6

SQLCA 59 SQLDA 60 ORACA 61

PRE-COMPILER OPTIONS 61 EMBEDDED PLSQL 61 ORACLE CALL INTERFACE 61

Database library calls 62 Global area processing 62 Fetch cycle 62 RAW binary data type processing 62 Parameter bindings 62

EMBEDDED SQL FOR C 63 VARCHAR 63 Host variables 63

EMBEDDED SQL FOR COBOL 63 VARCHAR 63 Level 88 64 SQLDA 64 REDEFINES 64 Tips 64

ODBC 64

C H A P T E R 6 APPLICATION ARCHITECTURE 65

TRANSACTION PROCESSING 65 Autonomous Transaction 66 Savepoints 67

CONCURRENCY 67 Row Level Locking 67 Transaction Isolation Level 68

C H A P T E R 7 SECURITY 70

USER AUTHENTICATION 70 Operating system security 70 Non-operating system security 70

ROLE BASED AUTHORITY 71 COLUMN-LEVEL ENCRYPTION 71

Passwords and hints 71 Encrypting a column 72 Querying an encrypted column 72 Performance impact of encryption 73 Storage considerations 73 Compliance regulations 73

C H A P T E R 8 ENVIRONMENT 74

SCRIPTS 74 SQL script substitution variables 74

UTILITIES 75 SYSTEM CATALOG 75

C H A P T E R 9 USING BLADELETS 76

WHAT IS A BLADELET 76 INFORMIX EXEC BLADELET FOR DYNAMIC SQL 77 SQLLIB DATABLADE MODULE (SQLLIBC11 SQLLIBJ11) 78

A P P E N D I X A PLANNING GUIDE 79

A P P E N D I X B SYNTAX COMPARISON 82

IBM Software Group IBM Information Management

Version 16 7

A P P E N D I X C DATABASE CONCEPTS 84

A P P E N D I X D SAMPLE CODE 85

DATE ARITHMETIC 88 UNITS Keyword 88 Using EXTEND function 88

STRING REPRESENTATION OF DATE AND TIME 88 Day and date 88 Abbreviation of day of week 88

USING AN INFORMIX COLLECTION DATA TYPE 89 A collection data type as a VARRAY 89 Using MULTISET and ROW to replace PLSQL TABLE and RECORD types 91

A P P E N D I X E COUNTING SYSTEM OBJECTS 93

USING THE SYSTEM CATALOG 93 System catalog 93

USING SQL CODE 94 Built-in function references 94 Object types and counts 95

A P P E N D I X F DATA TYPE MAPPING 97

DOUBLE 101 VARCHAR 101 NUMBER 101 National language types 102 ROWID 102 TYPE 102 ROWTYPE 102 FLOAT 102 XMLType 103

IBM Software Group IBM Information Management

Version 16 8

C H A P T E R 1 Introduction

This document is a technical document describing the differences between Oracle and Informixreg Dynamic Server (IDS) functionality and syntax This porting guide details differences between Oraclersquos 10g release 1 (101) and 10g release 2 (102) and Informix Dynamic Server (version 1110) In addition it can be a useful reference for all migrations between the two database servers regardless of version In addition to DDL DML and overall SQL syntax this document explores the differences between Oracle and Informix with regards to object technology through the use of large objects user defined types and user defined routines It also looks at the differences between Oraclersquos table partitioning and Informixrsquos table fragmentation Part of the explanation is a discussion on what needs to be changed to make an application running on an Oracle database run on an Informix database If there is more than one way to port some piece of functionality alternatives and recommendations are also discussed This document is intended to be a living document Missing items better ways of implementing Oracle functionality in Informix other than what is documented here examples to better illustrate a point and other suggestions should be sent to Chris Golledge (golledgeusibmcom) so they may be included with future revisions

Purpose This document should be used as a guide to assist in porting applications that run on an Oracle database server to run on an Informix database server Regardless of whether a porting effort will be completely manual or if tools will be utilized this document can provide value Obviously if the port is performed manually this guide will provide the most value If the port will utilize tools then analysis can be performed using this guide to determine how much of the application the tools will convert and how much must be converted manually In any case this guide is intended to be used to both visualize the scope of a porting effort and to aid in the porting effort by addressing the technical issues This document will be refined based on usersrsquo experiences to identify as many of the porting issues as possible at the beginning of a project

Product overview IBM Informix Server provides high performance and scalability with legendary reliability and nearly hands-free administration of databases of all size IDS is industry proven on UNIX Linux or Windows platforms with online transaction processing (OLTP) systems data marts data warehouses and e-business applications The IDS 11 release features significant additions over prior versions It supports the services-oriented architecture (SOA) model for application integration and offers many new features for data replication continuous availability and ldquohands freerdquo database administration

Organization This document is broken into sections to logically discuss the different database concepts Some of the sections may contain the same sub-sections for example stored procedures and triggers

IBM Software Group IBM Information Management

Version 16 9

are discussed in the DDL and DML sections This allows separate discussions on the issues facing the same item in each area For example the issues surrounding creating a stored procedure are discussed in the DDL section and the issues surrounding the stored procedure language are discussed in the DML section Among the other references the ldquoPlanning Guiderdquo appendix contains a quick reference of most of the differences between Oracle and Informix along with the degree of difficulty to port each difference This reference is intended for use in the planning process to illustrate the scope and the effort required to perform the porting project Some of the stored procedure logic used to convert Oracle functions is included in the appendix rdquoSample coderdquo

Conventions The conventions used in this document include

Courier Text Distinguishes a logic example

from regular text

Example Illustrates a point In most cases an Oracle example will be followed by an Informix example

Italicized Text Signifies a substitution in other words substitutes for the italicized word the actual object the word is describing for example table_name column_name and so on

UPPER CASE TEXT Signifies database vendor reserved words or statements such as INTEGER CREATE TABLE and so on

Bold example text highlights the item that is being explained

IBM Software Group IBM Information Management

Version 16 10

IBM Software Group IBM Information Management

Version 16 11

C H A P T E R 2 Defining the Problem Space

It is important to define the set of objects to be migrated and it is better if effort is put into this prior to beginning the actual migration This is true if you are the responsible for both the database in general and its migration from one supporting DBMS to another but it is particularly true that there be a clear agreement on the scope of what is to be migrated if the migration is to be performed by a party other than the one with long term responsibility for the database Defining the scope will involve extracting a representation of the objects to be migrated out of the Oracle system catalogs and representing them in some format that can be manipulated into constructs that can be used in Informix

Extracting the objects to be migrated It is possible to represent the objects in more than one language Using the SQL language is the most common method and it will be the only one discussed at length in this document (in its current revision) However it is also possible to express database objects in XML SQL has the advantage that the standard common grammars are widely understood in the context of defining tables indexes etc XML would have an advantage of not requiring parsing that is sensitive to the minor differences in ways of expressing essentially the same object

Working With Oracle Dump Files

There exist 3rd

-party tools for reading system catalogs but it is doubtful that any can read the Oracle catalogs more reliably than Oraclersquos own tools There are two incompatible export and import tool sets used by Oracle The older tools are imp and exp and the newer ones are impdp and expdp where dp stands for Data Pump Oracle has encouraged the use of the newer tools instead of the older ones since the newer ones were introduced at version 10 Nonetheless there are many Oracle users still using imp and exp In the discussions below only the metadata will be extracted into a dump file That is because any data in the dump file will be in a proprietary format and very likely some of the data will have to go through a type conversion process before being loaded into an Informix system Oracle exported data generally cannot be used to load a database in Informix Export and Import

If someone has given you a dump file created with the older export tool there exist tools such as The DDL Wizard by Net 2000 Limited which can be used to extract viable DDL The contents of the dump file contain the SQL for re-creating the database but they are not in a readily usable format The older export and import tools are also more sensitive to the layout of the tablespaces than impdb The ability to extract DDL from the dump file in a usable form segmented by whatever grouping you choose is limited compared to what can be achieved through the Data Pump versions

IBM Software Group IBM Information Management

Version 16 12

It may be tempting to feed the dump file into the IBM Migration Toolkit (MTK) or other tool that works on SQL flat files This will not work MTK works on flat text SQL files and the dump file is binary If you open it up you can see what may be a large number of SQL statements but there are also binary codes within the same file That binary data will prevent MTK from being able to process it Getting SQL statements

If you want to get the SQL statements out of the dump file as they would be executed on the server there is an option available from the import tool itself show=y

imp myIDmyPWD as sysdba file=myFiledmp

full=yes show=y gt dmp_showtxt

This will produce a file which contains the statements but they are wrapped in quotes The contents will look something like

ALTER SESSION SET CURRENT_SCHEMA= SYSTEM CREATE UNDO TABLESPACE TBSPC1 BLOCKSIZE 8192 DATAFILE DORACLEORADA TASCHEMA1CHUNKDBF SIZE 387973120 AUTOEXTEND ON NEXT 5242880 MAXS IZE 32767M EXTENT MANAGEMENT LOCAL

which makes them strings instead of SQL statements Fixing this is a two-step process

-- removes quotes from the start of lines

sed s^ g dmp_showtxt gt step1txt

-- removes quotes from the end of lines

sed s$g step1txt gt dmp_step2sql

The statements are still not correctly formatted because they have been truncated to a fixed length and line-endings inserted However at this point it is possible to get a count of how many of each object type there is using the script in the appendix ldquoGetting an initial count of database objectsrdquo

Data Pump Export and Import

These newer tools provide better performance and more capabilities than their predecessors Please refer to documentation on Oracle for a complete description searches for ldquoData Pump Importrdquo and ldquoData Pump Exportrdquo should return relevant results quickly Below is enough information to get started on defining and extracting the objects to be migrated Metadata can be filtered through the use of the export mode clause and INCLUDE and EXCLUDE parameters However any dependent object of an included or excluded object is likewise included or excluded For example if you include an index then the table associated with the index will also be included and if you exclude a table then any associated indexes will also be excluded The SQL that will generate all the objects in the dump file can be created by the impdp command with the SQLFILE parameter If the output file is very large you might want to break it into smaller pieces There are a couple of ways to do this and the one that is best for you somewhat depends

IBM Software Group IBM Information Management

Version 16 13

on how you intend to proceed with the conversion Data definition language (DDL) SQL for all the objects can be put into one file or the INCLUDE or EXCLUDE parameters can be added to direct Data Pump to filter on the types of objects If you put all the objects into one file then you can break that into smaller files by object type fairly easily because the objects are sorted by type in the SQL file So it is just a matter of cutting the file into smaller pieces This method may be preferred because it allows for you to do things like create all tables load the data and then create the indexes and triggers If the data set is large creating the indexes after loading the data can yield substantial performance improvements However this is less useful if you want to convert sets of objects according to dependencies in which case the filtering option is likely to be more useful Just to illustrate a difference between these two methods in one customer case the metadata dump file was about 18MB and putting all objects in one SQL file resulted in a file that was about 15MB The table definitions occupied a little under 300KB of the 15MB The output file generated by filtering on objects of type TABLE was just over 1MB The addition content was mostly GRANT INDEX and TRIGGER creation statements There were no differences in the CREATE TABLE statements themselves Examples

Prerequisite The Data Pump tools require the use of an Oracle DIRECTORY object This is basically a mapping between a name that exists within the DBMS and a system path It can be a tripping point but it provides an abstraction layer that for instance allows the same commands to work across systems with different disk layouts or different operating systems Creating a DIRECTORY on a Windows system from SQLPlus

SQLgtconnect as sysdba

SQLgtCREATE OR REPLACE DIRECTORY dumpDir AS ctemp

Note Make sure this directory is not read-only There also could be problems if the directory is a network drive on Windows these can be related to there being different users between the Oracle executable and the current user and those users having different permissions on the network drive

SQLgtGRANT read write ON DIRECTORY dumpDir TO userID

Creating a dump file of the entire database

expdp userNameuserPwd as sysdba FULL=Y dumpfile=DB_fulldmp

LOGFILE=LG_expdplog CONTENT=METADATA_ONLY DIRECTORY=dumpDir

Creating a dump file of just one schema

expdp userNameuserPwd as sysdba SCHEMAS=hr DIRECTORY=dumpDir

DUMPFILE=hr dmp LOGFILE=hr log CONTENT=METADATA_ONLY

Creating a dump of just the tables and their dependents

expdp userNameuserPwd as sysdba SCHEMAS=hr INCLUDE=TABLE

DIRECTORY=dumpDir DUMPFILE=hrdmp LOGFILE=hrlog

CONTENT=METADATA_ONLY

Creating a dump of just one table

expdp userNameuserPwd as sysdba SCHEMAS=hr

INCLUDE=TABLELIKE COUNTRIES DIRECTORY=dumpDir

DUMPFILE=hrdmp LOGFILE=hrlog CONTENT=METADATA_ONLY

IBM Software Group IBM Information Management

Version 16 14

Creatinge an SQL file from a dump file

impdp userNameuserPwd as sysdba DIRECTORY=dumpDir

DUMPFILE=hrdmp SQLFILE=dumpDirhrsql

The INCLUDE and EXCLUDE options are also valid when used with impdb so it may be easier to get a complete dump of everything to be migrated then use these options to create subsets of objects it smaller SQL files than it would be to create separate dump files It is easier to divide objects than to merge them together if they are not divided initially as wanted There is a caveat when using this impdp to generate an SQL file the object names will all be delimited identifiers Example

CREATE TABLE HRCOUNTRIES Because of differences between how Informix handles these and how Oracle handles these case-sensitivity issues could occur See the chapter on ldquoDelimited Identifiersrdquo and in particular the description of default shift problems If it can be determined that there are no name collisions if regular identifiers are used removing the quotation marks as part of the conversion might avoid many problems In other words if there are no objects whose names only differ in case like foo and FOO then changing every occurrence of ldquoFOOrdquo to FOO in the DDL could eliminate case-sensitivity issues in the application DML It depends on if the application code uses the delimited form of the name predominantly or not

IBM Software Group IBM Information Management

Version 16 15

C H A P T E R 3 Data Definition Language

Identifiers An identifier specifies the simple name of a database object such as a table name column name index name view name stored procedure name and so on The maximum length of an Oracle identifier is 30 characters and can contain letters numbers ldquo_rdquo ldquo$rdquo and ldquordquo although Oracle highly recommends that ldquo$rdquo and ldquordquo should not be used In contrast Informix identifiers have a maximum length of 128 characters and may contain letters numbers ldquo_rdquo and ldquo$rdquo (as long as ldquo$rdquo is not the first character) See the Delimited Identifiers section below for information This means that all Oracle identifiers containing a ldquordquo anywhere in the identifier or a ldquo$rdquo as the first character must be replaced or modified to remove those characters from the identifier

Delimited identifiers

Delimited identifiers are also known as quoted identifiers and sometimes as escaped identifiers They have been part of the SQL standard since SQL92 but existed in various database management systems (DBMS) prior to that time In a nutshell they are a way to preserve case sensitivity in object names as well as to allow objects to have names outside of the conventions of SQL regular identifiers Prior to the behavior of identifiers in general being standardized different DBMS vendors implemented different means of achieving case-insensitivity for object names some converted all regular identifiers to uppercase and some converted regular identifiers to lowercase By SQL99 the concept of case normal form was standardized to mean simply stated that if there exists an uppercase equivalent of any character in a name then the uppercase version is stored in the system catalogs and used for comparison purposes See the SQL99 standard chapter 5 section 2 and in particular items 21 and 22 for a formal description of case normal form and how it applies to identifier comparisons Delimited identifiers can be used to specify names for database objects that are otherwise identical to SQL reserved keywords such as TABLE WHERE DECLARE and so on The only database object for which delimited identifiers cannot be used is a database name Database administrators and application programmers do not always communicate to each other with 100 efficiency and there is no guarantee that within either of these pools every member codes by the standard practice of the other members After describing how delimited identifiers work in Informix there will be a description of how any inconsistency of usage and the differences between Oracle and Informix can introduce some migration hurdles DELIMIDENT Environment Variable

To use delimited identifiers with Informix you must set the DELIMIDENT environment variable While DELIMIDENT is set strings enclosed in quotation marks ( ldquo ) are treated as identifiers of database objects and strings enclosed in apostrophes ( rsquo ) are treated as literal strings If the

IBM Software Group IBM Information Management

Version 16 16

DELIMIDENT environment variable is not set strings enclosed in quotation marks are also treated as literal strings When you set the DELIMIDENT environment variable you cannot use quotation marks ( rdquo ) to delimit literal strings If DELIMIDENT is set the database server interprets all strings enclosed in quotation marks as SQL identifiers not string literals Commonly within Informix systems DELIMIDENT is set or not on the client side according to the design of the application However if you are converting a database and all applications accessing it from a system where every occurrence of quotation marks (ldquoobjectNamerdquo) indicates an identifier and not a string literal you may want to consider setting it in the server environment in order to avoid any inconsistency between clients where it is set and where it might not be Using Quotes in Strings The apostrophe ( rsquo ) has no special significance in string literals delimited by quotation marks Conversely double quote ( Prime ) has no special significance in strings delimited by apostrophes For example these strings are valid Nancyrsquos puppy jumped the fence

rsquoBilly told his kitten No rsquo A string delimited by quotation marks can include a double quote character by preceding it with another double quote as the following string shows Enter y to

select this row When the DELIMIDENT environment variable is set quotation marks can only delimit identifiers not strings Use of Uppercase Characters You can specify the name of a database object with uppercase characters but the Informix server shifts these to lowercase characters unless the DELIMIDENT environment variable is set and the name of the database object is enclosed in quotation marks In this case the database server treats the name of the database object as a delimited identifier and preserves the uppercase characters in the name Delimited Identifiers By default the character set of a valid SQL identifier is restricted to letters digits underscore and dollar-sign symbols If you set the DELIMIDENT environment variable however SQL identifiers can also include additional characters from the codeset implied by the setting of the DB_LOCALE environment variable See the Identifier section of the Informix Guide to SQL Syntax for more information Storage Object Names In Informix delimited identifiers can be used to specify non-alphanumeric characters in the names of database objects However delimited identifiers can not be used to specify non-alpha characters in the names of storage objects such as dbspaces and blobspaces To use delimited identifiers DELIMIDENT must be set both at compile and run times For example to set DELIMIDENT environment variable with sh or ksh issue the following at the command line prompt

export DELIMIDENT=

Note You do not need to assign a value to the environment variable and counter-intuitively setting DELIMIDENT=n has the same effect as DELIMIDENT=y Also in a Windows environment

set DELIMIDENT=

effectively undefines the variable Default shift problems

Any direct access of system catalog information involving names will cause problems when migrating from a system like Oracle where system catalog names are stored in uppercase to a system like Informix where the catalog names are stored in lowercase For example

CREATE TABLE foo (c1 int)

IBM Software Group IBM Information Management

Version 16 17

Within Oracle the following will return information about the table

select from sysall_objects where object_name = FOO

and the following will not

select from sysall_objects where object_name = foo

Conversely in Informix

select from systables where tabname = foo

will be successful and the same with FOO will not be A similar if not more common problem can occur when the table has been created without the name being delimited but is sometimes delimited when accessed by the application Per the standard foo == FOO == ldquoFOOrdquo but in Informix foo == FOO == ldquofoordquo In Oracle the following SELECT statement will be successful

SELECT FROM ldquoFOOrdquo

but within Informix this will result in an error ldquo206 The specified table (FOO) is not in the databaserdquo Likewise if the name is delimited in its definition such as

CREATE TABLE SCHEMA1TABLE1

this creates a table that can be referenced in Oracle without the name being delimited The statements

SELECT FROM schema1table1

and SELECT FROM SCHEMA1TABLE1

will be successful in the Oracle system but will fail in the Informix one In theory whether on object name is delimited or not should be the same in the database and at every occurrence within the application but this is not always the case It may be beneficial to examine whether delimited identifiers or regular identifiers are most commonly used in application code and use whichever is most common as a naming convention when translating the DDL

Explicit versus implicit schemaowner names

Another complication to keep in mind is that when the log mode is ANSI implicit and explicit owner names are treated differently between the Oracle and Informix servers In Oracle there is no difference in the case handling of an implicit owner name and an explicit one For example if connected to Oracle as scott the following CREATE TABLE statements

create table foo1(c1 int) create table scottfoo2(c1 int) create table SCOTTfoo3(c1 int)

all result in tables owned by SCOTT The following select statements in various forms that may be in application code will all run without error

select from foo1 select from scottfoo1

IBM Software Group IBM Information Management

Version 16 18

select from SCOTTfoo1 select from foo2 select from scottfoo2 select from SCOTTfoo2 select from foo3 select from scottfoo3 select from SCOTTfoo3

These statements will also run without error within a non-ANSI mode Informix database but not all of them will run successfully within an ANSI mode database This is because Informix does not uniformly fold the case of owner names and handles implicit names differently from explicit names so there will always be some combination of DDL and DML usage patterns that work within an Oracle system that do not work in an Informix one You can set ANSIOWNER before starting your Informix server but that will merely change which combinations do not work You may want to examine usage patterns within the applications and choose a naming convention when translating the DDL that matches the most common naming convention used in the applications Note This behavior of Informix forces a tradeoff between using an ANSI mode database which most closely matches the transaction behavior of Oracle and a non-ANSI mode database which has the least mismatch in identifier case sensitivity

Reserved words or keywords

Oracle and Informix both allow identifiers to be reserved words as long as they are delimited However Oracle and Informix reserved words differ In addition both systems have keywords like FROM that are not always reserved in the sense that using them as an identifier will always generate a syntax error There should be few problems with reserved words or keywords if identifiers that are delimited in the original database remain delimited in the destination database The appendix Keywords of SQL for IBM Informix in the Guide to SQL Syntax contains more information about Informix keywords Also one word non-delimited identifiers should be verified against the Informix reserved words list to ensure that they do not need to be delimited or renamed Although almost any word can be used as an identifier in Informix syntactic ambiguities can result from using reserved words as identifiers in SQL statements Delimited identifiers provide a way to use a reserved word as an identifier without causing syntactic ambiguities However doing this changes a case-insensitive name into a case-sensitive one and that means that every reference to the object has to be checked for issues related to case-sensitivity Essentially this is not much less work than changing the name of the object because in essence it is changing the name of the object Examples

The following example shows how to create an Informix table with a case sensitive table name

CREATE TABLE My_Customers (hellip)

The following example shows how to create a table whose name includes a space character If the table name were not in quotation marks () a space character or any other non-alpha character except an underscore ( _ ) or dollar sign ($) (see special conditions above) could be used in the name

CREATE TABLE My Customers (hellip)

IBM Software Group IBM Information Management

Version 16 19

The following example shows how to create a table that uses a keyword as the table name

CREATE TABLE TABLE (hellip)

To include a double-quote () within a delimited identifier the double-quote () must be preceded with another double-quote () as shown in the following example

CREATE TABLE MyGoodData (hellip)

Summary

The main points to keep in mind when deciding about any questions on how identifiers should be translated are

Oracle always has delimited identifiers enabled and Informix does not

Oracle folds regular identifiers to uppercase and Informix folds to lowercase

Informix has behavioral differences between an ANSI mode database and a non-ANSI mode one

It is beneficial to consider the most common usage patterns within the existing application code prior to deciding default identifier translation patterns

Databases

Databases database names and instances

Oracle and Informix implement databases and instances differently Oracle considers a database to be a set of data files control file(s) and log files while an instance is a set of background processes and memory structures accessing database data Oracle instances are also known as servers Each Oracle instance or server runs against one database but through the use of Oracle Parallel Server a database may have multiple instances accessing it An Oracle database is named at initialization and the name has a limit of 8 ASCII characters Informix databases are defined as ldquoa collection of information contained in tables that are useful to a particular organization or used for a specific purposerdquo Informix database names may be up to 128 characters in length An Informix instance is a set of processes memory and disk allocations that manage data and will contain at least two and in most cases many databases Informix instances are also referred to as servers Informix databases may share disk allocations (dbspaces) with other databases within an Informix instance Oracle databases cannot share disk allocations (tablespaces) Informix databases should be created in a dbspace other than the root dbspace The root dbspace holds data for the system configuration information for the engine and so on If user-defined objects are created in this dbspace then the dbspace may become unmanageably large and during backup the system information may also get backed up unnecessarily The CREATE DATABASE statements of Informix and Oracle have differences which may require modification to routines responsible for database creation Informix will accept the same minimal syntax required by Oracle (eg CREATE DATABASE myDB) however issuing the command will implicitly accept the creation of a database without transaction logging enabled and establish the default location for all database objects as the instancersquos default storage location The instancersquos default storage location or ldquorootrdquo dbspace should not contain user-defined objects The root dbspace holds data for the system and some configuration information for the engine If user-

IBM Software Group IBM Information Management

Version 16 20

defined objects are created in this dbspace it may become unmanageable and result in the system contending with user objects for the available space

ANSI vs non-ANSI

Informix supports both ANSI and non-ANSI databases Informix non-ANSI databases are most common but there are some advantages of ANSI databases when porting from Oracle

Oraclersquos transaction behavior is more or less like that of an ANSI database Applications ported on Oracle are always in a transaction In Oracle and ANSI databases transactions begin implicitly with the first of a series of SQL statements and will end immediately after a commit or rollback statement Therefore unlike a non-ANSI database a COMMIT WORK statement does not need to be preceded with a BEGIN WORK statement

In ANSI databases database object references must be prefixed by the ownerrsquos name unless the owner is the one referencing the object If Oracle applications reference database objects with a both parts of the object name prefixing the object name with schema using an ANSI database may ease modifications necessary when porting to Informix

The ldquolsquogrant to PUBLICrdquorsquo concept provide by Informix database security does not apply to ANSI databases Every database object is private and privileges must be explicitly granted to each user

If an Informix ESQLC or 4GL application was developed to run on a non-ANSI Informix database (including BEGIN WORK statements) the application could run on an ANSI Informix database in one of two ways

By placing the BEGIN WORK statement in a pre-processor directive such as IFDEF object_name and omitting the proper preprocessor compile options such as -D object_name

By compiling the application normally and ignoring the resulting warning messages

Additionally the LOG MODE ANSI clause must be added to the CREATE DATABASE statements ANSI mode databases cannot have buffered logging Applications written to use an open API like ODBC or JDBC are compiled without awareness of the database and these APIs are written with the intent to abstract specific database behavior For instance in one of these the application developer would call a function to begin or end a transaction rather than execute a BEGIN and COMMIT or ROLLBACK The API would execute these statements internally or not as necessary for the database connection See the Transaction Processing section in Application Architecture for more information on how an application running on a non-ANSI Informix database can simulate Oracle transaction behavior

Tablespaces and dbspaces Oracle tablespace names need to be replaced with Informix dbspace names Unlike the Oracle tablespace the Informix dbspace cannot be created using DDL (SQL) scripts It must be created using the Informix onspaces utility before any DDL (SQL) scripts are executed Therefore Oraclersquos CREATE TABLESPACE statements should be removed from the DDL (SQL) scripts The user interface for accomplishing these tasks is onmonitor The command line utility is onspaces Therefore the onspaces commands can be placed in shell or batch scripts After successfully executing the onspaces commands the DDL (SQL) scripts may be called through the same shell or batch scripts For example

IBM Software Group IBM Information Management

Version 16 21

onspaces hellip onspaces hellip hellip dbaccess database_name DDL_script_file_name dbaccess database_name DDL_script_file_name hellip

Tables

Attributes and general syntax

When creating tables the Oracle CREATE TABLE statement must be converted to Informix taking advantage of the Informix options IN EXTENT NEXT and LOCK MODE

IN specifies the dbspace in which the table will reside

EXTENT specifies the amount of space that will initially be allocated to the table (16K default on most platforms)

NEXT specifies the amount of space that will be allocated when additional space is needed (16K default on most platforms

Lock mode

LOCK MODE specifies whether to use row or page locks for the table In Oracle the default is row level locking in Informix the default setting is page level locking However it can be changed by using one of the following methods (resolved in the following order of precedence)

1 LOCK MODE specified using an attribute of the CREATE TABLE or ALTER TABLE command syntax

2 IFX_DEF_TABLE_LOCKMODE environment variable setting 3 DEF_TABLE_LOCKMODE parameter setting in the ONCONFIG file

NOTE If the DEF_TABLE_LOCKMODE parameter cannot be found in the ONCONFIG file it can be added to make the specification for every database within the instance The Informix instance must be restarted for this parameter to take effect The new ldquodefaultrdquo LOCK MODE will apply to all tables created after the parameter has been changed To change the LOCK MODE of existing objects use the ALTER TABLE statement

Storage

The Oracle STORAGE INITIAL and STORAGE NEXT clauses must be changed to the Informix EXTENT SIZE and NEXT SIZE clauses respectively In Oracle the STORAGE clause options MINEXTENTS MAXEXTENTS and PCTINCREASE should be removed For example Oracle

CREATE TABLE dept(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13)

)

STORAGE (INITIAL 100K NEXT 50K MINEXTENTS 1 MAXEXTENTS 50

PCTINCREASE 5)

Informix CREATE TABLE dept (

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

IBM Software Group IBM Information Management

Version 16 22

EXTENT SIZE 200 NEXT SIZE 50

When an Oracle CREATE TABLE statement does not include a STORAGE clause the table will be created using the tablespace STORAGE clause by default If an Oracle tablespace is created specifying a STORAGE INITIAL of 100KB and a STORAGE NEXT of 50KB then all tables created within that tablespace will have a default value of STORAGE INITIAL 100KB and STORAGE NEXT 50KB Oracle tables cannot be created with smaller STORAGE clause values than the tablespace default they are created in Informix dbspaces do not have storage clauses attached to them As stated earlier the default Informix EXTENT and NEXT sizes are 16KB on most platforms The minimum EXTENT and NEXT sizes are 4 times the page size

Constraints

The Oracle constraint syntax must be changed to the Informix syntax for primary keys foreign keys unique and so on For example

Oracle CONSTRAINT PK_NUMBER PRIMARY KEY(CUST_NUM)

CONSTRAINT CK_EMP_CODE CHECK (EMP_CODE gt 100)

Informix PRIMARY KEY(CUST_NUM) CONSTRAINT PK_NUMBER

CHECK (EMP_CODE gt 100) CONSTRAINT CK_EMP_CODE

An Oracle check constraint statement may contain functions that are not available in Informix In this circumstance it may be necessary to code the combination of a trigger and a stored procedure to emulate the same functionality A trigger based on an insert or update event can execute a stored procedure which tests the constraint condition and if necessary raise an exception to reject the row data which violates the constraint The Oracle PARALLEL clause which specifies parallel execution of an operation must be removed from any SQL statements (such as CREATE TABLE and ALTER TABLE) In Informix there are ways to accomplish this parallel execution depending on the context in which these SQL statements are called (shell script file batch file and so on)

ALTER TABLE

Informix offers a rich set of ALTER TABLE features adding and dropping columns (rename by using the RENAME statement) changing column data types altering the next size and changing the lock mode Informix will choose one of three algorithms when executing an ALTER TABLE statement depending upon the operation to be performed For certain conditions the database server uses either a ldquoslowrdquo ldquoin-place or ldquofastrdquo alter algorithm to modify the table Informix provides ldquoin-placerdquo alter table support for adding or dropping a column anywhere in the table changing the column length and changing the column data type without an exclusive lock on the table An ldquoin-placerdquo alter will modify the tablersquos definition without changing the existing rows or unloading and reloading the data After the ALTER TABLE operation the database server inserts rows using the latest definition Informix will not change the row structure until a data row is touched by a user operation Once a query accesses a row that is not yet converted there can be a slight degradation in the performance because the database server reformats each row in memory before it is returned Informix uses the ldquoslowrdquo alter algorithm when the ALTER TABLE statement makes column changes that it cannot perform in place This type of alter would be

Adding or drop a column created with the ROWIDS keyword

Dropping a column of the TEXT or BYTE data type

IBM Software Group IBM Information Management

Version 16 23

Converting an INT or a SMALLINT column to SERIAL or SERIAL8

Modifying the data type of a column so that some possible values of the old data type cannot be converted to the new data type

For example if you modify a column of data type INTEGER to CHAR(n) the database server uses the slow ALTER algorithm if the value of n is less than 11 An INTEGER requires 10 characters plus one for the minus sign for the lowest possible negative values

Modifying the data type of a fragmentation column in a way that value conversion might cause rows to move to another fragment

Adding dropping or modifying any column when the table contains user-defined data types or smart large objects

When the database server uses the slow alter algorithm to process an ALTER TABLE statement the table can be unavailable to other users for a long period of time because the database server will lock the table exclusively for the duration of the operation make a copy of the table to convert the table to the new definition and convert the data rows This type of ALTER TABLE processing can encounter the scenario of a statement being a long transaction and abort it if the Long Transaction High Water Mark (LTXHWM) threshold is exceeded Informix will use the ldquofastrdquo alter algorithm when the ALTER TABLE statement changes attributes of the table but does not affect the data The database server uses the fast alter algorithm when you use the ALTER TABLE statement to make the following changes

bull Change the next-extent size

bull Add or drop a constraint

bull Change the lock mode of the table

bull Change the unique index attribute without modifying the column type

With the ldquofastrdquo alter algorithm the database server holds a lock on the table for a very brief period In some cases the database server will lock the system catalog tables but only long enough to change the attribute In either case the table is unavailable for queries for only a short time

Data Partitioning

Informix Table Fragmentation is the counterpart to Oraclersquos Table Partitioning and allows the user to control where data is physically placed at the table level Table Fragmentation or Data Partitioning is typically done to large tables but Informix and Oracle implement fragmentation and partitioning for different reasons and with different results Informix recommends using table fragmentation to improve single-user response time concurrency data availability backup restore characteristics and data-load performance While Oracle does state that table partitioning may improve the performance of queries and that the Oracle optimizer takes partitioning into account the primary goal of partitioning in Oracle is improving database maintenance Partitioning strategies in Oracle include range partitioning as well as hash and composite partitioning Composite partitioning combines range and hash partitions through the use of sub-partitions Tables incorporating Oracle LOBrsquos (large objects) cannot be partitioned Informix fragmentation strategies include expression-based and round robin Basic expression-based fragmentation can replace Oracle range partitioning Unlike Oracle LOBs Informixrsquos Smart Large Objects can be fragmented Examples of creating tables with Oracle range partitioning and Informix fragmentation by expression are shown below Oracle range partitioning

CREATE TABLE dept

IBM Software Group IBM Information Management

Version 16 24

(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13) )

partition by range (deptno)

(partition PART1 values less than (11)

tablespace PART1_TS

partition PART2 values less than (21)

tablespace PART2_TS

partition PART3 values less than (31)

tablespace PART3_TS

partition PART4 values less than (MAXVALUE)

tablespace PART4_TS)

Informix expression based fragmentation CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

deptno lt 11 IN dbspace1

deptno gt= 11 AND deptno lt 21 IN dbspace2

deptno gt= 21 AND deptno lt 31 IN dbspace3

REMAINDER IN dbspace4

Oracle uses MAXVALUE for values not found in the specified range while Informix uses the REMAINDER keyword for values that fall outside the specified expression or expressions Prior to IDS version 1000 each table fragment had to go into a separate dbspace Now tables can be fragmented within a single dbspace You can create partitions within a dbspace that can each support a table fragment It is better to have one chunk per disk drive and now it is not necessary to create a dbspace just to facilitate fragmentation This feature can simplify the management of dbspaces The benefits gained through this new development include

It reduces the total number of dbspaces needed for a fragmented table

Storing multiple table fragments in a single dbspace improves query performance over storing each fragmented expression in a different dbspace

For example Informix partition fragmention in a single dbspace

CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

PARTITION part1 (deptno lt 11) IN dbspace1

PARTITION part2 (deptno lt 21) IN dbspace1

PARTITION part3 (deptno lt 31) IN dbspace1

PARTITION part4 REMAINDER IN dbspace1

Partitions of an Informix fragmented table can be manipulated using the ALTER FRAGMENT statement which supports attaching detaching adding modifying and dropping as well as initializing the distribution strategy

IBM Software Group IBM Information Management

Version 16 25

For example the following SQL removes a partition fragment and places the contents into a new table

ALTER FRAGMENT ON TABLE dept DETACH PARTITION part3 dept_part3

Making use of ALTER FRAGMENT to detach fragments can be an effective way of deleting large quantities of rows from a table quickly and easily After the above statement completes the table will no longer contain rows with a deptno greater than 21 and less than 31 Refer to the Informix Guide to SQL Syntax for a complete description on how to use the ALTER FRAGMENT statement to change the distribution strategy or the storage location of an existing table or index

Data types

Numeric

Oraclersquos NUMBER data type needs to be replaced with one of the following Informix equivalent data types depending on the size of the column The Informix numeric data types are listed below

SMALLINT (-32767 to 32767)

INTEGER (-2147483647 to 2147483647)

BIGINT (-9223372036854775807 to 9223372036854775807)

INT8 (-9223372036854775807 to 9223372036854775807)

The BIGINT type is more efficient in terms of space and speed there are few reasons to use INT8 now that BIGINT is available

DECIMAL (floating point up to 32 significant digits -10-130

to 10124

)

In an ANSI database there is an implied scale of 0 when no scale is given so this is not strictly speaking a floating point type within an ANSI database

NUMERIC (floating point up to 32 significant digits -10-130

to 10124

)

FLOAT (double precision like double data type of C)

SMALLFLOAT (single precision like float data type of C)

REAL (same as SMALLFLOAT)

DOUBLE (same as FLOAT)

LONG (same as long data type of C)

Oraclersquos NUMBER data type is used to store zero positive and negative fixed size and floating point numbers with magnitudes between 10 x 10

-130 and 999 x 10

125 (38 9s followed by 88 0s)

with 38 digits of precision A fixed-point number is specified by NUMBER(p s) where p is the precision or the total number of digits and s is the scale or the number of digits to the right of the decimal point For example a column defined as NUMBER(104) would contain numbers in the format 9999999999 In Oracle the scale can range from -84 to 127 If the scale is 0 or not mentioned then the data type can be converted into Informixrsquos SMALLINT INTEGER or BIGINT depending on the precision or FLOAT SMALLFLOAT DOUBLE or REAL depending on usage in the application When the scale is positive the data type should be converted to Informixrsquos DECIMAL or NUMERIC A floating-point data type in Oracle is declared using the type NUMBER without mentioning scale and precision In Informix this can be replaced with FLOAT SMALLFLOAT REAL DOUBLE PRECISION or DECIMAL(p) in an non-ANSI database

IBM Software Group IBM Information Management

Version 16 26

Oracle allows a negative scale If the scale is negative the actual data is rounded to the specified number of places to the left of the decimal point For example a specification of NUMBER (10 -2) means to round to the hundred If the general form for any number is

mantissa X 10exponent

then precision is the number of digits in the mantissa and scale is the negative exponent Example

select cast( 987654321 AS NUMBER(10-2) ) from dual

returns

987654300

Informix does not support a negative scale If precision - scale is less than the maximum precision of an integer type then that is the most efficient type to use Failing that and if the database is non-ANSI a floating point DECIMAL can be used If that is not sufficient then it may be necessary to define a user type and associated functions Oracle also allows the scale to be greater than the precision Precision is just the number of digits that will be preserved A NUMBER(3 5) might have the value 000123 If the Oracle scale is less than the Informix maximum precision then the Oracle scale can be used for both the Informix precision and scale A NUMERIC(55) column could also store the value 000123 You may need to take into consideration not only the minimum and maximum values but the default size for data types For example when the size of the NUMBER data type is absent Oracle will default to NUMBER(38) while Informix defaults to NUMERIC(16) Oracle and Informix support the ANSI DECIMAL data type Therefore in the case of an ANSI data type the Oracle data type can be converted to the same Informix data type There are differences between conversions based on theory versus those based on practice For instance it is very common to see an undecorated NUMBER declaration where the customer database and applications are using integer data When converting NUMBER declarations it may be necessary to consider how the data is being used in order to determine the best type mapping

CHAR VARCHAR and LVARCHAR

In Oracle the default for a CHAR column is one character and the maximum allowed is 255 characters In Informix the maximum length of CHAR and LVARCHAR columns is 32767 Therefore Oraclersquos CHAR columns can always be converted to an Informix CHAR column The CHAR data type columns can only contain printable characters tabs and spaces The CHAR columns store leading and trailing spaces In Oracle a zero-length string can be inserted into a CHAR column but the column is padded with one blank character when it is used in comparisons Also in Informix a zero-length string can be inserted into a CHAR column however the column is padded with enough spaces to fill the column In the case of inserting NULL into an Informix CHAR column no padding occurs Oraclersquos VARCHAR and VARCHAR2 are currently synonymous and have a maximum data length of 4000 bytes while the maximum length for the Informix VARCHAR data type is 255 Informixrsquos CHAR and LVARCHAR data types have a maximum length of 32767 and 32739 respectively measured in bytes These should be used to replace Oraclersquos VARCHAR VARCHAR2 LONG and LONG VARCHAR if the data length is between 256 and the maximum If the data length exceeds the maximum use Informixrsquos TEXT BYTE BLOB or CLOB data types See the Raw Data section below for more information on TEXT BYTE BLOB and CLOB data types

IBM Software Group IBM Information Management

Version 16 27

Empty Oracle VARCHAR2 strings are considered NULL Empty Informix VARCHAR and LVARCHAR strings are not considered NULL rather they contain at least one space Oracle

compares VARCHAR2 values using non-padded comparison semantics Therefore ldquoBOBrdquo ldquoBOB ldquo Informix ignores trailing blanks Therefore ldquoBOBrdquo = ldquoBOB ldquo or ldquordquo = ldquo rdquo Hence checks for NULL within the application must be replaced with checks for an empty string (such as ldquordquo or ldquo rdquo) whenever an empty string is inserted into the column If NULL is truly inserted into the column checking for NULL is appropriate (for example SELECT FROM hellip WHERE hellip IS NULL) In Oracle LONG columns store variable length character strings containing up to 2 gigabytes or 2

31-1 bytes Informix LONG columns store numeric data Oraclersquos LONG columns have many of

the characteristics of VARCHAR2 columns They can be used in a SELECT list in the SET clause of an UPDATE statement and in an INSERT statement but they cannot be used in a WHERE clause a GROUP BY clause or an ORDER BY clause and they cannot be indexed Oraclersquos LONG columns should be converted to an Informix Smart Large Object or ldquoSLOBrdquo (BLOB CLOB) column

Date and Time

Oraclersquos DATE data type contains date and time components from year down to second It can be to be replaced most directly with Informixrsquos DATETIME YEAR TO SECOND Some analysis may be necessary to determine whether the time is really necessary In other words does the application reference the date and time portions of the values If the application only references the date portion then replace Oraclersquos DATE with Informixrsquos DATE and change the host variable to X(10) or char(10) accordingly The Informix DATE default display format is MM-DD-YYYY although the DATE data type stores the calendar date The Informix DATE data type requires 4 bytes which is stored internally as an integer value equal to the number of days since December 31 1899 The default display format can be changed with the environment variable DBDATE If the application uses different date formats then using DBDATE is not a solution Sometimes it might be necessary to write small subroutines to emulate Oraclersquos DATE representations See the Informix Guide to SQL Reference manual for details on DBDATE and also DBCENTURY If the application only references the time portion of the values replace Oraclersquos DATE with Informixrsquos DATETIME using the EXTEND function to specify precision In addition Informix provides the data type INTERVAL for use while performing DATE and DATETIME calculations In Oracle the DATE data type is used to store date and time information Although date and time information can be represented in both CHAR and NUMBER data types the DATE data type has special associated properties For each DATE value the following information is stored

century

year

month

day

hour

minute

second

Also regarding the Oracle DATE data type if a date value without a time component is specified the default time is 120000am If a DATE value without a date is specified the default date is the first day of the current month

Interval

Within Informix there are two classes of interval types YEAR-MONTH and DAY-FRACTION There are different numbers if days in different months so the MONTH-DAY boundary cannot be crossed without creating ill-defined results Within each of these classes Informix allows you to declare columns or variables as any subset of the start and end fields Oracle has one INTERVAL

IBM Software Group IBM Information Management

Version 16 28

type for each of the two classes YEAR(p) TO MONTH and DAY(p) TO SECOND(s) The Oracle scale on the SECOND field is logically equivalent to the Informix scale on the FRACTION field

Raw data and Large Objects

Oraclersquos support of large blocks of raw unstructured data (such as graphic images video clips and sound waveforms) in binary or character format is provided by the large object (LOB) data types BLOB CLOB NCLOB and BFILE Traditional Oracle data types MLSLABEL (used with Trusted Oracle) RAW and LONG RAW are also used for data that is not to be interpreted by the engine and converted when moving data between different systems Informix supports two types of large objects (LOBs Simple Large Objects and Smart Large Objects Simple LOBs consist of the TEXT and BYTE data types and can be 2

31 bytes or 2

Gigabytes in size Smart LOBs include both Character Large Object (CLOB) and Binary Large Object (BLOB) data types and may be up to 42

40 bytes or 4 Terabytes in size Simple LOBs can

be stored either in-line with table data or in blobspaces while Smart LOBrsquos are stored in sbspaces Oraclersquos CLOB BLOB MLSLABEL RAW and LONG RAW data types should be replaced with Informixrsquos BYTE TEXT CLOB or BLOB depending on the columnrsquos size and usage Informixrsquos Smart BLOB data types CLOB and BLOB should be used under the following conditions and considerations

The large object needs to be referenced by multiple sources

The object size exceeds 2 GB

Fragmentation is required

Byte level locking is available making it possible to lock only a portion of the object

Logging can be specified at the object level

Updates are done in place or moved as needed

Be aware of the following restrictions for Simple Large Objects

Data can only be inserted into a BYTE or TEXT column with the dbload or onload utilities the DBACCESS load statement BYTE or TEXT host variables respectively in ESQLC or declaring a file in ESQLCOBOL

BYTE and TEXT columns cannot be inserted or updated with a literal neither quoted text string nor number

BYTE or TEXT columns cannot be used in string operations with aggregate functions with the GROUP BY ORDER BY IN LIKE or MATCHES clauses

ROWID

The implementation of ROWID differs between Oracle and Informix Oraclersquos ROWID is both a pseudo-column and a data type See the ROWID subsection in the Pseudo-Columns section in CHAPTER 3 Data Manipulation Language for more information Informix implements ROWID as a pseudo-column only Oracle stores the ROWID column and ROWID data type column values in hexadecimal format Informix stores the ROWID column values in INTEGER format The Oracle and Informix engines maintain the values of the ROWID pseudo-column Oraclersquos engine does not maintain the values of other columns of type ROWID In Informix the term rowid refers to an integer that defines the physical location of a row Informix assigns rows in a non-fragmented table a unique rowid which allows applications access to a particular row in a table Rows in fragmented tables in contrast are not assigned a rowid To access data by rowid in a fragmented table a rowid column must be explicitly created as is described in the Informix Guide to SQL Reference manual Creating a Rowid Column If applications attempt to reference a rowid in a fragmented table that does not contain a rowid that was explicitly created Informix displays an appropriate error message and execution of the application is halted

IBM Software Group IBM Information Management

Version 16 29

When used as a data type for a column Oracle does not guarantee that the values are valid ROWIDs For example if the ROWID is used as a data type on a column such as a column in a child table named parent_rowid containing the ROWID of the parent then the values are maintained by the application outside of the engine The application must read the ROWID of the parent and insert it into the parentrsquos corresponding child table rows This is usually done so the two tables can be joined on the parentrsquos ROWID and the childrsquos parent_rowid column This functionality can be duplicated in Informix by using primary and foreign keys Informix recommends that primary keys are used as a method of access in applications rather than rowids because primary keys are defined in the ANSI specification of SQL using them to access data makes applications more portable Refer to the Informix Guide to SQL Reference and the Informix Guide to SQL Syntax for a complete description on how to define and use primary keys to access data

User-defined types

Both Oracle and Informix allow the user to create and define data types Oracle refers to these as abstract data types while Informix refers to these as user-defined types In Oracle all user-defined types are referred to as abstract data types while Informix may refer to user-defined types as COLLECTION types ROW types DISTINCT types and OPAQUE types Currently the Informix ROW type is closest in form and function to the Oracle abstract data type An example of syntax for creating both an Oracle abstract data type and an Informix ROW type is shown below

Oracle abstract data type

CREATE TYPE name_type AS OBJECT

(first_name VARCHAR2(25)

middle_initial CHAR(1)

last_name VARCHAR2(30))

Informix row type

CREATE ROW TYPE name_type

(first_name VARCHAR(25)

middle_initial CHAR(1)

last_name VARCHAR(30))

Both Oracle and Informix support the use of user-defined types for table definition or column definition within a table Building on the example above the following create table example show a table definition and column definition within a table based on user-defined types Oracle table creation

CREATE TABLE name OF name_type

Informix table creation

CREATE TABLE name OF type name_type

Oracle column definition

CREATE TABLE employee

(empno NUMBER(9)

name name_type)

Informix column definition

CREATE TABLE employee

IBM Software Group IBM Information Management

Version 16 30

(empno INTEGER

name name_type)

For more information on User Defined Types see the Informix Guide to SQL Syntax

Complex data types

Informix offers users the ability to create data types from existing built-in types OPAQUE types DISTINCT types and other complex types Complex data types may either be a ROW type or a COLLECTION type Oracle treats complex data types as abstract data types For more information on Oracle abstract data types see the User Defined Types section above For more information on Complex Data Types see the Informix Guide to SQL Syntax For recommended type mappings and additional information see the appendix ldquoData type mappingsrdquo

Sequence objects

Oracle sequences

An Oracle sequence is a database object from which multiple users or transactions may generate unique integers For example sequences can be used to automatically generate primary key values When a sequence object is queried the sequence number is incremented and passed to the query independent of the transaction committing or rolling back If two applications increment the same sequence the sequence numbers each application acquires may not be sequential since sequence numbers are being generated by the other application One user or transaction can never acquire the sequence number generated by another user or transaction Once a user or transaction generates a sequence value that value will never be generated and passed to another user or transaction

Informix sequences

Informix rsquos implementation of sequence objects is identical to that of Oracle Issues regarding syntax compatibility should be negligible with the exception of some keywords which have no effect on the behavior of the sequence Informix supports DML statements (CREATE SEQUENCE ALTER SEQUENCE RENAME SEQUENCE DROP SEQUENCE) for sequence objects that multiple users can access concurrently to generate unique integers in the 8-byte integer range GRANT and REVOKE statements support access privileges on sequence objects and the CREATE SYNONYM and DROP SYNONYM statements can be used to reference synonyms for sequence objects in the local database The operators CURRVAL and NEXTVAL can read or increment the value of an existing synonym with behavior the same as Oracle

Indexes

Composite indexes

A composite index can have up to 16 key parts that are columns or up to 341 key parts that are values returned by a UDR This limit is language-dependent and applies to UDRs written in SPL or Javatrade functional indexes based on C language UDRs can have up to 102 key parts A composite index can have any of the following items as an index key

One or more columns

IBM Software Group IBM Information Management

Version 16 31

One or move values that is returned by a user-defined function (referred to as a functional index)

A combination of columns and user-defined functions

Maximum key size

The total widths of all indexed columns in a single CREATE INDEX statement have a limitation based upon the page size of the dbspace in which the index resides This limitation does not apply to functional indexes An enhancement introduced with Informix Dynamic Server Version 1110 is configurable page sizes for dbspaces Prior to this release the page size of dbspaces were restricted to that of the operating system and could not be changed thus Informix was limited to 390 byte indexes With page sizes configurable from 2K through 16K wider indexes are supported Refer to the table below 16K page sizes raises the limit on index width to over 3000 bytes Lifting the 390 byte limit also permits LVARCHAR columns larger than 387 bytes to be included in an index definition

Page Size Maximum Key Size

2 kilobytes 387 bytes

4 kilobytes 796 bytes

8 kilobytes 1615 bytes

12 kilobytes 2435 bytes

16 kilobytes 3245 bytes

In addition to aiding the porting process wider indexes have satisfied requirements for Unicode data as well as provide performance gains by reducing B-Tree index traversal costs since indexing can be built with more items on an index page and produce fewer levels

Index fragmentation

Just as Oracle and Informix support table fragmentation or partitioning in Oracle both support index fragmentation as well See the Table fragmentation section above for more information regarding Informix table fragmentation and Oracle table partitioning Oracle indexes that are partitioned in the same manner as the table they are indexing are referred to as local indexes Informix refers to these as attached indexes Oracle indexes that span partitions are known as global indexes Informix refers to these as detached indexes Informix detached indexes may also refer to indexes that do not follow the same fragmentation scheme as the table they are indexing Starting with Informix version 1110 indexes can be fragmented similarly to tables on a partition level

General index information

The Informix CLUSTER option should be used when appropriate This option orders the data within the table in the order the index requires It is important to note that the CLUSTER index is not maintained over time The primary factor determining the frequency of CLUSTER index rebuilds is the amount of DML performed against the table Frequent INSERTS UPDATES and DELETES make it necessary to closely monitor CLUSTER indexes There is only one clustered index per table since a tablersquos data can only be stored in one order Oraclersquos INITRANS and PCTFREE functionality is similar to the Informix index FILLFACTOR option of the CREATE INDEX statement or the FILLFACTOR configuration parameter in the ONCONFIG file In either case the functionality is handled by Informixrsquos engine once it is set and can be removed from the application FILLFACTOR specifies the degree of index-page

IBM Software Group IBM Information Management

Version 16 32

compactness A low value provides room for growth in the index A high value compacts the index If an index is fully compacted (100 percent) any new inserts result in splitting nodes The setting on the CREATE INDEX statement overrides the ONCONFIG file value The FILLFACTOR default value for both the CREATE INDEX statement as well as the ONCONFIG is 90 Informix has no support for bitmap indexes

Views Oraclersquos CREATE VIEW statement contains three options FORCE NO FORCE and WITH READ ONLY FORCE creates the view regardless of whether the views base tables exist or the owner of the schema containing the view has privileges on them NO FORCE creates the view only if the base tables exist and the owner of the schema containing the view has privileges on them WITH READ ONLY specifies that no deletes inserts or updates can be performed through the view These options must be removed from the Informix CREATE VIEW statements Because a view is not really a table it cannot be indexed and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE The columns of a view cannot be renamed with RENAME COLUMN To change anything about the definition of a view you must drop the view and re-create it Because it must be merged with the userrsquos query the SELECT statement on which a view is based cannot contain any of the following clauses

INTO TEMP The userrsquos query might contain INTO TEMP if the view also contains it the data would not know where to go

UNION The userrsquos query might contain UNION No meaning has been defined for nested

UNION clauses

ORDER BY The userrsquos query might contain ORDER BY If the view also contains it the choice of columns or sort directions could be in conflict

Stored procedures and triggers The ways stored procedures and triggers are created differ between Oracle and Informix Oracle allows a REPLACE clause in the CREATE statement to handle situations when the object already exists Informix does not support the REPLACE option Instead a DROP PROCEDURE or DROP TRIGGER statement must precede the CREATE PROCEDURE or CREATE TRIGGER statement respectively to handle the situation when the object already exists It should be noted a DROP statement will generate an error when the object does not exist If it is run interactively within the DBACCESS user interface the DROP statement error will terminate processing If it is run using script execution using DBACCESS at the command line processing will continue To run DBACCESS from the command line type

dbaccess db_name

To run the file containing the create statements from the command line type dbaccess db_name sql_file_name

Informix introduced an IF EXISTS clause to most of the CREATE and DROP statements at 117 but the logic is different from Oraclersquos OR REPLACE clause For example these statements

IBM Software Group IBM Information Management

Version 16 33

DROP PROCEDURE IF EXISTS hellip

CREATE PROCEDURE hellip

are logically the same as this Oracle statement

CREATE OR REPLACE PROCEDURE hellip

So it is possible to achieve the same result but not necessarily the same number of statements

Oracle extensions The Oracle CLUSTER option in CREATE statements should be removed These are not to be confused with Informix CLUSTER index statements (See Indexes section above) An Oracle cluster is a database schema object that contains one or more tables that all have one or more columns in common Rows of one or more tables that share the same value in these common columns are physically stored together within the database Removing this Oracle feature will not affect the application Other non-Informix DDL statements like CREATE DATAFILE CREATE CONTROLFILE CREATE ROLLBACK SEGMENT CREATE SNAPSHOT CREATE DATABASE and CREATE DATABASE LINK must be removed or changed (in the case of the CREATE DATABASE statement) The Oracle CREATE PROFILE statement must be removed An Oracle profile is a set of limits on database resources Profiles can be used to limit the database resources available to a user for a single SQL statement or a single session

IBM Software Group IBM Information Management

Version 16 34

C H A P T E R 4 Data Manipulation Language

SQL

Labels using keywords

Oracle displays labels in SQL statements that are Informix reserved words such as UNITS YEAR MONTH DAY HOUR and so on must be converted by using the Informix AS clause between the column name and the display label Otherwise syntactic ambiguities will cause errors

Inequality operations

In addition to the Informix supported ldquonot equal tordquo symbols ldquoltgtrdquo and ldquo=rdquo Oracle supports the symbol ldquo^=rdquo All occurrences of ^= must be replaced with one of the Informix supported symbols

Selects

Queries are executed based on how the optimizer determines the best path to the data Oracle and Informix developed their own query optimizers with their proprietary methods and rules A query that looks exactly the same in both environments may run differently in each following a different path and executing faster or slower Therefore every query in the ported application should be tested for performance regardless of whether a query had to be converted Furthermore Oracle supports optimizer hints within a SELECT statement Prior to IDS 73 and Informix Dynamic Server 92 Informix did not allow optimizer hints See the Optimizer Directives subsection below for more information on porting Oraclersquos optimizer hints to Informixrsquos optimizer directives

Optimizer directives

Informix offers optimizer directives similar to Oraclersquos optimizer hints This feature provides the query developer the flexibility to direct the optimizer to follow specific paths rather than choosing a plan through its analysis A query is processed in two steps First it is optimized and compiled to product a query plan Secondly it is executed to produce a result Optimizer directives are a method for influencing the choice of the optimizer in the creation of the plan

IBM Software Group IBM Information Management

Version 16 35

Optimizer directives address the following key issues

Reduced time for correcting performance problems Rewriting queries can be very time consuming and this allows you to have a quick way to alter a plan

Competitive pressure Users accustomed to this function were looking for it in Informix

Product development tuning This allows product development to alter plans dynamically rather than through code changes to evaluate the effect of different optimization techniques

The syntax and behavior of Informixrsquos implementation is compatible with Oraclersquos optimizer hints which eases the porting of applications from Oracle to Informix Directives are written as a comment whose first character is a lsquo+rsquo (plus sign) An example is

select + ORDERED AVOID_FULL(e) empname deptno

from employee e department d

where edept_no = ddept_no

This above example specifies that the tables should be joined in the order specified in the query and that the employee table (e) should NOT be accessed with a full table scan The Informix implementation differentiates itself significantly from Oraclersquos in one way Informix supports the notion of negative directives whereas Oracle only supports direct hints A directive that tells the optimizer what to avoid rather than what to choose is unique to Informix The query result can be realized by writing a directive to avoid certain actions known to cause performance issues but allow any new indexes or table attributes to be explored by the optimizer as they are added over the life of the table and query This allows a DBA to continue to add indexes to tables and not have to rewrite directives Additionally Informix supports full recognition of directives with SET EXPLAIN output Informix will highlight semantic and syntactic errors which Oracle does not Optimizer directives support control in the following areas of the optimization process

Access methods Index versus scans

Join Methods Forcing hash joins nested loop joins

Join Order Specify which order the tables are joined

Goal Specify first rows or all rows (response time versus throughput) See the Informix Guide to SQL Syntax or Reference for more information

External optimizer directives

External optimizer directives give the DBA the ability to specify query directives and save them in the database These directives are applied automatically to subsequent instances of the same query The SAVE EXTERNAL DIRECTIVES statement associates one or more optimizer directives with a query and stores a record of this association in the sysdirectives system catalog table for subsequent use with queries that match the specified query string The query string must be an exact match that includes case and white space positioning This statement establishes an association between the list of optimizer directives and the text of a query but it does not execute the specified query Only the DBA or user informix can execute SAVE EXTERNAL DIRECTIVES This associates AVOID_INDEX and FULL directives with the specified query

SAVE EXTERNAL DIRECTIVES

+ AVOID_INDEX (table1 index1) + FULL(table1)

ACTIVE FOR

SELECT col1 col2 FROM table1 table2

IBM Software Group IBM Information Management

Version 16 36

WHERE table1col1 = table2col1

These directives are applied automatically to subsequent instances of the same query You must include one of the ACTIVE INACTIVE or TEST ONLY keyword options to enable disable or restrict the scope of external directives When external directives are enabled and the sysdirectives system catalog table is not empty the database server compares every query with the query text of every ACTIVE external directive and for queries executed by the DBA or user informix with every TEST ONLY external directive External directives are ignored if the EXT_DIRECTIVES parameter is set to 0 in the ONCONFIG file In addition the client system can disable this feature for its current session by setting the IFX_EXTDIRECTIVES environment variable to 0 If an external directive has been applied to a query output from the SET EXPLAIN statement indicates ldquoEXTERNAL DIRECTIVES IN EFFECTrdquo for that query Any inline directive is ignored by the optimizer when the external directives are applied to a query that matches the SELECT statement Like inline optimizer directives that are embedded within a query external directives can improve performance in some queries for which the default behavior of the query optimizer is not satisfactory Unlike inline directives external directives can be applied without revising or recompiling existing applications

Inserts

Informix does not support Oraclersquos INSERT with SELECT statement utilizing an UNION clause (although a view with an UNION clause can be referenced resulting in an UNION operation) Additionally Informix does not support an INSERT statement with a VALUE clause with SELECT statements The SELECT statement within a VALUE clause can be rewritten by omitting the VALUE clause and performing an INSERT INTO table_name SELECT hellip FROM other_table_name

Temporary tables

Informix and Oracle implemented the concept of temporary tables differently Oracle implements temporary tables as a work area during batch data loads Informix implements temporary tables just like regular database tables These temporary tables can be created manipulated and dropped only within a session such as stored procedures and ESQL programs Once the session ends any remaining temporary tables are automatically dropped Temporary tables can give an application extra functionality however their use should be limited if reducing database extensions to increase database independence within an application is a priority

Outer joins

Both Oracle (starting with Oracle 9i) and Informix support ANSI standard syntax for outer join specification The syntax for left and right outer join using the plus sign (+) in the WHERE clause is only supported for backward compatibility however it is still in existence The use of ANSI outer join syntax is recommended The Oracle outer join syntax + (placed after the column which has values not matching the corresponding column in the joined table) can be replaced with the Informix equivalent OUTER The OUTER keyword is placed within the SELECT statement before the name of the subservient table Unlike Oracle in Informix multiple outer joins per SELECT statement are allowed grouped with parentheses

Sorts

In Oracle sorts NULL values are considered the highest value and are therefore ordered last in ascending sorts Informix sorts with NULLS as the lowest value ordering them first in ascending sorts First it must be determined whether this sorting difference will affect the outcome enough to warrant a work around In most cases it will not If it does then a stored procedure can be

IBM Software Group IBM Information Management

Version 16 37

written to evaluate whether a column is NULL and if so replace it with a high value so that it will sort last Once the application receives the results it must replace the high values with NULL if the column is going to be displayed or manipulated

Exceptions

Error handling using hard coded Oracle SQL codes must be replaced with the corresponding Informix SQL codes

Correlation names

Informix does not support correlation names with aliases on the main table of an UPDATE or DELETE statement Such cases must be converted For example

Oracle UPDATE customer C

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE Ccreate_date lt= Zeffective_date)

Informix UPDATE customer

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE customercreate_date lt= Zeffective_date)

-and-

Oracle DELETE customer C

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND Cstate = Tstate )

Informix DELETE customer

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND customerstate = Tstate )

Note that Informix allows correlation names with aliases on tables other than the updated or deleted table

Aliases

Unlike Oracle in Informix if an alias is used in the FROM clause of a SELECT statement it must also be used in the SELECT list and WHERE clauses The original table name should be replaced with the alias wherever aliases and original names are used together within a SELECT statement in an Oracle application

Hierarchical queries

Informix does not allow query results to be organized hierarchically in a B-tree fashion Oracle does allow it by using the clauses START WITHhellip and CONNECT BY PRIOR in the SQL

IBM Software Group IBM Information Management

Version 16 38

statement In Oracle if a table contains hierarchical data a bill of materials for example rows can be selected in a hierarchical order using the following clauses START WITH

The START WITH clause identifies the row(s) to be used as the root(s) of a hierarchical query This clause specifies a condition that the root(s) must satisfy If this clause is omitted Oracle uses all rows in the table as root rows A START WITH condition can contain a subquery

CONNECT BY

The CONNECT BY clause specifies the relationship between parent and child rows in a hierarchical query This clause contains a condition that defines this relationship The part of the condition containing the PRIOR operator must have one of the following forms

PRIOR expression comparison_operator expression -or- expression comparison_operator PRIOR expression

To find the children of a parent row Oracle first evaluates the PRIOR expression to identify the parent row(s) and the other expression for each row in the table Rows for which the other expression is true are the children of the parent The CONNECT BY clause can contain other conditions to further filter the rows selected by the query

WHERE

The WHERE clause can restrict the rows returned by the query without affecting other rows of the hierarchy

Oracle uses the information from each of the clauses mentioned above to form the hierarchy using the following steps

1 Oracle selects the root row(s) of the hierarchy These are the rows that satisfy the condition of the START WITH clause

2 Oracle selects the child rows of each root row Each child row must satisfy the condition of the CONNECT BY clause with respect to one of the root rows

3 Oracle selects successive generations of child rows Oracle first selects the children of the rows returned in step 2 and then the children of those children and so on Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row

4 If the query contains a WHERE clause Oracle removes all rows from the hierarchy that do not satisfy the condition of the WHERE clause Oracle evaluates the WHERE condition for each row individually after the row has been fetched rather than only fetching rows that satisfy the WHERE condition

5 Oracle returns the rows in the order of an in-order or left-root-right binary tree traversal

IBM Software Group IBM Information Management

Version 16 39

For example the following SQL statement returns the data in the adjacent table in hierarchical order The root row is defined to be the employee whose job is lsquoPRESIDENTrsquo The child rows of a parent row are defined to be those rows whose manager number is the employee number of the parent row

SELECT ename empno mgr job FROM emp START WITH job = lsquoPRESIDENTrsquo CONNECT BY PRIOR empno = mgr

To duplicate this hierarchical functionality in Informix stored procedures or functions can be written requiring intensive use of cursors and program arrays Informix offers the choice of creating and using a User Defined Routine or ldquoUDRrdquo See User Defined Routines section below Use of Informix global arrays will help considerably To maximize read processing at the expense of insert processing another method is to break the table into two tables one containing the data and the other containing the relationship (foreign keys) between each parent and child A parent row would have an entry in the relationship table for each of its children grandchildren great grandchildren and so on The opposite is true where a child row would have an entry in the relationship table for its parent grandparent great grandparent and so on

Truncate

Informix supports the TRUNCATE statement for deleting all active data rows from a table and associated indexes When using Informixrsquos TRUNCATE you also have the option of releasing the storage space that was occupied by the rows and index extents or keeping the space allocated to be used as the table is repopulated with new data

TRUNCATE [TABLE] table [ [ DROP | REUSE ] STORAGE ]

You may use the commandrsquos simplest usage

TRUNCATE my_table

In the example above the TRUNCATE statement drops all the data for the table and keeps only the initial extents There is a minor difference from Oracle syntax as Informix does not require the keyword TABLE Another example

TRUNCATE my_table REUSE STORAGE

ENAME EMPNO MGR JOB

KING 7839 PRESIDENT

JONES 7566 7839 MANAGER

SCOTT 7788 7566 ANALYST

ADAMS 7876 7788 CLERK

FORD 7902 7566 ANALYST

SMITH 7369 7902 CLERK

BLAKE 7698 7839 MANAGER

ALLEN 7499 7698 SALESMAN

WARD 7521 7698 SALESMAN

MARTIN 7654 7698 SALESMAN

TURNER 7844 7698 SALESMAN

JAMES 7900 7698 CLERK

CLARK 7782 7839 MANAGER

MILLER 7934 7782 CLERK

IBM Software Group IBM Information Management

Version 16 40

This example drops all the data for the table but retains all the space allocated The permissions needed for TRUNCATE TABLE depend on the existence of DELETE triggers on the table For tables with DELETE triggers ALTER permission on the table is required and RESOURCE or DBA privileges because the DELETE triggers will be bypassed For tables without DELETE triggers you need DELETE permission on the table and CONNECT privilege to the database While Oracle does not provide rollback Informix does permit TRUNCATE TABLE to execute within a transaction When you rollback a TRUNCATE statement no rows are removed from the table and the storage extents that hold the data rows and index pages continue to be allocated to the table In a database that supports transaction logging only the COMMIT WORK or ROLLBACK WORK statement is valid after the TRUNCATE statement within a transaction Any other statement will generate an error The TRUNCATE statement does not reset the serial value of SERIAL or SERIAL8 columns To reset the counter of a serial column you must do so explicitly by using the MODIFY clause of the ALTER TABLE statement either before or after you execute the TRUNCATE statement After the TRUNCATE statement successfully executes Informix automatically updates the statistics and distributions for the table and for its indexes in the system catalog to show no rows in the table nor in its dbspace partitions It is not necessary to run the UPDATE STATISTICS statement immediately after you commit the TRUNCATE statement

Host variables Host variable formats should not change during the porting process Instead data types should be converted in a manner to preserve the column and host variablersquos formats However there are times when the database schema changes in a way where the host variable format must change Any column converted to a different format in Informix than that of Oracle requires that its corresponding host variable format be changed to be consistent Alternatively if an Oracle format such as date and numeric variables is not directly supported in Informix then the conversion may require some format processing before or after the SQL statement For example the Oracle function TO_CHAR is used to format both date and numerical values A similar function or at least two functions one to handle date data types and another to handle numeric data types can be declared and used in the Informix application Informix provides two built-in functions TO_DATE which converts a character string to a DATETIME variable and TO_CHAR which converts a DATETIME variable to a character string When converting variables an optional formatting string is allowed which determines how the string is displayed (full day names partial day names full months month number and so on) There is also a function ifx_to_gl_datetime() which takes an Oracle date format and returns the corresponding Informix date format This function is supplied in genlib and is for use in ESQL programs to ease migration efforts from Oracle The syntax is as follows

TO_CHAR (source_date fmt) Returns a character string containing the date specified in source_date in the format specified by fmt if one is provided If fmt is missing the function will use the default date format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

TO_DATE (source_string fmt) Evaluates source_string as a date according to the

format fmt If fmt is missing the function will use the

IBM Software Group IBM Information Management

Version 16 41

default format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

These functions are mainly useful for simplifying migration from Oracle to Informix but are also useful for performing advanced searches on DATETIME data types and for better output presentation

Date and time functions Informix version now has built-in support for most of Oraclersquos date functions so it will not be necessary to modify or replace Oraclersquos SYSDATE or ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat)

SYSDATE

IDS 1110 will support the SYSDATE operator which returns a single value representing the current date and time from the operating system clock SYSDATE is identical to the Informixrsquos CURRENT operator except that the default precision of SYSDATE is YEAR TO FRACTION(5) while the default precision of CURRENT is YEAR TO FRACTION(3) On Windows platforms that do not support a seconds scale greater than FRACTION(3) SYSDATE is effectively a synonym for the CURRENT operator In addition to SYSDATE Informix version 1110 has support for Oraclersquos date functions ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat) Depending on the whether or not the Oracle date_format argument is supported by Informix TO_CHAR(date char_format) and TO_DATE(character_string date_format) may have to be converted to Informix date processing Date processing may be required because the Oracle application may format the date in many different ways unsupported by Informix The formats used in the Oracle functions TO_CHAR TO_NUMBER and TO_DATE are illustrated below These formats should be replaced with Informix formats wherever possible format processing functions or stored procedures written to duplicate the Oracle functionality Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

Number formats

Element Example Description 9 9999 Return value with the specified number of digits with a leading

space if positive Return value with the specified number of digits with a leading minus if negative Leading zeros are blank except for a zero value which returns a zero for the integer part of the fixed-point number

0 09999990 Return leading zeros Return trailing zeros $ $9999 Return value with a leading dollar sign B B9999 Return blanks for the integer part of a fixed-point number

when the integer part is zero (suppress leading zeros regardless of whether zeros are used in the format model ie B00999 )

MI 9999MI Return negative value with a trailing minus sign ldquo-ldquo Return positive value with a trailing blank

S S9999999 Return negative value with a leading minus sign ldquo-ldquo Return

IBM Software Group IBM Information Management

Version 16 42

Element Example Description S positive value with a leading plus sign ldquo+rdquo Return negative

value with a trailing minus sign ldquo-ldquo Return positive value with a trailing plus sign ldquo+rdquo

PR 9999PR Return negative value in ltangle bracketsgt Return positive value with a leading and trailing blank

D 99D99 Return a decimal point ldquordquo In the specified position G 9G999 Return a group separator in the specified position C C999 Return the ISO currency symbol in the specified position L L999 Return the local currency symbol in the specified position 9999 Return a comma in the specified position 9999 Return a decimal point ldquordquo In the specified position V 999V99 Return a value multiplied by 10

n (and if necessary round it

up) where n is the number of ldquo9rdquos after the ldquoVrdquo EEEE 99EEEE Return a value in scientific notation RNrn RN Return a value as Roman numerals in uppercase Return a

value as Roman numerals in lowercase Value can be an integer between 1 and 3999

FM FM909 Return a value with no leading or trailing blanks

Date formats

Element Meaning -rdquotextrdquo Punctuation and quoted text is reproduced in the result AD or AD AD indicator with or without periods AM or AM Meridian indicator with or without periods BC or BC BC indicator with or without periods CC or SCC Century ldquoSrdquo prefixes BC dates with ldquo-ldquo D Day of week (1-7) DAY Name of day padded with blanks to length of 9 characters DD Day of month (1-31) DDD Day of year (1-366) DY Abbreviated name of day IW Week of year (1-52 or 1-53) based on the ISO standard IYY or IY or I Last 3 2 or 1 digit(s) of ISO year IYYY 4-digit year based on the ISO standard HH or HH12 Hour of day (1-12) HH24 Hour of day (0-23) J Julian day the number of days since January 1 4712 BC Number

specified with lsquoJrsquo must be integers MI Minute (0-59) MM Month (01-12 JAN = 01) MONTH Name of month padded with blanks to length of 9 characters MON Abbreviated name of month RM Roman numeral month (I-XII JAN = I) Q Quarter of year (1 2 3 4 JAN-MAR = 1) RR Last 2 digits of year see below for years in other centuries WW Week of year (1-53) where week 1 starts on the first day of the year

and continues to the seventh day of the year W Week of month (1-5) where week 1 starts on the first day of the

month and ends on the seventh PM or PM Meridian indicator with and without periods SS Second (0-59) SSSSS Seconds past midnight (0-86399) YYYY Year with comma in the ldquordquo position YEAR or SYEAR Year spelled out ldquoSrdquo prefixes BC dates with ldquo-ldquo YYYY or SYYYY 4-digit year ldquoSrdquo prefixes BC dates with ldquo-ldquo

IBM Software Group IBM Information Management

Version 16 43

YYY or YY or Y Last 3 2 or 1 digit(s) of year

The RR date format element

The RR date format element is similar to the YY date format element but it provides additional flexibility for storing date values in other centuries The RR date format element allows storing the century even though only two digits are entered for the year The table below illustrates how the year is stored based on only two digits

If the year is entered as

0 ndash 49 50 - 99 If the last two digits of the

0 - 49 The return date is in the current century

The return date is in the century before the current one

current year are

50 - 99 The return date is in the century after the current one

The return date is in the current century

User-defined routines User-defined data types user defined behaviors and user defined access methods add rich functionality to Informix A user-defined routine (UDR) can be developed in C Java or Informix SPL language to vastly extend the capabilities of the database Porting applications to Informix gives the option to create UDRs for aggregate and mathematical functions or to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or you can rename an Informix function to the corresponding Oracle function name

Compatible SQL Functions Informix Dynamic Server version 1110 has added support for a number of built-in SQL functions to ease a migration effort These new functions which perform common operations and data manipulation provide compatibility with Oracle routines thus simplifying the migration of applications that have been developed for an Oracle database

Date and time functions ROUND TRUNC ADD_MONTHS LAST_DAY NEXT_DAY MONTHS_BETWEEN SYSDATE

Conversion functions ASCII TO_CHAR TO_NUMBER

String manipulation LTRIM RTRIM

Number manipulation ROUND TRUNC CEIL FLOOR POWER

Bit manipulation BITAND BITOR BITXOR BITNOT BITANDNOT

Others NULLIF FORMAT_UNITS These functions are documented with examples in the IBM Informix Guide to SQL Syntax

Aggregate functions Like Oracle the result returned by an Informix aggregate function is NULL if all of the column values are NULL with the exception of COUNT which returns 0 (zero) Like Oracle Informix aggregate functions cannot be used in a WHERE clause unless it is on a corresponding column originating from a parent query and the WHERE clause is within a sub-query that is within a HAVING clause or the aggregate function is contained within a sub-query Unlike Oracle in Informix the argument of an aggregate function cannot be another aggregate function Informix supports the SELECT COUNT (column_name) hellip statement where the number of rows containing non-null values in the specified column is returned

IBM Software Group IBM Information Management

Version 16 44

The Oracle aggregate functions STDDEV and VARIANCE are supported however the Informix standard deviation routine is named STDEV thus all references to Oraclersquos STDDEV must be changed to match Informixrsquos STDEV Informix does not support Oraclersquos greatest lower boundary (GLB ) or least upper boundary (LUB) Therefore UDRs must be written to provide equivalent functionality Informix allows users to define their own aggregate functions known as user-defined aggregates (UDA) This extension of existing aggregates can be used for new data types as well as the definition of new aggregates In Informix TEXT and BYTE columns cannot be used in aggregate functions such as COUNT AVG MAX MIN and SUM

Mathematical functions Informix does not support all of Oraclersquos mathematical functions such as SIGN COSH SINH and TANH Therefore functions or UDRs must be written in the Informix application to provide equivalent functionality In Informix the rounding factor within the ROUND function must be a value from -32 to 32 This limitation has seldom been encountered as a migration issue

String functions

LENGTH

Oraclersquos LENGTH function will return different values than Informix for strings stored in CHAR data types The numeric return value representing the string length returned by Oracle will include all trailing spaces Whereas Informixrsquos LENGTH function will ignore trailing blanks regardless of data type For example for the two CHAR strings ldquoBOBrdquo and ldquoBOB ldquo Oraclersquos LENGTH function will return different values for each string 3 and 5 respectively Whereas Informixrsquos LENGTH function will ignore trailing blanks and return the value 3 for both When the input string is NULL both database functions will return a NULL

LTRIM and RTRIM

The SQL Compatibility features of Informx has support for LTRIM and RTRIM and will return identical values to that of Oracle No modifications will be necessary to SQL statements utilizing these functions

Oracle Extensions

Informix does not support all of Oraclersquos string functions such as CHR INSTR SOUNDEX and TRANSLATE Therefore corresponding user-defined routines or UDRs (ie functions or stored procedures) must be written in the Informix application to provide equivalent functionality Please note that the VERITY and EXCALIBUR Datablades included with Informix will work with Oraclersquos string function SOUNDEX

Other Oracle Functions Informix does not support the following Oracle functions Therefore corresponding functions must be written in the Informix application to provide equivalent functionality Alternatives to some of the more common Oracle functions follow this list

CHARTOROWID CONVERT DUMP GREATEST GREATEST_LB

IBM Software Group IBM Information Management

Version 16 45

HEXTORAW LEAST LEAST_UB RAWTOHEX ROWIDTOCHAR TO_LABEL TO_MULTI_BYTE TO_SINGLE_BYTE UID USERENV(OSDBA LABEL LANGUAGE TERMINAL SESSIONID ENTRYID) VSIZE

Macros Oracle contains macros sometimes referred to as language constructs which can determine the status of an object Informix does not support Oraclersquos macros These macros must be removed from the code and the associated logic should be implemented with equivalent Informix logic where applicable

ISOPEN and NOT FOUND

The macro cursor_nameISOPEN returns a Boolean value to indicate whether the cursor is open and cursor_nameNOTFOUND indicates whether there are any more rows yet to be fetched from the cursor cursor_name These macros used in condition statements are followed by some logic to handle the true andor false conditions In the case of ISOPEN this macro and its associated logic can just be omitted since the FOREACH loop processing does not explicitly open a cursor and therefore the condition cannot be checked In the case of NOTFOUND this macro should be omitted and its associated logic converted to Informix logic within an Informix FOREACH loop

ROWTYPE

The Oracle macro prefixROWTYPE is used in the declarative section as a data type to declare variables similar to the structure construct of C or RECORD of INFORMIX The prefix can be either a table name or another structure name Structure names ultimately refer back to a table name This macro may be replaced with the Informix statement LIKE table_name The construct LIKE table_name cannot be used in SPL Instead the construct DEFINE column1 LIKE table_namecolumn1 DEFINE column2 LIKE table_namecolumn2 and so on should be used to declare variables corresponding to all the columns of the table Then operations on the whole or part of the structure should be replaced with operations on single SPL variables

TYPE

The Oracle macro prefixTYPE is used in the declarative section as a data type to declare single variables The prefix is either a table_namecolumn_name or a structure_namevariable_name A structure_namevariable_name ultimately refers back to a table_namecolumn_name This macro can be replaced with the Informix statement LIKE table_namecolumn_name

Pseudo-columns Pseudo-columns are columns that exist in tables but are not displayed from a SELECT FROM table_name query Informix pseudo-columns are generally reserved for the enginersquos use Eliminating the use of such columns increases an applicationrsquos portability and eliminates the need for future modifications if the engine is ever modified to process the column differently or not at all

IBM Software Group IBM Information Management

Version 16 46

LEVEL

In Oracle for each row returned by a hierarchical query the pseudo-column LEVEL returns 1 for a root node 2 for a child of a root 3 for a child whose parent is at level 2 and so on A root node is the highest node within an inverted tree and therefore has no parent A child node is any non-root node A parent node is any node that has children A leaf node is any node without children To define a hierarchical relationship in a query you must use the START WITH and CONNECT BY clauses Informix does not support the LEVEL clause See the Hierarchical Queries subsection in the SQL section in the ldquoData Manipulation Languagerdquo chapter for more information on how to process these queries

ROWID

Oraclersquos ROWID pseudo-column returns the rows address for each row in the database ROWID values contain the following information necessary to locate a row

Which data block in the data file

Which row in the data block (first row is 0)

Which data file (first file is 1)

Usually a ROWID value uniquely identifies a row in the database However rows in different tables that are stored together in the same cluster can have the same ROWID Values of the ROWID pseudo-column have the data type ROWID ROWID values have several important uses

They are the fastest way to access a single row

They can show you how a tables rows are stored

They are unique identifiers for rows in a table

A ROWID does not change during the lifetime of its row However you should not use ROWID as a tables primary key If a row is deleted and re-inserted its ROWID may change even when using the export and import utilities If a row is deleted Oracle may re-assign its ROWID to a new row inserted later Although you can use the ROWID pseudo-column in the SELECT and WHERE clauses of a query these pseudo-column values are not actually stored in the database The value of a ROWID pseudo-column cannot be inserted updated or deleted For example the following Oracle statement selects the address of all rows that contain data for employees in department 20

SELECT ROWID ename FROM emp WHERE deptno = 20

The equivalent pseudo-column in Informix is also known as ROWID and although the behavior is similar the data type is different from Oraclersquos See the ROWID subsection in the Data Types section in the chapter ldquoData definition languagerdquo for more information

ROWNUM

In Oracle for each row returned by a query the ROWNUM pseudo-column returns a number indicating the order in which Oracle selected the row from a table or set of joined rows The first row selected has a ROWNUM of 1 the second has 2 and so on ROWNUM can be used to limit the number of rows returned by a query as in this example to read 9 rows

SELECT

FROM emp

WHERE ROWNUM lt 10

ROWID ENAME 0000000F00000002 SMITH 0000000F00030002 JONES 0000000F00070002 SCOTT 0000000F000A0002 ADAMS 0000000F000C0002 FORD

IBM Software Group IBM Information Management

Version 16 47

You can also use ROWNUM to assign unique values to each row of a table as in this example

UPDATE tabx

SET col1 = ROWNUM

Oracle assigns a ROWNUM value to each row as it is retrieved before the rows are sorted by an ORDER BY clause Therefore the final order of the rows is in ORDER BY order not in ROWNUM order An ORDER BY clause does not affect the ROWNUM values except in the case where the ORDER BY clause causes Oracle to use an index In that case the ROWNUM values are set in the order the rows are retrieved using the index and hence in ORDER BY order This order is different than if the rows were retrieved without the index So in this case the ORDER BY can affect the ROWNUM values Conditions which test for ROWNUM values greater than zero are always false For example this query returns no rows

SELECT FROM employee WHERE ROWNUM gt 1

The first row fetched is assigned a ROWNUM of 1 thus making the condition false The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 making the condition false All rows subsequently fail to satisfy the condition so no rows are returned Although there is no ROWNUM equivalent in Informix there are solutions Beginning with IDS 73 and in Informix Dynamic Server 2000 Informix provides a feature which allows the user to limit the results of a query to the first N rows This was implemented for TPC-D compliance and to support ldquorankrdquo queries Rank queries can be assembled by using FIRST N with the ORDER BY clause Informix will return the top N rows according to some ordering criteria Therefore the following Oracle SELECT utilizing ROWNUM

SELECT FROM emp WHERE ROWNUM lt 10

can be ported to Informix as follows

SELECT FIRST 9 FROM emp

Informix does not support SELECT FIRST N in complex cases as the following

Sub-queries (SELECT within a SELECT)

View definitions (Cannot be used by a SELECT statement which references a view)

UNION queries The behavior of SELECT FIRST N depends on the presence of an ORDER BY clause If no order by clause is specified the first N rows returned may be in any order Examples are as follows

find 10 highest paid employees

SELECT FIRST 10 name salary

FROM emp

ORDER BY salary

find 10 highest salary values

SELECT FIRST 10 DISTINCT salary

FROM emp

ORDER BY salary

IBM Software Group IBM Information Management

Version 16 48

Informix supports column names of ldquofirstrdquo Thus without a positive integer following the word ldquofirstrdquo the token is parsed as a column name rather than a keyword The value of N may be between 1 and (2

31-1)

When ROWNUM is used in a WHERE clause the same results can be obtained through the use of the FIRST N and SKIP clauses but if ROWNUM is used in the select list the solution is a little more complicated Simply stated you can construct a query where the ROWNUM column in any row is the count of the rows that came before This involves creating a correlated subquery where the subquery contains a self-join This can be done for any table or set of tables which has a unique key defined on it Here is an example using the customer table of the stores7 database

select

counterrownum

basecustomer_num

basefname

baselname

from

-- There can be more than one table here and the result

-- set should thought of as a table (just not a base table)

-- The result table has to be joined to itself in the

-- subquery so if there are multiple tables in this FROM

-- clause the expansion can get messy You have to have a

-- set of columns that uniquely identify each row in the

-- result table and join across them ROWID would

-- likely work if the table is not fragmented but if it is

-- there is no guarantee the final results would be accurate

-- because ROWID is not guaranteed to be unique across

-- fragments

customer base

(select

count() as rownum

acustomer_num -- any unique key possibly multiple

-- columns

from

customer a

customer b

where

-- This is where the rownum is determined the relationship

-- here has to match the outer order-by where the rows

-- are sorted and has to create a unique sort order

--

-- Any columns to be ordered by go here

-- Also the unique key has to be used to keep rows

-- that do not have a unique sort order from being merged

(alname gt blname) -- example sorting by last name

or

(alname = blname and afname gt bfname)

-- sorting by fname where lname is equal

or

(alname = blname and afname = bfname

and acustomer_num gt= bcustomer_num)

-- sorting by unique key where all the

-- other sort columns are equal

-- The expansion above is logically the same as

-- alname || afname || to_char(acustomer_num) gt=

-- blname || bfname || to_char(bcustomer_num)

-- but it allows the server to utilize any indexes that

-- may exist

group by

-- unique key columns go here

IBM Software Group IBM Information Management

Version 16 49

acustomer_num

) counter

where

-- key columns in the base tables go here

basecustomer_num = countercustomer_num

-- if you want to limit on rownum it goes here

-- and rownum lt= 10

order by

counterrownum

If using ROWNUM as an assignment as in

UPDATE tabx

SET col1 = ROWNUM

The following Informix-ESQLC pseudo-code example would have to be used

int counter = 0

EXEC SQL declare c1 cursor for

SELECT col1 col2

INTO col1 col2

FROM table 1

WHERE col1 = XX

EXEC SQL open c1

while (SQLCODE == 0)

EXEC SQL fetch c1

counter++ Increment counter for each row

fetched

if (counter gt= 5)

break

logic

End if

End while

Update using cursors There are slight differences between the ways Informix and Oracle process cursors Unlike Oracle in Informix the WHERE CURRENT OF clause cannot be used to update tables in a SELECT statement joining multiple tables since the WHERE CURRENT OF clause requires a FOR UPDATE cursor and Informix does not support the FOR UPDATE clause in SELECT statements that join multiple tables Therefore in the multi-table join statements the Oracle options FOR UPDATE and WHERE CURRENT OF should be removed and the update of the rows should be done using a separate UPDATE statement in the same cursor loop

IBM Software Group IBM Information Management

Version 16 50

In Informix a commit or rollback statement closes all cursors open in a given transaction boundary See the Transaction Processing section in CHAPTER 5 Application Architecture for more information In situations where the intention is to commit or rollback without closing the cursor in other words where the commit or rollback is executed within a cursor fetch loop the cursor can be declared as a HOLD cursor This requires that a BEGIN WORK is issued before the cursor loop starts A HOLD cursor is not closed when a commit or rollback statement is issued In Informix the FOR UPDATE clause cannot be used when declaring a HOLD cursor Thus where an Oracle application updates a table from which it fetches data in the fetch loop or issues a commit work in the fetch loop it must be converted to Informix The cursor can be declared with HOLD and then an UPDATE statement can be issued without the WHERE CURRENT OF clause In order to uniquely identify the row to be updated in the table in other words in order to simulate the WHERE CURRENT OF clause the ROWID or unique primary key columns of the table(s) to be updated must also be fetched and the WHERE CURRENT OF clause can be replaced with WHERE ROWID = fetched rowid or WHERE unique primary key column(s) = fetched unique primary key column(s) A BEGIN WORK must follow immediately after a COMMIT WORK or ROLLBACK WORK in the fetch loops to simulate Oracle implied transaction boundaries These transaction control statements work for either Informix logged databases or Informix ANSI mode databases however ANSI mode database processing with these statements will set certain warning flags after executing the BEGIN WORK statement and continue processing without failure See the ANSI vs Non-ANSI subsection in the Databases section in the chapter ldquoData Manipulation Languagerdquo for more information

System tables References to Oracle system tables should be replaced with corresponding references to Informix system tables The information schema views provided by Informix can be used These views are created after the database is installed They are populated by data in the system catalog tables and are used for easier porting

Stored procedures Informix procedures and functions are considered to be user-defined routines (UDR) A UDR can be written in Informixrsquos Stored Procedure Language (SPL) or an external language such as C or Java A procedure is a routine written that does not return a value A function is a routine written that returns a single value a value with a complex data type or multiple values Informix SPL is an extension to Informix SQL and provides procedural flow control such as looping and branching A SPL routine is a generic term that includes both SPL procedures and SPL

functions You use SQL and SPL statements to write an SPL routine SPL statements can be used only inside the CREATE PROCEDURE CREATE PROCEDURE FROM CREATE FUNCTION and CREATE FUNCTION FROM statements SPL routines are parsed optimized and stored in the system catalog tables in executable format Like Oracle Informix stored procedures support input output and inputoutput parameters and can be used in SQL statements wherever expressions are allowed

Size limit

Informix stored procedures have a size limit of approximately 64K Oracle stored procedures greater than 64K in size can be broken into smaller Informix stored procedures communicating with each other as though they were one by passing and returning the necessary values

Parameter limit

IBM Software Group IBM Information Management

Version 16 51

Informix has a limit of 341 parameters for each stored procedure This limit also applies to UDRs written in the Java language UDRs written in the C language can have no more than 102 parameters You can define any number of SPL routine parameters but the total length of all parameters passed to an SPL routine must be less than 64 kilobytes No more than nine arguments to a UDR written in the Java language can be DECIMAL data types of SQL that the UDR declares as BigDecimal data types of the Java language Any C language UDR that returns an opaque data type must specify opaque_type in the var binary declaration of the C host variable

Packages

An Oracle package is a collection of functions procedures and variables that can be enabled and accessed as a unit There is no direct equivalent within Informix but there are ways of achieving similar capabilities Within Oracle a procedure within a package can be accessed through grammar such as package_nameprocedure_name If you create an owner or schema name within the Informix system the same as the package name then it will be easier to migrate calls to that procedure because the grammar is effectively the same although the meaning changes somewhat Using this practice a call to a migrated procedure would be ownerprocedure_name where the owner name is the same as the package name Translating package names as owner names is a way to maintain the scoping of the objects within the package Maintaining the aspect of being able to enable use of or upgrade the collection of package objects can be done by creating a datablade that contains all the objects that used to be part of the package Datablade routines can be procedures or functions written in Stored Procedure Language (SPL) C and Java In addition routines can be written in C++ on Windows platforms

Routines

Oraclersquos stored functions and stored procedures are similar in concept to Informixrsquos stored procedures Oraclersquos user defined database level functions such as stored functions stored procedures all need to be converted to Informix stored procedures using the Informix SPL C or Java Routines written in SPL have the advantage of being maintained and backed up with database backups Routines written in C are fast but are not automatically backed up when the database is and need to be compiled specifically for the operating system on which it will run Routines written in Java also not backed up by the DBMS itself but they are platform independent However probably as a result of having to convert between system memory where the objects have C structures and Java virtual machine memory where the objects have Java structures the performance of Java routines can be slow compared with the C equivalent All procedures written in an Oracle package body must be rewritten as separate Informix procedures When rewriting package bodies into separate procedures Oraclersquos variable declarations can be replaced at the package level (global) with Informixrsquos global variables The Informix global variables must be defined in the first stored procedure of the logical group

Exceptions

The method of handling exceptions is different between Informix and Oracle Oracle has many predefined and user defined exception labels such as CURSOR_ALREADY_OPEN NO_DATA_FOUND ZERO_DIVIDE and so on The labels can be used in the logic to identify errors Only one exception check is allowed per BEGIN and END block using the EXCEPTION construct and it is normally placed just before the END statement Informix also supports predefined and user defined exceptions however they are represented numerically not with labels In Informix all the exceptions checked in the stored procedure control blocks delimited with BEGIN and END statements must be declared explicitly at the top of each

IBM Software Group IBM Information Management

Version 16 52

control block with the Informix EXCEPTION construct Therefore Oracle procedure code must be restructured to manipulate these exceptions In Oracle an exception can be raised globally and acted upon globally In Informix the scope of an exception mechanism is always restricted to the block in which it is located This leads to the addition of multiple Informix exception handling mechanisms for each Oracle exception raised as well as a redesign of the overall stored procedure to a more blocked format

Error handling

In Oracle errors are processed as part of a function call return value In Informix errors are retrieved as a separate function call that has multiple structures that have to be created in order to retrieve error and status The SQLCA structure is not fully available in Informix stored procedures It is not possible to check the SQLCODE variable in the stored procedure body Instead the function DBINFO can be used to extract the value of two members of the SQLCA structure sqlcasqlerrd1 and sqlcasqlerrd2 This function should be used inside the FOREACH construct while the cursor is open Once the cursor is closed the DBINFO function cannot return proper values The sqlcasqlerrd1 option returns different values depending on the type of SQL statement For INSERT statements if the table contains a serial column then the sqlcasqlerrd1 option will return the serial value of the last row inserted into the table For SELECT DELETE and UPDATE statements the sqlcasqlerrd1 option will return the number of rows processed by the query In these cases upon each pass through the FOREACH loop sqlcasqlerrd1 is the same value the number of rows the FOREACH loop will process The sqlcasqlerrd1 value can still be interrogated during each pass through the FOREACH loop The sqlcasqlerrd2 option returns the number of rows processed by a SELECT INSERT UPDATE DELETE or EXECUTE PROCEDURE statement It should not be interrogated until after the cursor has finished processing In other words within the FOREACH loop the sqlcasqlerrd2 value can be moved to a variable which is then interrogated outside of the FOREACH loop

Cursors

Unlike Informix in Oracle cursors can be global to a package In Informix Oraclersquos global cursors can be replaced with temporary tables A temporary table can be created and populated in place of where the cursor is opened The temporary table can then be processed the same way the cursor is processed Finally the temporary table should be dropped in place of where the cursor is closed Cursors are explicitly declared opened and fetched in Oracle stored procedures In Informix cursors do not need to be explicitly declared opened and fetched in stored procedures Instead Oracle stored procedure cursors can be replaced with Informixrsquos FOREACH construct The Oracle cursor name should be used in the FOREACH statement for example FOREACH cursor_name SELECT hellip END FOREACH In order to update a cursor row in Oracle the cursor must be declared with the FOR UPDATE clause In Informix if the SELECT statement in the FOREACH construct is not a multi-table join then each fetched row can be updated using the UPDATE lttable_namegt WHERE CURRENT OF ltcursor_namegt statement See the Update Using Cursors section in ldquoData Manipulation Languagerdquo for more information Informix does not support the SELECT FOR UPDATE statement in a stored procedure Therefore the SELECT FOR UPDATE clause cannot be used in the FOREACH construct

IBM Software Group IBM Information Management

Version 16 53

Variable declaration and assignment

Oracle allows implicit variable definitions within a FOR loop The variables are defined using an assignment operator and a column name For example

out_customer_name = customername

The variable out_customer_name is defined as the same type as the column name in the customer table Informix requires that all variables be defined at the beginning of each stored procedure control block For example

DEFINE out_customer_name LIKE customername

DEFINE counter INTEGER

Therefore Oraclersquos implicit variable declaration must be replaced with Informixrsquos explicit variable declaration before the control block Additionally assignment operations will need to be ported Oracle uses a colon and an equal sign (=) for assignment while Informix utilizes the LET keyword in combination with an equal sign (=) (ie LET var = 1) Therefore assignment statements must be modified with the LET keyword and an equal sign

Boolean

Oraclersquos BOOLEAN variable type can be replaced with Informixrsquos BOOLEAN data type

Binary data types

Binary data types are very different between Oracle and Informix In Oracle the binary type is defined as a type RAW and is explicitly defined with a maximum length as part of the declaration In Informix the binary type is defined as REFERENCES BYTE which deals only with pointers to BLOBs It implicitly defines a maximum length as part of the function call in which the pointer to the BLOB and maximum length (as used in the function call) was passed as values As a result the binary type cannot be assigned a binary value in a stored procedure nor can it be inserted into a table via the SQL INSERT statement in a stored procedure These operations that initialize a binary type must be performed outside of stored procedures

Dynamic SQL

Unlike Oracle Informix does not support dynamic SQL within the Stored Procedure Language In other words a statement such as SELECT variable_name FROM variable_name WHERE variable_name is not supported This kind of processing can be achieved in Informix within an embedded SQL program This requires that either the Oracle stored procedure be converted to an embedded SQL program or just the Dynamic SQL portion be placed in an embedded SQL program and then called from within the stored procedure The latter option will have performance implications since calling an embedded SQL program from a stored procedure requires an operating system call Another option is to use the Informix EXEC Bladelet The EXEC Bladelet consists of user-defined functions that take a SQL query as an argument execute it and return a result (the format of which varies depending on the function and the kind of query) The EXEC Bladelet functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries Further details can be found in Chapter 7 Using Bladelets

Compiler

Unlike Oracle the Informix compiler was developed with the concept that developers can create stored procedures independently of the database Therefore Informixrsquos stored procedure

IBM Software Group IBM Information Management

Version 16 54

compiler has a limited set of errors that it checks compared to Oraclersquos For example the Informix stored procedure compiler does not validate database object names such as table column and view names Therefore database object naming errors will occur at runtime not compile time Additionally the error messages generated from the compiler are not very specific Identifying a problem in a stored procedure may require breaking it apart and recompiling the pieces until the problem is found This may impact the time necessary to unit test the stored procedures

Triggers Oracle supports the use of multiple trigger events for example insert update and delete within the same trigger Informix only supports one trigger event per trigger In Informix the Oracle trigger body in this example must be copied into three different triggers each with only one event Informix triggers have some constraints Oraclersquos do not In Informix if a trigger is fired due to inserting a row into a table a trigger can only act on any rows or columns within that table using the EXECUTE PROCEDURE hellip INTO syntax Similarly if a trigger is fired due to updating a row then the trigger can only act on the column that caused the trigger to fire using the EXECUTE PROCEDURE hellip INTO syntax Like Oracle if a trigger is fired due to deleting a row there are no restrictions Prior to IDS 73 when a trigger was fired on an INSERTUPDATE action no modification could be done to the columns (in the row) which just fired the trigger The reentrant UPDATEINSERT triggers feature introduced with IDS 1110 enables users to update the triggering columns by using the EXECUTE PROCEDURE INTO syntax Additionally the feature enforce that this action will not cause any additional triggers to be fired (same or different trigger) causing a cascading of triggers and potentially an infinite loop The following example demonstrates how the reentrant UPDATEINSERT trigger feature is used

create table foo

(

x int default NULL

y int default NULL

z int default NULL

)

create procedure reentrant()

returning int

return 56

end procedure

create trigger reentrant_trigger insert on foo for each row

(

execute procedure reentrant() into z

)

insert into foo values

(

1

2

3

)

The following SELECT will result in the following returned data

select from foo

x y z

1 2 56

IBM Software Group IBM Information Management

Version 16 55

Oracle allows SQL statements logical statements and stored procedure calls within a trigger body Informix allows only SQL statements and stored procedure calls within a trigger body Oracle triggers containing logical statements must be converted to Informix by moving their contents into a stored procedure The stored procedure should then be executed from the trigger

Constraints Constraints in both Oracle and Informix can be enabled and disabled within an application transaction however there are behavioral differences In Oracle the application is always executing within a transaction In Informix transaction boundaries are explicitly declared and care should be taken to ensure that this functionality is performed within the boundaries of a transaction See the Transaction Processing section in CHAPTER 5 Application Architecture for more information The constraint syntax available in Informix is

SET CONSTRAINTSINDEXESTRIGGERS FOR table_name

ENABLED|DISABLED

SET CONSTRAINTS comma_separated_constraint_names

ENABLED|DISABLED

SET INDEXES comma_separated_index_names ENABLED|DISABLED

SET TRIGGERS comma_triggers_constraint_names ENABLED|DISABLED

SET CONSTRAINTS ALLconstraint_name IMMEDIATE|DEFERRED

The first four statements must be executed with DBA privileges if placed in the application Therefore care should be taken when using them Note that the last statement contains a DEFERRED clause This is the statement used if the users of the application do not have DBA privileges When the constraint is set with the DEFERRED clause the specified constraints are not checked until the transaction is committed If a constraint violation occurs while the transaction is being committed the transaction is rolled back

DUAL table Oraclersquos DUAL table is a system table with only one row containing one column named DUMMY This table is used to complete the syntax of an SQL statement that does not involve an existing table such as

A SELECT statement which assigns some constant value (which can only be derived in an SQL statement) to a host variable

SELECT TO_CHAR(SYSDATE) INTO date_var FROM DUAL

A SELECT statement which assigns a value of another variable to a variable

SELECT source_var INTO dest_var FROM DUAL

A SELECT statement which unions application host variable values with another SELECT statement to return a result containing a row of application variable values

SELECT col1 col2 col3 FROM table_name

UNION

SELECT host_var1 host_var2 host_var3 FROM DUAL

Converting Oraclersquos DUAL table functionality to Informix depends on the way it is used Converting statements that just assign constants is as simple as replacing the DUAL statement with an Informix assignment statement The solutions below apply to Informix versions prior to 11 At 11 and above the concept of a DUAL table as well as sysdate is supported

IBM Software Group IBM Information Management

Version 16 56

SELECT sysdate FROM sysmastersysdual

If you want a dual table in your local database then create the following synonym The sysmastersysdual table is much faster than a physical table in your database because it is an in- memory pseudo table

CREATE SYNONYM dual FOR sysmastersysdual

If you are restricted to using a version of Informix prior to 11 then the following solutions can be used A dummy table can be created to mimic the behavior of simple SELECT INTO statements used to assign values to variables

CREATE TABLE dual (dummy VARCHAR(1))

INSERT INTO dual VALUES(lsquoXrsquo)

An alternate solution to widespread use of the DUAL table could be creating a permanent view that is generally accessible

CREATE VIEW dual (d) as SELECT X

FROM systables WHERE tabid = 1

The exact definition could be used or modified as needed but this would solve the problem of having DUAL be permanent usable by anyone and not modifiable

IBM Software Group IBM Information Management

Version 16 57

C H A P T E R 5 Embedded SQL

Oraclersquos embedded SQL products are ProC and ProCOBOL Informixrsquos corresponding embedded SQL products are ESQLC and ESQLCOBOL

Host variables

Declaration override

The Oracle EXEC SQL VAR declarative statement (host variable equivalency of Oracle external data types by overriding the default assignment) can be converted to an Informix explicit declaration statement For example

Oracle char char_var[20]

EXEC SQL VAR char_var IS STRING(11)

Informix

char char_var[11]

Note that the size and type used in the EXEC SQL VAR section is the final information required to declare the host variable in Informix

Arrays

Oracle arrays are not subscripted in SQL statements since it is not required to process the host arrays in a loop in the SQL statement In Informix subscripting is mandatory In Oracle if an array is defined of size 200 then an SQL statement would be

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A

VAR-B

VAR-C

END-EXEC

-or- EXEC SQL SELECT COL1 COL2 COL3

INTO VAR-A

VAR-B

VAR-C

FROM TABLE1

WHERE COL2 gt 100

END-EXEC

where VAR-A VAR-B and VAR-C are each an array of say 200

IBM Software Group IBM Information Management

Version 16 58

In Informix the first example would be converted to

PERFORM VARYING LOOP-CTR FROM 1 BY 1 UNTIL

LOOP-CTR IS GREATER THAN 200

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A(LOOP-CTR)

VAR-B(LOOP-CTR)

VAR-C(LOOP-CTR)

END-EXEC

IF SQLCODE = 100

GO TO EXIT-PERFORM

END-IF

END-PERFORM

EXIT-PERFORM

For the second Oracle example given above a cursor must be declared in Informix opened and fetched for 200 rows or less (less because there may be less than 200 qualifying rows) into the host array and then should be closed If the number of qualifying rows is more than 200 then the extra rows must be ignored to duplicate the Oracle functionality But for the first example each fetch in Oracle will return the next 200 or less number of rows Therefore each Oracle fetch needs to be replaced by another call to the Informix fetch loop Oracle also uses this method for inserts deletes and updates These array techniques are mainly used in batch SQL processing

Formatting

In Informix when a DECIMAL MONEY DATE or DATETIME value is selected into a host variable of the same data type the value must be formatted using the available Informix formatting routines before they can be printed or displayed For example

hellip

dec_t dec_host_var

char formatted_dec[40]

EXEC SQL SELECT DEC_COLUMN INTO dec_host_var FROM TABLE_NAME

rfmtdec(ampdec_host_var ldquoampampampampampampampampampamprdquo formatted_dec)

printf(ldquoThe Decimal Value is snrdquo formatted_dec)

hellip

IBM Software Group IBM Information Management

Version 16 59

Informix supplies many formatting functions and formatting strings The names of these functions are different in Informix ESQLC and ESQLCOBOL but the functionality is the same Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

SQL structures

SQLCA

Oraclersquos SQLCA structure is different from that of Informix However the components of both structures are logically the same Oraclersquos SQLCA components can be replaced with the corresponding Informix components Oraclersquos SQLCA structure

SQLCAID string containing ldquoSQLCArdquo SQLCABC length of SQLCA data structure SQLCODE Oracle error message code SQLERRM sub-record for error message

SQLERRML length of error message SQLERRMC text of error message SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) reserved for future use SQLERRD(1) reserved for future use SQLERRD(2) number of rows processed SQLERRD(3) reserved for future use SQLERRD(4) parse error offset SQLERRD(5) reserved for future use

SQLWARN array of eight warning flags SQLWARN(0) another warning flag set SQLWARN(1) character string truncated SQLWARN(2) no longer in use SQLWARN(3) SELECT list not equal to INTO list SQLWARN(4) DELETE or UPDATE without WHERE clause SQLWARN(5) reserved for future use SQLWARN(6) no longer in use SQLWARN(7) no longer in use

SQLTEXT reserved for future use

IBM Software Group IBM Information Management

Version 16 60

Informixrsquos SQLCA structure

SQLCODE Informix error code SQLERRM error message parameter SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) estimated number of rows returned SQLERRD(1) serial value of INSERT or ISAM error code SQLERRD(2) number of rows processed SQLERRD(3) estimated cost SQLERRD(4) parse error offset SQLERRD(5) ROWID after INSERT

SQLWARN structure of eight warning flags SQLWARN0 another warning flag set SQLWARN1 character string truncated or no privileges revoked SQLWARN2 NULL value returned or ANSI database SQLWARN3 SELECT list not equal to INTO list or turbo back-end SQLWARN4 DELETE or UPDATE without WHERE clause SQLWARN5 if non-ANSI statement SQLWARN6 if server is in data replication secondary mode SQLWARN7 reserved

In order to get Oracle error messages an application normally uses the SQLCA element SQLERRMC The Informix equivalent is SQLERRM On the HPUX and Solaris platforms the Informix function rgetmsg should be used instead of the element SQLERRM At the time of this writing using SQLERRM would cause an error on the HPUX and Solaris platforms

SQLDA

The implementation of Oraclersquos SQLDA structure is very different from that of Informix Significant changes are necessary to convert Oraclersquos functionality to Informix Oraclersquos sqlald function can be replaced with Informixrsquos ALLOCATE DESCRIPTOR statement Since Oraclersquos and Informixrsquos SQLDA structures are so different Oraclersquos SQLDA logic must be rewritten with the more powerful Informix SQLDA logic or alternatively the Informix system-descriptor area logic Oraclersquos SQLDA Structure

N maximum number of SELECT list items or placeholders V pointer to array of address of SELECT list items or bind variables L pointer to array of lengths of SELECT list items or bind variables T pointer to array of data types of SELECT list items or bind variables I pointer to array of addresses of indicator variable values F actual number of SELECT list items or placeholders S pointer to array of addresses of SELECT list items or placeholder names M pointer to array of max lengths of SELECT list items or placeholder names C pointer to array of current lengths of SELECT list items or placeholder names X pointer to array of addresses of indicator variable names Y pointer to array of maximum lengths of indicator variable names Z pointer to array of current lengths of indicator variable names

IBM Software Group IBM Information Management

Version 16 61

Informixrsquos SQLDA Structure SQLD count of the following SQLVAR members SQLVAR pointer to array of structures

SQLDATA pointer to actual data SQLTYPE data type of placeholder or SELECT item SQLLEN length of the placeholder or SELECT item SQLIND pointer to the indicator SQLNAME pointer to placeholder or SELECT item name SQLFORMAT reserved SQLIDATA indicator data pointer SQLITYPE indicator variable type SQLILEN length of indicator variable

If an Oracle application uses the simple dynamic SQL method using macros only not the SQLDA structure directly the value indicatorsplaceholders can be replaced with a lsquorsquo in Informix For example Oracle sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES (v1 v2)rdquo) Informix sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES ( )rdquo)

ORACA

Oraclersquos ORACA structure is not supported by Informix This structure is used to handle Oracle specific communication and more runtime information than SQLCA Oracle statements containing references to this structure should be removed from the application

Pre-compiler options The Oracle options beginning with the EXEC ORACLE OPTION statement can be removed from the application The options set after this statement do not affect the application logic They may affect some application performance only

Embedded PLSQL Oracle allows procedure language (PLSQL) blocks inside ProC and ProCOBOL code delimited by the EXEC SQL EXECUTE and END-EXEC statements In Informix these blocks must be replaced with the equivalent ESQLC or ESQLCOBOL code

Oracle Call Interface Oracle call interface (OCI) is the base layer for a variety of other application programming interfaces such as JDBC-OCI Oracle Precompilers and Oracle ODBC It is also used directly by customers who are willing to develop their code using a lower level proprietary API From a high level it can be thought of as if IBM Informix had standardized and published the function calls in the ESQLC library Although some customers have reverse engineered these calls and developed applications using them this is generally discouraged because there is no guarantee that the library of calls will not change There is no direct equivalent to this Oracle API in Informix Migrating applications written using Oracle Call Interface (OCI) will require rewriting the code from scratch OCI is native to the C language and so it should be less effort to migrate the application to an Informix API that is also native to C This could be ESQLC or CLI The following information explains differences between Oracle OCI and Informix ODBC

IBM Software Group IBM Information Management

Version 16 62

The following table is an approximate mapping of the differences between the Informix CLI and Oracle OCI function calls in which there is not a direct one-to-one mapping

Oracle Informix Buffer Areas HAD LDA CDA HENV HDBC HSTMT

Connect and allocate resources

OLOG OOPEN SQLConnect SQLAllocEnv SQLAllocConnect SQLAllocStmt

Update delete insert select OPARSE OBNDRV OEXEC SQLPrepare SQLBindParameter SQLExecute

Select ODEFIN OFETCH SQLBindCol SQLFetch

Commit Rollback OCOM OROL SQLTransact

Disconnect OLOGOF OCLOSE SQLDisconnect SQLFreeStmt SQLFreeConnect SQLFreeEnv

Database library calls

One of the first main differences between Informix CLI and Oracle OCI calls is the overall data structures and mechanisms used to process database library calls Oracle uses direct connections to the database server Informix uses an ODBC connection to the database server As a result the Informix calls will be implemented as ODBC SQL calls utilizing three tiers of increasing SQL levels of complexity

Global area processing

Another main difference between Informix CLI and Oracle OCI is Informixrsquos use of pointers to three global areas versus Oraclersquos use of pointers to three different but similar global areas Hence the Oracle OCI calls that utilize HAD (Handle Data Area) LDA (Logon Data Area) and CDA (Cursor Data Area) pointers must be translated over to Informix CLI calls that utilize HENV (Environment Area) HDBC (Database Connection Area) and HSTMT (Statement Area) pointers respectively in conjunction with an ODBC interface

Fetch cycle

Another difference between Informix CLI and Oracle OCI calls is that the overall fetch cycle is different for each and must be modified accordingly In Oracle the fetch cycle for selecting multiple rows utilizing a cursor area involves parsing binding defining fetching and then executing into a cursor data area These must be translated to a cycle that involves preparing binding executing binding and then fetching via the ldquoFor Eachrdquo cycle

RAW binary data type processing

RAW binary data types in Oracle will need to be translated to a pointer-to-BLOB REFERENCES BYTE type in Informix See the Binary Data Types subsection of the Stored Procedures section in CHAPTER 3

Parameter bindings

In Oracle multiple output bindings of parameters are declared as type ldquoOUTPUTrdquo in the ODEFIN() calls In Informix convert the calls to Informix SQLBindCol() calls and bind the output parameters as columns Differences also exist between Informix CLI and Oracle OCI in the use of inputoutput bindings In Oracle these bindings are declared as type ldquoINPUTOUTPUTrdquo in the ODEFIN() calls In Informix a ldquoround robinrdquo approach is used using three variables in the following manner A=B B=C C=A A variable (A) is declared before the SQL bindings as an input variable The function is called

IBM Software Group IBM Information Management

Version 16 63

using a second input variable (B) that is set to the first input variable (A) The function returns a third variable (C) that is bound as an output column Finally the first variable (A) is now set to the returned third variable (C) that made the first variable (A) appear as an ldquoinputoutputrdquo variable to the rest of the program

Embedded SQL for C

VARCHAR

Oraclersquos ProC VARCHAR data type is expanded after pre-compiling into a structure with two elements one is unsigned short len and the other is unsigned char arr[size] The name of the expanded structure is the same name as the VARCHAR variable and size is replaced with the size of the VARCHAR variable In Informix the VARCHAR data type is just a synonym for the C languagersquos char data type Therefore statements that use variable_namelen can be removed from the application and all occurrences of variable_namearr can be replaced with variable_name For example

Oracle VARCHAR vName[40]

strcpy(vNamearr ldquoCompany Namerdquo)

vNamelen = strlen(vNamearr)

Informix VARCHAR vName[40]

strcpy(vName ldquoCompany Namerdquo)

Host variables

The Oracle statement EXEC SQL TYPE is synonymous with the C languagersquos typedef declarative instruction It can be easily replaced with the Informix declarative instruction typedef

Embedded SQL for COBOL

VARCHAR

Oraclersquos ProCOBOL character host variable declaration statementrsquos VARYING clause is expanded after pre-compiling into a group with two elements one is variable-name-LEN PIC S9(4) COMP and the other is variable-name-ARR PIC X(size) The group name is the same as the host variable name and size is replaced with the size of the VARYING variable Informix does not support this concept Therefore statements that use variable-name-LEN must be removed from the application and all occurrences of variable-name-ARR must be replaced with variable-name Also the VARYING clause must be removed from the declarative statement For example

Oracle

05 vName PIC X(40) VARYING

hellip

MOVE ldquoCompany Namerdquo TO vName-ARR

MOVE 12 TO vName-LEN

Informix

05 vName PIC X(40)

hellip

MOVE ldquoCompany Namerdquo TO vName

IBM Software Group IBM Information Management

Version 16 64

Level 88

COBOLrsquos level 88 functionality is not supported within an Informix ESQLCOBOL host variable declaration section in versions prior to 72 Level 88 functionality is supported in Informix ESQLCOBOL 72

SQLDA

In Informix ESQLCOBOL the SQLDA structure is not available The Informix macros such as ALLOCATE DESCRIPTOR DESCRIBE GET DESCRIPTOR and SET DESCRIPTOR must be used to retrieve and manipulate the SQLDA data

REDEFINES

Oracle supports the use of the REDEFINES clause at the elementary level in the host variable declaration section In other words the redefined item cannot be a group item but the redefining item may be a group item Informix does not support the use of the REDEFINES clause in the host variable declaration section in versions prior to 72 The REDEFINES clause is supported in Informix ESQLCOBOL 72

Tips

If the Informix pre-compiler finds an SQL statement within an IF [ELSE IF hellip ] END-IF or EVALUATE END-EVALUATE or PERFORM END-PERFORM block then the pre-compiler adds a period after the generated COBOL statements regardless of whether there is a period at the end of the SQL statement This is a violation of COBOL rules for such blocks and the code may cause syntax errors during compilation or may behave unexpectedly To avoid these problems each SQL statement group should be moved to a new paragraph and these paragraphs should be performed from the block from which they were moved

ODBC Although the Open Database Connectivity (ODBC) API is designed to make it possible to write and compile an application once and use it with any ODBC driver on the same platform there are frequently differences between the underlying DBMSs that can expose problems to the applications For instance there can be differences between how unspecified parts of a date-time value are filled Most of these kinds of differences that get exposed through ODBC have their origins in the differences between the DBMSs themselves There are also cases where there are gaps in the ODBC standard for example there is a standard ODBC call that allows the application to ask the driver if it can support scrollable cursors and there is another call to ask if it can support updateable cursors There is no call to ask if it can support both at the same time With Informix you can have a scrollable cursor and you can have an updateable cursor but you can not have one cursor that is both scrollable and updateable A more complete description of ODBC application migration issues is beyond the scope of this article

IBM Software Group IBM Information Management

Version 16 65

C H A P T E R 6 Application Architecture

Transaction processing Transaction boundaries are defined differently in Oracle and Informix Oraclersquos transactions begin implicitly in one of two ways either by issuing a CONNECT statement or issuing a COMMIT or ROLLBACK statement A CONNECT statement marks the beginning of a transaction and a COMMIT or ROLLBACK statement commits or rolls back the previous transaction respectively and then implicitly begins a new transaction CONNECT statements are usually issued once at the beginning of a program however they may be nested or issued more than once serially to connect to the same or a different database When using more than one CONNECT statement within a program each CONNECT statement must be named This marks the beginning of named transactions Every SQL statement within a named transaction must also be named with the same transaction name as the CONNECT statement at where the SQL is to be executed SQL is named using the EXEC SQL statementrsquos AT clause Informixrsquos transaction boundaries are explicitly marked with the reserved words BEGIN WORK and COMMIT WORK or ROLLBACK WORK Note that once a transaction has begun for a given connection it stays open until a COMMIT or ROLLBACK is executed In other words if an ESQL program begins a transaction and then calls a stored procedure the stored procedure executes within the same transaction If the stored procedure issues a COMMIT then the whole transaction is committed and the calling ESQL program should not issue a COMMIT or ROLLBACK Informix transactions can be written to behave the same way as Oraclersquos To simulate Oraclersquos CONNECT statement behavior an Informix CONNECT should also be issued followed by a BEGIN WORK statement If more than one CONNECT statement is used in a program Informix also requires that the CONNECT and SQL statements be named To simulate Oraclersquos COMMIT and ROLLBACK statement behavior an Informix COMMIT WORK or ROLLBACK WORK statement should be issued followed by a BEGIN WORK statement Nested transactions can be simulated in Informix with the CONNECT statement and naming the transactions Then the Informix SET CONNECTION connection_name statement can be used to switch between transactions Committing or rolling back each named transaction does not commit or roll back other active transactions The Oracle statement EXEC SQL COMMITROLLBACK RELEASE should be replaced with the Informix statements EXEC SQL COMMITROLLBACK [WORK] followed by EXEC SQL DISCONNECT CURRENT In the following examples ws-dbenviron is the database name ws-connect-nm is the user name and ws-identity-nm is the password set in the program enp and connection-name are the connection names For Informix the user name and password information should correspond to the entries in the etcpasswd file on the UNIX system See the User Authentication section later in this chapter for more information The default server name is automatically obtained from the environment variable INFORMIXSERVER The following examples illustrate how Oracle and Informix implement the CONNECT functionality

IBM Software Group IBM Information Management

Version 16 66

Simple Connect

Oracle

CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm

Informix

CONNECT ws-dbenviron USER ws-connect-nm USING ws-identity-nm

Named Connect with Literal

Oracle

DECLARE enp DATABASE hellip CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm AT enp USING ws-dbenviron hellip AT enp SELECT col1 col2 INTO var1 var2

FROM table_name

Informix

CONNECT TO ws-dbenviron AS ldquoenprdquo USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION ldquoenprdquo hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Named Connect with Variable

Oracle

CONNECT ws-connect-nm

IDENTIFIED BY ws-identity-nm AT connection-name USING ws-dbenviron hellip AT connection-name SELECT col1 col2 INTO var1 var2 FROM table_name

Informix

CONNECT TO ws-dbenviron AS connection-name USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION connection-name hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Autonomous Transaction

An autonomous transaction is an independent transaction that is initiated by another transaction (the parent transaction) An autonomous transaction can modify data and commit or rollback independent of the state of the parent transaction The autonomous transaction must commit or roll back before the autonomous transaction is ended and the parent transaction continues

IBM Software Group IBM Information Management

Version 16 67

An autonomous transactions has been available since the release of Oracle 8i An autonomous transaction is defined in the declaration of a PLSQL block This can be an anonymous block function procedure object method or triggerThis is done by adding the statement PRAGMA AUTONOMOUS_TRANSACTION anywhere in the declaration block There isnt much involved in defining a PLSQL block as an autonomous transaction You simply include the following statement in your declaration section PRAGMA AUTONOMOUS_TRANSACTION Sample code

PROCEDURE test_autonomous

IS

PRAGMA AUTONOMOUS_TRANSACTION

BEGIN

insert

commit

END test_autonomous

Autonomous transactions can be used for logging in the database independent of the rollbackcommit of the parent transaction

Savepoints

Oracle allows savepoints within its PLSQL For example a PLSQL block can be structured so that SAVEPOINT A is issued upon entry and SAVEPOINT B is issued after some processing Then after some more processing a COMMIT or ROLLBACK can be issued against all the logic since the last COMMIT point which is before the PLSQL block or up to any of the savepoints by naming the COMMIT or ROLLBACK with the savepoint name In other words a savepoint can be issued at the beginning of a stored procedure and then only the stored procedure logic can be committed without committing the changes pending before the stored procedure was executed Those changes can be committed or rolled back once processing is returned from the stored procedure Informix does not support savepoint processing within a stored procedure

Concurrency Database concurrency can be managed through the combination of two configurable settings one specifies the lock granularity on database objects while the other influences how the application behaves in regards to the presence and placement of locks using a transaction isolation level

Row Level Locking

Oracle and Informix implement locking differently on database objects Oracle defaults to row level locking whereas Informix defaults to page level In most cases row level locking is preferred to improve concurrency Informix supports row level locking however it must be either explicitly requested specified by an environment variable or permanently changed in the instancersquos configuration Having three methods for establishing the lock level there is an order of precedence

1 To be explicitly requested the CREATE TABLE statement must include the specification of the LOCK MODE attribute

CREATE TABLE emp (

name CHAR(40)

salary MONEY

ssn LVARCHAR(64)

) LOCK MODE ROW

IBM Software Group IBM Information Management

Version 16 68

2 The environment variable IFX_DEF_TABLE_LOCKMODE will establish the default for CREATE TABLE statements issued without the LOCK MODE attribute and will override the Instancersquos configuration setting The variable setting on the client will override the server environment setting

set IFX_DEF_TABLE_LOCKMODE=ROW -or- export IFX_DEF_TABLE_LOCKMODE=ROW

3 Informix allows the instancersquos lock level default to be changed using a configuration parameter Row level locking can be as the default by adding the parameter DEF_TABLE_LOCKMODE to the instancersquos ONCONFIG file This parameter may not be found in the existing file and if not present can be added using an editor and establish a new default setting of ROW

DEF_TABLE_LOCKMODE ROW

None of the steps will apply a change to existing tables only establish the lock level for the CREATE TABLE statement

Transaction Isolation Level

Oracle databases incorporate a feature known as ldquoread consistencyrdquo which allows a query return a result based on the state of the data when the query started regardless of other processes updating or deleting the same data while the query is running Informix facilitates this type of behavior differently by providing control of the applicationrsquos placement of locks as well as how it reacts to those placed by other processes through the use of the transactionrsquos isolation level If Oraclersquos technique of ldquoreaders not blocking writersrdquo is a requirement then in many circumstance Informixrsquos DIRTY READ isolation level can be used The readers will not block the writers with dirty read processing however the query result may contain updates performed while the query was running which may be uncommitted If the emulation of Oraclersquos ldquoread consistencyrdquo is desired the LAST COMMITTED option of Informixrsquos COMMITTED READ isolation level can reduce the risk of locking conflicts when two or more sessions attempt to access the same row in a table whose locking granularity is row-level When an application attempts to read a row on which another session holds an exclusive lock these keywords instruct the database server to return the most recently committed version of the row rather than wait for the lock to be released This isolation level attribute could be preferable to executing queries using DIRTY READ since it will return only the most recently committed versions of the data The LAST COMMITTED option can be enabled in the following ways

1 Setting the USELASTCOMMITTED parameter in the Instancersquos configuration (ONCONFIG) will apply this feature as the default isolation level to all database transactions The parameterlsquos values will designate the scope of applying the LAST COMMITED option to either ALL NONE or only COMMITED READ and DIRTY READ isolation levels

USELASTCOMMITTED [ALL | NONE | COMMITTED READ | DIRTY READ]

2 The SET ENVIRONMENT statement can override the USELASTCOMMITTED configuration parameter setting for the duration of the current session The same semantics apply as the parameter within the ONCONFIG file with the setting value enclosed in quotes (lsquo)

SET ENVIRONMENT USELASTCOMMITTED lsquoALLrsquo

IBM Software Group IBM Information Management

Version 16 69

3 The SET ISOLATION statement can be used to override the instance configuration and session environment setting The SET ISOLATION statement is an Informix extension to the ANSI SQL-92 standard and provides the same functionality as the ISOANSI-compliant SET TRANSACTION statement There is no support for the LAST COMMITTED option with the SET TRANSACTION statement SET TRANSACTION complies with ANSI SQL-92 and only ANSI supported isolation levels are supported

SET ISOLATION TO COMMITTED READ LAST COMMITTED

4 PREPARE statements in ODBCJDBC applications

This feature is primarily documented in the Guide to SQL Syntax Guide to SQL Reference Administrators Reference and Administrators Guide

IBM Software Group IBM Information Management

Version 16 70

C H A P T E R 7 Security

User authentication In Oracle security information is stored in the database Up until recently Informix has used only the operating system security subsystem to check security For security purposes Oracle connects to the server and passes the user ID and password information to the database for verification

Operating system security

Informix does not store user ID and password information in the database Instead they are validated against the operating systemrsquos security mechanism on the server for example the etcpasswd file in UNIX Therefore either every database user must have an entry in the serverrsquos password file or the application must handle a level of security where user IDs are converted into a group id based on database permissions and only those group IDs are entered into the password file Note that if the second alternative is chosen then auditing capabilities based on user ID are lost Also if the application performs security functions then those functions are not applicable to third party applications such as report writers application development tools and so on when they access the database The home directory of all the users should point to the same physical directory where the application executable resides The Informix method of using the operating system for security checking allows external programs to be called from within stored procedures This capability is not allowed in Oracle In Oracle the OPS$User_name is sometimes used to connect to the database where OPS$User_name is a valid Oracle user and User_name is a valid operating system level user In this case the connection is made to the database using just the lsquorsquo character without the user id and password Informixrsquos technique of using the etcpasswd file for security works fine for this type of connection

Non-operating system security

In previous releases each user who needed to access the database server also needed an operating system account on the host computer Now you can configure Informix so that users who are authenticated by an external authentication service (such as Kerberos or Microsoft Active Directory) can connect to Informix The new USERMAPPING configuration parameter specifies whether or not such users can access the database server and whether any of those users can have administrative privileges When Informix is configured to allow user mapping you can still control which externally authenticated users are allowed to connect to Informix and their privileges Please refer to the IBM Informix documentation on connection security for more information

IBM Software Group IBM Information Management

Version 16 71

Informix supports for the pluggable authentication module (PAM) framework which lets an administrator customize authentication for individual applications and permits column-level encryption

Role based authority Role based authority can help you manage your database permissions As of version 1110 you can create a role and assign that as a default role for individual users (or to PUBLIC) A role is a work-task classification such as ldquopayrollrdquo or ldquomanagerrdquo Each defined role has privileges on the database object granted to the role You use the CREATE ROLE statement to define a role and GRANT DEFAULT ROLE to establish the userrsquos initial setting when connecting to the database A userrsquos role can be changed after connecting by using the SET ROLE statement

Column-level encryption You can use column-level encryption to improve the confidentiality of your data IDS Version 1110 has new built-in SQL scalar functions provide methods for data in columns to be stored in an encrypted format Use the ENCRYPT_AES or the ENCRYPT_TDES function to define encrypted data Use the DECRYPT_BINARY() and DECRYPT_CHAR() functions to query encrypted data When using the routines the encryption of data is under application control and the DBMS is not aware that data is encrypted Informixrsquos support of column level encryption is analogous to Oraclersquos DBMS Obfuscation Tool Kit Built-in ENCRYPT functions provide methods for encrypting and decrypting the following character data types or smart large object data types

CHAR

NCHAR

VARCHAR

NVARCHAR

LVARCHAR

BLOB

CLOB

Passwords and hints

Passwords are necessary when using the encryption functions Only users who can provide a secret password can view copy or modify encrypted data The password must be a minimum of 6 bytes and can be a maximum of 128 bytes When you set an encryption password you have the option of specifying a password hint Hints can be up to 32 bytes of text If you specify a hint you can store the hint with the encrypted password or in another location Passwords (and hints) to be used by default can be set for a session using the SET ENCRYPTION PASSWORD statement

SET ENCRYPTION PASSWORD lsquopasswordrsquo [ WITH HINT lsquohint stringrsquo ]

Hence the password and hint parameters can be optional when calling the encryption function Explicit values override the session default values The password or hint can be a single word or several words The hint should be a word or phrase that helps you to remember the password but does not include the password You can subsequently execute the built-in GETHINT function (with an encrypted value as its argument) to return the plain text of hint Calling the GETHINT function with an argument of encrypted data will return the hint (if any) from the encrypted data or an empty string (NULL) is no hint was provided There is no privilege needed anybody can get any hint at any time When you set a password Informix transfers the password and any hint to 128-bit key that is used to encrypt the password and hint Passwords and hints are not stored as plain text any table of the system catalog The key is a time-based random value per instance The database server

IBM Software Group IBM Information Management

Version 16 72

initializes the key when the server starts the key is destroyed when the database server shuts down

Encrypting a column

Column data can be encrypted through the use of two functions ENCRYPT_TDES and ENCRYPT_AES corresponding to the two data encryption standards Triple Data Encryption Standard (Triple-DES) and Advanced Encryption Standard (AES) which describes the cipher algorithm used to protect data from unauthorized viewing AES encryption (also known as Rijndael) uses a 128-bit key size and Triple-DES encryption uses two 56-bit keys for 112-bits overall Both functions are variant functions and will return a different result every time it is used The following example demonstrates how to use the encryption functions with a column that contains a social security number

CREATE TABLE emp (name CHAR (40) salary MONEY ssn LVARCHAR(64))

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890one two

three 123))

-or-

CREATE TABLE emp (name CHAR(40) salary MONEY ssn LVARCHAR(64))

SET ENCRYPTION PASSWORD one two three 123

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890))

Querying an encrypted column

Encrypted data can be translated using Informixrsquos DECRYPT_CHAR and DECRYPT_BINARY scalar functions Encrypted data contains information about the encryption method and all the other data needed to decrypt it except the password The encrypted data value is passed as the first argument and a password as the second unless the SET ENCRYPTION statement has specified for this session with the same session password by which the first argument was encrypted If the data is not encrypted the function call will return an error The DECRYPT_CHAR function is used to invoke a decryption routine on character data types (ie CHAR LVARCHAR NCHAR NVARCHAR and VARCHAR) while the DECRYPT_BINARY function accepts an encrypted large object of type BLOB or CLOB If the first argument to DECRYPT_CHAR or DECRYPT_BINARY is not an encrypted value or if the second argument (or the default password specified by SET ENCRYPTION) is not the password that was used when the first argument was encrypted Informix will issue an error and the call fails If the call to the decryption function is successful it returns the plain text version of the encrypted data argument The following example demonstrates how to use the decrypt function to query encrypted data

SELECT name salary DECRYPT_CHAR(ssn lsquoone two three 123rsquo)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

-or-

SET ENCRYPTION PASSWORD lsquoone two three 123rsquo

SELECT name salary DECRYPT_CHAR(ssn)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

The first argument to DECRYPT_BINARY is expected to be an encrypted value of a large object data type however if it is called with a character data type Informix invokes the DECRYPT_CHAR function and attempts to decrypt the specified value

IBM Software Group IBM Information Management

Version 16 73

Do not use either decryption function to create a functional index on an encrypted column This would store the decrypted values as plain text data in the database defeating the purpose of encryption

Performance impact of encryption

The performance impact of encryption is significant Encryption by its nature will slow down most SQL statements If some care and discretion are used the amount of extra overhead should be minimal Also encrypted data will have a significant impact on your database design In general you want to encrypt a few very sensitive data elements in a schema like social security numbers credit card numbers patient names and so on The effect on performance depends on direction encrypting is slower than decrypting It does not depend measurably on which algorithm is used AES performs at the same speed as Triple-DES It does depend on data size the relative overhead is less when there is more data to encrypt

Storage considerations

An encrypted value uses more storage space than the corresponding plain text value Data encrypted using AES can be bigger than Triple-DES but not by a significant amount This occurs because all of the information needed to decrypt the value except the encryption key is stored with the value Therefore before you set the encryption password and encrypt the data you must be sure the encrypted data can fit in the column A chart of the expected sizes can be found in the IBM Informix Administrator Guide

Compliance regulations

Informixrsquos encryption routines comply with the United Statesrsquo regulations of Health Insurance Portability and Accountability Act (HIPAA) Sarbanes-Oxley Gramm-Leach-Bliley and California Personal Information Privacy (SB 1386) as well as the international requirements of Basel II Also they comply with the latest cryptographic standards (OpenSSL 097c)

IBM Software Group IBM Information Management

Version 16 74

C H A P T E R 8 Environment

Scripts Oracle make files used to build the application should be modified to invoke the appropriate Informix ESQLCOBOL ESQLC MF COBOL and other application language commands The shell scripts shell startup scripts and command files should be modified for Informix compliant statements

SQL script substitution variables

In Oracle a substitution variable is a user variable name preceded by one or two ampersands (amp) When Oracle (SQLPlus) encounters a substitution variable in a command Oracle executes the command as though it contained the value of the substitution variable rather than the variable itself In Oracle the substitution variables can be used anywhere in SQL and SQLPlus commands except as the first word entered at the command prompt When SQLPlus encounters an undefined substitution variable in a command SQLPlus prompts the user for the value SQLPlus reads the responses from the keyboard even if terminal input or output has been redirected to a file If a terminal is not available (if for example the command file is run in batch mode) SQLPlus uses the redirected file Informixrsquos dbaccess does not provide this functionality however a work-around for the redirected file type of substitution is a follows (no user prompting) Create the following shell script (named subvalsksh in this case)

binkshif [[ $ -ne 2 ]]

then

echo nUsage $0 ltdfilegt ltcfilegtn

echo Desc This script accepts two files - dfile the decode

file

echo and cfile the change file It modifies the

change file

echo using the values listed in the decode file

echo The decode file should contain two columns - old

value

echo and new value

echo Ex

echo changethis tothis

echo

echo In this case every occurance of changethis

would be

echo replaced with tothisn

exit 1

fi

IBM Software Group IBM Information Management

Version 16 75

-----------------------

Declare variables

-----------------------

dfile=$1

cfile=$2

awk print s$1$2 $dfile gt $dfile_sed

sed -f $dfile_sed $cfile

The preceding script is used by creating a ldquodecoderdquo file (named decodefile in this case) which holds two columns in the form which may contain multiple rows

oldval newval

Executing the following command

subvalsksh decodefile chgfile

will replace every occurrence of oldval with newval in the file chgfile The shell script (subvalsksh) writes to standard output therefore the output should be redirected The redirected file will then be able to run with dbaccess

Utilities To improve performance the Informix EXPLAIN utility should be used by executing the SET EXPLAIN ON command to see how an SQL statement accesses the database From that point forward the access path for every SQL statement is written in the SQEXPLAINOUT file in the current working directory or the home directory of the process that initiated the request on the host machine The Informix SET EXPLAIN OFF should be executed to turn off this feature when finished The overall system performance should be monitored using the Informix ONSTAT utility

System catalog The following items discuss how Informix implements the system catalog differently than Oracle Each item refers to the Informix implementation only Object names are stored in lower case The system catalog tables are owned by lsquoinformixrsquo To query the systables table use SELECT from lsquoinformixrsquosystables Each table in systables is assigned a tabid by the system It is used as the primary key and therefore the foreign key for the other catalog tables The identifier information is stored in sysindexes Columns part1 - part16 each contain a column component of a composite index They are integers positive for ascending order negative for descending order In syscolumns collength and coltype have special meanings depending on the data type of the column See the Informix Guide to SQL Reference Version for details

IBM Software Group IBM Information Management

Version 16 76

C H A P T E R 9 Using Bladelets

What is a Bladelet

A Bladelet is a small informal Informix Datablade module Its meant to be useful out of the box and is offered complete with source code at no cost -- and no support or warranty In the context of this document the term Datablade refers to an extension to the standard IBM Informix database engine These generally take the form of new data types (for example timeseries or video) andor new routines that execute inside the server The new routines might operate on new data types or on existing ones A Datablade module is usually a formal product available for sale In addition a Datablade is

Developed either by IBM Informix or by a third-party developer

Rigorously tested

Packaged and sold for profit

May or may not be formally certified by IBM Informix as having been developed according to approved Datablade coding practices

In contrast a Bladelet is

Not rigorously tested

Not sold for profit

Not certified by IBM Informix A Bladelet is an extension to the database engine that is narrow in scope and thought to be generally useful being offered at no cost complete with source Just remember before you use any of this code in mission-critical applications its up to you to thoroughly test it and fix any problems you find Please review the disclaimer which applies to any sample code you find on this site httpwwwibmcomdeveloperworksdb2zonesinformixlibrarysamplesdb_downloadshtml Note The bladelets at this link have not been updated for some time (at the time of this writing) some of the capabilities especially simple function call that increase compatibility may have been introduced into the Informix server itself since they were written

Useful Bladelets

Bladelet Description

Exec Defines two user-defined functions that provide dynamic SQL functionality within a SPL procedure

Flat File Access Method A complete access method that lets you build virtual tables based on operating system files

IUtil Implements a collection of other database vendor functions for Informix

IBM Software Group IBM Information Management

Version 16 77

JPEG Image Bladelet Provides a user-defined type for JPEG images that allows you to manipulate images and to extract and search on image properties

Multirepresentational lvarchar Opaque Type

Creates the idn_mrLvarchar opaque type which stores character data up to 2 gigabytes

Node Datablade Module Creates the node opaque type which is intended to solve one of the hardest problems in relational databases transitive closure

Regexp Creates routines that let you manipulate character and clob data using regular expressions

Shapes DataBlade Module Creates several opaque types for managing spatial data including R-tree index support

Smart Blob Information DataBlade Module

Includes a variety of useful routines for working with smart blobs

SqlLib C SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

SqlLib Java SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

Versioning Table Access Method

Permits users to create and manage versioned tables

We will look closer at two bladelets which could assist with migration the Exec datablade and SQLLib

Informix Exec bladelet for Dynamic SQL Often it is desirable to execute a SQL query that is generated at run-time within the RDBMS For example a developer may not know the name of the temporary table they wish to run the query against or they might want to append predicates to a query In external programs this can be accomplished using the ESQLC SQLCA and DESCRIPTOR facilities Unfortunately the INFORMIX Stored Procedure Language (SPL) does not support Dynamic SQL Queries must be hard-coded into the SPL logic The objective of the Exec bladelet is to remedy this situation Exec consists of user-defined functions that take an SQL query as an argument execute it and return the result (the format of which varies depending on which function is called and the kind of query) The Exec functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries For more details and download refer to

httpwwwibmcomdeveloperworksdb2zonesinformixlibrarydemoids_exechtml

There are three User Defined Routines (UDRs) in the Exec bladelet Two of them are external C functions that use the Server API (SAPI) These must be compiled into shared libraries on the target machine and you need to declare them to the server using CREATE FUNCTION statements The third UDR is a routine written in Informix Stored Procedure Language (SPL) that uses the first two UDRs to return a collection of items The Exec bladelet module consists of the following

1 EXEC The EXEC() function takes an LVARCHAR that it treats as a SQL query executes the query and returns a single LVARCHAR result string Depending on what kind of SQL statement is submitted Exec() returns a different result format

IBM Software Group IBM Information Management

Version 16 78

2 EXEC_FOR_ROWS The EXEC_FOR_ROWS() UDR is an iterator function which means it can return more than one result row Of course it only does so when it is asked to execute a SELECT Otherwise it behaves exactly as the EXEC() UDR Being an iterator function limits the ways in which such a UDR can be used It cannot be used in another SQL query The only place it can be used effectively is inside a SPL routine

3 EXEC_FOR_MSET EXEC_FOR_MSET() is a SPL routine that uses the EXEC_FOR_ROWS() routine introduced above Instead of returning a set of rows as an iterator or a single row as the EXEC() UDF does this UDR collects the results of the SQL query together into a single object a multi-set

Refer to Appendix E Sample Code for examples on using the EXEC bladelet functions

SqlLib DataBlade module (SqlLibC11 SqlLibJ11) The SqlLib DataBlade module implements SQL routines that the Informix does not support natively but that are supported by some other database vendors Source code is freely available for download and includes two implementations one in C (SqlLibC) and the other in Java (SqlLibJ)

The following routines are included

ascii - takes a single character as input and returns the ASCII value in decimal that corresponds to that character

ceil - takes a single numeric value as input and returns the smallest integer that is either equal to or greater than the input value

chr - takes an integer value and returns the character that is represented by the ASCII value (in decimal) of that integer

instr - searches for a value in a string and returns the position where it was found It

returns 0 if the search value was not found instrb - provides the exact same functionality as instr() but for single-byte character sets

sign - takes a numeric argument and returns an integer that indicates if the input value is

positive (1) negative (-1) or zero (0) to_decimal - converts the input character argument into a decimal type

to_float - converts the input character argument into a float type

to_integer - converts the input character argument into an integer type For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

IBM Software Group IBM Information Management

Version 16 79

A P P E N D I X A Planning guide

The checklist below will help an analyst determine which Oracle features which need to be converted to Informix and give some guidance on the effort involved Each porting task is listed They are followed by a quantity field used to determine how prevalent the item the difficulty or amount of effort involved 1 (low) to 5 (high) is used to estimate the amount of time needed to perform the task when the associated item exists in the application a moderate number of times What is moderate depends on the size of the application If there are an unusually large number of occurrences of an item then the effort should be increased Conversely if there are a small number of occurrences of an item then the effort should be decreased Each of these items is discussed in detail within this document Each heading corresponds to a section heading within the document

Tasks Quantity Effort

DDL

Identifiers Delimit identifiers named with Informix reserved words 2 Databases Determine database names and create databases 3 Replace Oracle tablespace names with Informix dbspace names 1 ANSI vs Non-ANSI considerations 3 Tables Convert create table statements 2 Convert DDL syntax 3 Reduce primary key length to 390 bytes 5 Data Types Convert Oraclersquos NUMBER data type 3 Convert VARCHAR columns 2 Convert Oraclersquos DATE data type 5 Convert raw data types 2 Convert Rowids 2 Indexes Convert Indexes 2 Views Remove CREATE VIEW statement options 1 Stored Procedures and Triggers Convert CREATE and REPLACE Stored Procedure and Trigger syntax 1 Oracle Extensions Remove non-supported Oracle extensions from DDL 1

Tasks Quantity Effort

DML

SQL Add the Informix AS clause to display labels 1 Replace non-supported DML syntax ^= hellip = ELSE IF 2 Convert Optimizer DirectiveHints 2 Convert InsertSelectUnion and InsertValueSelect statements 3

IBM Software Group IBM Information Management

Version 16 80

Convert Delete statement syntax 1 Convert temporary table processing 2 Convert Join statements + MINUS INTERSECT different data types 2 Convert sorts 4 Convert hard coded SQL error messages 3 Remove correlation names on the main table of Update and Delete statements

2

Replace original table names in SELECT statements using aliases 1 Convert hierarchical implementation (CONNECT BY PRIOR) 5 Host Variables Convert host variable format or add conversion processing 5 Functions Convert date and time functions 5 Convert aggregate functions 3 Convert mathematical functions 5 Convert string function syntax 1 Convert other unsupported Oracle functions 5 Macros Convert ISOPEN NOT FOUND ROWTYPE and TYPE macros 3 Pseudo-Columns Convert Level processing 3 Convert Rownum processing 2 Update Using Cursors Convert WHERE CURRENT OF processing for multiple table joins 5 Convert FOR UPDATE with a HOLD cursor processing 2 Convert concurrency processing from Oraclersquos implicit to Informixrsquos explicit

4

System Tables Convert system table references 1

Tasks Quantity Effort

Stored procedures Break stored procedures greater than 64K in size into smaller ones 2 Convert Oraclersquos stored procedure packages 3 Convert exception processing 5 Convert error handling (SQLCA) 2 Convert Oraclersquos global cursor processing 5 Convert Oraclersquos explicit cursor processing 2 Convert flow control processing 5 Convert Oraclersquos implicit variable declaration and assignment 3 Convert Oraclersquos BOOLEAN variable type 1 Convert binary data type processing Convert Oraclersquos dynamic SQL processing 5 Triggers Convert multi-functional triggers 3 Convert Insert and Update triggers which are not supported in Informix 5 Place logical statements in a stored procedure 5 Constraints Convert constraint enabling and disabling processing 5 DUAL table Convert Dual table processing 4

Embedded SQL

Host variables

IBM Software Group IBM Information Management

Version 16 81

Convert declaration overrides 1 Convert array processing 5 Convert Oraclersquos formatting functions 4 SQL structures Convert SQLDA processing 5 Convert ORACA processing 1 Pre-compiler options Convert Oracle pre-compiler options 1 Embedded PLSQL Convert Oraclersquos Embedded PLSQL 5 ODBC Convert Oraclersquos OCI 5 Convert database library calls Convert global area processing Convert fetch cycle Convert RAW data type processing Convert parameter bindings Embedded SQL for C Convert VARCHAR processing 2 Embedded SQL for COBOL Convert VARCHAR processing 2 Convert 88 Level processing in COBOL 2 Convert Redefine processing in COBOL 4

Tasks Quantity Effort

Application architecture

Transaction processing Convert application to Informix transaction processing 5 Convert multiple connect processing 5 Convert savepoints Concurrency Address Informix locking processing na 2 User authentication Address Informix security processing na 4

Environment

Convert make files 2 Convert shell scripts shell startup scripts and command files 2 Convert script substitution variables

IBM Software Group IBM Information Management

Version 16 82

A P P E N D I X B Syntax comparison

See the Informix Guide to SQL Syntax for more information on each item

Oracle Informix Boolean AND AND AND NOT NOT NOT OR OR OR Greater Than or Equal To gt= gt= Less Than or Equal TO lt= lt= Not Equal ltgt = or ^= ltgt or = Identifiers letters numbersrdquo_rdquordquo$rdquordquordquo letters numbers and ldquo_rdquo Data types Character CHAR CHAR Long Character VARCHAR (2000) if lt= 2000

LONG VARCHAR if gt 2000 CHAR or TEXT

Number (2 bytes) NUMBER SMALLINT Number (4 bytes) NUMBER INTEGER Number (gt 4 bytes) NUMBER DECIMAL Image LONG RAW CLOB BLOB BYTE TEXT CLOB BLOB DML Comments -- hellip -- hellip Assignment var1 = expression LET var1 = expression Condition ELSE IF ELSE or ELIF

IF Aggregate functions Average AVG(expression) AVG(ALL

expression) AVG(DISTINCT expression)

AVG(expression) AVG(ALL expression) AVG(DISTINCT column_name) AVG(UNIQUE column_name)

Count COUNT() COUNT (expression) COUNT(ALL expression) COUNT (DISTINCT expression)

COUNT() COUNT(DISTINCT column_name) COUNT (UNIQUE column_name)

Maximum MAX(expression) MAX(ALL expression) MAX(DISTINCT expression)

MAX(expression) MAX(ALL expression) MAX(DISTINCT column_name) MAX(UNIQUE column_name)

Minimum MIN(expression) MIN(ALL expression) MIN(DISTINCT expression)

MIN(expression) MIN(ALL expression) MIN(DISTINCT column_name) MIN(UNIQUE column_name)

Sum SUM(expression) SUM(ALL expression) SUM(DISTINCT expression)

SUM(expression) SUM(ALL expression) SUM(DISTINCT column_name) SUM(UNIQUE column_name)

Algebraic functions Round ROUND(expressionrounding

factor) ROUND(expressionrounding factor)

Statistical functions Standard Deviation STDEV(expression) STDDEV(expression) Variance VARIANCE(expression) VARIANCE(expression) Range RANGE(expression)

IBM Software Group IBM Information Management

Version 16 83

String functions

Trim LTRIM(expression) RTRIM(expression)

LTRIM(expression) RTRIM(expression)

Length LENGTH(string) LENGTH(string) Like LIKE(string) LIKE(string) Like (single character) _ _ Like (wildcard) String Delimiter lsquo or ldquo lsquo or ldquo Escape Character set within LIKE clause using

ESCAPE ldquordquo to make ldquordquo the escape character

or set within LIKE clause using ESCAPE ldquordquo to make ldquordquo the escape character

Stored procedures Create CREATE OR REPLACE

PROCEDURE procedure_name (var1 IN CHAR(1) var2 OUT DATE var3 IN OUT NUMBER)

DROP PROCEDURE procedure_name CREATE PROCEDURE procedure_name (var1 CHAR(1) var3 INTEGER) RETURNING DATE INTEGER

Arguments EXECUTE PROCEDURE procedure_name (var1 IN var2 OUT var3 IN OUT)

EXECUTE PROCEDURE procedure_name (var1 var3) RETURNING var2 var3

IBM Software Group IBM Information Management

Version 16 84

A P P E N D I X C Database concepts

The table below illustrates the relationship between each database vendorrsquos database objects

Oracle Informix

Database name attached to a group of files Specific database name

Data file Chunk

Tablespace (logical partition) or Segments (Index Segment Table Segment and so on)

Dbspace

Extent Extent

Rollback Segment Physical Log

Redo Log Logical Log

System tablespace Root dbspace

Temporary tablespace Temporary dbspaces dbspacetemp environment variable or dbspacetemp onconfig parameter

Pointer Blobspace Sbspace

Table partitioning table fragmentation

Database link Not supported

Snapshot Not supported

oerr utility finderr utility

sqldba and svrmgrl - monitor utilities onstat and oncheck utilities

SQLPlus utility dbaccess utility

ProC ESQLC

ProCOBOL ESQLCOBOL

SQLNET INet

OCI Like the ESQL function library after pre-compiling if they were publically documented

Read Consistency COMMITTED READ LAST COMMITTED

IBM Software Group IBM Information Management

Version 16 85

A P P E N D I X D Sample code

User defined functions User Defined Routines (UDR) can be developed to extend the capabilities of the database and provides the option to create UDRs to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or rename an Informix function to the corresponding Oracle function name

CONCAT

CREATE PROCEDURE concat (str1 VARCHAR(255) str2 VARCHAR(255)) RETURNING VARCHAR(255) RETURN str1 || str2

END PROCEDURE

INSTR

CREATE PROCEDURE instr( str VARCHAR(255) mask VARCHAR(255) strt SMALLINT DEFAULT 1 occur SMALLINT DEFAULT 1 ) RETURNING INT DEFINE slen SMALLINT DEFINE mlen SMALLINT DEFINE tempstr VARCHAR(255) DEFINE tempmask VARCHAR(255)

DEFINE nomatch SMALLINT DEFINE count SMALLINT DEFINE pos SMALLINT DEFINE retpos SMALLINT DEFINE i SMALLINT DEFINE j SMALLINT DEFINE srchstrt SMALLINT LET slen = LENGTH(str) LET mlen = LENGTH(mask) LET count = 0 LET nomatch = 0 LET pos = 1 LET retpos = 1 LET tempstr = LET tempmask = LET srchstrt = strt

IF (strt lt 0) THEN - reverse the str FOR i = 1 TO slen LET tempstr = str[11] || tempstr LET str = str[2255] END FOR -- reverse the mask FOR i = 1 TO mlen LET tempmask = mask[11] || tempmask LET mask = mask[2255] END FOR

IBM Software Group IBM Information Management

Version 16 86

LET srchstrt = strt -1 LET str = tempstr LET mask = tempmask END IF FOR j = 1 TO slen LET tempstr = str LET tempmask = mask FOR i = 1 TO mlen IF (tempmask[11] = tempstr[11]) THEN LET nomatch = 1 EXIT FOR END IF LET tempmask = tempmask[2255] LET tempstr = tempstr[2255]

END FOR IF (nomatch = 0) THEN IF (pos gt= srchstrt) THEN LET count = count + 1 END IF IF (count = occur) THEN IF (strt lt 0) THEN RETURN slen - pos + 1 ELSE RETURN pos END IF END IF END IF LET str = str[2255] LET nomatch = 0

LET pos = pos + 1 END FOR RETURN 0 END PROCEDURE

YYYYMMDD

CREATE PROCEDURE yyyymmdd (str VARCHAR(10)) RETURNING varchar(8)

DEFINE retstr VARCHAR(8)

IF str IS NULL THEN

RETURN NULL

ELSE

LET retstr = str[710] || str[12] || str[45]

RETURN retstr

END IF

END PROCEDURE

Using EXEC bladelet functions

IBM Software Group IBM Information Management

Version 16 87

Using EXEC

Note the ROW data type variable can be referenced using table and column syntax CREATE PROCEDURE example1() RETURNING INTEGER

DEFINE sql_stmt LVARCHAR(255)

DEFINE rcnt ROW(val INTEGER)

LET sql_stmt = select count() from items where manu_code = lsquoANZrsquo

EXECUTE FUNCTION EXEC(sql_stmt) INTO rcnt

RETURN rcntval

END PROCEDURE

Using EXEC_FOR_ROWS

CREATE PROCEDURE example2() RETURNING INTEGER CHAR(1)

DEFINE rs_rowdata ROW(customer_num INTEGER call_code CHAR(1))

DEFINE sql_stmt LVARCHAR(255)

LET sql_stmt = select customer_num call_code from cust_calls where

customer_num = 106

FOREACH

EXECUTE FUNCTION EXEC_FOR_ROWS(sql_stmt) INTO rs_rowdata

RETURN rs_rowdatacustomer_num rs_rowdatacall_code WITH RESUME

END FOREACH

END PROCEDURE

Using EXEC_FOR_MSET

Note the DEFINE statement for the variable rs_data Collection data types used in a SPL routine cannot be defined using the LIKE attribute in the DEFINE statement CREATE PROCEDURE example3() RETURNING INTEGER VARCHAR(8)

DEFINE v_customer_num LIKE accountscustomer_num

DEFINE v_account_cd LIKE accountsaccount_cd

DEFINE rs_data MULTISET(ROW(

r_customer_num INTEGER

r_account_cd VARCHAR(8)) NOT NULL)

DEFINE sql_stmt LVARCHAR

LET sql_stmt = select customer_num order_num from orders where

company_id = 51155

EXECUTE FUNCTION EXEC_FOR_MSET(sql_stmt) INTO rs_data

FOREACH

SELECT r_customer_num r_account_cd INTO v_customer_num

v_account_cd FROM TABLE(rs_data)

RETURN v_customer_num v_account_cd WITH RESUME

END FOREACH

END PROCEDURE

IBM Software Group IBM Information Management

Version 16 88

Date arithmetic Informix has extensive capabilities for manipulating dates and times You can add or subtract DATE and DATETIME variables from each other You can add or subtract an INTERVAL to a DATE or DATETIME

UNITS Keyword

When working with INTERVAL values sometimes it is necessary to specify the precision with which you are dealing For example suppose you have the following field defined To add 10 days to the lead time you could use a SQL statement like this

SELECT lead_time + INTERVAL(10) DAY to DAY FROM orders

-or- SELECT lead_time + 10 UNITS DAY FROM orders

Using EXTEND function

The EXTEND function allows operations between data types of different precisions SELECT

EXTEND(myvar YEAR to MINUTE) ndash INTERVAL(5) MINUTE to MINUTE

FROM member

Calculate Week Of The Year

SELECT ROUND((TODAY - DATE(0101||YEAR(TODAY))) 7 + 5) FROM DUAL

Number of days difference SELECT DATE(0106||YEAR(TODAY)) - DATE(01062005) FROM DUAL

Number of weeks difference

SELECT ROUND((DATE(0106||YEAR(TODAY)) - DATE(01062005))

7 + 5) FROM DUAL

String representation of date and time

Day and date

SELECT TO_CHAR(TODAY A B d Y) FROM dual

-returns month day and 4 digit year-

Tuesday January 03 2006

Abbreviation of day of week

SELECT SUBSTR(TO_CHAR(TODAY A B d Y R)13) FROM dual

-or-

SELECT TO_CHAR(TODAY a) FROM dual

-returns MON TUE WED THU FRI SAT SUN-

Returning the number of rows affected

IBM Software Group IBM Information Management

Version 16 89

Within SPL routines you can use the DBINFO function to find out the number of rows that have been processed in SELECT INSERT UPDATE DELETE EXECUTE PROCEDURE and EXECUTE FUNCTION statements

CREATE FUNCTION del_rows(pnumb INT) RETURNING INT

DEFINE nrows INT

DELETE FROM sec_tab WHERE part_num = pnumb

LET nrows = DBINFO(sqlcasqlerrd2)

RETURN nrows

END FUNCTION

To ensure valid results use this option after SELECT and EXECUTE PROCEDURE or EXECUTE FUNCTION statements have completed executing If you use the sqlcasqlerrd2 option within cursors make sure that all rows are fetched before the cursors are closed

Using an Informix collection data type

A collection data type as a VARRAY

In the following examples the collection data types of MULTISET and SET are used in a function to hold a collection of values You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value Informix SPL allows you to declare a cursor for a collection variable using the FOREACH statement called a collection cursor

Also demonstrated is how to utilize a variable declared with the keyword COLLECTION A variable declared as type SET MULTISET or LIST is a typed collection variable It can hold a collection of its specified data type only However a COLLECTION is an un-typed (or generic) collection variable that can hold a collection of any data type

This function will build a MULTISET list of values

CREATE FUNCTION func1() RETURNING MULTISET(INTEGER NOT NULL)

DEFINE v_array_of_ints MULTISET(INTEGER NOT NULL)

INSERT INTO TABLE (v_array_of_ints) VALUES(1)

INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(5)

INSERT INTO TABLE (v_array_of_ints) VALUES(4)

RETURN v_array_of_ints

END FUNCTION

This function will receive the COLLECTION list of values from func1

CREATE FUNCTION func2() RETURNING INTEGER

--

-- DEFINE lmset MULTISET(INTEGER NOT NULL)

--

DEFINE lmset COLLECTION

DEFINE v_int INTEGER

--

-- call func1 to populate local multiset variable

--

LET lmset = func1()

--

-- tally a count the number of elements

--

FOREACH

SELECT COUNT() INTO v_int FROM TABLE(lmset)

IBM Software Group IBM Information Management

Version 16 90

RETURN v_int WITH RESUME

END FOREACH

--

-- return the values

--

FOREACH

SELECT INTO v_int FROM TABLE(lmset)

RETURN v_int WITH RESUME

END FOREACH

END FUNCTION

NOTE In the example func2 a duplicate declaration for the ldquolmsetrdquo variable as a MULTISET data type has been commented out by declaring the variable as a COLLECTION it can accept any of the 3 types (MULTISET SET and LIST)

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

4 (row count) 1 2 5 4

By using a SET data type inserts will not permit duplicates

CREATE FUNCTION func1() RETURNING SET(INTEGER NOT NULL) DEFINE v_array_of_ints SET(INTEGER NOT NULL) INSERT INTO TABLE (v_array_of_ints) VALUES(1) INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(2) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) RETURN v_array_of_ints END FUNCTION

NOTE Because func2 is expecting a un-typed COLLECTION variable func1 does not have to be dropped and recreated It can receive a value from any Collection Data Type (MULITSET SET and LIST)

The functionrsquos return values would change to (with duplicates suppressed)

EXECUTE FUNCTION func2()

(expression)

3 (row count) 1 2 5

Using a LIST data type support for assigning values based on ordinal position

IBM Software Group IBM Information Management

Version 16 91

CREATE FUNCTION func1() RETURNING LIST(INTEGER NOT NULL)

DEFINE v_array_of_ints LIST(INTEGER NOT NULL) -- -- first insert no ordinal position can be established By default the -- database server inserts LIST elements at the end of the list -- INSERT AT 5 INTO TABLE (v_array_of_ints) VALUES(5) INSERT AT 1 INTO TABLE (v_array_of_ints) VALUES(1) INSERT AT 2 INTO TABLE (v_array_of_ints) VALUES(2) -- -- Only 3 LIST elements exist position 4 has not been instantiated -- this element will insert at the end of the list -- INSERT AT 4 INTO TABLE (v_array_of_ints) VALUES(4) INSERT AT 3 INTO TABLE (v_array_of_ints) VALUES(3) RETURN v_array_of_ints END FUNCTION

NOTE The elements of a LIST have ordinal positions with a first second and third element in a LIST To support the ordinal position of a LIST the INSERT statement provides the AT clause This clause allows you to specify the position at which you want to insert a list-element value Note the behavior of the ordinal positioning above preceded by a commented explanation

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

5 (row count) 1 2 3 5 4

Using MULTISET and ROW to replace PLSQL TABLE and RECORD types

Creating variables using Informix Collection data types SET MULTISET and LIST in combination with ROW data types can be useful when migrating applications which use Oracle REF CURSORS as arguments to functions as well as Oracle collection data types TABLE and RECORD

Typical Oracle Package specification

CREATE OR REPLACE PACKAGE MyPackage

IS

TYPE recOrders IS RECORD (

order_num ordersorder_numTYPE

order_date ordersorder_dateTYPE

customer_num orderscustomer_numTYPE

po_num orderspo_numTYPE

)

TYPE tabOrders IS TABLE OF recOrders

INDEX BY BINARY_INTEGER

TYPE ref_curtype IS REF CURSOR

Both tabOrders or ref_curtype can be converted to the following Informix SPL definition

DEFINE tabOrders MULTISET(ROW(

IBM Software Group IBM Information Management

Version 16 92

order_num INTEGER

order_date DATETIME YEAR TO FRACTION(3)

customer_num INTEGER

po_num CHAR(10)) NOT NULL)

DEFINE ref_curtype MULTISET(ROW(

define columns based on query result set

) NOT NULL)

IBM Software Group IBM Information Management

Version 16 93

A P P E N D I X E Counting system objects

Using the system catalog

System catalog

Below is a list of SQL statements that will extract most if not all of the counts of system objects owned by user lsquoXXXrsquo

select count(table_name) from all_tables

where owner=rsquoxxxrsquo

select count() from dba_indexes

where owner=rsquoxxxrsquo

select count(synonym_name) from dba_synonyms

where owner=rsquoxxxrsquo

select count() from dba_views

where owner=rsquoxxxrsquo

select count() from dba_tab_columns

where length(column_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

and owner=rsquoxxxrsquo

select count distinct() from dba_tab_columns

and owner=rsquoxxxrsquo

select count() from dba_tables

where length(table_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_synonyms

where length(synonym_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_views

where length(view_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_indexes

where length(index_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and owner=rsquoxxxrsquo

IBM Software Group IBM Information Management

Version 16 94

select data_type count(data_type) from dba_tab_columns

where owner=rsquoxxxrsquo

group by data_type

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and length(data_type)gt254

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquonumberrsquo

and data_scale=0

and owner=rsquoxxxrsquo

Using SQL code

Built-in function references

The following instructions can be used to find references to built-in functions On the UNIX machine or the NT box where your code resides please create the following file as tmpfunctionlist

convert(

hextoint(

inttohex(

getdate(

datename(

datepart(

datediff(

dateadd(

months_between(

char(

char_length(

charindex(

compute(

difference(

length(

lower(

patindex(

replicate(

reverse(

right(

soundex(

space(

str(

stuff(

substring(

upper(

abs(

atn2(

log(

ceiling(

IBM Software Group IBM Information Management

Version 16 95

cot(

degrees(

floor(

radians(

rand(

sign(

to_char(

to_date(

to_number(

exception(

pi(

raise_application_error(

raiserror(

SQLCODE

rollback

savepoint

declare

decode(

nvl(

print(

rowid

waitfor

recompile

bcp

isopen(

notfound(

rowtype(

type(

Then please run the following program with the proper subdirectories

binksh

rm ndashf somehomeoutfile

cd somesourcedatabase

export sourcebase=rdquosomepathrdquo

for functor in `cat tmpfunction_list`

do

echo before find $functor

find $sourcebasedatabase -exec grep -i $functor gtgt

somehome$functoroutfile

find $sourcebaseintfc -exec grep -i $functor gtgt

somehome$functoroutfile

echo after find $functor

done

Object types and counts

This script attempts to count the objects of each type by grepping for CREATE statements containing the object type and counts procedure definitions that are inside package bodies which are not proceeded by a CREATE keyword It is not a sophisticated parser so the results may not be perfect

binbash if [ $1 = ] then

IBM Software Group IBM Information Management

Version 16 96

echo Usage objCountssh ltFilePatterngt return 1 fi declare -a objectTypes=(CLUSTER CONTEXT CONTROLFILE DATABASE DATABASE +LINK DIMENSION DIRECTORY DISKGROUP FUNCTION INDEX INDEXTYPE JAVA LIBRARY MATERIALIZED +VIEW MATERIALIZED +VIEW +LOG OPERATOR OUTLINE PACKAGE PACKAGE +BODY PFILE PROCEDURE PROFILE RESTORE +POINT ROLE ROLLBACK +SEGMENT SCHEMA SEQUENCE SPFILE SYNONYM TABLE TABLESPACE TRIGGER TYPE TYPE +BODY USER VIEW) echo for type in $objectTypes[] do if [ $type = PROCEDURE ] then echo $type object count `cat $1 | grep -icE ^ (|CREATE +|OR REPLACE +)b$typeb` else echo $type object count `cat $1 | grep -icE ^ (CREATE +|OR +REPLACE +)b$typeb` fi done

IBM Software Group IBM Information Management

Version 16 97

A P P E N D I X F Data type mapping

Oracle built-in data types (including ANSI types) can be converted to similar data types in the Informix database according to the mapping described here This table provides default mappings based on most common usage patterns in some cases another mapping may work better

In the following table n is used to indicate length p is used to indicate precision and s is used to indicate scale

Oracle data type Informixreg Server data type

BFILE LONG RAW BLOB

BLOB

BINARY_DOUBLE DOUBLE PRECISION

BINARY_FLOAT DOUBLE PRECISION

BINARY_INTEGER

PLS_INTEGER

NATURAL

NATURALN

POSITIVE

POSITIVEN

32-bit integers only used in PLSQL NATURAL and POSITIVE are unsigned integers

INTEGER

BOOLEAN (PLSQL only) BOOLEAN

CHAR(n) or CHARACTER(n) CHAR(n)

DATE DATETIME YEAR TO SECOND

DOUBLE PRECISION DOUBLE PRECISION

IBM Software Group IBM Information Management

Version 16 98

FLOAT

See note on FLOAT below

FLOAT

INTEGER INT

A 38-digit NUMBER sub-type May want to flag with a warning on possible overflow

INTEGER

INTERVAL DAY(p) TO SECOND(s)

Note Oracle fractional seconds have 9 digits

INTERVAL DAY(p) TO FRACTION(min(5 s))

INTERVAL YEAR(p) TO MONTH

INTERVAL YEAR(p) TO MONTH

LONG CLOB

CLOB

LONG VARCHAR (xxx)

Oracle recommends not using this type

LVARCHAR

NCHAR(n) NATIONAL CHAR(n) or NATIONAL CHARACTER(n)

NCHAR(n)

See National Language Types below

NCLOB CLOB

NUMBER

NUMBER(0)

NUMBER(p) NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s lt 10

NUMBER(3-2) 12300

INTEGER

IBM Software Group IBM Information Management

Version 16 99

NUMBER(p) NUMBER (p0)

Where precision (p) is greater than or equal to 10 and lt= 18

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and 10 lt= p-s lt 19

NUMBER(9-2) 12345678900

BIGINT

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is greater than or equal to s (that is s gt 0 and p gt= s)

NUMERIC (min(p32) min(s32))

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is less than s (that is s gt 0 and p lt s)

NUMBER(35) 000123

NUMERIC (min(s32)min(s32))

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s gt 18 and p-s lt= 32

NUMERIC (min(p-s32)0)

NUMBER(p s)

Where scale (s) is greater than 32 or pInformix-s is greater than 32

NUMERIC (32)

Scale cannot be greater than precision

NUMERIC(3232) would guarantee that digits to the left of the decimal would be lost Using a floating point decimal provides the simplest best way to capture as many digits in a value as possible

IBM Software Group IBM Information Management

Version 16 100

DEC

DECIMAL

NUMERIC

DEC(p)

DECIMAL(p)

NUMERIC(p)

DEC(p s)

DECIMAL(p s) NUMERIC(p s)

There is no difference within Oracle between these types and each other and these types and NUMBER The Oracle system catalogs contain the NUMBER type id for all declarations of these types and the integer types as well Declarations of these types can be mapped using the same rules as those for NUMBER

NVARCHAR2(n) NCHAR VARYING(n) NATIONAL CHAR VARYING(n) NATIONAL CHARACTER VARYING(n)

LVARCHAR(min(n 32767))

RAW(n) BLOB

REAL DOUBLE PRECISION

Record ROWTYPE

Using a CREATE ROWTYPE statement

ROWID INTEGER

SMALLINT SMALLINT

TIMESTAMP(p)

If p is not specified precision defaults to 6

DATETIME YEAR TO FRACTION(min(5 p))

UROWID(n) INTEGER

IBM Software Group IBM Information Management

Version 16 101

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is less than or equal to 255 (that is n lt= 255)

VARCHAR(n)

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is greater than 255 (that is n gt 255)

LVARCHAR(n)

XMLType CLOB

Notes on specific types are below

DOUBLE

The range of values for the DOUBLE PRECISION data type is the same as the range of the C double data type on your computer

VARCHAR

While Oracle VARCHAR data types have a limit of 4000 bytes an Informix Server VARCHAR data types has a limit of 255 bytes An Informix Server LVARCHAR has a limit of 32739 Bytes

NUMBER

Oracle abstracts its numeric types from the hardware and operating system through the use of its NUMBER type Most numeric types like INTEGER are actually NUMBERs internally When porting to a database server like Informix which retains more of a relationship between the operating system types and the database types it is essentially a one-to-many mapping and heuristics have to be used to determine the best-fit target type No single set of type mapping rules will fit all use scenarios The converter has default rules which fit the more common user patterns When considering a number represented as mantissa and exponent

mantissa x 10exponent

precision is the number of digits in the mantissa and scale is the negative exponent how many places to the right of the decimal point the least significant digit is located Oracle NUMBERs have a maximum precision of 38 and the maximum precision available in Informix native types is 32 The first step in a type mapping is to truncate the target type precision to min(precision 32) The scale of a type can be considered its anchor point with respect to the decimal point The most

IBM Software Group IBM Information Management

Version 16 102

significant digit of a numeric type is located precision digits to the left of the decimal point and precision-scale digits to the right of the decimal point The start and end locations of the digits are used to determine the closest fitting Informix type The order of preference is INTEGER BIGINT NUMERIC(p s) and lastly NUMERIC(p) NUMERIC(p) in a non-ANSI mode database is a decimal type with a floating point type In an ANSI mode database the scale is implicitly 0 All Oracle integer declaration types such as INT INTEGER SMALLINT become NUMBER(38) type in the Oracle metadata In Oracle when precision is given but scale is not scale becomes 0 implicitly which makes the type in the set of integral types One exception to the general mapping rules is the NUMBER type specified without precision or scale Strictly speaking this has a floating point scale with 38 digits of precision but most commonly it is used where an integer is more appropriate Even if the user does specify INTEGER in a type definition when it comes out of the Oracle catalogs the type is NUMBER This is one case in particular where one type mapping will not fit well with all usage scenarios

National language types

Oracle Nchar types are allocated by number of characters where Informix is allocated by the number of bytes For Oracle the storage size of the characters varies with the encoding used and is always subject to the standard 32767 limit on maximum bytes but during declarations n always means the number of characters Oracle PLSQL supports explicit and implicit data type conversions These explicit and implicit data types are converted to syntax by using Informix Dynamic Servers explicit and implicit data type conversion mechanism

ROWID

Oracle databases support a pseudo-column named ROWID such that every row in every table is assigned an auto-generated ID Oracle also allows you to define a column of type ROWID which can be used as a foreign key to a ROWID pseudo-column Oracle ROWID columns contain data that if converted to a string are 18 characters long for example lsquoAAAQ+jAAEAAAAAeAANrsquo It is probably not advisable to migrate this data to an Informix database and instead use the Informix type which is an integer If there is a dependency on the values themselves and therefore need migrate the data then an integer type would not hold the values

TYPE

In PLSQL you can refer to the type of an existing variable field or column by using the TYPE attribute The converter replaces this reference directly by the type it refers to

ROWTYPE

In PLSQL you can refer to the record type that represents a row of a table a cursor or a cursor variable PLSQL scripts containing the ROWTYPE attribute are handled in the same way as a record type that has been previously declared

FLOAT

Oracle FLOAT type is a floating point number capable of storing up to 38 decimal digits or 126 binary digits It has a floating point scale that can exist outside the boundaries of what an Informix DECIMAL can represent A C language double or Informix float type is capable of only 16 digits so there is the chance that some data will be lost Using an Informix FLOAT type makes it so that less significant digits are lost in preference to more significant digits

IBM Software Group IBM Information Management

Version 16 103

References to subtypes declared in packages and PLSQL blocks are converted to the Informix Server equivalent base types Variables of type RECORD are not translated by the DDL Converter at the time of this writing They will be handled by the stored procedure converter

XMLType

Informix does not have a built-in type for representing XML The nearest approximation is to store it in a CLOB Another character type like LVARCHAR can be used if it can be determined that the actual data will fit in it

Page 5: Oracle to IBM Informix Server Porting Guide

IBM Software Group IBM Information Management

Version 16 5

External optimizer directives 35 Inserts 36 Temporary tables 36 Outer joins 36 Sorts 36 Exceptions 37 Correlation names 37 Aliases 37 Hierarchical queries 37 Truncate 39

HOST VARIABLES 40 DATE AND TIME FUNCTIONS 41

SYSDATE 41 Number formats 41 Date formats 42 The RR date format element 43

USER-DEFINED ROUTINES 43 COMPATIBLE SQL FUNCTIONS 43 AGGREGATE FUNCTIONS 43 MATHEMATICAL FUNCTIONS 44 STRING FUNCTIONS 44

LENGTH 44 LTRIM and RTRIM 44 Oracle Extensions 44

OTHER ORACLE FUNCTIONS 44 MACROS 45

ISOPEN and NOT FOUND 45 ROWTYPE 45 TYPE 45

PSEUDO-COLUMNS 45 LEVEL 46 ROWID 46 ROWNUM 46

UPDATE USING CURSORS 49 SYSTEM TABLES 50 STORED PROCEDURES 50

Size limit 50 Parameter limit 50 Packages 51 Routines 51 Exceptions 51 Error handling 52 Cursors 52 Variable declaration and assignment 53 Boolean 53 Binary data types 53 Dynamic SQL 53 Compiler 53

TRIGGERS 54 CONSTRAINTS 55 DUAL TABLE 55

C H A P T E R 5 EMBEDDED SQL 57

HOST VARIABLES 57 Declaration override 57 Arrays 57 Formatting 58

SQL STRUCTURES 59

IBM Software Group IBM Information Management

Version 16 6

SQLCA 59 SQLDA 60 ORACA 61

PRE-COMPILER OPTIONS 61 EMBEDDED PLSQL 61 ORACLE CALL INTERFACE 61

Database library calls 62 Global area processing 62 Fetch cycle 62 RAW binary data type processing 62 Parameter bindings 62

EMBEDDED SQL FOR C 63 VARCHAR 63 Host variables 63

EMBEDDED SQL FOR COBOL 63 VARCHAR 63 Level 88 64 SQLDA 64 REDEFINES 64 Tips 64

ODBC 64

C H A P T E R 6 APPLICATION ARCHITECTURE 65

TRANSACTION PROCESSING 65 Autonomous Transaction 66 Savepoints 67

CONCURRENCY 67 Row Level Locking 67 Transaction Isolation Level 68

C H A P T E R 7 SECURITY 70

USER AUTHENTICATION 70 Operating system security 70 Non-operating system security 70

ROLE BASED AUTHORITY 71 COLUMN-LEVEL ENCRYPTION 71

Passwords and hints 71 Encrypting a column 72 Querying an encrypted column 72 Performance impact of encryption 73 Storage considerations 73 Compliance regulations 73

C H A P T E R 8 ENVIRONMENT 74

SCRIPTS 74 SQL script substitution variables 74

UTILITIES 75 SYSTEM CATALOG 75

C H A P T E R 9 USING BLADELETS 76

WHAT IS A BLADELET 76 INFORMIX EXEC BLADELET FOR DYNAMIC SQL 77 SQLLIB DATABLADE MODULE (SQLLIBC11 SQLLIBJ11) 78

A P P E N D I X A PLANNING GUIDE 79

A P P E N D I X B SYNTAX COMPARISON 82

IBM Software Group IBM Information Management

Version 16 7

A P P E N D I X C DATABASE CONCEPTS 84

A P P E N D I X D SAMPLE CODE 85

DATE ARITHMETIC 88 UNITS Keyword 88 Using EXTEND function 88

STRING REPRESENTATION OF DATE AND TIME 88 Day and date 88 Abbreviation of day of week 88

USING AN INFORMIX COLLECTION DATA TYPE 89 A collection data type as a VARRAY 89 Using MULTISET and ROW to replace PLSQL TABLE and RECORD types 91

A P P E N D I X E COUNTING SYSTEM OBJECTS 93

USING THE SYSTEM CATALOG 93 System catalog 93

USING SQL CODE 94 Built-in function references 94 Object types and counts 95

A P P E N D I X F DATA TYPE MAPPING 97

DOUBLE 101 VARCHAR 101 NUMBER 101 National language types 102 ROWID 102 TYPE 102 ROWTYPE 102 FLOAT 102 XMLType 103

IBM Software Group IBM Information Management

Version 16 8

C H A P T E R 1 Introduction

This document is a technical document describing the differences between Oracle and Informixreg Dynamic Server (IDS) functionality and syntax This porting guide details differences between Oraclersquos 10g release 1 (101) and 10g release 2 (102) and Informix Dynamic Server (version 1110) In addition it can be a useful reference for all migrations between the two database servers regardless of version In addition to DDL DML and overall SQL syntax this document explores the differences between Oracle and Informix with regards to object technology through the use of large objects user defined types and user defined routines It also looks at the differences between Oraclersquos table partitioning and Informixrsquos table fragmentation Part of the explanation is a discussion on what needs to be changed to make an application running on an Oracle database run on an Informix database If there is more than one way to port some piece of functionality alternatives and recommendations are also discussed This document is intended to be a living document Missing items better ways of implementing Oracle functionality in Informix other than what is documented here examples to better illustrate a point and other suggestions should be sent to Chris Golledge (golledgeusibmcom) so they may be included with future revisions

Purpose This document should be used as a guide to assist in porting applications that run on an Oracle database server to run on an Informix database server Regardless of whether a porting effort will be completely manual or if tools will be utilized this document can provide value Obviously if the port is performed manually this guide will provide the most value If the port will utilize tools then analysis can be performed using this guide to determine how much of the application the tools will convert and how much must be converted manually In any case this guide is intended to be used to both visualize the scope of a porting effort and to aid in the porting effort by addressing the technical issues This document will be refined based on usersrsquo experiences to identify as many of the porting issues as possible at the beginning of a project

Product overview IBM Informix Server provides high performance and scalability with legendary reliability and nearly hands-free administration of databases of all size IDS is industry proven on UNIX Linux or Windows platforms with online transaction processing (OLTP) systems data marts data warehouses and e-business applications The IDS 11 release features significant additions over prior versions It supports the services-oriented architecture (SOA) model for application integration and offers many new features for data replication continuous availability and ldquohands freerdquo database administration

Organization This document is broken into sections to logically discuss the different database concepts Some of the sections may contain the same sub-sections for example stored procedures and triggers

IBM Software Group IBM Information Management

Version 16 9

are discussed in the DDL and DML sections This allows separate discussions on the issues facing the same item in each area For example the issues surrounding creating a stored procedure are discussed in the DDL section and the issues surrounding the stored procedure language are discussed in the DML section Among the other references the ldquoPlanning Guiderdquo appendix contains a quick reference of most of the differences between Oracle and Informix along with the degree of difficulty to port each difference This reference is intended for use in the planning process to illustrate the scope and the effort required to perform the porting project Some of the stored procedure logic used to convert Oracle functions is included in the appendix rdquoSample coderdquo

Conventions The conventions used in this document include

Courier Text Distinguishes a logic example

from regular text

Example Illustrates a point In most cases an Oracle example will be followed by an Informix example

Italicized Text Signifies a substitution in other words substitutes for the italicized word the actual object the word is describing for example table_name column_name and so on

UPPER CASE TEXT Signifies database vendor reserved words or statements such as INTEGER CREATE TABLE and so on

Bold example text highlights the item that is being explained

IBM Software Group IBM Information Management

Version 16 10

IBM Software Group IBM Information Management

Version 16 11

C H A P T E R 2 Defining the Problem Space

It is important to define the set of objects to be migrated and it is better if effort is put into this prior to beginning the actual migration This is true if you are the responsible for both the database in general and its migration from one supporting DBMS to another but it is particularly true that there be a clear agreement on the scope of what is to be migrated if the migration is to be performed by a party other than the one with long term responsibility for the database Defining the scope will involve extracting a representation of the objects to be migrated out of the Oracle system catalogs and representing them in some format that can be manipulated into constructs that can be used in Informix

Extracting the objects to be migrated It is possible to represent the objects in more than one language Using the SQL language is the most common method and it will be the only one discussed at length in this document (in its current revision) However it is also possible to express database objects in XML SQL has the advantage that the standard common grammars are widely understood in the context of defining tables indexes etc XML would have an advantage of not requiring parsing that is sensitive to the minor differences in ways of expressing essentially the same object

Working With Oracle Dump Files

There exist 3rd

-party tools for reading system catalogs but it is doubtful that any can read the Oracle catalogs more reliably than Oraclersquos own tools There are two incompatible export and import tool sets used by Oracle The older tools are imp and exp and the newer ones are impdp and expdp where dp stands for Data Pump Oracle has encouraged the use of the newer tools instead of the older ones since the newer ones were introduced at version 10 Nonetheless there are many Oracle users still using imp and exp In the discussions below only the metadata will be extracted into a dump file That is because any data in the dump file will be in a proprietary format and very likely some of the data will have to go through a type conversion process before being loaded into an Informix system Oracle exported data generally cannot be used to load a database in Informix Export and Import

If someone has given you a dump file created with the older export tool there exist tools such as The DDL Wizard by Net 2000 Limited which can be used to extract viable DDL The contents of the dump file contain the SQL for re-creating the database but they are not in a readily usable format The older export and import tools are also more sensitive to the layout of the tablespaces than impdb The ability to extract DDL from the dump file in a usable form segmented by whatever grouping you choose is limited compared to what can be achieved through the Data Pump versions

IBM Software Group IBM Information Management

Version 16 12

It may be tempting to feed the dump file into the IBM Migration Toolkit (MTK) or other tool that works on SQL flat files This will not work MTK works on flat text SQL files and the dump file is binary If you open it up you can see what may be a large number of SQL statements but there are also binary codes within the same file That binary data will prevent MTK from being able to process it Getting SQL statements

If you want to get the SQL statements out of the dump file as they would be executed on the server there is an option available from the import tool itself show=y

imp myIDmyPWD as sysdba file=myFiledmp

full=yes show=y gt dmp_showtxt

This will produce a file which contains the statements but they are wrapped in quotes The contents will look something like

ALTER SESSION SET CURRENT_SCHEMA= SYSTEM CREATE UNDO TABLESPACE TBSPC1 BLOCKSIZE 8192 DATAFILE DORACLEORADA TASCHEMA1CHUNKDBF SIZE 387973120 AUTOEXTEND ON NEXT 5242880 MAXS IZE 32767M EXTENT MANAGEMENT LOCAL

which makes them strings instead of SQL statements Fixing this is a two-step process

-- removes quotes from the start of lines

sed s^ g dmp_showtxt gt step1txt

-- removes quotes from the end of lines

sed s$g step1txt gt dmp_step2sql

The statements are still not correctly formatted because they have been truncated to a fixed length and line-endings inserted However at this point it is possible to get a count of how many of each object type there is using the script in the appendix ldquoGetting an initial count of database objectsrdquo

Data Pump Export and Import

These newer tools provide better performance and more capabilities than their predecessors Please refer to documentation on Oracle for a complete description searches for ldquoData Pump Importrdquo and ldquoData Pump Exportrdquo should return relevant results quickly Below is enough information to get started on defining and extracting the objects to be migrated Metadata can be filtered through the use of the export mode clause and INCLUDE and EXCLUDE parameters However any dependent object of an included or excluded object is likewise included or excluded For example if you include an index then the table associated with the index will also be included and if you exclude a table then any associated indexes will also be excluded The SQL that will generate all the objects in the dump file can be created by the impdp command with the SQLFILE parameter If the output file is very large you might want to break it into smaller pieces There are a couple of ways to do this and the one that is best for you somewhat depends

IBM Software Group IBM Information Management

Version 16 13

on how you intend to proceed with the conversion Data definition language (DDL) SQL for all the objects can be put into one file or the INCLUDE or EXCLUDE parameters can be added to direct Data Pump to filter on the types of objects If you put all the objects into one file then you can break that into smaller files by object type fairly easily because the objects are sorted by type in the SQL file So it is just a matter of cutting the file into smaller pieces This method may be preferred because it allows for you to do things like create all tables load the data and then create the indexes and triggers If the data set is large creating the indexes after loading the data can yield substantial performance improvements However this is less useful if you want to convert sets of objects according to dependencies in which case the filtering option is likely to be more useful Just to illustrate a difference between these two methods in one customer case the metadata dump file was about 18MB and putting all objects in one SQL file resulted in a file that was about 15MB The table definitions occupied a little under 300KB of the 15MB The output file generated by filtering on objects of type TABLE was just over 1MB The addition content was mostly GRANT INDEX and TRIGGER creation statements There were no differences in the CREATE TABLE statements themselves Examples

Prerequisite The Data Pump tools require the use of an Oracle DIRECTORY object This is basically a mapping between a name that exists within the DBMS and a system path It can be a tripping point but it provides an abstraction layer that for instance allows the same commands to work across systems with different disk layouts or different operating systems Creating a DIRECTORY on a Windows system from SQLPlus

SQLgtconnect as sysdba

SQLgtCREATE OR REPLACE DIRECTORY dumpDir AS ctemp

Note Make sure this directory is not read-only There also could be problems if the directory is a network drive on Windows these can be related to there being different users between the Oracle executable and the current user and those users having different permissions on the network drive

SQLgtGRANT read write ON DIRECTORY dumpDir TO userID

Creating a dump file of the entire database

expdp userNameuserPwd as sysdba FULL=Y dumpfile=DB_fulldmp

LOGFILE=LG_expdplog CONTENT=METADATA_ONLY DIRECTORY=dumpDir

Creating a dump file of just one schema

expdp userNameuserPwd as sysdba SCHEMAS=hr DIRECTORY=dumpDir

DUMPFILE=hr dmp LOGFILE=hr log CONTENT=METADATA_ONLY

Creating a dump of just the tables and their dependents

expdp userNameuserPwd as sysdba SCHEMAS=hr INCLUDE=TABLE

DIRECTORY=dumpDir DUMPFILE=hrdmp LOGFILE=hrlog

CONTENT=METADATA_ONLY

Creating a dump of just one table

expdp userNameuserPwd as sysdba SCHEMAS=hr

INCLUDE=TABLELIKE COUNTRIES DIRECTORY=dumpDir

DUMPFILE=hrdmp LOGFILE=hrlog CONTENT=METADATA_ONLY

IBM Software Group IBM Information Management

Version 16 14

Creatinge an SQL file from a dump file

impdp userNameuserPwd as sysdba DIRECTORY=dumpDir

DUMPFILE=hrdmp SQLFILE=dumpDirhrsql

The INCLUDE and EXCLUDE options are also valid when used with impdb so it may be easier to get a complete dump of everything to be migrated then use these options to create subsets of objects it smaller SQL files than it would be to create separate dump files It is easier to divide objects than to merge them together if they are not divided initially as wanted There is a caveat when using this impdp to generate an SQL file the object names will all be delimited identifiers Example

CREATE TABLE HRCOUNTRIES Because of differences between how Informix handles these and how Oracle handles these case-sensitivity issues could occur See the chapter on ldquoDelimited Identifiersrdquo and in particular the description of default shift problems If it can be determined that there are no name collisions if regular identifiers are used removing the quotation marks as part of the conversion might avoid many problems In other words if there are no objects whose names only differ in case like foo and FOO then changing every occurrence of ldquoFOOrdquo to FOO in the DDL could eliminate case-sensitivity issues in the application DML It depends on if the application code uses the delimited form of the name predominantly or not

IBM Software Group IBM Information Management

Version 16 15

C H A P T E R 3 Data Definition Language

Identifiers An identifier specifies the simple name of a database object such as a table name column name index name view name stored procedure name and so on The maximum length of an Oracle identifier is 30 characters and can contain letters numbers ldquo_rdquo ldquo$rdquo and ldquordquo although Oracle highly recommends that ldquo$rdquo and ldquordquo should not be used In contrast Informix identifiers have a maximum length of 128 characters and may contain letters numbers ldquo_rdquo and ldquo$rdquo (as long as ldquo$rdquo is not the first character) See the Delimited Identifiers section below for information This means that all Oracle identifiers containing a ldquordquo anywhere in the identifier or a ldquo$rdquo as the first character must be replaced or modified to remove those characters from the identifier

Delimited identifiers

Delimited identifiers are also known as quoted identifiers and sometimes as escaped identifiers They have been part of the SQL standard since SQL92 but existed in various database management systems (DBMS) prior to that time In a nutshell they are a way to preserve case sensitivity in object names as well as to allow objects to have names outside of the conventions of SQL regular identifiers Prior to the behavior of identifiers in general being standardized different DBMS vendors implemented different means of achieving case-insensitivity for object names some converted all regular identifiers to uppercase and some converted regular identifiers to lowercase By SQL99 the concept of case normal form was standardized to mean simply stated that if there exists an uppercase equivalent of any character in a name then the uppercase version is stored in the system catalogs and used for comparison purposes See the SQL99 standard chapter 5 section 2 and in particular items 21 and 22 for a formal description of case normal form and how it applies to identifier comparisons Delimited identifiers can be used to specify names for database objects that are otherwise identical to SQL reserved keywords such as TABLE WHERE DECLARE and so on The only database object for which delimited identifiers cannot be used is a database name Database administrators and application programmers do not always communicate to each other with 100 efficiency and there is no guarantee that within either of these pools every member codes by the standard practice of the other members After describing how delimited identifiers work in Informix there will be a description of how any inconsistency of usage and the differences between Oracle and Informix can introduce some migration hurdles DELIMIDENT Environment Variable

To use delimited identifiers with Informix you must set the DELIMIDENT environment variable While DELIMIDENT is set strings enclosed in quotation marks ( ldquo ) are treated as identifiers of database objects and strings enclosed in apostrophes ( rsquo ) are treated as literal strings If the

IBM Software Group IBM Information Management

Version 16 16

DELIMIDENT environment variable is not set strings enclosed in quotation marks are also treated as literal strings When you set the DELIMIDENT environment variable you cannot use quotation marks ( rdquo ) to delimit literal strings If DELIMIDENT is set the database server interprets all strings enclosed in quotation marks as SQL identifiers not string literals Commonly within Informix systems DELIMIDENT is set or not on the client side according to the design of the application However if you are converting a database and all applications accessing it from a system where every occurrence of quotation marks (ldquoobjectNamerdquo) indicates an identifier and not a string literal you may want to consider setting it in the server environment in order to avoid any inconsistency between clients where it is set and where it might not be Using Quotes in Strings The apostrophe ( rsquo ) has no special significance in string literals delimited by quotation marks Conversely double quote ( Prime ) has no special significance in strings delimited by apostrophes For example these strings are valid Nancyrsquos puppy jumped the fence

rsquoBilly told his kitten No rsquo A string delimited by quotation marks can include a double quote character by preceding it with another double quote as the following string shows Enter y to

select this row When the DELIMIDENT environment variable is set quotation marks can only delimit identifiers not strings Use of Uppercase Characters You can specify the name of a database object with uppercase characters but the Informix server shifts these to lowercase characters unless the DELIMIDENT environment variable is set and the name of the database object is enclosed in quotation marks In this case the database server treats the name of the database object as a delimited identifier and preserves the uppercase characters in the name Delimited Identifiers By default the character set of a valid SQL identifier is restricted to letters digits underscore and dollar-sign symbols If you set the DELIMIDENT environment variable however SQL identifiers can also include additional characters from the codeset implied by the setting of the DB_LOCALE environment variable See the Identifier section of the Informix Guide to SQL Syntax for more information Storage Object Names In Informix delimited identifiers can be used to specify non-alphanumeric characters in the names of database objects However delimited identifiers can not be used to specify non-alpha characters in the names of storage objects such as dbspaces and blobspaces To use delimited identifiers DELIMIDENT must be set both at compile and run times For example to set DELIMIDENT environment variable with sh or ksh issue the following at the command line prompt

export DELIMIDENT=

Note You do not need to assign a value to the environment variable and counter-intuitively setting DELIMIDENT=n has the same effect as DELIMIDENT=y Also in a Windows environment

set DELIMIDENT=

effectively undefines the variable Default shift problems

Any direct access of system catalog information involving names will cause problems when migrating from a system like Oracle where system catalog names are stored in uppercase to a system like Informix where the catalog names are stored in lowercase For example

CREATE TABLE foo (c1 int)

IBM Software Group IBM Information Management

Version 16 17

Within Oracle the following will return information about the table

select from sysall_objects where object_name = FOO

and the following will not

select from sysall_objects where object_name = foo

Conversely in Informix

select from systables where tabname = foo

will be successful and the same with FOO will not be A similar if not more common problem can occur when the table has been created without the name being delimited but is sometimes delimited when accessed by the application Per the standard foo == FOO == ldquoFOOrdquo but in Informix foo == FOO == ldquofoordquo In Oracle the following SELECT statement will be successful

SELECT FROM ldquoFOOrdquo

but within Informix this will result in an error ldquo206 The specified table (FOO) is not in the databaserdquo Likewise if the name is delimited in its definition such as

CREATE TABLE SCHEMA1TABLE1

this creates a table that can be referenced in Oracle without the name being delimited The statements

SELECT FROM schema1table1

and SELECT FROM SCHEMA1TABLE1

will be successful in the Oracle system but will fail in the Informix one In theory whether on object name is delimited or not should be the same in the database and at every occurrence within the application but this is not always the case It may be beneficial to examine whether delimited identifiers or regular identifiers are most commonly used in application code and use whichever is most common as a naming convention when translating the DDL

Explicit versus implicit schemaowner names

Another complication to keep in mind is that when the log mode is ANSI implicit and explicit owner names are treated differently between the Oracle and Informix servers In Oracle there is no difference in the case handling of an implicit owner name and an explicit one For example if connected to Oracle as scott the following CREATE TABLE statements

create table foo1(c1 int) create table scottfoo2(c1 int) create table SCOTTfoo3(c1 int)

all result in tables owned by SCOTT The following select statements in various forms that may be in application code will all run without error

select from foo1 select from scottfoo1

IBM Software Group IBM Information Management

Version 16 18

select from SCOTTfoo1 select from foo2 select from scottfoo2 select from SCOTTfoo2 select from foo3 select from scottfoo3 select from SCOTTfoo3

These statements will also run without error within a non-ANSI mode Informix database but not all of them will run successfully within an ANSI mode database This is because Informix does not uniformly fold the case of owner names and handles implicit names differently from explicit names so there will always be some combination of DDL and DML usage patterns that work within an Oracle system that do not work in an Informix one You can set ANSIOWNER before starting your Informix server but that will merely change which combinations do not work You may want to examine usage patterns within the applications and choose a naming convention when translating the DDL that matches the most common naming convention used in the applications Note This behavior of Informix forces a tradeoff between using an ANSI mode database which most closely matches the transaction behavior of Oracle and a non-ANSI mode database which has the least mismatch in identifier case sensitivity

Reserved words or keywords

Oracle and Informix both allow identifiers to be reserved words as long as they are delimited However Oracle and Informix reserved words differ In addition both systems have keywords like FROM that are not always reserved in the sense that using them as an identifier will always generate a syntax error There should be few problems with reserved words or keywords if identifiers that are delimited in the original database remain delimited in the destination database The appendix Keywords of SQL for IBM Informix in the Guide to SQL Syntax contains more information about Informix keywords Also one word non-delimited identifiers should be verified against the Informix reserved words list to ensure that they do not need to be delimited or renamed Although almost any word can be used as an identifier in Informix syntactic ambiguities can result from using reserved words as identifiers in SQL statements Delimited identifiers provide a way to use a reserved word as an identifier without causing syntactic ambiguities However doing this changes a case-insensitive name into a case-sensitive one and that means that every reference to the object has to be checked for issues related to case-sensitivity Essentially this is not much less work than changing the name of the object because in essence it is changing the name of the object Examples

The following example shows how to create an Informix table with a case sensitive table name

CREATE TABLE My_Customers (hellip)

The following example shows how to create a table whose name includes a space character If the table name were not in quotation marks () a space character or any other non-alpha character except an underscore ( _ ) or dollar sign ($) (see special conditions above) could be used in the name

CREATE TABLE My Customers (hellip)

IBM Software Group IBM Information Management

Version 16 19

The following example shows how to create a table that uses a keyword as the table name

CREATE TABLE TABLE (hellip)

To include a double-quote () within a delimited identifier the double-quote () must be preceded with another double-quote () as shown in the following example

CREATE TABLE MyGoodData (hellip)

Summary

The main points to keep in mind when deciding about any questions on how identifiers should be translated are

Oracle always has delimited identifiers enabled and Informix does not

Oracle folds regular identifiers to uppercase and Informix folds to lowercase

Informix has behavioral differences between an ANSI mode database and a non-ANSI mode one

It is beneficial to consider the most common usage patterns within the existing application code prior to deciding default identifier translation patterns

Databases

Databases database names and instances

Oracle and Informix implement databases and instances differently Oracle considers a database to be a set of data files control file(s) and log files while an instance is a set of background processes and memory structures accessing database data Oracle instances are also known as servers Each Oracle instance or server runs against one database but through the use of Oracle Parallel Server a database may have multiple instances accessing it An Oracle database is named at initialization and the name has a limit of 8 ASCII characters Informix databases are defined as ldquoa collection of information contained in tables that are useful to a particular organization or used for a specific purposerdquo Informix database names may be up to 128 characters in length An Informix instance is a set of processes memory and disk allocations that manage data and will contain at least two and in most cases many databases Informix instances are also referred to as servers Informix databases may share disk allocations (dbspaces) with other databases within an Informix instance Oracle databases cannot share disk allocations (tablespaces) Informix databases should be created in a dbspace other than the root dbspace The root dbspace holds data for the system configuration information for the engine and so on If user-defined objects are created in this dbspace then the dbspace may become unmanageably large and during backup the system information may also get backed up unnecessarily The CREATE DATABASE statements of Informix and Oracle have differences which may require modification to routines responsible for database creation Informix will accept the same minimal syntax required by Oracle (eg CREATE DATABASE myDB) however issuing the command will implicitly accept the creation of a database without transaction logging enabled and establish the default location for all database objects as the instancersquos default storage location The instancersquos default storage location or ldquorootrdquo dbspace should not contain user-defined objects The root dbspace holds data for the system and some configuration information for the engine If user-

IBM Software Group IBM Information Management

Version 16 20

defined objects are created in this dbspace it may become unmanageable and result in the system contending with user objects for the available space

ANSI vs non-ANSI

Informix supports both ANSI and non-ANSI databases Informix non-ANSI databases are most common but there are some advantages of ANSI databases when porting from Oracle

Oraclersquos transaction behavior is more or less like that of an ANSI database Applications ported on Oracle are always in a transaction In Oracle and ANSI databases transactions begin implicitly with the first of a series of SQL statements and will end immediately after a commit or rollback statement Therefore unlike a non-ANSI database a COMMIT WORK statement does not need to be preceded with a BEGIN WORK statement

In ANSI databases database object references must be prefixed by the ownerrsquos name unless the owner is the one referencing the object If Oracle applications reference database objects with a both parts of the object name prefixing the object name with schema using an ANSI database may ease modifications necessary when porting to Informix

The ldquolsquogrant to PUBLICrdquorsquo concept provide by Informix database security does not apply to ANSI databases Every database object is private and privileges must be explicitly granted to each user

If an Informix ESQLC or 4GL application was developed to run on a non-ANSI Informix database (including BEGIN WORK statements) the application could run on an ANSI Informix database in one of two ways

By placing the BEGIN WORK statement in a pre-processor directive such as IFDEF object_name and omitting the proper preprocessor compile options such as -D object_name

By compiling the application normally and ignoring the resulting warning messages

Additionally the LOG MODE ANSI clause must be added to the CREATE DATABASE statements ANSI mode databases cannot have buffered logging Applications written to use an open API like ODBC or JDBC are compiled without awareness of the database and these APIs are written with the intent to abstract specific database behavior For instance in one of these the application developer would call a function to begin or end a transaction rather than execute a BEGIN and COMMIT or ROLLBACK The API would execute these statements internally or not as necessary for the database connection See the Transaction Processing section in Application Architecture for more information on how an application running on a non-ANSI Informix database can simulate Oracle transaction behavior

Tablespaces and dbspaces Oracle tablespace names need to be replaced with Informix dbspace names Unlike the Oracle tablespace the Informix dbspace cannot be created using DDL (SQL) scripts It must be created using the Informix onspaces utility before any DDL (SQL) scripts are executed Therefore Oraclersquos CREATE TABLESPACE statements should be removed from the DDL (SQL) scripts The user interface for accomplishing these tasks is onmonitor The command line utility is onspaces Therefore the onspaces commands can be placed in shell or batch scripts After successfully executing the onspaces commands the DDL (SQL) scripts may be called through the same shell or batch scripts For example

IBM Software Group IBM Information Management

Version 16 21

onspaces hellip onspaces hellip hellip dbaccess database_name DDL_script_file_name dbaccess database_name DDL_script_file_name hellip

Tables

Attributes and general syntax

When creating tables the Oracle CREATE TABLE statement must be converted to Informix taking advantage of the Informix options IN EXTENT NEXT and LOCK MODE

IN specifies the dbspace in which the table will reside

EXTENT specifies the amount of space that will initially be allocated to the table (16K default on most platforms)

NEXT specifies the amount of space that will be allocated when additional space is needed (16K default on most platforms

Lock mode

LOCK MODE specifies whether to use row or page locks for the table In Oracle the default is row level locking in Informix the default setting is page level locking However it can be changed by using one of the following methods (resolved in the following order of precedence)

1 LOCK MODE specified using an attribute of the CREATE TABLE or ALTER TABLE command syntax

2 IFX_DEF_TABLE_LOCKMODE environment variable setting 3 DEF_TABLE_LOCKMODE parameter setting in the ONCONFIG file

NOTE If the DEF_TABLE_LOCKMODE parameter cannot be found in the ONCONFIG file it can be added to make the specification for every database within the instance The Informix instance must be restarted for this parameter to take effect The new ldquodefaultrdquo LOCK MODE will apply to all tables created after the parameter has been changed To change the LOCK MODE of existing objects use the ALTER TABLE statement

Storage

The Oracle STORAGE INITIAL and STORAGE NEXT clauses must be changed to the Informix EXTENT SIZE and NEXT SIZE clauses respectively In Oracle the STORAGE clause options MINEXTENTS MAXEXTENTS and PCTINCREASE should be removed For example Oracle

CREATE TABLE dept(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13)

)

STORAGE (INITIAL 100K NEXT 50K MINEXTENTS 1 MAXEXTENTS 50

PCTINCREASE 5)

Informix CREATE TABLE dept (

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

IBM Software Group IBM Information Management

Version 16 22

EXTENT SIZE 200 NEXT SIZE 50

When an Oracle CREATE TABLE statement does not include a STORAGE clause the table will be created using the tablespace STORAGE clause by default If an Oracle tablespace is created specifying a STORAGE INITIAL of 100KB and a STORAGE NEXT of 50KB then all tables created within that tablespace will have a default value of STORAGE INITIAL 100KB and STORAGE NEXT 50KB Oracle tables cannot be created with smaller STORAGE clause values than the tablespace default they are created in Informix dbspaces do not have storage clauses attached to them As stated earlier the default Informix EXTENT and NEXT sizes are 16KB on most platforms The minimum EXTENT and NEXT sizes are 4 times the page size

Constraints

The Oracle constraint syntax must be changed to the Informix syntax for primary keys foreign keys unique and so on For example

Oracle CONSTRAINT PK_NUMBER PRIMARY KEY(CUST_NUM)

CONSTRAINT CK_EMP_CODE CHECK (EMP_CODE gt 100)

Informix PRIMARY KEY(CUST_NUM) CONSTRAINT PK_NUMBER

CHECK (EMP_CODE gt 100) CONSTRAINT CK_EMP_CODE

An Oracle check constraint statement may contain functions that are not available in Informix In this circumstance it may be necessary to code the combination of a trigger and a stored procedure to emulate the same functionality A trigger based on an insert or update event can execute a stored procedure which tests the constraint condition and if necessary raise an exception to reject the row data which violates the constraint The Oracle PARALLEL clause which specifies parallel execution of an operation must be removed from any SQL statements (such as CREATE TABLE and ALTER TABLE) In Informix there are ways to accomplish this parallel execution depending on the context in which these SQL statements are called (shell script file batch file and so on)

ALTER TABLE

Informix offers a rich set of ALTER TABLE features adding and dropping columns (rename by using the RENAME statement) changing column data types altering the next size and changing the lock mode Informix will choose one of three algorithms when executing an ALTER TABLE statement depending upon the operation to be performed For certain conditions the database server uses either a ldquoslowrdquo ldquoin-place or ldquofastrdquo alter algorithm to modify the table Informix provides ldquoin-placerdquo alter table support for adding or dropping a column anywhere in the table changing the column length and changing the column data type without an exclusive lock on the table An ldquoin-placerdquo alter will modify the tablersquos definition without changing the existing rows or unloading and reloading the data After the ALTER TABLE operation the database server inserts rows using the latest definition Informix will not change the row structure until a data row is touched by a user operation Once a query accesses a row that is not yet converted there can be a slight degradation in the performance because the database server reformats each row in memory before it is returned Informix uses the ldquoslowrdquo alter algorithm when the ALTER TABLE statement makes column changes that it cannot perform in place This type of alter would be

Adding or drop a column created with the ROWIDS keyword

Dropping a column of the TEXT or BYTE data type

IBM Software Group IBM Information Management

Version 16 23

Converting an INT or a SMALLINT column to SERIAL or SERIAL8

Modifying the data type of a column so that some possible values of the old data type cannot be converted to the new data type

For example if you modify a column of data type INTEGER to CHAR(n) the database server uses the slow ALTER algorithm if the value of n is less than 11 An INTEGER requires 10 characters plus one for the minus sign for the lowest possible negative values

Modifying the data type of a fragmentation column in a way that value conversion might cause rows to move to another fragment

Adding dropping or modifying any column when the table contains user-defined data types or smart large objects

When the database server uses the slow alter algorithm to process an ALTER TABLE statement the table can be unavailable to other users for a long period of time because the database server will lock the table exclusively for the duration of the operation make a copy of the table to convert the table to the new definition and convert the data rows This type of ALTER TABLE processing can encounter the scenario of a statement being a long transaction and abort it if the Long Transaction High Water Mark (LTXHWM) threshold is exceeded Informix will use the ldquofastrdquo alter algorithm when the ALTER TABLE statement changes attributes of the table but does not affect the data The database server uses the fast alter algorithm when you use the ALTER TABLE statement to make the following changes

bull Change the next-extent size

bull Add or drop a constraint

bull Change the lock mode of the table

bull Change the unique index attribute without modifying the column type

With the ldquofastrdquo alter algorithm the database server holds a lock on the table for a very brief period In some cases the database server will lock the system catalog tables but only long enough to change the attribute In either case the table is unavailable for queries for only a short time

Data Partitioning

Informix Table Fragmentation is the counterpart to Oraclersquos Table Partitioning and allows the user to control where data is physically placed at the table level Table Fragmentation or Data Partitioning is typically done to large tables but Informix and Oracle implement fragmentation and partitioning for different reasons and with different results Informix recommends using table fragmentation to improve single-user response time concurrency data availability backup restore characteristics and data-load performance While Oracle does state that table partitioning may improve the performance of queries and that the Oracle optimizer takes partitioning into account the primary goal of partitioning in Oracle is improving database maintenance Partitioning strategies in Oracle include range partitioning as well as hash and composite partitioning Composite partitioning combines range and hash partitions through the use of sub-partitions Tables incorporating Oracle LOBrsquos (large objects) cannot be partitioned Informix fragmentation strategies include expression-based and round robin Basic expression-based fragmentation can replace Oracle range partitioning Unlike Oracle LOBs Informixrsquos Smart Large Objects can be fragmented Examples of creating tables with Oracle range partitioning and Informix fragmentation by expression are shown below Oracle range partitioning

CREATE TABLE dept

IBM Software Group IBM Information Management

Version 16 24

(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13) )

partition by range (deptno)

(partition PART1 values less than (11)

tablespace PART1_TS

partition PART2 values less than (21)

tablespace PART2_TS

partition PART3 values less than (31)

tablespace PART3_TS

partition PART4 values less than (MAXVALUE)

tablespace PART4_TS)

Informix expression based fragmentation CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

deptno lt 11 IN dbspace1

deptno gt= 11 AND deptno lt 21 IN dbspace2

deptno gt= 21 AND deptno lt 31 IN dbspace3

REMAINDER IN dbspace4

Oracle uses MAXVALUE for values not found in the specified range while Informix uses the REMAINDER keyword for values that fall outside the specified expression or expressions Prior to IDS version 1000 each table fragment had to go into a separate dbspace Now tables can be fragmented within a single dbspace You can create partitions within a dbspace that can each support a table fragment It is better to have one chunk per disk drive and now it is not necessary to create a dbspace just to facilitate fragmentation This feature can simplify the management of dbspaces The benefits gained through this new development include

It reduces the total number of dbspaces needed for a fragmented table

Storing multiple table fragments in a single dbspace improves query performance over storing each fragmented expression in a different dbspace

For example Informix partition fragmention in a single dbspace

CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

PARTITION part1 (deptno lt 11) IN dbspace1

PARTITION part2 (deptno lt 21) IN dbspace1

PARTITION part3 (deptno lt 31) IN dbspace1

PARTITION part4 REMAINDER IN dbspace1

Partitions of an Informix fragmented table can be manipulated using the ALTER FRAGMENT statement which supports attaching detaching adding modifying and dropping as well as initializing the distribution strategy

IBM Software Group IBM Information Management

Version 16 25

For example the following SQL removes a partition fragment and places the contents into a new table

ALTER FRAGMENT ON TABLE dept DETACH PARTITION part3 dept_part3

Making use of ALTER FRAGMENT to detach fragments can be an effective way of deleting large quantities of rows from a table quickly and easily After the above statement completes the table will no longer contain rows with a deptno greater than 21 and less than 31 Refer to the Informix Guide to SQL Syntax for a complete description on how to use the ALTER FRAGMENT statement to change the distribution strategy or the storage location of an existing table or index

Data types

Numeric

Oraclersquos NUMBER data type needs to be replaced with one of the following Informix equivalent data types depending on the size of the column The Informix numeric data types are listed below

SMALLINT (-32767 to 32767)

INTEGER (-2147483647 to 2147483647)

BIGINT (-9223372036854775807 to 9223372036854775807)

INT8 (-9223372036854775807 to 9223372036854775807)

The BIGINT type is more efficient in terms of space and speed there are few reasons to use INT8 now that BIGINT is available

DECIMAL (floating point up to 32 significant digits -10-130

to 10124

)

In an ANSI database there is an implied scale of 0 when no scale is given so this is not strictly speaking a floating point type within an ANSI database

NUMERIC (floating point up to 32 significant digits -10-130

to 10124

)

FLOAT (double precision like double data type of C)

SMALLFLOAT (single precision like float data type of C)

REAL (same as SMALLFLOAT)

DOUBLE (same as FLOAT)

LONG (same as long data type of C)

Oraclersquos NUMBER data type is used to store zero positive and negative fixed size and floating point numbers with magnitudes between 10 x 10

-130 and 999 x 10

125 (38 9s followed by 88 0s)

with 38 digits of precision A fixed-point number is specified by NUMBER(p s) where p is the precision or the total number of digits and s is the scale or the number of digits to the right of the decimal point For example a column defined as NUMBER(104) would contain numbers in the format 9999999999 In Oracle the scale can range from -84 to 127 If the scale is 0 or not mentioned then the data type can be converted into Informixrsquos SMALLINT INTEGER or BIGINT depending on the precision or FLOAT SMALLFLOAT DOUBLE or REAL depending on usage in the application When the scale is positive the data type should be converted to Informixrsquos DECIMAL or NUMERIC A floating-point data type in Oracle is declared using the type NUMBER without mentioning scale and precision In Informix this can be replaced with FLOAT SMALLFLOAT REAL DOUBLE PRECISION or DECIMAL(p) in an non-ANSI database

IBM Software Group IBM Information Management

Version 16 26

Oracle allows a negative scale If the scale is negative the actual data is rounded to the specified number of places to the left of the decimal point For example a specification of NUMBER (10 -2) means to round to the hundred If the general form for any number is

mantissa X 10exponent

then precision is the number of digits in the mantissa and scale is the negative exponent Example

select cast( 987654321 AS NUMBER(10-2) ) from dual

returns

987654300

Informix does not support a negative scale If precision - scale is less than the maximum precision of an integer type then that is the most efficient type to use Failing that and if the database is non-ANSI a floating point DECIMAL can be used If that is not sufficient then it may be necessary to define a user type and associated functions Oracle also allows the scale to be greater than the precision Precision is just the number of digits that will be preserved A NUMBER(3 5) might have the value 000123 If the Oracle scale is less than the Informix maximum precision then the Oracle scale can be used for both the Informix precision and scale A NUMERIC(55) column could also store the value 000123 You may need to take into consideration not only the minimum and maximum values but the default size for data types For example when the size of the NUMBER data type is absent Oracle will default to NUMBER(38) while Informix defaults to NUMERIC(16) Oracle and Informix support the ANSI DECIMAL data type Therefore in the case of an ANSI data type the Oracle data type can be converted to the same Informix data type There are differences between conversions based on theory versus those based on practice For instance it is very common to see an undecorated NUMBER declaration where the customer database and applications are using integer data When converting NUMBER declarations it may be necessary to consider how the data is being used in order to determine the best type mapping

CHAR VARCHAR and LVARCHAR

In Oracle the default for a CHAR column is one character and the maximum allowed is 255 characters In Informix the maximum length of CHAR and LVARCHAR columns is 32767 Therefore Oraclersquos CHAR columns can always be converted to an Informix CHAR column The CHAR data type columns can only contain printable characters tabs and spaces The CHAR columns store leading and trailing spaces In Oracle a zero-length string can be inserted into a CHAR column but the column is padded with one blank character when it is used in comparisons Also in Informix a zero-length string can be inserted into a CHAR column however the column is padded with enough spaces to fill the column In the case of inserting NULL into an Informix CHAR column no padding occurs Oraclersquos VARCHAR and VARCHAR2 are currently synonymous and have a maximum data length of 4000 bytes while the maximum length for the Informix VARCHAR data type is 255 Informixrsquos CHAR and LVARCHAR data types have a maximum length of 32767 and 32739 respectively measured in bytes These should be used to replace Oraclersquos VARCHAR VARCHAR2 LONG and LONG VARCHAR if the data length is between 256 and the maximum If the data length exceeds the maximum use Informixrsquos TEXT BYTE BLOB or CLOB data types See the Raw Data section below for more information on TEXT BYTE BLOB and CLOB data types

IBM Software Group IBM Information Management

Version 16 27

Empty Oracle VARCHAR2 strings are considered NULL Empty Informix VARCHAR and LVARCHAR strings are not considered NULL rather they contain at least one space Oracle

compares VARCHAR2 values using non-padded comparison semantics Therefore ldquoBOBrdquo ldquoBOB ldquo Informix ignores trailing blanks Therefore ldquoBOBrdquo = ldquoBOB ldquo or ldquordquo = ldquo rdquo Hence checks for NULL within the application must be replaced with checks for an empty string (such as ldquordquo or ldquo rdquo) whenever an empty string is inserted into the column If NULL is truly inserted into the column checking for NULL is appropriate (for example SELECT FROM hellip WHERE hellip IS NULL) In Oracle LONG columns store variable length character strings containing up to 2 gigabytes or 2

31-1 bytes Informix LONG columns store numeric data Oraclersquos LONG columns have many of

the characteristics of VARCHAR2 columns They can be used in a SELECT list in the SET clause of an UPDATE statement and in an INSERT statement but they cannot be used in a WHERE clause a GROUP BY clause or an ORDER BY clause and they cannot be indexed Oraclersquos LONG columns should be converted to an Informix Smart Large Object or ldquoSLOBrdquo (BLOB CLOB) column

Date and Time

Oraclersquos DATE data type contains date and time components from year down to second It can be to be replaced most directly with Informixrsquos DATETIME YEAR TO SECOND Some analysis may be necessary to determine whether the time is really necessary In other words does the application reference the date and time portions of the values If the application only references the date portion then replace Oraclersquos DATE with Informixrsquos DATE and change the host variable to X(10) or char(10) accordingly The Informix DATE default display format is MM-DD-YYYY although the DATE data type stores the calendar date The Informix DATE data type requires 4 bytes which is stored internally as an integer value equal to the number of days since December 31 1899 The default display format can be changed with the environment variable DBDATE If the application uses different date formats then using DBDATE is not a solution Sometimes it might be necessary to write small subroutines to emulate Oraclersquos DATE representations See the Informix Guide to SQL Reference manual for details on DBDATE and also DBCENTURY If the application only references the time portion of the values replace Oraclersquos DATE with Informixrsquos DATETIME using the EXTEND function to specify precision In addition Informix provides the data type INTERVAL for use while performing DATE and DATETIME calculations In Oracle the DATE data type is used to store date and time information Although date and time information can be represented in both CHAR and NUMBER data types the DATE data type has special associated properties For each DATE value the following information is stored

century

year

month

day

hour

minute

second

Also regarding the Oracle DATE data type if a date value without a time component is specified the default time is 120000am If a DATE value without a date is specified the default date is the first day of the current month

Interval

Within Informix there are two classes of interval types YEAR-MONTH and DAY-FRACTION There are different numbers if days in different months so the MONTH-DAY boundary cannot be crossed without creating ill-defined results Within each of these classes Informix allows you to declare columns or variables as any subset of the start and end fields Oracle has one INTERVAL

IBM Software Group IBM Information Management

Version 16 28

type for each of the two classes YEAR(p) TO MONTH and DAY(p) TO SECOND(s) The Oracle scale on the SECOND field is logically equivalent to the Informix scale on the FRACTION field

Raw data and Large Objects

Oraclersquos support of large blocks of raw unstructured data (such as graphic images video clips and sound waveforms) in binary or character format is provided by the large object (LOB) data types BLOB CLOB NCLOB and BFILE Traditional Oracle data types MLSLABEL (used with Trusted Oracle) RAW and LONG RAW are also used for data that is not to be interpreted by the engine and converted when moving data between different systems Informix supports two types of large objects (LOBs Simple Large Objects and Smart Large Objects Simple LOBs consist of the TEXT and BYTE data types and can be 2

31 bytes or 2

Gigabytes in size Smart LOBs include both Character Large Object (CLOB) and Binary Large Object (BLOB) data types and may be up to 42

40 bytes or 4 Terabytes in size Simple LOBs can

be stored either in-line with table data or in blobspaces while Smart LOBrsquos are stored in sbspaces Oraclersquos CLOB BLOB MLSLABEL RAW and LONG RAW data types should be replaced with Informixrsquos BYTE TEXT CLOB or BLOB depending on the columnrsquos size and usage Informixrsquos Smart BLOB data types CLOB and BLOB should be used under the following conditions and considerations

The large object needs to be referenced by multiple sources

The object size exceeds 2 GB

Fragmentation is required

Byte level locking is available making it possible to lock only a portion of the object

Logging can be specified at the object level

Updates are done in place or moved as needed

Be aware of the following restrictions for Simple Large Objects

Data can only be inserted into a BYTE or TEXT column with the dbload or onload utilities the DBACCESS load statement BYTE or TEXT host variables respectively in ESQLC or declaring a file in ESQLCOBOL

BYTE and TEXT columns cannot be inserted or updated with a literal neither quoted text string nor number

BYTE or TEXT columns cannot be used in string operations with aggregate functions with the GROUP BY ORDER BY IN LIKE or MATCHES clauses

ROWID

The implementation of ROWID differs between Oracle and Informix Oraclersquos ROWID is both a pseudo-column and a data type See the ROWID subsection in the Pseudo-Columns section in CHAPTER 3 Data Manipulation Language for more information Informix implements ROWID as a pseudo-column only Oracle stores the ROWID column and ROWID data type column values in hexadecimal format Informix stores the ROWID column values in INTEGER format The Oracle and Informix engines maintain the values of the ROWID pseudo-column Oraclersquos engine does not maintain the values of other columns of type ROWID In Informix the term rowid refers to an integer that defines the physical location of a row Informix assigns rows in a non-fragmented table a unique rowid which allows applications access to a particular row in a table Rows in fragmented tables in contrast are not assigned a rowid To access data by rowid in a fragmented table a rowid column must be explicitly created as is described in the Informix Guide to SQL Reference manual Creating a Rowid Column If applications attempt to reference a rowid in a fragmented table that does not contain a rowid that was explicitly created Informix displays an appropriate error message and execution of the application is halted

IBM Software Group IBM Information Management

Version 16 29

When used as a data type for a column Oracle does not guarantee that the values are valid ROWIDs For example if the ROWID is used as a data type on a column such as a column in a child table named parent_rowid containing the ROWID of the parent then the values are maintained by the application outside of the engine The application must read the ROWID of the parent and insert it into the parentrsquos corresponding child table rows This is usually done so the two tables can be joined on the parentrsquos ROWID and the childrsquos parent_rowid column This functionality can be duplicated in Informix by using primary and foreign keys Informix recommends that primary keys are used as a method of access in applications rather than rowids because primary keys are defined in the ANSI specification of SQL using them to access data makes applications more portable Refer to the Informix Guide to SQL Reference and the Informix Guide to SQL Syntax for a complete description on how to define and use primary keys to access data

User-defined types

Both Oracle and Informix allow the user to create and define data types Oracle refers to these as abstract data types while Informix refers to these as user-defined types In Oracle all user-defined types are referred to as abstract data types while Informix may refer to user-defined types as COLLECTION types ROW types DISTINCT types and OPAQUE types Currently the Informix ROW type is closest in form and function to the Oracle abstract data type An example of syntax for creating both an Oracle abstract data type and an Informix ROW type is shown below

Oracle abstract data type

CREATE TYPE name_type AS OBJECT

(first_name VARCHAR2(25)

middle_initial CHAR(1)

last_name VARCHAR2(30))

Informix row type

CREATE ROW TYPE name_type

(first_name VARCHAR(25)

middle_initial CHAR(1)

last_name VARCHAR(30))

Both Oracle and Informix support the use of user-defined types for table definition or column definition within a table Building on the example above the following create table example show a table definition and column definition within a table based on user-defined types Oracle table creation

CREATE TABLE name OF name_type

Informix table creation

CREATE TABLE name OF type name_type

Oracle column definition

CREATE TABLE employee

(empno NUMBER(9)

name name_type)

Informix column definition

CREATE TABLE employee

IBM Software Group IBM Information Management

Version 16 30

(empno INTEGER

name name_type)

For more information on User Defined Types see the Informix Guide to SQL Syntax

Complex data types

Informix offers users the ability to create data types from existing built-in types OPAQUE types DISTINCT types and other complex types Complex data types may either be a ROW type or a COLLECTION type Oracle treats complex data types as abstract data types For more information on Oracle abstract data types see the User Defined Types section above For more information on Complex Data Types see the Informix Guide to SQL Syntax For recommended type mappings and additional information see the appendix ldquoData type mappingsrdquo

Sequence objects

Oracle sequences

An Oracle sequence is a database object from which multiple users or transactions may generate unique integers For example sequences can be used to automatically generate primary key values When a sequence object is queried the sequence number is incremented and passed to the query independent of the transaction committing or rolling back If two applications increment the same sequence the sequence numbers each application acquires may not be sequential since sequence numbers are being generated by the other application One user or transaction can never acquire the sequence number generated by another user or transaction Once a user or transaction generates a sequence value that value will never be generated and passed to another user or transaction

Informix sequences

Informix rsquos implementation of sequence objects is identical to that of Oracle Issues regarding syntax compatibility should be negligible with the exception of some keywords which have no effect on the behavior of the sequence Informix supports DML statements (CREATE SEQUENCE ALTER SEQUENCE RENAME SEQUENCE DROP SEQUENCE) for sequence objects that multiple users can access concurrently to generate unique integers in the 8-byte integer range GRANT and REVOKE statements support access privileges on sequence objects and the CREATE SYNONYM and DROP SYNONYM statements can be used to reference synonyms for sequence objects in the local database The operators CURRVAL and NEXTVAL can read or increment the value of an existing synonym with behavior the same as Oracle

Indexes

Composite indexes

A composite index can have up to 16 key parts that are columns or up to 341 key parts that are values returned by a UDR This limit is language-dependent and applies to UDRs written in SPL or Javatrade functional indexes based on C language UDRs can have up to 102 key parts A composite index can have any of the following items as an index key

One or more columns

IBM Software Group IBM Information Management

Version 16 31

One or move values that is returned by a user-defined function (referred to as a functional index)

A combination of columns and user-defined functions

Maximum key size

The total widths of all indexed columns in a single CREATE INDEX statement have a limitation based upon the page size of the dbspace in which the index resides This limitation does not apply to functional indexes An enhancement introduced with Informix Dynamic Server Version 1110 is configurable page sizes for dbspaces Prior to this release the page size of dbspaces were restricted to that of the operating system and could not be changed thus Informix was limited to 390 byte indexes With page sizes configurable from 2K through 16K wider indexes are supported Refer to the table below 16K page sizes raises the limit on index width to over 3000 bytes Lifting the 390 byte limit also permits LVARCHAR columns larger than 387 bytes to be included in an index definition

Page Size Maximum Key Size

2 kilobytes 387 bytes

4 kilobytes 796 bytes

8 kilobytes 1615 bytes

12 kilobytes 2435 bytes

16 kilobytes 3245 bytes

In addition to aiding the porting process wider indexes have satisfied requirements for Unicode data as well as provide performance gains by reducing B-Tree index traversal costs since indexing can be built with more items on an index page and produce fewer levels

Index fragmentation

Just as Oracle and Informix support table fragmentation or partitioning in Oracle both support index fragmentation as well See the Table fragmentation section above for more information regarding Informix table fragmentation and Oracle table partitioning Oracle indexes that are partitioned in the same manner as the table they are indexing are referred to as local indexes Informix refers to these as attached indexes Oracle indexes that span partitions are known as global indexes Informix refers to these as detached indexes Informix detached indexes may also refer to indexes that do not follow the same fragmentation scheme as the table they are indexing Starting with Informix version 1110 indexes can be fragmented similarly to tables on a partition level

General index information

The Informix CLUSTER option should be used when appropriate This option orders the data within the table in the order the index requires It is important to note that the CLUSTER index is not maintained over time The primary factor determining the frequency of CLUSTER index rebuilds is the amount of DML performed against the table Frequent INSERTS UPDATES and DELETES make it necessary to closely monitor CLUSTER indexes There is only one clustered index per table since a tablersquos data can only be stored in one order Oraclersquos INITRANS and PCTFREE functionality is similar to the Informix index FILLFACTOR option of the CREATE INDEX statement or the FILLFACTOR configuration parameter in the ONCONFIG file In either case the functionality is handled by Informixrsquos engine once it is set and can be removed from the application FILLFACTOR specifies the degree of index-page

IBM Software Group IBM Information Management

Version 16 32

compactness A low value provides room for growth in the index A high value compacts the index If an index is fully compacted (100 percent) any new inserts result in splitting nodes The setting on the CREATE INDEX statement overrides the ONCONFIG file value The FILLFACTOR default value for both the CREATE INDEX statement as well as the ONCONFIG is 90 Informix has no support for bitmap indexes

Views Oraclersquos CREATE VIEW statement contains three options FORCE NO FORCE and WITH READ ONLY FORCE creates the view regardless of whether the views base tables exist or the owner of the schema containing the view has privileges on them NO FORCE creates the view only if the base tables exist and the owner of the schema containing the view has privileges on them WITH READ ONLY specifies that no deletes inserts or updates can be performed through the view These options must be removed from the Informix CREATE VIEW statements Because a view is not really a table it cannot be indexed and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE The columns of a view cannot be renamed with RENAME COLUMN To change anything about the definition of a view you must drop the view and re-create it Because it must be merged with the userrsquos query the SELECT statement on which a view is based cannot contain any of the following clauses

INTO TEMP The userrsquos query might contain INTO TEMP if the view also contains it the data would not know where to go

UNION The userrsquos query might contain UNION No meaning has been defined for nested

UNION clauses

ORDER BY The userrsquos query might contain ORDER BY If the view also contains it the choice of columns or sort directions could be in conflict

Stored procedures and triggers The ways stored procedures and triggers are created differ between Oracle and Informix Oracle allows a REPLACE clause in the CREATE statement to handle situations when the object already exists Informix does not support the REPLACE option Instead a DROP PROCEDURE or DROP TRIGGER statement must precede the CREATE PROCEDURE or CREATE TRIGGER statement respectively to handle the situation when the object already exists It should be noted a DROP statement will generate an error when the object does not exist If it is run interactively within the DBACCESS user interface the DROP statement error will terminate processing If it is run using script execution using DBACCESS at the command line processing will continue To run DBACCESS from the command line type

dbaccess db_name

To run the file containing the create statements from the command line type dbaccess db_name sql_file_name

Informix introduced an IF EXISTS clause to most of the CREATE and DROP statements at 117 but the logic is different from Oraclersquos OR REPLACE clause For example these statements

IBM Software Group IBM Information Management

Version 16 33

DROP PROCEDURE IF EXISTS hellip

CREATE PROCEDURE hellip

are logically the same as this Oracle statement

CREATE OR REPLACE PROCEDURE hellip

So it is possible to achieve the same result but not necessarily the same number of statements

Oracle extensions The Oracle CLUSTER option in CREATE statements should be removed These are not to be confused with Informix CLUSTER index statements (See Indexes section above) An Oracle cluster is a database schema object that contains one or more tables that all have one or more columns in common Rows of one or more tables that share the same value in these common columns are physically stored together within the database Removing this Oracle feature will not affect the application Other non-Informix DDL statements like CREATE DATAFILE CREATE CONTROLFILE CREATE ROLLBACK SEGMENT CREATE SNAPSHOT CREATE DATABASE and CREATE DATABASE LINK must be removed or changed (in the case of the CREATE DATABASE statement) The Oracle CREATE PROFILE statement must be removed An Oracle profile is a set of limits on database resources Profiles can be used to limit the database resources available to a user for a single SQL statement or a single session

IBM Software Group IBM Information Management

Version 16 34

C H A P T E R 4 Data Manipulation Language

SQL

Labels using keywords

Oracle displays labels in SQL statements that are Informix reserved words such as UNITS YEAR MONTH DAY HOUR and so on must be converted by using the Informix AS clause between the column name and the display label Otherwise syntactic ambiguities will cause errors

Inequality operations

In addition to the Informix supported ldquonot equal tordquo symbols ldquoltgtrdquo and ldquo=rdquo Oracle supports the symbol ldquo^=rdquo All occurrences of ^= must be replaced with one of the Informix supported symbols

Selects

Queries are executed based on how the optimizer determines the best path to the data Oracle and Informix developed their own query optimizers with their proprietary methods and rules A query that looks exactly the same in both environments may run differently in each following a different path and executing faster or slower Therefore every query in the ported application should be tested for performance regardless of whether a query had to be converted Furthermore Oracle supports optimizer hints within a SELECT statement Prior to IDS 73 and Informix Dynamic Server 92 Informix did not allow optimizer hints See the Optimizer Directives subsection below for more information on porting Oraclersquos optimizer hints to Informixrsquos optimizer directives

Optimizer directives

Informix offers optimizer directives similar to Oraclersquos optimizer hints This feature provides the query developer the flexibility to direct the optimizer to follow specific paths rather than choosing a plan through its analysis A query is processed in two steps First it is optimized and compiled to product a query plan Secondly it is executed to produce a result Optimizer directives are a method for influencing the choice of the optimizer in the creation of the plan

IBM Software Group IBM Information Management

Version 16 35

Optimizer directives address the following key issues

Reduced time for correcting performance problems Rewriting queries can be very time consuming and this allows you to have a quick way to alter a plan

Competitive pressure Users accustomed to this function were looking for it in Informix

Product development tuning This allows product development to alter plans dynamically rather than through code changes to evaluate the effect of different optimization techniques

The syntax and behavior of Informixrsquos implementation is compatible with Oraclersquos optimizer hints which eases the porting of applications from Oracle to Informix Directives are written as a comment whose first character is a lsquo+rsquo (plus sign) An example is

select + ORDERED AVOID_FULL(e) empname deptno

from employee e department d

where edept_no = ddept_no

This above example specifies that the tables should be joined in the order specified in the query and that the employee table (e) should NOT be accessed with a full table scan The Informix implementation differentiates itself significantly from Oraclersquos in one way Informix supports the notion of negative directives whereas Oracle only supports direct hints A directive that tells the optimizer what to avoid rather than what to choose is unique to Informix The query result can be realized by writing a directive to avoid certain actions known to cause performance issues but allow any new indexes or table attributes to be explored by the optimizer as they are added over the life of the table and query This allows a DBA to continue to add indexes to tables and not have to rewrite directives Additionally Informix supports full recognition of directives with SET EXPLAIN output Informix will highlight semantic and syntactic errors which Oracle does not Optimizer directives support control in the following areas of the optimization process

Access methods Index versus scans

Join Methods Forcing hash joins nested loop joins

Join Order Specify which order the tables are joined

Goal Specify first rows or all rows (response time versus throughput) See the Informix Guide to SQL Syntax or Reference for more information

External optimizer directives

External optimizer directives give the DBA the ability to specify query directives and save them in the database These directives are applied automatically to subsequent instances of the same query The SAVE EXTERNAL DIRECTIVES statement associates one or more optimizer directives with a query and stores a record of this association in the sysdirectives system catalog table for subsequent use with queries that match the specified query string The query string must be an exact match that includes case and white space positioning This statement establishes an association between the list of optimizer directives and the text of a query but it does not execute the specified query Only the DBA or user informix can execute SAVE EXTERNAL DIRECTIVES This associates AVOID_INDEX and FULL directives with the specified query

SAVE EXTERNAL DIRECTIVES

+ AVOID_INDEX (table1 index1) + FULL(table1)

ACTIVE FOR

SELECT col1 col2 FROM table1 table2

IBM Software Group IBM Information Management

Version 16 36

WHERE table1col1 = table2col1

These directives are applied automatically to subsequent instances of the same query You must include one of the ACTIVE INACTIVE or TEST ONLY keyword options to enable disable or restrict the scope of external directives When external directives are enabled and the sysdirectives system catalog table is not empty the database server compares every query with the query text of every ACTIVE external directive and for queries executed by the DBA or user informix with every TEST ONLY external directive External directives are ignored if the EXT_DIRECTIVES parameter is set to 0 in the ONCONFIG file In addition the client system can disable this feature for its current session by setting the IFX_EXTDIRECTIVES environment variable to 0 If an external directive has been applied to a query output from the SET EXPLAIN statement indicates ldquoEXTERNAL DIRECTIVES IN EFFECTrdquo for that query Any inline directive is ignored by the optimizer when the external directives are applied to a query that matches the SELECT statement Like inline optimizer directives that are embedded within a query external directives can improve performance in some queries for which the default behavior of the query optimizer is not satisfactory Unlike inline directives external directives can be applied without revising or recompiling existing applications

Inserts

Informix does not support Oraclersquos INSERT with SELECT statement utilizing an UNION clause (although a view with an UNION clause can be referenced resulting in an UNION operation) Additionally Informix does not support an INSERT statement with a VALUE clause with SELECT statements The SELECT statement within a VALUE clause can be rewritten by omitting the VALUE clause and performing an INSERT INTO table_name SELECT hellip FROM other_table_name

Temporary tables

Informix and Oracle implemented the concept of temporary tables differently Oracle implements temporary tables as a work area during batch data loads Informix implements temporary tables just like regular database tables These temporary tables can be created manipulated and dropped only within a session such as stored procedures and ESQL programs Once the session ends any remaining temporary tables are automatically dropped Temporary tables can give an application extra functionality however their use should be limited if reducing database extensions to increase database independence within an application is a priority

Outer joins

Both Oracle (starting with Oracle 9i) and Informix support ANSI standard syntax for outer join specification The syntax for left and right outer join using the plus sign (+) in the WHERE clause is only supported for backward compatibility however it is still in existence The use of ANSI outer join syntax is recommended The Oracle outer join syntax + (placed after the column which has values not matching the corresponding column in the joined table) can be replaced with the Informix equivalent OUTER The OUTER keyword is placed within the SELECT statement before the name of the subservient table Unlike Oracle in Informix multiple outer joins per SELECT statement are allowed grouped with parentheses

Sorts

In Oracle sorts NULL values are considered the highest value and are therefore ordered last in ascending sorts Informix sorts with NULLS as the lowest value ordering them first in ascending sorts First it must be determined whether this sorting difference will affect the outcome enough to warrant a work around In most cases it will not If it does then a stored procedure can be

IBM Software Group IBM Information Management

Version 16 37

written to evaluate whether a column is NULL and if so replace it with a high value so that it will sort last Once the application receives the results it must replace the high values with NULL if the column is going to be displayed or manipulated

Exceptions

Error handling using hard coded Oracle SQL codes must be replaced with the corresponding Informix SQL codes

Correlation names

Informix does not support correlation names with aliases on the main table of an UPDATE or DELETE statement Such cases must be converted For example

Oracle UPDATE customer C

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE Ccreate_date lt= Zeffective_date)

Informix UPDATE customer

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE customercreate_date lt= Zeffective_date)

-and-

Oracle DELETE customer C

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND Cstate = Tstate )

Informix DELETE customer

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND customerstate = Tstate )

Note that Informix allows correlation names with aliases on tables other than the updated or deleted table

Aliases

Unlike Oracle in Informix if an alias is used in the FROM clause of a SELECT statement it must also be used in the SELECT list and WHERE clauses The original table name should be replaced with the alias wherever aliases and original names are used together within a SELECT statement in an Oracle application

Hierarchical queries

Informix does not allow query results to be organized hierarchically in a B-tree fashion Oracle does allow it by using the clauses START WITHhellip and CONNECT BY PRIOR in the SQL

IBM Software Group IBM Information Management

Version 16 38

statement In Oracle if a table contains hierarchical data a bill of materials for example rows can be selected in a hierarchical order using the following clauses START WITH

The START WITH clause identifies the row(s) to be used as the root(s) of a hierarchical query This clause specifies a condition that the root(s) must satisfy If this clause is omitted Oracle uses all rows in the table as root rows A START WITH condition can contain a subquery

CONNECT BY

The CONNECT BY clause specifies the relationship between parent and child rows in a hierarchical query This clause contains a condition that defines this relationship The part of the condition containing the PRIOR operator must have one of the following forms

PRIOR expression comparison_operator expression -or- expression comparison_operator PRIOR expression

To find the children of a parent row Oracle first evaluates the PRIOR expression to identify the parent row(s) and the other expression for each row in the table Rows for which the other expression is true are the children of the parent The CONNECT BY clause can contain other conditions to further filter the rows selected by the query

WHERE

The WHERE clause can restrict the rows returned by the query without affecting other rows of the hierarchy

Oracle uses the information from each of the clauses mentioned above to form the hierarchy using the following steps

1 Oracle selects the root row(s) of the hierarchy These are the rows that satisfy the condition of the START WITH clause

2 Oracle selects the child rows of each root row Each child row must satisfy the condition of the CONNECT BY clause with respect to one of the root rows

3 Oracle selects successive generations of child rows Oracle first selects the children of the rows returned in step 2 and then the children of those children and so on Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row

4 If the query contains a WHERE clause Oracle removes all rows from the hierarchy that do not satisfy the condition of the WHERE clause Oracle evaluates the WHERE condition for each row individually after the row has been fetched rather than only fetching rows that satisfy the WHERE condition

5 Oracle returns the rows in the order of an in-order or left-root-right binary tree traversal

IBM Software Group IBM Information Management

Version 16 39

For example the following SQL statement returns the data in the adjacent table in hierarchical order The root row is defined to be the employee whose job is lsquoPRESIDENTrsquo The child rows of a parent row are defined to be those rows whose manager number is the employee number of the parent row

SELECT ename empno mgr job FROM emp START WITH job = lsquoPRESIDENTrsquo CONNECT BY PRIOR empno = mgr

To duplicate this hierarchical functionality in Informix stored procedures or functions can be written requiring intensive use of cursors and program arrays Informix offers the choice of creating and using a User Defined Routine or ldquoUDRrdquo See User Defined Routines section below Use of Informix global arrays will help considerably To maximize read processing at the expense of insert processing another method is to break the table into two tables one containing the data and the other containing the relationship (foreign keys) between each parent and child A parent row would have an entry in the relationship table for each of its children grandchildren great grandchildren and so on The opposite is true where a child row would have an entry in the relationship table for its parent grandparent great grandparent and so on

Truncate

Informix supports the TRUNCATE statement for deleting all active data rows from a table and associated indexes When using Informixrsquos TRUNCATE you also have the option of releasing the storage space that was occupied by the rows and index extents or keeping the space allocated to be used as the table is repopulated with new data

TRUNCATE [TABLE] table [ [ DROP | REUSE ] STORAGE ]

You may use the commandrsquos simplest usage

TRUNCATE my_table

In the example above the TRUNCATE statement drops all the data for the table and keeps only the initial extents There is a minor difference from Oracle syntax as Informix does not require the keyword TABLE Another example

TRUNCATE my_table REUSE STORAGE

ENAME EMPNO MGR JOB

KING 7839 PRESIDENT

JONES 7566 7839 MANAGER

SCOTT 7788 7566 ANALYST

ADAMS 7876 7788 CLERK

FORD 7902 7566 ANALYST

SMITH 7369 7902 CLERK

BLAKE 7698 7839 MANAGER

ALLEN 7499 7698 SALESMAN

WARD 7521 7698 SALESMAN

MARTIN 7654 7698 SALESMAN

TURNER 7844 7698 SALESMAN

JAMES 7900 7698 CLERK

CLARK 7782 7839 MANAGER

MILLER 7934 7782 CLERK

IBM Software Group IBM Information Management

Version 16 40

This example drops all the data for the table but retains all the space allocated The permissions needed for TRUNCATE TABLE depend on the existence of DELETE triggers on the table For tables with DELETE triggers ALTER permission on the table is required and RESOURCE or DBA privileges because the DELETE triggers will be bypassed For tables without DELETE triggers you need DELETE permission on the table and CONNECT privilege to the database While Oracle does not provide rollback Informix does permit TRUNCATE TABLE to execute within a transaction When you rollback a TRUNCATE statement no rows are removed from the table and the storage extents that hold the data rows and index pages continue to be allocated to the table In a database that supports transaction logging only the COMMIT WORK or ROLLBACK WORK statement is valid after the TRUNCATE statement within a transaction Any other statement will generate an error The TRUNCATE statement does not reset the serial value of SERIAL or SERIAL8 columns To reset the counter of a serial column you must do so explicitly by using the MODIFY clause of the ALTER TABLE statement either before or after you execute the TRUNCATE statement After the TRUNCATE statement successfully executes Informix automatically updates the statistics and distributions for the table and for its indexes in the system catalog to show no rows in the table nor in its dbspace partitions It is not necessary to run the UPDATE STATISTICS statement immediately after you commit the TRUNCATE statement

Host variables Host variable formats should not change during the porting process Instead data types should be converted in a manner to preserve the column and host variablersquos formats However there are times when the database schema changes in a way where the host variable format must change Any column converted to a different format in Informix than that of Oracle requires that its corresponding host variable format be changed to be consistent Alternatively if an Oracle format such as date and numeric variables is not directly supported in Informix then the conversion may require some format processing before or after the SQL statement For example the Oracle function TO_CHAR is used to format both date and numerical values A similar function or at least two functions one to handle date data types and another to handle numeric data types can be declared and used in the Informix application Informix provides two built-in functions TO_DATE which converts a character string to a DATETIME variable and TO_CHAR which converts a DATETIME variable to a character string When converting variables an optional formatting string is allowed which determines how the string is displayed (full day names partial day names full months month number and so on) There is also a function ifx_to_gl_datetime() which takes an Oracle date format and returns the corresponding Informix date format This function is supplied in genlib and is for use in ESQL programs to ease migration efforts from Oracle The syntax is as follows

TO_CHAR (source_date fmt) Returns a character string containing the date specified in source_date in the format specified by fmt if one is provided If fmt is missing the function will use the default date format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

TO_DATE (source_string fmt) Evaluates source_string as a date according to the

format fmt If fmt is missing the function will use the

IBM Software Group IBM Information Management

Version 16 41

default format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

These functions are mainly useful for simplifying migration from Oracle to Informix but are also useful for performing advanced searches on DATETIME data types and for better output presentation

Date and time functions Informix version now has built-in support for most of Oraclersquos date functions so it will not be necessary to modify or replace Oraclersquos SYSDATE or ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat)

SYSDATE

IDS 1110 will support the SYSDATE operator which returns a single value representing the current date and time from the operating system clock SYSDATE is identical to the Informixrsquos CURRENT operator except that the default precision of SYSDATE is YEAR TO FRACTION(5) while the default precision of CURRENT is YEAR TO FRACTION(3) On Windows platforms that do not support a seconds scale greater than FRACTION(3) SYSDATE is effectively a synonym for the CURRENT operator In addition to SYSDATE Informix version 1110 has support for Oraclersquos date functions ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat) Depending on the whether or not the Oracle date_format argument is supported by Informix TO_CHAR(date char_format) and TO_DATE(character_string date_format) may have to be converted to Informix date processing Date processing may be required because the Oracle application may format the date in many different ways unsupported by Informix The formats used in the Oracle functions TO_CHAR TO_NUMBER and TO_DATE are illustrated below These formats should be replaced with Informix formats wherever possible format processing functions or stored procedures written to duplicate the Oracle functionality Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

Number formats

Element Example Description 9 9999 Return value with the specified number of digits with a leading

space if positive Return value with the specified number of digits with a leading minus if negative Leading zeros are blank except for a zero value which returns a zero for the integer part of the fixed-point number

0 09999990 Return leading zeros Return trailing zeros $ $9999 Return value with a leading dollar sign B B9999 Return blanks for the integer part of a fixed-point number

when the integer part is zero (suppress leading zeros regardless of whether zeros are used in the format model ie B00999 )

MI 9999MI Return negative value with a trailing minus sign ldquo-ldquo Return positive value with a trailing blank

S S9999999 Return negative value with a leading minus sign ldquo-ldquo Return

IBM Software Group IBM Information Management

Version 16 42

Element Example Description S positive value with a leading plus sign ldquo+rdquo Return negative

value with a trailing minus sign ldquo-ldquo Return positive value with a trailing plus sign ldquo+rdquo

PR 9999PR Return negative value in ltangle bracketsgt Return positive value with a leading and trailing blank

D 99D99 Return a decimal point ldquordquo In the specified position G 9G999 Return a group separator in the specified position C C999 Return the ISO currency symbol in the specified position L L999 Return the local currency symbol in the specified position 9999 Return a comma in the specified position 9999 Return a decimal point ldquordquo In the specified position V 999V99 Return a value multiplied by 10

n (and if necessary round it

up) where n is the number of ldquo9rdquos after the ldquoVrdquo EEEE 99EEEE Return a value in scientific notation RNrn RN Return a value as Roman numerals in uppercase Return a

value as Roman numerals in lowercase Value can be an integer between 1 and 3999

FM FM909 Return a value with no leading or trailing blanks

Date formats

Element Meaning -rdquotextrdquo Punctuation and quoted text is reproduced in the result AD or AD AD indicator with or without periods AM or AM Meridian indicator with or without periods BC or BC BC indicator with or without periods CC or SCC Century ldquoSrdquo prefixes BC dates with ldquo-ldquo D Day of week (1-7) DAY Name of day padded with blanks to length of 9 characters DD Day of month (1-31) DDD Day of year (1-366) DY Abbreviated name of day IW Week of year (1-52 or 1-53) based on the ISO standard IYY or IY or I Last 3 2 or 1 digit(s) of ISO year IYYY 4-digit year based on the ISO standard HH or HH12 Hour of day (1-12) HH24 Hour of day (0-23) J Julian day the number of days since January 1 4712 BC Number

specified with lsquoJrsquo must be integers MI Minute (0-59) MM Month (01-12 JAN = 01) MONTH Name of month padded with blanks to length of 9 characters MON Abbreviated name of month RM Roman numeral month (I-XII JAN = I) Q Quarter of year (1 2 3 4 JAN-MAR = 1) RR Last 2 digits of year see below for years in other centuries WW Week of year (1-53) where week 1 starts on the first day of the year

and continues to the seventh day of the year W Week of month (1-5) where week 1 starts on the first day of the

month and ends on the seventh PM or PM Meridian indicator with and without periods SS Second (0-59) SSSSS Seconds past midnight (0-86399) YYYY Year with comma in the ldquordquo position YEAR or SYEAR Year spelled out ldquoSrdquo prefixes BC dates with ldquo-ldquo YYYY or SYYYY 4-digit year ldquoSrdquo prefixes BC dates with ldquo-ldquo

IBM Software Group IBM Information Management

Version 16 43

YYY or YY or Y Last 3 2 or 1 digit(s) of year

The RR date format element

The RR date format element is similar to the YY date format element but it provides additional flexibility for storing date values in other centuries The RR date format element allows storing the century even though only two digits are entered for the year The table below illustrates how the year is stored based on only two digits

If the year is entered as

0 ndash 49 50 - 99 If the last two digits of the

0 - 49 The return date is in the current century

The return date is in the century before the current one

current year are

50 - 99 The return date is in the century after the current one

The return date is in the current century

User-defined routines User-defined data types user defined behaviors and user defined access methods add rich functionality to Informix A user-defined routine (UDR) can be developed in C Java or Informix SPL language to vastly extend the capabilities of the database Porting applications to Informix gives the option to create UDRs for aggregate and mathematical functions or to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or you can rename an Informix function to the corresponding Oracle function name

Compatible SQL Functions Informix Dynamic Server version 1110 has added support for a number of built-in SQL functions to ease a migration effort These new functions which perform common operations and data manipulation provide compatibility with Oracle routines thus simplifying the migration of applications that have been developed for an Oracle database

Date and time functions ROUND TRUNC ADD_MONTHS LAST_DAY NEXT_DAY MONTHS_BETWEEN SYSDATE

Conversion functions ASCII TO_CHAR TO_NUMBER

String manipulation LTRIM RTRIM

Number manipulation ROUND TRUNC CEIL FLOOR POWER

Bit manipulation BITAND BITOR BITXOR BITNOT BITANDNOT

Others NULLIF FORMAT_UNITS These functions are documented with examples in the IBM Informix Guide to SQL Syntax

Aggregate functions Like Oracle the result returned by an Informix aggregate function is NULL if all of the column values are NULL with the exception of COUNT which returns 0 (zero) Like Oracle Informix aggregate functions cannot be used in a WHERE clause unless it is on a corresponding column originating from a parent query and the WHERE clause is within a sub-query that is within a HAVING clause or the aggregate function is contained within a sub-query Unlike Oracle in Informix the argument of an aggregate function cannot be another aggregate function Informix supports the SELECT COUNT (column_name) hellip statement where the number of rows containing non-null values in the specified column is returned

IBM Software Group IBM Information Management

Version 16 44

The Oracle aggregate functions STDDEV and VARIANCE are supported however the Informix standard deviation routine is named STDEV thus all references to Oraclersquos STDDEV must be changed to match Informixrsquos STDEV Informix does not support Oraclersquos greatest lower boundary (GLB ) or least upper boundary (LUB) Therefore UDRs must be written to provide equivalent functionality Informix allows users to define their own aggregate functions known as user-defined aggregates (UDA) This extension of existing aggregates can be used for new data types as well as the definition of new aggregates In Informix TEXT and BYTE columns cannot be used in aggregate functions such as COUNT AVG MAX MIN and SUM

Mathematical functions Informix does not support all of Oraclersquos mathematical functions such as SIGN COSH SINH and TANH Therefore functions or UDRs must be written in the Informix application to provide equivalent functionality In Informix the rounding factor within the ROUND function must be a value from -32 to 32 This limitation has seldom been encountered as a migration issue

String functions

LENGTH

Oraclersquos LENGTH function will return different values than Informix for strings stored in CHAR data types The numeric return value representing the string length returned by Oracle will include all trailing spaces Whereas Informixrsquos LENGTH function will ignore trailing blanks regardless of data type For example for the two CHAR strings ldquoBOBrdquo and ldquoBOB ldquo Oraclersquos LENGTH function will return different values for each string 3 and 5 respectively Whereas Informixrsquos LENGTH function will ignore trailing blanks and return the value 3 for both When the input string is NULL both database functions will return a NULL

LTRIM and RTRIM

The SQL Compatibility features of Informx has support for LTRIM and RTRIM and will return identical values to that of Oracle No modifications will be necessary to SQL statements utilizing these functions

Oracle Extensions

Informix does not support all of Oraclersquos string functions such as CHR INSTR SOUNDEX and TRANSLATE Therefore corresponding user-defined routines or UDRs (ie functions or stored procedures) must be written in the Informix application to provide equivalent functionality Please note that the VERITY and EXCALIBUR Datablades included with Informix will work with Oraclersquos string function SOUNDEX

Other Oracle Functions Informix does not support the following Oracle functions Therefore corresponding functions must be written in the Informix application to provide equivalent functionality Alternatives to some of the more common Oracle functions follow this list

CHARTOROWID CONVERT DUMP GREATEST GREATEST_LB

IBM Software Group IBM Information Management

Version 16 45

HEXTORAW LEAST LEAST_UB RAWTOHEX ROWIDTOCHAR TO_LABEL TO_MULTI_BYTE TO_SINGLE_BYTE UID USERENV(OSDBA LABEL LANGUAGE TERMINAL SESSIONID ENTRYID) VSIZE

Macros Oracle contains macros sometimes referred to as language constructs which can determine the status of an object Informix does not support Oraclersquos macros These macros must be removed from the code and the associated logic should be implemented with equivalent Informix logic where applicable

ISOPEN and NOT FOUND

The macro cursor_nameISOPEN returns a Boolean value to indicate whether the cursor is open and cursor_nameNOTFOUND indicates whether there are any more rows yet to be fetched from the cursor cursor_name These macros used in condition statements are followed by some logic to handle the true andor false conditions In the case of ISOPEN this macro and its associated logic can just be omitted since the FOREACH loop processing does not explicitly open a cursor and therefore the condition cannot be checked In the case of NOTFOUND this macro should be omitted and its associated logic converted to Informix logic within an Informix FOREACH loop

ROWTYPE

The Oracle macro prefixROWTYPE is used in the declarative section as a data type to declare variables similar to the structure construct of C or RECORD of INFORMIX The prefix can be either a table name or another structure name Structure names ultimately refer back to a table name This macro may be replaced with the Informix statement LIKE table_name The construct LIKE table_name cannot be used in SPL Instead the construct DEFINE column1 LIKE table_namecolumn1 DEFINE column2 LIKE table_namecolumn2 and so on should be used to declare variables corresponding to all the columns of the table Then operations on the whole or part of the structure should be replaced with operations on single SPL variables

TYPE

The Oracle macro prefixTYPE is used in the declarative section as a data type to declare single variables The prefix is either a table_namecolumn_name or a structure_namevariable_name A structure_namevariable_name ultimately refers back to a table_namecolumn_name This macro can be replaced with the Informix statement LIKE table_namecolumn_name

Pseudo-columns Pseudo-columns are columns that exist in tables but are not displayed from a SELECT FROM table_name query Informix pseudo-columns are generally reserved for the enginersquos use Eliminating the use of such columns increases an applicationrsquos portability and eliminates the need for future modifications if the engine is ever modified to process the column differently or not at all

IBM Software Group IBM Information Management

Version 16 46

LEVEL

In Oracle for each row returned by a hierarchical query the pseudo-column LEVEL returns 1 for a root node 2 for a child of a root 3 for a child whose parent is at level 2 and so on A root node is the highest node within an inverted tree and therefore has no parent A child node is any non-root node A parent node is any node that has children A leaf node is any node without children To define a hierarchical relationship in a query you must use the START WITH and CONNECT BY clauses Informix does not support the LEVEL clause See the Hierarchical Queries subsection in the SQL section in the ldquoData Manipulation Languagerdquo chapter for more information on how to process these queries

ROWID

Oraclersquos ROWID pseudo-column returns the rows address for each row in the database ROWID values contain the following information necessary to locate a row

Which data block in the data file

Which row in the data block (first row is 0)

Which data file (first file is 1)

Usually a ROWID value uniquely identifies a row in the database However rows in different tables that are stored together in the same cluster can have the same ROWID Values of the ROWID pseudo-column have the data type ROWID ROWID values have several important uses

They are the fastest way to access a single row

They can show you how a tables rows are stored

They are unique identifiers for rows in a table

A ROWID does not change during the lifetime of its row However you should not use ROWID as a tables primary key If a row is deleted and re-inserted its ROWID may change even when using the export and import utilities If a row is deleted Oracle may re-assign its ROWID to a new row inserted later Although you can use the ROWID pseudo-column in the SELECT and WHERE clauses of a query these pseudo-column values are not actually stored in the database The value of a ROWID pseudo-column cannot be inserted updated or deleted For example the following Oracle statement selects the address of all rows that contain data for employees in department 20

SELECT ROWID ename FROM emp WHERE deptno = 20

The equivalent pseudo-column in Informix is also known as ROWID and although the behavior is similar the data type is different from Oraclersquos See the ROWID subsection in the Data Types section in the chapter ldquoData definition languagerdquo for more information

ROWNUM

In Oracle for each row returned by a query the ROWNUM pseudo-column returns a number indicating the order in which Oracle selected the row from a table or set of joined rows The first row selected has a ROWNUM of 1 the second has 2 and so on ROWNUM can be used to limit the number of rows returned by a query as in this example to read 9 rows

SELECT

FROM emp

WHERE ROWNUM lt 10

ROWID ENAME 0000000F00000002 SMITH 0000000F00030002 JONES 0000000F00070002 SCOTT 0000000F000A0002 ADAMS 0000000F000C0002 FORD

IBM Software Group IBM Information Management

Version 16 47

You can also use ROWNUM to assign unique values to each row of a table as in this example

UPDATE tabx

SET col1 = ROWNUM

Oracle assigns a ROWNUM value to each row as it is retrieved before the rows are sorted by an ORDER BY clause Therefore the final order of the rows is in ORDER BY order not in ROWNUM order An ORDER BY clause does not affect the ROWNUM values except in the case where the ORDER BY clause causes Oracle to use an index In that case the ROWNUM values are set in the order the rows are retrieved using the index and hence in ORDER BY order This order is different than if the rows were retrieved without the index So in this case the ORDER BY can affect the ROWNUM values Conditions which test for ROWNUM values greater than zero are always false For example this query returns no rows

SELECT FROM employee WHERE ROWNUM gt 1

The first row fetched is assigned a ROWNUM of 1 thus making the condition false The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 making the condition false All rows subsequently fail to satisfy the condition so no rows are returned Although there is no ROWNUM equivalent in Informix there are solutions Beginning with IDS 73 and in Informix Dynamic Server 2000 Informix provides a feature which allows the user to limit the results of a query to the first N rows This was implemented for TPC-D compliance and to support ldquorankrdquo queries Rank queries can be assembled by using FIRST N with the ORDER BY clause Informix will return the top N rows according to some ordering criteria Therefore the following Oracle SELECT utilizing ROWNUM

SELECT FROM emp WHERE ROWNUM lt 10

can be ported to Informix as follows

SELECT FIRST 9 FROM emp

Informix does not support SELECT FIRST N in complex cases as the following

Sub-queries (SELECT within a SELECT)

View definitions (Cannot be used by a SELECT statement which references a view)

UNION queries The behavior of SELECT FIRST N depends on the presence of an ORDER BY clause If no order by clause is specified the first N rows returned may be in any order Examples are as follows

find 10 highest paid employees

SELECT FIRST 10 name salary

FROM emp

ORDER BY salary

find 10 highest salary values

SELECT FIRST 10 DISTINCT salary

FROM emp

ORDER BY salary

IBM Software Group IBM Information Management

Version 16 48

Informix supports column names of ldquofirstrdquo Thus without a positive integer following the word ldquofirstrdquo the token is parsed as a column name rather than a keyword The value of N may be between 1 and (2

31-1)

When ROWNUM is used in a WHERE clause the same results can be obtained through the use of the FIRST N and SKIP clauses but if ROWNUM is used in the select list the solution is a little more complicated Simply stated you can construct a query where the ROWNUM column in any row is the count of the rows that came before This involves creating a correlated subquery where the subquery contains a self-join This can be done for any table or set of tables which has a unique key defined on it Here is an example using the customer table of the stores7 database

select

counterrownum

basecustomer_num

basefname

baselname

from

-- There can be more than one table here and the result

-- set should thought of as a table (just not a base table)

-- The result table has to be joined to itself in the

-- subquery so if there are multiple tables in this FROM

-- clause the expansion can get messy You have to have a

-- set of columns that uniquely identify each row in the

-- result table and join across them ROWID would

-- likely work if the table is not fragmented but if it is

-- there is no guarantee the final results would be accurate

-- because ROWID is not guaranteed to be unique across

-- fragments

customer base

(select

count() as rownum

acustomer_num -- any unique key possibly multiple

-- columns

from

customer a

customer b

where

-- This is where the rownum is determined the relationship

-- here has to match the outer order-by where the rows

-- are sorted and has to create a unique sort order

--

-- Any columns to be ordered by go here

-- Also the unique key has to be used to keep rows

-- that do not have a unique sort order from being merged

(alname gt blname) -- example sorting by last name

or

(alname = blname and afname gt bfname)

-- sorting by fname where lname is equal

or

(alname = blname and afname = bfname

and acustomer_num gt= bcustomer_num)

-- sorting by unique key where all the

-- other sort columns are equal

-- The expansion above is logically the same as

-- alname || afname || to_char(acustomer_num) gt=

-- blname || bfname || to_char(bcustomer_num)

-- but it allows the server to utilize any indexes that

-- may exist

group by

-- unique key columns go here

IBM Software Group IBM Information Management

Version 16 49

acustomer_num

) counter

where

-- key columns in the base tables go here

basecustomer_num = countercustomer_num

-- if you want to limit on rownum it goes here

-- and rownum lt= 10

order by

counterrownum

If using ROWNUM as an assignment as in

UPDATE tabx

SET col1 = ROWNUM

The following Informix-ESQLC pseudo-code example would have to be used

int counter = 0

EXEC SQL declare c1 cursor for

SELECT col1 col2

INTO col1 col2

FROM table 1

WHERE col1 = XX

EXEC SQL open c1

while (SQLCODE == 0)

EXEC SQL fetch c1

counter++ Increment counter for each row

fetched

if (counter gt= 5)

break

logic

End if

End while

Update using cursors There are slight differences between the ways Informix and Oracle process cursors Unlike Oracle in Informix the WHERE CURRENT OF clause cannot be used to update tables in a SELECT statement joining multiple tables since the WHERE CURRENT OF clause requires a FOR UPDATE cursor and Informix does not support the FOR UPDATE clause in SELECT statements that join multiple tables Therefore in the multi-table join statements the Oracle options FOR UPDATE and WHERE CURRENT OF should be removed and the update of the rows should be done using a separate UPDATE statement in the same cursor loop

IBM Software Group IBM Information Management

Version 16 50

In Informix a commit or rollback statement closes all cursors open in a given transaction boundary See the Transaction Processing section in CHAPTER 5 Application Architecture for more information In situations where the intention is to commit or rollback without closing the cursor in other words where the commit or rollback is executed within a cursor fetch loop the cursor can be declared as a HOLD cursor This requires that a BEGIN WORK is issued before the cursor loop starts A HOLD cursor is not closed when a commit or rollback statement is issued In Informix the FOR UPDATE clause cannot be used when declaring a HOLD cursor Thus where an Oracle application updates a table from which it fetches data in the fetch loop or issues a commit work in the fetch loop it must be converted to Informix The cursor can be declared with HOLD and then an UPDATE statement can be issued without the WHERE CURRENT OF clause In order to uniquely identify the row to be updated in the table in other words in order to simulate the WHERE CURRENT OF clause the ROWID or unique primary key columns of the table(s) to be updated must also be fetched and the WHERE CURRENT OF clause can be replaced with WHERE ROWID = fetched rowid or WHERE unique primary key column(s) = fetched unique primary key column(s) A BEGIN WORK must follow immediately after a COMMIT WORK or ROLLBACK WORK in the fetch loops to simulate Oracle implied transaction boundaries These transaction control statements work for either Informix logged databases or Informix ANSI mode databases however ANSI mode database processing with these statements will set certain warning flags after executing the BEGIN WORK statement and continue processing without failure See the ANSI vs Non-ANSI subsection in the Databases section in the chapter ldquoData Manipulation Languagerdquo for more information

System tables References to Oracle system tables should be replaced with corresponding references to Informix system tables The information schema views provided by Informix can be used These views are created after the database is installed They are populated by data in the system catalog tables and are used for easier porting

Stored procedures Informix procedures and functions are considered to be user-defined routines (UDR) A UDR can be written in Informixrsquos Stored Procedure Language (SPL) or an external language such as C or Java A procedure is a routine written that does not return a value A function is a routine written that returns a single value a value with a complex data type or multiple values Informix SPL is an extension to Informix SQL and provides procedural flow control such as looping and branching A SPL routine is a generic term that includes both SPL procedures and SPL

functions You use SQL and SPL statements to write an SPL routine SPL statements can be used only inside the CREATE PROCEDURE CREATE PROCEDURE FROM CREATE FUNCTION and CREATE FUNCTION FROM statements SPL routines are parsed optimized and stored in the system catalog tables in executable format Like Oracle Informix stored procedures support input output and inputoutput parameters and can be used in SQL statements wherever expressions are allowed

Size limit

Informix stored procedures have a size limit of approximately 64K Oracle stored procedures greater than 64K in size can be broken into smaller Informix stored procedures communicating with each other as though they were one by passing and returning the necessary values

Parameter limit

IBM Software Group IBM Information Management

Version 16 51

Informix has a limit of 341 parameters for each stored procedure This limit also applies to UDRs written in the Java language UDRs written in the C language can have no more than 102 parameters You can define any number of SPL routine parameters but the total length of all parameters passed to an SPL routine must be less than 64 kilobytes No more than nine arguments to a UDR written in the Java language can be DECIMAL data types of SQL that the UDR declares as BigDecimal data types of the Java language Any C language UDR that returns an opaque data type must specify opaque_type in the var binary declaration of the C host variable

Packages

An Oracle package is a collection of functions procedures and variables that can be enabled and accessed as a unit There is no direct equivalent within Informix but there are ways of achieving similar capabilities Within Oracle a procedure within a package can be accessed through grammar such as package_nameprocedure_name If you create an owner or schema name within the Informix system the same as the package name then it will be easier to migrate calls to that procedure because the grammar is effectively the same although the meaning changes somewhat Using this practice a call to a migrated procedure would be ownerprocedure_name where the owner name is the same as the package name Translating package names as owner names is a way to maintain the scoping of the objects within the package Maintaining the aspect of being able to enable use of or upgrade the collection of package objects can be done by creating a datablade that contains all the objects that used to be part of the package Datablade routines can be procedures or functions written in Stored Procedure Language (SPL) C and Java In addition routines can be written in C++ on Windows platforms

Routines

Oraclersquos stored functions and stored procedures are similar in concept to Informixrsquos stored procedures Oraclersquos user defined database level functions such as stored functions stored procedures all need to be converted to Informix stored procedures using the Informix SPL C or Java Routines written in SPL have the advantage of being maintained and backed up with database backups Routines written in C are fast but are not automatically backed up when the database is and need to be compiled specifically for the operating system on which it will run Routines written in Java also not backed up by the DBMS itself but they are platform independent However probably as a result of having to convert between system memory where the objects have C structures and Java virtual machine memory where the objects have Java structures the performance of Java routines can be slow compared with the C equivalent All procedures written in an Oracle package body must be rewritten as separate Informix procedures When rewriting package bodies into separate procedures Oraclersquos variable declarations can be replaced at the package level (global) with Informixrsquos global variables The Informix global variables must be defined in the first stored procedure of the logical group

Exceptions

The method of handling exceptions is different between Informix and Oracle Oracle has many predefined and user defined exception labels such as CURSOR_ALREADY_OPEN NO_DATA_FOUND ZERO_DIVIDE and so on The labels can be used in the logic to identify errors Only one exception check is allowed per BEGIN and END block using the EXCEPTION construct and it is normally placed just before the END statement Informix also supports predefined and user defined exceptions however they are represented numerically not with labels In Informix all the exceptions checked in the stored procedure control blocks delimited with BEGIN and END statements must be declared explicitly at the top of each

IBM Software Group IBM Information Management

Version 16 52

control block with the Informix EXCEPTION construct Therefore Oracle procedure code must be restructured to manipulate these exceptions In Oracle an exception can be raised globally and acted upon globally In Informix the scope of an exception mechanism is always restricted to the block in which it is located This leads to the addition of multiple Informix exception handling mechanisms for each Oracle exception raised as well as a redesign of the overall stored procedure to a more blocked format

Error handling

In Oracle errors are processed as part of a function call return value In Informix errors are retrieved as a separate function call that has multiple structures that have to be created in order to retrieve error and status The SQLCA structure is not fully available in Informix stored procedures It is not possible to check the SQLCODE variable in the stored procedure body Instead the function DBINFO can be used to extract the value of two members of the SQLCA structure sqlcasqlerrd1 and sqlcasqlerrd2 This function should be used inside the FOREACH construct while the cursor is open Once the cursor is closed the DBINFO function cannot return proper values The sqlcasqlerrd1 option returns different values depending on the type of SQL statement For INSERT statements if the table contains a serial column then the sqlcasqlerrd1 option will return the serial value of the last row inserted into the table For SELECT DELETE and UPDATE statements the sqlcasqlerrd1 option will return the number of rows processed by the query In these cases upon each pass through the FOREACH loop sqlcasqlerrd1 is the same value the number of rows the FOREACH loop will process The sqlcasqlerrd1 value can still be interrogated during each pass through the FOREACH loop The sqlcasqlerrd2 option returns the number of rows processed by a SELECT INSERT UPDATE DELETE or EXECUTE PROCEDURE statement It should not be interrogated until after the cursor has finished processing In other words within the FOREACH loop the sqlcasqlerrd2 value can be moved to a variable which is then interrogated outside of the FOREACH loop

Cursors

Unlike Informix in Oracle cursors can be global to a package In Informix Oraclersquos global cursors can be replaced with temporary tables A temporary table can be created and populated in place of where the cursor is opened The temporary table can then be processed the same way the cursor is processed Finally the temporary table should be dropped in place of where the cursor is closed Cursors are explicitly declared opened and fetched in Oracle stored procedures In Informix cursors do not need to be explicitly declared opened and fetched in stored procedures Instead Oracle stored procedure cursors can be replaced with Informixrsquos FOREACH construct The Oracle cursor name should be used in the FOREACH statement for example FOREACH cursor_name SELECT hellip END FOREACH In order to update a cursor row in Oracle the cursor must be declared with the FOR UPDATE clause In Informix if the SELECT statement in the FOREACH construct is not a multi-table join then each fetched row can be updated using the UPDATE lttable_namegt WHERE CURRENT OF ltcursor_namegt statement See the Update Using Cursors section in ldquoData Manipulation Languagerdquo for more information Informix does not support the SELECT FOR UPDATE statement in a stored procedure Therefore the SELECT FOR UPDATE clause cannot be used in the FOREACH construct

IBM Software Group IBM Information Management

Version 16 53

Variable declaration and assignment

Oracle allows implicit variable definitions within a FOR loop The variables are defined using an assignment operator and a column name For example

out_customer_name = customername

The variable out_customer_name is defined as the same type as the column name in the customer table Informix requires that all variables be defined at the beginning of each stored procedure control block For example

DEFINE out_customer_name LIKE customername

DEFINE counter INTEGER

Therefore Oraclersquos implicit variable declaration must be replaced with Informixrsquos explicit variable declaration before the control block Additionally assignment operations will need to be ported Oracle uses a colon and an equal sign (=) for assignment while Informix utilizes the LET keyword in combination with an equal sign (=) (ie LET var = 1) Therefore assignment statements must be modified with the LET keyword and an equal sign

Boolean

Oraclersquos BOOLEAN variable type can be replaced with Informixrsquos BOOLEAN data type

Binary data types

Binary data types are very different between Oracle and Informix In Oracle the binary type is defined as a type RAW and is explicitly defined with a maximum length as part of the declaration In Informix the binary type is defined as REFERENCES BYTE which deals only with pointers to BLOBs It implicitly defines a maximum length as part of the function call in which the pointer to the BLOB and maximum length (as used in the function call) was passed as values As a result the binary type cannot be assigned a binary value in a stored procedure nor can it be inserted into a table via the SQL INSERT statement in a stored procedure These operations that initialize a binary type must be performed outside of stored procedures

Dynamic SQL

Unlike Oracle Informix does not support dynamic SQL within the Stored Procedure Language In other words a statement such as SELECT variable_name FROM variable_name WHERE variable_name is not supported This kind of processing can be achieved in Informix within an embedded SQL program This requires that either the Oracle stored procedure be converted to an embedded SQL program or just the Dynamic SQL portion be placed in an embedded SQL program and then called from within the stored procedure The latter option will have performance implications since calling an embedded SQL program from a stored procedure requires an operating system call Another option is to use the Informix EXEC Bladelet The EXEC Bladelet consists of user-defined functions that take a SQL query as an argument execute it and return a result (the format of which varies depending on the function and the kind of query) The EXEC Bladelet functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries Further details can be found in Chapter 7 Using Bladelets

Compiler

Unlike Oracle the Informix compiler was developed with the concept that developers can create stored procedures independently of the database Therefore Informixrsquos stored procedure

IBM Software Group IBM Information Management

Version 16 54

compiler has a limited set of errors that it checks compared to Oraclersquos For example the Informix stored procedure compiler does not validate database object names such as table column and view names Therefore database object naming errors will occur at runtime not compile time Additionally the error messages generated from the compiler are not very specific Identifying a problem in a stored procedure may require breaking it apart and recompiling the pieces until the problem is found This may impact the time necessary to unit test the stored procedures

Triggers Oracle supports the use of multiple trigger events for example insert update and delete within the same trigger Informix only supports one trigger event per trigger In Informix the Oracle trigger body in this example must be copied into three different triggers each with only one event Informix triggers have some constraints Oraclersquos do not In Informix if a trigger is fired due to inserting a row into a table a trigger can only act on any rows or columns within that table using the EXECUTE PROCEDURE hellip INTO syntax Similarly if a trigger is fired due to updating a row then the trigger can only act on the column that caused the trigger to fire using the EXECUTE PROCEDURE hellip INTO syntax Like Oracle if a trigger is fired due to deleting a row there are no restrictions Prior to IDS 73 when a trigger was fired on an INSERTUPDATE action no modification could be done to the columns (in the row) which just fired the trigger The reentrant UPDATEINSERT triggers feature introduced with IDS 1110 enables users to update the triggering columns by using the EXECUTE PROCEDURE INTO syntax Additionally the feature enforce that this action will not cause any additional triggers to be fired (same or different trigger) causing a cascading of triggers and potentially an infinite loop The following example demonstrates how the reentrant UPDATEINSERT trigger feature is used

create table foo

(

x int default NULL

y int default NULL

z int default NULL

)

create procedure reentrant()

returning int

return 56

end procedure

create trigger reentrant_trigger insert on foo for each row

(

execute procedure reentrant() into z

)

insert into foo values

(

1

2

3

)

The following SELECT will result in the following returned data

select from foo

x y z

1 2 56

IBM Software Group IBM Information Management

Version 16 55

Oracle allows SQL statements logical statements and stored procedure calls within a trigger body Informix allows only SQL statements and stored procedure calls within a trigger body Oracle triggers containing logical statements must be converted to Informix by moving their contents into a stored procedure The stored procedure should then be executed from the trigger

Constraints Constraints in both Oracle and Informix can be enabled and disabled within an application transaction however there are behavioral differences In Oracle the application is always executing within a transaction In Informix transaction boundaries are explicitly declared and care should be taken to ensure that this functionality is performed within the boundaries of a transaction See the Transaction Processing section in CHAPTER 5 Application Architecture for more information The constraint syntax available in Informix is

SET CONSTRAINTSINDEXESTRIGGERS FOR table_name

ENABLED|DISABLED

SET CONSTRAINTS comma_separated_constraint_names

ENABLED|DISABLED

SET INDEXES comma_separated_index_names ENABLED|DISABLED

SET TRIGGERS comma_triggers_constraint_names ENABLED|DISABLED

SET CONSTRAINTS ALLconstraint_name IMMEDIATE|DEFERRED

The first four statements must be executed with DBA privileges if placed in the application Therefore care should be taken when using them Note that the last statement contains a DEFERRED clause This is the statement used if the users of the application do not have DBA privileges When the constraint is set with the DEFERRED clause the specified constraints are not checked until the transaction is committed If a constraint violation occurs while the transaction is being committed the transaction is rolled back

DUAL table Oraclersquos DUAL table is a system table with only one row containing one column named DUMMY This table is used to complete the syntax of an SQL statement that does not involve an existing table such as

A SELECT statement which assigns some constant value (which can only be derived in an SQL statement) to a host variable

SELECT TO_CHAR(SYSDATE) INTO date_var FROM DUAL

A SELECT statement which assigns a value of another variable to a variable

SELECT source_var INTO dest_var FROM DUAL

A SELECT statement which unions application host variable values with another SELECT statement to return a result containing a row of application variable values

SELECT col1 col2 col3 FROM table_name

UNION

SELECT host_var1 host_var2 host_var3 FROM DUAL

Converting Oraclersquos DUAL table functionality to Informix depends on the way it is used Converting statements that just assign constants is as simple as replacing the DUAL statement with an Informix assignment statement The solutions below apply to Informix versions prior to 11 At 11 and above the concept of a DUAL table as well as sysdate is supported

IBM Software Group IBM Information Management

Version 16 56

SELECT sysdate FROM sysmastersysdual

If you want a dual table in your local database then create the following synonym The sysmastersysdual table is much faster than a physical table in your database because it is an in- memory pseudo table

CREATE SYNONYM dual FOR sysmastersysdual

If you are restricted to using a version of Informix prior to 11 then the following solutions can be used A dummy table can be created to mimic the behavior of simple SELECT INTO statements used to assign values to variables

CREATE TABLE dual (dummy VARCHAR(1))

INSERT INTO dual VALUES(lsquoXrsquo)

An alternate solution to widespread use of the DUAL table could be creating a permanent view that is generally accessible

CREATE VIEW dual (d) as SELECT X

FROM systables WHERE tabid = 1

The exact definition could be used or modified as needed but this would solve the problem of having DUAL be permanent usable by anyone and not modifiable

IBM Software Group IBM Information Management

Version 16 57

C H A P T E R 5 Embedded SQL

Oraclersquos embedded SQL products are ProC and ProCOBOL Informixrsquos corresponding embedded SQL products are ESQLC and ESQLCOBOL

Host variables

Declaration override

The Oracle EXEC SQL VAR declarative statement (host variable equivalency of Oracle external data types by overriding the default assignment) can be converted to an Informix explicit declaration statement For example

Oracle char char_var[20]

EXEC SQL VAR char_var IS STRING(11)

Informix

char char_var[11]

Note that the size and type used in the EXEC SQL VAR section is the final information required to declare the host variable in Informix

Arrays

Oracle arrays are not subscripted in SQL statements since it is not required to process the host arrays in a loop in the SQL statement In Informix subscripting is mandatory In Oracle if an array is defined of size 200 then an SQL statement would be

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A

VAR-B

VAR-C

END-EXEC

-or- EXEC SQL SELECT COL1 COL2 COL3

INTO VAR-A

VAR-B

VAR-C

FROM TABLE1

WHERE COL2 gt 100

END-EXEC

where VAR-A VAR-B and VAR-C are each an array of say 200

IBM Software Group IBM Information Management

Version 16 58

In Informix the first example would be converted to

PERFORM VARYING LOOP-CTR FROM 1 BY 1 UNTIL

LOOP-CTR IS GREATER THAN 200

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A(LOOP-CTR)

VAR-B(LOOP-CTR)

VAR-C(LOOP-CTR)

END-EXEC

IF SQLCODE = 100

GO TO EXIT-PERFORM

END-IF

END-PERFORM

EXIT-PERFORM

For the second Oracle example given above a cursor must be declared in Informix opened and fetched for 200 rows or less (less because there may be less than 200 qualifying rows) into the host array and then should be closed If the number of qualifying rows is more than 200 then the extra rows must be ignored to duplicate the Oracle functionality But for the first example each fetch in Oracle will return the next 200 or less number of rows Therefore each Oracle fetch needs to be replaced by another call to the Informix fetch loop Oracle also uses this method for inserts deletes and updates These array techniques are mainly used in batch SQL processing

Formatting

In Informix when a DECIMAL MONEY DATE or DATETIME value is selected into a host variable of the same data type the value must be formatted using the available Informix formatting routines before they can be printed or displayed For example

hellip

dec_t dec_host_var

char formatted_dec[40]

EXEC SQL SELECT DEC_COLUMN INTO dec_host_var FROM TABLE_NAME

rfmtdec(ampdec_host_var ldquoampampampampampampampampampamprdquo formatted_dec)

printf(ldquoThe Decimal Value is snrdquo formatted_dec)

hellip

IBM Software Group IBM Information Management

Version 16 59

Informix supplies many formatting functions and formatting strings The names of these functions are different in Informix ESQLC and ESQLCOBOL but the functionality is the same Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

SQL structures

SQLCA

Oraclersquos SQLCA structure is different from that of Informix However the components of both structures are logically the same Oraclersquos SQLCA components can be replaced with the corresponding Informix components Oraclersquos SQLCA structure

SQLCAID string containing ldquoSQLCArdquo SQLCABC length of SQLCA data structure SQLCODE Oracle error message code SQLERRM sub-record for error message

SQLERRML length of error message SQLERRMC text of error message SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) reserved for future use SQLERRD(1) reserved for future use SQLERRD(2) number of rows processed SQLERRD(3) reserved for future use SQLERRD(4) parse error offset SQLERRD(5) reserved for future use

SQLWARN array of eight warning flags SQLWARN(0) another warning flag set SQLWARN(1) character string truncated SQLWARN(2) no longer in use SQLWARN(3) SELECT list not equal to INTO list SQLWARN(4) DELETE or UPDATE without WHERE clause SQLWARN(5) reserved for future use SQLWARN(6) no longer in use SQLWARN(7) no longer in use

SQLTEXT reserved for future use

IBM Software Group IBM Information Management

Version 16 60

Informixrsquos SQLCA structure

SQLCODE Informix error code SQLERRM error message parameter SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) estimated number of rows returned SQLERRD(1) serial value of INSERT or ISAM error code SQLERRD(2) number of rows processed SQLERRD(3) estimated cost SQLERRD(4) parse error offset SQLERRD(5) ROWID after INSERT

SQLWARN structure of eight warning flags SQLWARN0 another warning flag set SQLWARN1 character string truncated or no privileges revoked SQLWARN2 NULL value returned or ANSI database SQLWARN3 SELECT list not equal to INTO list or turbo back-end SQLWARN4 DELETE or UPDATE without WHERE clause SQLWARN5 if non-ANSI statement SQLWARN6 if server is in data replication secondary mode SQLWARN7 reserved

In order to get Oracle error messages an application normally uses the SQLCA element SQLERRMC The Informix equivalent is SQLERRM On the HPUX and Solaris platforms the Informix function rgetmsg should be used instead of the element SQLERRM At the time of this writing using SQLERRM would cause an error on the HPUX and Solaris platforms

SQLDA

The implementation of Oraclersquos SQLDA structure is very different from that of Informix Significant changes are necessary to convert Oraclersquos functionality to Informix Oraclersquos sqlald function can be replaced with Informixrsquos ALLOCATE DESCRIPTOR statement Since Oraclersquos and Informixrsquos SQLDA structures are so different Oraclersquos SQLDA logic must be rewritten with the more powerful Informix SQLDA logic or alternatively the Informix system-descriptor area logic Oraclersquos SQLDA Structure

N maximum number of SELECT list items or placeholders V pointer to array of address of SELECT list items or bind variables L pointer to array of lengths of SELECT list items or bind variables T pointer to array of data types of SELECT list items or bind variables I pointer to array of addresses of indicator variable values F actual number of SELECT list items or placeholders S pointer to array of addresses of SELECT list items or placeholder names M pointer to array of max lengths of SELECT list items or placeholder names C pointer to array of current lengths of SELECT list items or placeholder names X pointer to array of addresses of indicator variable names Y pointer to array of maximum lengths of indicator variable names Z pointer to array of current lengths of indicator variable names

IBM Software Group IBM Information Management

Version 16 61

Informixrsquos SQLDA Structure SQLD count of the following SQLVAR members SQLVAR pointer to array of structures

SQLDATA pointer to actual data SQLTYPE data type of placeholder or SELECT item SQLLEN length of the placeholder or SELECT item SQLIND pointer to the indicator SQLNAME pointer to placeholder or SELECT item name SQLFORMAT reserved SQLIDATA indicator data pointer SQLITYPE indicator variable type SQLILEN length of indicator variable

If an Oracle application uses the simple dynamic SQL method using macros only not the SQLDA structure directly the value indicatorsplaceholders can be replaced with a lsquorsquo in Informix For example Oracle sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES (v1 v2)rdquo) Informix sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES ( )rdquo)

ORACA

Oraclersquos ORACA structure is not supported by Informix This structure is used to handle Oracle specific communication and more runtime information than SQLCA Oracle statements containing references to this structure should be removed from the application

Pre-compiler options The Oracle options beginning with the EXEC ORACLE OPTION statement can be removed from the application The options set after this statement do not affect the application logic They may affect some application performance only

Embedded PLSQL Oracle allows procedure language (PLSQL) blocks inside ProC and ProCOBOL code delimited by the EXEC SQL EXECUTE and END-EXEC statements In Informix these blocks must be replaced with the equivalent ESQLC or ESQLCOBOL code

Oracle Call Interface Oracle call interface (OCI) is the base layer for a variety of other application programming interfaces such as JDBC-OCI Oracle Precompilers and Oracle ODBC It is also used directly by customers who are willing to develop their code using a lower level proprietary API From a high level it can be thought of as if IBM Informix had standardized and published the function calls in the ESQLC library Although some customers have reverse engineered these calls and developed applications using them this is generally discouraged because there is no guarantee that the library of calls will not change There is no direct equivalent to this Oracle API in Informix Migrating applications written using Oracle Call Interface (OCI) will require rewriting the code from scratch OCI is native to the C language and so it should be less effort to migrate the application to an Informix API that is also native to C This could be ESQLC or CLI The following information explains differences between Oracle OCI and Informix ODBC

IBM Software Group IBM Information Management

Version 16 62

The following table is an approximate mapping of the differences between the Informix CLI and Oracle OCI function calls in which there is not a direct one-to-one mapping

Oracle Informix Buffer Areas HAD LDA CDA HENV HDBC HSTMT

Connect and allocate resources

OLOG OOPEN SQLConnect SQLAllocEnv SQLAllocConnect SQLAllocStmt

Update delete insert select OPARSE OBNDRV OEXEC SQLPrepare SQLBindParameter SQLExecute

Select ODEFIN OFETCH SQLBindCol SQLFetch

Commit Rollback OCOM OROL SQLTransact

Disconnect OLOGOF OCLOSE SQLDisconnect SQLFreeStmt SQLFreeConnect SQLFreeEnv

Database library calls

One of the first main differences between Informix CLI and Oracle OCI calls is the overall data structures and mechanisms used to process database library calls Oracle uses direct connections to the database server Informix uses an ODBC connection to the database server As a result the Informix calls will be implemented as ODBC SQL calls utilizing three tiers of increasing SQL levels of complexity

Global area processing

Another main difference between Informix CLI and Oracle OCI is Informixrsquos use of pointers to three global areas versus Oraclersquos use of pointers to three different but similar global areas Hence the Oracle OCI calls that utilize HAD (Handle Data Area) LDA (Logon Data Area) and CDA (Cursor Data Area) pointers must be translated over to Informix CLI calls that utilize HENV (Environment Area) HDBC (Database Connection Area) and HSTMT (Statement Area) pointers respectively in conjunction with an ODBC interface

Fetch cycle

Another difference between Informix CLI and Oracle OCI calls is that the overall fetch cycle is different for each and must be modified accordingly In Oracle the fetch cycle for selecting multiple rows utilizing a cursor area involves parsing binding defining fetching and then executing into a cursor data area These must be translated to a cycle that involves preparing binding executing binding and then fetching via the ldquoFor Eachrdquo cycle

RAW binary data type processing

RAW binary data types in Oracle will need to be translated to a pointer-to-BLOB REFERENCES BYTE type in Informix See the Binary Data Types subsection of the Stored Procedures section in CHAPTER 3

Parameter bindings

In Oracle multiple output bindings of parameters are declared as type ldquoOUTPUTrdquo in the ODEFIN() calls In Informix convert the calls to Informix SQLBindCol() calls and bind the output parameters as columns Differences also exist between Informix CLI and Oracle OCI in the use of inputoutput bindings In Oracle these bindings are declared as type ldquoINPUTOUTPUTrdquo in the ODEFIN() calls In Informix a ldquoround robinrdquo approach is used using three variables in the following manner A=B B=C C=A A variable (A) is declared before the SQL bindings as an input variable The function is called

IBM Software Group IBM Information Management

Version 16 63

using a second input variable (B) that is set to the first input variable (A) The function returns a third variable (C) that is bound as an output column Finally the first variable (A) is now set to the returned third variable (C) that made the first variable (A) appear as an ldquoinputoutputrdquo variable to the rest of the program

Embedded SQL for C

VARCHAR

Oraclersquos ProC VARCHAR data type is expanded after pre-compiling into a structure with two elements one is unsigned short len and the other is unsigned char arr[size] The name of the expanded structure is the same name as the VARCHAR variable and size is replaced with the size of the VARCHAR variable In Informix the VARCHAR data type is just a synonym for the C languagersquos char data type Therefore statements that use variable_namelen can be removed from the application and all occurrences of variable_namearr can be replaced with variable_name For example

Oracle VARCHAR vName[40]

strcpy(vNamearr ldquoCompany Namerdquo)

vNamelen = strlen(vNamearr)

Informix VARCHAR vName[40]

strcpy(vName ldquoCompany Namerdquo)

Host variables

The Oracle statement EXEC SQL TYPE is synonymous with the C languagersquos typedef declarative instruction It can be easily replaced with the Informix declarative instruction typedef

Embedded SQL for COBOL

VARCHAR

Oraclersquos ProCOBOL character host variable declaration statementrsquos VARYING clause is expanded after pre-compiling into a group with two elements one is variable-name-LEN PIC S9(4) COMP and the other is variable-name-ARR PIC X(size) The group name is the same as the host variable name and size is replaced with the size of the VARYING variable Informix does not support this concept Therefore statements that use variable-name-LEN must be removed from the application and all occurrences of variable-name-ARR must be replaced with variable-name Also the VARYING clause must be removed from the declarative statement For example

Oracle

05 vName PIC X(40) VARYING

hellip

MOVE ldquoCompany Namerdquo TO vName-ARR

MOVE 12 TO vName-LEN

Informix

05 vName PIC X(40)

hellip

MOVE ldquoCompany Namerdquo TO vName

IBM Software Group IBM Information Management

Version 16 64

Level 88

COBOLrsquos level 88 functionality is not supported within an Informix ESQLCOBOL host variable declaration section in versions prior to 72 Level 88 functionality is supported in Informix ESQLCOBOL 72

SQLDA

In Informix ESQLCOBOL the SQLDA structure is not available The Informix macros such as ALLOCATE DESCRIPTOR DESCRIBE GET DESCRIPTOR and SET DESCRIPTOR must be used to retrieve and manipulate the SQLDA data

REDEFINES

Oracle supports the use of the REDEFINES clause at the elementary level in the host variable declaration section In other words the redefined item cannot be a group item but the redefining item may be a group item Informix does not support the use of the REDEFINES clause in the host variable declaration section in versions prior to 72 The REDEFINES clause is supported in Informix ESQLCOBOL 72

Tips

If the Informix pre-compiler finds an SQL statement within an IF [ELSE IF hellip ] END-IF or EVALUATE END-EVALUATE or PERFORM END-PERFORM block then the pre-compiler adds a period after the generated COBOL statements regardless of whether there is a period at the end of the SQL statement This is a violation of COBOL rules for such blocks and the code may cause syntax errors during compilation or may behave unexpectedly To avoid these problems each SQL statement group should be moved to a new paragraph and these paragraphs should be performed from the block from which they were moved

ODBC Although the Open Database Connectivity (ODBC) API is designed to make it possible to write and compile an application once and use it with any ODBC driver on the same platform there are frequently differences between the underlying DBMSs that can expose problems to the applications For instance there can be differences between how unspecified parts of a date-time value are filled Most of these kinds of differences that get exposed through ODBC have their origins in the differences between the DBMSs themselves There are also cases where there are gaps in the ODBC standard for example there is a standard ODBC call that allows the application to ask the driver if it can support scrollable cursors and there is another call to ask if it can support updateable cursors There is no call to ask if it can support both at the same time With Informix you can have a scrollable cursor and you can have an updateable cursor but you can not have one cursor that is both scrollable and updateable A more complete description of ODBC application migration issues is beyond the scope of this article

IBM Software Group IBM Information Management

Version 16 65

C H A P T E R 6 Application Architecture

Transaction processing Transaction boundaries are defined differently in Oracle and Informix Oraclersquos transactions begin implicitly in one of two ways either by issuing a CONNECT statement or issuing a COMMIT or ROLLBACK statement A CONNECT statement marks the beginning of a transaction and a COMMIT or ROLLBACK statement commits or rolls back the previous transaction respectively and then implicitly begins a new transaction CONNECT statements are usually issued once at the beginning of a program however they may be nested or issued more than once serially to connect to the same or a different database When using more than one CONNECT statement within a program each CONNECT statement must be named This marks the beginning of named transactions Every SQL statement within a named transaction must also be named with the same transaction name as the CONNECT statement at where the SQL is to be executed SQL is named using the EXEC SQL statementrsquos AT clause Informixrsquos transaction boundaries are explicitly marked with the reserved words BEGIN WORK and COMMIT WORK or ROLLBACK WORK Note that once a transaction has begun for a given connection it stays open until a COMMIT or ROLLBACK is executed In other words if an ESQL program begins a transaction and then calls a stored procedure the stored procedure executes within the same transaction If the stored procedure issues a COMMIT then the whole transaction is committed and the calling ESQL program should not issue a COMMIT or ROLLBACK Informix transactions can be written to behave the same way as Oraclersquos To simulate Oraclersquos CONNECT statement behavior an Informix CONNECT should also be issued followed by a BEGIN WORK statement If more than one CONNECT statement is used in a program Informix also requires that the CONNECT and SQL statements be named To simulate Oraclersquos COMMIT and ROLLBACK statement behavior an Informix COMMIT WORK or ROLLBACK WORK statement should be issued followed by a BEGIN WORK statement Nested transactions can be simulated in Informix with the CONNECT statement and naming the transactions Then the Informix SET CONNECTION connection_name statement can be used to switch between transactions Committing or rolling back each named transaction does not commit or roll back other active transactions The Oracle statement EXEC SQL COMMITROLLBACK RELEASE should be replaced with the Informix statements EXEC SQL COMMITROLLBACK [WORK] followed by EXEC SQL DISCONNECT CURRENT In the following examples ws-dbenviron is the database name ws-connect-nm is the user name and ws-identity-nm is the password set in the program enp and connection-name are the connection names For Informix the user name and password information should correspond to the entries in the etcpasswd file on the UNIX system See the User Authentication section later in this chapter for more information The default server name is automatically obtained from the environment variable INFORMIXSERVER The following examples illustrate how Oracle and Informix implement the CONNECT functionality

IBM Software Group IBM Information Management

Version 16 66

Simple Connect

Oracle

CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm

Informix

CONNECT ws-dbenviron USER ws-connect-nm USING ws-identity-nm

Named Connect with Literal

Oracle

DECLARE enp DATABASE hellip CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm AT enp USING ws-dbenviron hellip AT enp SELECT col1 col2 INTO var1 var2

FROM table_name

Informix

CONNECT TO ws-dbenviron AS ldquoenprdquo USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION ldquoenprdquo hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Named Connect with Variable

Oracle

CONNECT ws-connect-nm

IDENTIFIED BY ws-identity-nm AT connection-name USING ws-dbenviron hellip AT connection-name SELECT col1 col2 INTO var1 var2 FROM table_name

Informix

CONNECT TO ws-dbenviron AS connection-name USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION connection-name hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Autonomous Transaction

An autonomous transaction is an independent transaction that is initiated by another transaction (the parent transaction) An autonomous transaction can modify data and commit or rollback independent of the state of the parent transaction The autonomous transaction must commit or roll back before the autonomous transaction is ended and the parent transaction continues

IBM Software Group IBM Information Management

Version 16 67

An autonomous transactions has been available since the release of Oracle 8i An autonomous transaction is defined in the declaration of a PLSQL block This can be an anonymous block function procedure object method or triggerThis is done by adding the statement PRAGMA AUTONOMOUS_TRANSACTION anywhere in the declaration block There isnt much involved in defining a PLSQL block as an autonomous transaction You simply include the following statement in your declaration section PRAGMA AUTONOMOUS_TRANSACTION Sample code

PROCEDURE test_autonomous

IS

PRAGMA AUTONOMOUS_TRANSACTION

BEGIN

insert

commit

END test_autonomous

Autonomous transactions can be used for logging in the database independent of the rollbackcommit of the parent transaction

Savepoints

Oracle allows savepoints within its PLSQL For example a PLSQL block can be structured so that SAVEPOINT A is issued upon entry and SAVEPOINT B is issued after some processing Then after some more processing a COMMIT or ROLLBACK can be issued against all the logic since the last COMMIT point which is before the PLSQL block or up to any of the savepoints by naming the COMMIT or ROLLBACK with the savepoint name In other words a savepoint can be issued at the beginning of a stored procedure and then only the stored procedure logic can be committed without committing the changes pending before the stored procedure was executed Those changes can be committed or rolled back once processing is returned from the stored procedure Informix does not support savepoint processing within a stored procedure

Concurrency Database concurrency can be managed through the combination of two configurable settings one specifies the lock granularity on database objects while the other influences how the application behaves in regards to the presence and placement of locks using a transaction isolation level

Row Level Locking

Oracle and Informix implement locking differently on database objects Oracle defaults to row level locking whereas Informix defaults to page level In most cases row level locking is preferred to improve concurrency Informix supports row level locking however it must be either explicitly requested specified by an environment variable or permanently changed in the instancersquos configuration Having three methods for establishing the lock level there is an order of precedence

1 To be explicitly requested the CREATE TABLE statement must include the specification of the LOCK MODE attribute

CREATE TABLE emp (

name CHAR(40)

salary MONEY

ssn LVARCHAR(64)

) LOCK MODE ROW

IBM Software Group IBM Information Management

Version 16 68

2 The environment variable IFX_DEF_TABLE_LOCKMODE will establish the default for CREATE TABLE statements issued without the LOCK MODE attribute and will override the Instancersquos configuration setting The variable setting on the client will override the server environment setting

set IFX_DEF_TABLE_LOCKMODE=ROW -or- export IFX_DEF_TABLE_LOCKMODE=ROW

3 Informix allows the instancersquos lock level default to be changed using a configuration parameter Row level locking can be as the default by adding the parameter DEF_TABLE_LOCKMODE to the instancersquos ONCONFIG file This parameter may not be found in the existing file and if not present can be added using an editor and establish a new default setting of ROW

DEF_TABLE_LOCKMODE ROW

None of the steps will apply a change to existing tables only establish the lock level for the CREATE TABLE statement

Transaction Isolation Level

Oracle databases incorporate a feature known as ldquoread consistencyrdquo which allows a query return a result based on the state of the data when the query started regardless of other processes updating or deleting the same data while the query is running Informix facilitates this type of behavior differently by providing control of the applicationrsquos placement of locks as well as how it reacts to those placed by other processes through the use of the transactionrsquos isolation level If Oraclersquos technique of ldquoreaders not blocking writersrdquo is a requirement then in many circumstance Informixrsquos DIRTY READ isolation level can be used The readers will not block the writers with dirty read processing however the query result may contain updates performed while the query was running which may be uncommitted If the emulation of Oraclersquos ldquoread consistencyrdquo is desired the LAST COMMITTED option of Informixrsquos COMMITTED READ isolation level can reduce the risk of locking conflicts when two or more sessions attempt to access the same row in a table whose locking granularity is row-level When an application attempts to read a row on which another session holds an exclusive lock these keywords instruct the database server to return the most recently committed version of the row rather than wait for the lock to be released This isolation level attribute could be preferable to executing queries using DIRTY READ since it will return only the most recently committed versions of the data The LAST COMMITTED option can be enabled in the following ways

1 Setting the USELASTCOMMITTED parameter in the Instancersquos configuration (ONCONFIG) will apply this feature as the default isolation level to all database transactions The parameterlsquos values will designate the scope of applying the LAST COMMITED option to either ALL NONE or only COMMITED READ and DIRTY READ isolation levels

USELASTCOMMITTED [ALL | NONE | COMMITTED READ | DIRTY READ]

2 The SET ENVIRONMENT statement can override the USELASTCOMMITTED configuration parameter setting for the duration of the current session The same semantics apply as the parameter within the ONCONFIG file with the setting value enclosed in quotes (lsquo)

SET ENVIRONMENT USELASTCOMMITTED lsquoALLrsquo

IBM Software Group IBM Information Management

Version 16 69

3 The SET ISOLATION statement can be used to override the instance configuration and session environment setting The SET ISOLATION statement is an Informix extension to the ANSI SQL-92 standard and provides the same functionality as the ISOANSI-compliant SET TRANSACTION statement There is no support for the LAST COMMITTED option with the SET TRANSACTION statement SET TRANSACTION complies with ANSI SQL-92 and only ANSI supported isolation levels are supported

SET ISOLATION TO COMMITTED READ LAST COMMITTED

4 PREPARE statements in ODBCJDBC applications

This feature is primarily documented in the Guide to SQL Syntax Guide to SQL Reference Administrators Reference and Administrators Guide

IBM Software Group IBM Information Management

Version 16 70

C H A P T E R 7 Security

User authentication In Oracle security information is stored in the database Up until recently Informix has used only the operating system security subsystem to check security For security purposes Oracle connects to the server and passes the user ID and password information to the database for verification

Operating system security

Informix does not store user ID and password information in the database Instead they are validated against the operating systemrsquos security mechanism on the server for example the etcpasswd file in UNIX Therefore either every database user must have an entry in the serverrsquos password file or the application must handle a level of security where user IDs are converted into a group id based on database permissions and only those group IDs are entered into the password file Note that if the second alternative is chosen then auditing capabilities based on user ID are lost Also if the application performs security functions then those functions are not applicable to third party applications such as report writers application development tools and so on when they access the database The home directory of all the users should point to the same physical directory where the application executable resides The Informix method of using the operating system for security checking allows external programs to be called from within stored procedures This capability is not allowed in Oracle In Oracle the OPS$User_name is sometimes used to connect to the database where OPS$User_name is a valid Oracle user and User_name is a valid operating system level user In this case the connection is made to the database using just the lsquorsquo character without the user id and password Informixrsquos technique of using the etcpasswd file for security works fine for this type of connection

Non-operating system security

In previous releases each user who needed to access the database server also needed an operating system account on the host computer Now you can configure Informix so that users who are authenticated by an external authentication service (such as Kerberos or Microsoft Active Directory) can connect to Informix The new USERMAPPING configuration parameter specifies whether or not such users can access the database server and whether any of those users can have administrative privileges When Informix is configured to allow user mapping you can still control which externally authenticated users are allowed to connect to Informix and their privileges Please refer to the IBM Informix documentation on connection security for more information

IBM Software Group IBM Information Management

Version 16 71

Informix supports for the pluggable authentication module (PAM) framework which lets an administrator customize authentication for individual applications and permits column-level encryption

Role based authority Role based authority can help you manage your database permissions As of version 1110 you can create a role and assign that as a default role for individual users (or to PUBLIC) A role is a work-task classification such as ldquopayrollrdquo or ldquomanagerrdquo Each defined role has privileges on the database object granted to the role You use the CREATE ROLE statement to define a role and GRANT DEFAULT ROLE to establish the userrsquos initial setting when connecting to the database A userrsquos role can be changed after connecting by using the SET ROLE statement

Column-level encryption You can use column-level encryption to improve the confidentiality of your data IDS Version 1110 has new built-in SQL scalar functions provide methods for data in columns to be stored in an encrypted format Use the ENCRYPT_AES or the ENCRYPT_TDES function to define encrypted data Use the DECRYPT_BINARY() and DECRYPT_CHAR() functions to query encrypted data When using the routines the encryption of data is under application control and the DBMS is not aware that data is encrypted Informixrsquos support of column level encryption is analogous to Oraclersquos DBMS Obfuscation Tool Kit Built-in ENCRYPT functions provide methods for encrypting and decrypting the following character data types or smart large object data types

CHAR

NCHAR

VARCHAR

NVARCHAR

LVARCHAR

BLOB

CLOB

Passwords and hints

Passwords are necessary when using the encryption functions Only users who can provide a secret password can view copy or modify encrypted data The password must be a minimum of 6 bytes and can be a maximum of 128 bytes When you set an encryption password you have the option of specifying a password hint Hints can be up to 32 bytes of text If you specify a hint you can store the hint with the encrypted password or in another location Passwords (and hints) to be used by default can be set for a session using the SET ENCRYPTION PASSWORD statement

SET ENCRYPTION PASSWORD lsquopasswordrsquo [ WITH HINT lsquohint stringrsquo ]

Hence the password and hint parameters can be optional when calling the encryption function Explicit values override the session default values The password or hint can be a single word or several words The hint should be a word or phrase that helps you to remember the password but does not include the password You can subsequently execute the built-in GETHINT function (with an encrypted value as its argument) to return the plain text of hint Calling the GETHINT function with an argument of encrypted data will return the hint (if any) from the encrypted data or an empty string (NULL) is no hint was provided There is no privilege needed anybody can get any hint at any time When you set a password Informix transfers the password and any hint to 128-bit key that is used to encrypt the password and hint Passwords and hints are not stored as plain text any table of the system catalog The key is a time-based random value per instance The database server

IBM Software Group IBM Information Management

Version 16 72

initializes the key when the server starts the key is destroyed when the database server shuts down

Encrypting a column

Column data can be encrypted through the use of two functions ENCRYPT_TDES and ENCRYPT_AES corresponding to the two data encryption standards Triple Data Encryption Standard (Triple-DES) and Advanced Encryption Standard (AES) which describes the cipher algorithm used to protect data from unauthorized viewing AES encryption (also known as Rijndael) uses a 128-bit key size and Triple-DES encryption uses two 56-bit keys for 112-bits overall Both functions are variant functions and will return a different result every time it is used The following example demonstrates how to use the encryption functions with a column that contains a social security number

CREATE TABLE emp (name CHAR (40) salary MONEY ssn LVARCHAR(64))

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890one two

three 123))

-or-

CREATE TABLE emp (name CHAR(40) salary MONEY ssn LVARCHAR(64))

SET ENCRYPTION PASSWORD one two three 123

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890))

Querying an encrypted column

Encrypted data can be translated using Informixrsquos DECRYPT_CHAR and DECRYPT_BINARY scalar functions Encrypted data contains information about the encryption method and all the other data needed to decrypt it except the password The encrypted data value is passed as the first argument and a password as the second unless the SET ENCRYPTION statement has specified for this session with the same session password by which the first argument was encrypted If the data is not encrypted the function call will return an error The DECRYPT_CHAR function is used to invoke a decryption routine on character data types (ie CHAR LVARCHAR NCHAR NVARCHAR and VARCHAR) while the DECRYPT_BINARY function accepts an encrypted large object of type BLOB or CLOB If the first argument to DECRYPT_CHAR or DECRYPT_BINARY is not an encrypted value or if the second argument (or the default password specified by SET ENCRYPTION) is not the password that was used when the first argument was encrypted Informix will issue an error and the call fails If the call to the decryption function is successful it returns the plain text version of the encrypted data argument The following example demonstrates how to use the decrypt function to query encrypted data

SELECT name salary DECRYPT_CHAR(ssn lsquoone two three 123rsquo)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

-or-

SET ENCRYPTION PASSWORD lsquoone two three 123rsquo

SELECT name salary DECRYPT_CHAR(ssn)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

The first argument to DECRYPT_BINARY is expected to be an encrypted value of a large object data type however if it is called with a character data type Informix invokes the DECRYPT_CHAR function and attempts to decrypt the specified value

IBM Software Group IBM Information Management

Version 16 73

Do not use either decryption function to create a functional index on an encrypted column This would store the decrypted values as plain text data in the database defeating the purpose of encryption

Performance impact of encryption

The performance impact of encryption is significant Encryption by its nature will slow down most SQL statements If some care and discretion are used the amount of extra overhead should be minimal Also encrypted data will have a significant impact on your database design In general you want to encrypt a few very sensitive data elements in a schema like social security numbers credit card numbers patient names and so on The effect on performance depends on direction encrypting is slower than decrypting It does not depend measurably on which algorithm is used AES performs at the same speed as Triple-DES It does depend on data size the relative overhead is less when there is more data to encrypt

Storage considerations

An encrypted value uses more storage space than the corresponding plain text value Data encrypted using AES can be bigger than Triple-DES but not by a significant amount This occurs because all of the information needed to decrypt the value except the encryption key is stored with the value Therefore before you set the encryption password and encrypt the data you must be sure the encrypted data can fit in the column A chart of the expected sizes can be found in the IBM Informix Administrator Guide

Compliance regulations

Informixrsquos encryption routines comply with the United Statesrsquo regulations of Health Insurance Portability and Accountability Act (HIPAA) Sarbanes-Oxley Gramm-Leach-Bliley and California Personal Information Privacy (SB 1386) as well as the international requirements of Basel II Also they comply with the latest cryptographic standards (OpenSSL 097c)

IBM Software Group IBM Information Management

Version 16 74

C H A P T E R 8 Environment

Scripts Oracle make files used to build the application should be modified to invoke the appropriate Informix ESQLCOBOL ESQLC MF COBOL and other application language commands The shell scripts shell startup scripts and command files should be modified for Informix compliant statements

SQL script substitution variables

In Oracle a substitution variable is a user variable name preceded by one or two ampersands (amp) When Oracle (SQLPlus) encounters a substitution variable in a command Oracle executes the command as though it contained the value of the substitution variable rather than the variable itself In Oracle the substitution variables can be used anywhere in SQL and SQLPlus commands except as the first word entered at the command prompt When SQLPlus encounters an undefined substitution variable in a command SQLPlus prompts the user for the value SQLPlus reads the responses from the keyboard even if terminal input or output has been redirected to a file If a terminal is not available (if for example the command file is run in batch mode) SQLPlus uses the redirected file Informixrsquos dbaccess does not provide this functionality however a work-around for the redirected file type of substitution is a follows (no user prompting) Create the following shell script (named subvalsksh in this case)

binkshif [[ $ -ne 2 ]]

then

echo nUsage $0 ltdfilegt ltcfilegtn

echo Desc This script accepts two files - dfile the decode

file

echo and cfile the change file It modifies the

change file

echo using the values listed in the decode file

echo The decode file should contain two columns - old

value

echo and new value

echo Ex

echo changethis tothis

echo

echo In this case every occurance of changethis

would be

echo replaced with tothisn

exit 1

fi

IBM Software Group IBM Information Management

Version 16 75

-----------------------

Declare variables

-----------------------

dfile=$1

cfile=$2

awk print s$1$2 $dfile gt $dfile_sed

sed -f $dfile_sed $cfile

The preceding script is used by creating a ldquodecoderdquo file (named decodefile in this case) which holds two columns in the form which may contain multiple rows

oldval newval

Executing the following command

subvalsksh decodefile chgfile

will replace every occurrence of oldval with newval in the file chgfile The shell script (subvalsksh) writes to standard output therefore the output should be redirected The redirected file will then be able to run with dbaccess

Utilities To improve performance the Informix EXPLAIN utility should be used by executing the SET EXPLAIN ON command to see how an SQL statement accesses the database From that point forward the access path for every SQL statement is written in the SQEXPLAINOUT file in the current working directory or the home directory of the process that initiated the request on the host machine The Informix SET EXPLAIN OFF should be executed to turn off this feature when finished The overall system performance should be monitored using the Informix ONSTAT utility

System catalog The following items discuss how Informix implements the system catalog differently than Oracle Each item refers to the Informix implementation only Object names are stored in lower case The system catalog tables are owned by lsquoinformixrsquo To query the systables table use SELECT from lsquoinformixrsquosystables Each table in systables is assigned a tabid by the system It is used as the primary key and therefore the foreign key for the other catalog tables The identifier information is stored in sysindexes Columns part1 - part16 each contain a column component of a composite index They are integers positive for ascending order negative for descending order In syscolumns collength and coltype have special meanings depending on the data type of the column See the Informix Guide to SQL Reference Version for details

IBM Software Group IBM Information Management

Version 16 76

C H A P T E R 9 Using Bladelets

What is a Bladelet

A Bladelet is a small informal Informix Datablade module Its meant to be useful out of the box and is offered complete with source code at no cost -- and no support or warranty In the context of this document the term Datablade refers to an extension to the standard IBM Informix database engine These generally take the form of new data types (for example timeseries or video) andor new routines that execute inside the server The new routines might operate on new data types or on existing ones A Datablade module is usually a formal product available for sale In addition a Datablade is

Developed either by IBM Informix or by a third-party developer

Rigorously tested

Packaged and sold for profit

May or may not be formally certified by IBM Informix as having been developed according to approved Datablade coding practices

In contrast a Bladelet is

Not rigorously tested

Not sold for profit

Not certified by IBM Informix A Bladelet is an extension to the database engine that is narrow in scope and thought to be generally useful being offered at no cost complete with source Just remember before you use any of this code in mission-critical applications its up to you to thoroughly test it and fix any problems you find Please review the disclaimer which applies to any sample code you find on this site httpwwwibmcomdeveloperworksdb2zonesinformixlibrarysamplesdb_downloadshtml Note The bladelets at this link have not been updated for some time (at the time of this writing) some of the capabilities especially simple function call that increase compatibility may have been introduced into the Informix server itself since they were written

Useful Bladelets

Bladelet Description

Exec Defines two user-defined functions that provide dynamic SQL functionality within a SPL procedure

Flat File Access Method A complete access method that lets you build virtual tables based on operating system files

IUtil Implements a collection of other database vendor functions for Informix

IBM Software Group IBM Information Management

Version 16 77

JPEG Image Bladelet Provides a user-defined type for JPEG images that allows you to manipulate images and to extract and search on image properties

Multirepresentational lvarchar Opaque Type

Creates the idn_mrLvarchar opaque type which stores character data up to 2 gigabytes

Node Datablade Module Creates the node opaque type which is intended to solve one of the hardest problems in relational databases transitive closure

Regexp Creates routines that let you manipulate character and clob data using regular expressions

Shapes DataBlade Module Creates several opaque types for managing spatial data including R-tree index support

Smart Blob Information DataBlade Module

Includes a variety of useful routines for working with smart blobs

SqlLib C SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

SqlLib Java SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

Versioning Table Access Method

Permits users to create and manage versioned tables

We will look closer at two bladelets which could assist with migration the Exec datablade and SQLLib

Informix Exec bladelet for Dynamic SQL Often it is desirable to execute a SQL query that is generated at run-time within the RDBMS For example a developer may not know the name of the temporary table they wish to run the query against or they might want to append predicates to a query In external programs this can be accomplished using the ESQLC SQLCA and DESCRIPTOR facilities Unfortunately the INFORMIX Stored Procedure Language (SPL) does not support Dynamic SQL Queries must be hard-coded into the SPL logic The objective of the Exec bladelet is to remedy this situation Exec consists of user-defined functions that take an SQL query as an argument execute it and return the result (the format of which varies depending on which function is called and the kind of query) The Exec functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries For more details and download refer to

httpwwwibmcomdeveloperworksdb2zonesinformixlibrarydemoids_exechtml

There are three User Defined Routines (UDRs) in the Exec bladelet Two of them are external C functions that use the Server API (SAPI) These must be compiled into shared libraries on the target machine and you need to declare them to the server using CREATE FUNCTION statements The third UDR is a routine written in Informix Stored Procedure Language (SPL) that uses the first two UDRs to return a collection of items The Exec bladelet module consists of the following

1 EXEC The EXEC() function takes an LVARCHAR that it treats as a SQL query executes the query and returns a single LVARCHAR result string Depending on what kind of SQL statement is submitted Exec() returns a different result format

IBM Software Group IBM Information Management

Version 16 78

2 EXEC_FOR_ROWS The EXEC_FOR_ROWS() UDR is an iterator function which means it can return more than one result row Of course it only does so when it is asked to execute a SELECT Otherwise it behaves exactly as the EXEC() UDR Being an iterator function limits the ways in which such a UDR can be used It cannot be used in another SQL query The only place it can be used effectively is inside a SPL routine

3 EXEC_FOR_MSET EXEC_FOR_MSET() is a SPL routine that uses the EXEC_FOR_ROWS() routine introduced above Instead of returning a set of rows as an iterator or a single row as the EXEC() UDF does this UDR collects the results of the SQL query together into a single object a multi-set

Refer to Appendix E Sample Code for examples on using the EXEC bladelet functions

SqlLib DataBlade module (SqlLibC11 SqlLibJ11) The SqlLib DataBlade module implements SQL routines that the Informix does not support natively but that are supported by some other database vendors Source code is freely available for download and includes two implementations one in C (SqlLibC) and the other in Java (SqlLibJ)

The following routines are included

ascii - takes a single character as input and returns the ASCII value in decimal that corresponds to that character

ceil - takes a single numeric value as input and returns the smallest integer that is either equal to or greater than the input value

chr - takes an integer value and returns the character that is represented by the ASCII value (in decimal) of that integer

instr - searches for a value in a string and returns the position where it was found It

returns 0 if the search value was not found instrb - provides the exact same functionality as instr() but for single-byte character sets

sign - takes a numeric argument and returns an integer that indicates if the input value is

positive (1) negative (-1) or zero (0) to_decimal - converts the input character argument into a decimal type

to_float - converts the input character argument into a float type

to_integer - converts the input character argument into an integer type For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

IBM Software Group IBM Information Management

Version 16 79

A P P E N D I X A Planning guide

The checklist below will help an analyst determine which Oracle features which need to be converted to Informix and give some guidance on the effort involved Each porting task is listed They are followed by a quantity field used to determine how prevalent the item the difficulty or amount of effort involved 1 (low) to 5 (high) is used to estimate the amount of time needed to perform the task when the associated item exists in the application a moderate number of times What is moderate depends on the size of the application If there are an unusually large number of occurrences of an item then the effort should be increased Conversely if there are a small number of occurrences of an item then the effort should be decreased Each of these items is discussed in detail within this document Each heading corresponds to a section heading within the document

Tasks Quantity Effort

DDL

Identifiers Delimit identifiers named with Informix reserved words 2 Databases Determine database names and create databases 3 Replace Oracle tablespace names with Informix dbspace names 1 ANSI vs Non-ANSI considerations 3 Tables Convert create table statements 2 Convert DDL syntax 3 Reduce primary key length to 390 bytes 5 Data Types Convert Oraclersquos NUMBER data type 3 Convert VARCHAR columns 2 Convert Oraclersquos DATE data type 5 Convert raw data types 2 Convert Rowids 2 Indexes Convert Indexes 2 Views Remove CREATE VIEW statement options 1 Stored Procedures and Triggers Convert CREATE and REPLACE Stored Procedure and Trigger syntax 1 Oracle Extensions Remove non-supported Oracle extensions from DDL 1

Tasks Quantity Effort

DML

SQL Add the Informix AS clause to display labels 1 Replace non-supported DML syntax ^= hellip = ELSE IF 2 Convert Optimizer DirectiveHints 2 Convert InsertSelectUnion and InsertValueSelect statements 3

IBM Software Group IBM Information Management

Version 16 80

Convert Delete statement syntax 1 Convert temporary table processing 2 Convert Join statements + MINUS INTERSECT different data types 2 Convert sorts 4 Convert hard coded SQL error messages 3 Remove correlation names on the main table of Update and Delete statements

2

Replace original table names in SELECT statements using aliases 1 Convert hierarchical implementation (CONNECT BY PRIOR) 5 Host Variables Convert host variable format or add conversion processing 5 Functions Convert date and time functions 5 Convert aggregate functions 3 Convert mathematical functions 5 Convert string function syntax 1 Convert other unsupported Oracle functions 5 Macros Convert ISOPEN NOT FOUND ROWTYPE and TYPE macros 3 Pseudo-Columns Convert Level processing 3 Convert Rownum processing 2 Update Using Cursors Convert WHERE CURRENT OF processing for multiple table joins 5 Convert FOR UPDATE with a HOLD cursor processing 2 Convert concurrency processing from Oraclersquos implicit to Informixrsquos explicit

4

System Tables Convert system table references 1

Tasks Quantity Effort

Stored procedures Break stored procedures greater than 64K in size into smaller ones 2 Convert Oraclersquos stored procedure packages 3 Convert exception processing 5 Convert error handling (SQLCA) 2 Convert Oraclersquos global cursor processing 5 Convert Oraclersquos explicit cursor processing 2 Convert flow control processing 5 Convert Oraclersquos implicit variable declaration and assignment 3 Convert Oraclersquos BOOLEAN variable type 1 Convert binary data type processing Convert Oraclersquos dynamic SQL processing 5 Triggers Convert multi-functional triggers 3 Convert Insert and Update triggers which are not supported in Informix 5 Place logical statements in a stored procedure 5 Constraints Convert constraint enabling and disabling processing 5 DUAL table Convert Dual table processing 4

Embedded SQL

Host variables

IBM Software Group IBM Information Management

Version 16 81

Convert declaration overrides 1 Convert array processing 5 Convert Oraclersquos formatting functions 4 SQL structures Convert SQLDA processing 5 Convert ORACA processing 1 Pre-compiler options Convert Oracle pre-compiler options 1 Embedded PLSQL Convert Oraclersquos Embedded PLSQL 5 ODBC Convert Oraclersquos OCI 5 Convert database library calls Convert global area processing Convert fetch cycle Convert RAW data type processing Convert parameter bindings Embedded SQL for C Convert VARCHAR processing 2 Embedded SQL for COBOL Convert VARCHAR processing 2 Convert 88 Level processing in COBOL 2 Convert Redefine processing in COBOL 4

Tasks Quantity Effort

Application architecture

Transaction processing Convert application to Informix transaction processing 5 Convert multiple connect processing 5 Convert savepoints Concurrency Address Informix locking processing na 2 User authentication Address Informix security processing na 4

Environment

Convert make files 2 Convert shell scripts shell startup scripts and command files 2 Convert script substitution variables

IBM Software Group IBM Information Management

Version 16 82

A P P E N D I X B Syntax comparison

See the Informix Guide to SQL Syntax for more information on each item

Oracle Informix Boolean AND AND AND NOT NOT NOT OR OR OR Greater Than or Equal To gt= gt= Less Than or Equal TO lt= lt= Not Equal ltgt = or ^= ltgt or = Identifiers letters numbersrdquo_rdquordquo$rdquordquordquo letters numbers and ldquo_rdquo Data types Character CHAR CHAR Long Character VARCHAR (2000) if lt= 2000

LONG VARCHAR if gt 2000 CHAR or TEXT

Number (2 bytes) NUMBER SMALLINT Number (4 bytes) NUMBER INTEGER Number (gt 4 bytes) NUMBER DECIMAL Image LONG RAW CLOB BLOB BYTE TEXT CLOB BLOB DML Comments -- hellip -- hellip Assignment var1 = expression LET var1 = expression Condition ELSE IF ELSE or ELIF

IF Aggregate functions Average AVG(expression) AVG(ALL

expression) AVG(DISTINCT expression)

AVG(expression) AVG(ALL expression) AVG(DISTINCT column_name) AVG(UNIQUE column_name)

Count COUNT() COUNT (expression) COUNT(ALL expression) COUNT (DISTINCT expression)

COUNT() COUNT(DISTINCT column_name) COUNT (UNIQUE column_name)

Maximum MAX(expression) MAX(ALL expression) MAX(DISTINCT expression)

MAX(expression) MAX(ALL expression) MAX(DISTINCT column_name) MAX(UNIQUE column_name)

Minimum MIN(expression) MIN(ALL expression) MIN(DISTINCT expression)

MIN(expression) MIN(ALL expression) MIN(DISTINCT column_name) MIN(UNIQUE column_name)

Sum SUM(expression) SUM(ALL expression) SUM(DISTINCT expression)

SUM(expression) SUM(ALL expression) SUM(DISTINCT column_name) SUM(UNIQUE column_name)

Algebraic functions Round ROUND(expressionrounding

factor) ROUND(expressionrounding factor)

Statistical functions Standard Deviation STDEV(expression) STDDEV(expression) Variance VARIANCE(expression) VARIANCE(expression) Range RANGE(expression)

IBM Software Group IBM Information Management

Version 16 83

String functions

Trim LTRIM(expression) RTRIM(expression)

LTRIM(expression) RTRIM(expression)

Length LENGTH(string) LENGTH(string) Like LIKE(string) LIKE(string) Like (single character) _ _ Like (wildcard) String Delimiter lsquo or ldquo lsquo or ldquo Escape Character set within LIKE clause using

ESCAPE ldquordquo to make ldquordquo the escape character

or set within LIKE clause using ESCAPE ldquordquo to make ldquordquo the escape character

Stored procedures Create CREATE OR REPLACE

PROCEDURE procedure_name (var1 IN CHAR(1) var2 OUT DATE var3 IN OUT NUMBER)

DROP PROCEDURE procedure_name CREATE PROCEDURE procedure_name (var1 CHAR(1) var3 INTEGER) RETURNING DATE INTEGER

Arguments EXECUTE PROCEDURE procedure_name (var1 IN var2 OUT var3 IN OUT)

EXECUTE PROCEDURE procedure_name (var1 var3) RETURNING var2 var3

IBM Software Group IBM Information Management

Version 16 84

A P P E N D I X C Database concepts

The table below illustrates the relationship between each database vendorrsquos database objects

Oracle Informix

Database name attached to a group of files Specific database name

Data file Chunk

Tablespace (logical partition) or Segments (Index Segment Table Segment and so on)

Dbspace

Extent Extent

Rollback Segment Physical Log

Redo Log Logical Log

System tablespace Root dbspace

Temporary tablespace Temporary dbspaces dbspacetemp environment variable or dbspacetemp onconfig parameter

Pointer Blobspace Sbspace

Table partitioning table fragmentation

Database link Not supported

Snapshot Not supported

oerr utility finderr utility

sqldba and svrmgrl - monitor utilities onstat and oncheck utilities

SQLPlus utility dbaccess utility

ProC ESQLC

ProCOBOL ESQLCOBOL

SQLNET INet

OCI Like the ESQL function library after pre-compiling if they were publically documented

Read Consistency COMMITTED READ LAST COMMITTED

IBM Software Group IBM Information Management

Version 16 85

A P P E N D I X D Sample code

User defined functions User Defined Routines (UDR) can be developed to extend the capabilities of the database and provides the option to create UDRs to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or rename an Informix function to the corresponding Oracle function name

CONCAT

CREATE PROCEDURE concat (str1 VARCHAR(255) str2 VARCHAR(255)) RETURNING VARCHAR(255) RETURN str1 || str2

END PROCEDURE

INSTR

CREATE PROCEDURE instr( str VARCHAR(255) mask VARCHAR(255) strt SMALLINT DEFAULT 1 occur SMALLINT DEFAULT 1 ) RETURNING INT DEFINE slen SMALLINT DEFINE mlen SMALLINT DEFINE tempstr VARCHAR(255) DEFINE tempmask VARCHAR(255)

DEFINE nomatch SMALLINT DEFINE count SMALLINT DEFINE pos SMALLINT DEFINE retpos SMALLINT DEFINE i SMALLINT DEFINE j SMALLINT DEFINE srchstrt SMALLINT LET slen = LENGTH(str) LET mlen = LENGTH(mask) LET count = 0 LET nomatch = 0 LET pos = 1 LET retpos = 1 LET tempstr = LET tempmask = LET srchstrt = strt

IF (strt lt 0) THEN - reverse the str FOR i = 1 TO slen LET tempstr = str[11] || tempstr LET str = str[2255] END FOR -- reverse the mask FOR i = 1 TO mlen LET tempmask = mask[11] || tempmask LET mask = mask[2255] END FOR

IBM Software Group IBM Information Management

Version 16 86

LET srchstrt = strt -1 LET str = tempstr LET mask = tempmask END IF FOR j = 1 TO slen LET tempstr = str LET tempmask = mask FOR i = 1 TO mlen IF (tempmask[11] = tempstr[11]) THEN LET nomatch = 1 EXIT FOR END IF LET tempmask = tempmask[2255] LET tempstr = tempstr[2255]

END FOR IF (nomatch = 0) THEN IF (pos gt= srchstrt) THEN LET count = count + 1 END IF IF (count = occur) THEN IF (strt lt 0) THEN RETURN slen - pos + 1 ELSE RETURN pos END IF END IF END IF LET str = str[2255] LET nomatch = 0

LET pos = pos + 1 END FOR RETURN 0 END PROCEDURE

YYYYMMDD

CREATE PROCEDURE yyyymmdd (str VARCHAR(10)) RETURNING varchar(8)

DEFINE retstr VARCHAR(8)

IF str IS NULL THEN

RETURN NULL

ELSE

LET retstr = str[710] || str[12] || str[45]

RETURN retstr

END IF

END PROCEDURE

Using EXEC bladelet functions

IBM Software Group IBM Information Management

Version 16 87

Using EXEC

Note the ROW data type variable can be referenced using table and column syntax CREATE PROCEDURE example1() RETURNING INTEGER

DEFINE sql_stmt LVARCHAR(255)

DEFINE rcnt ROW(val INTEGER)

LET sql_stmt = select count() from items where manu_code = lsquoANZrsquo

EXECUTE FUNCTION EXEC(sql_stmt) INTO rcnt

RETURN rcntval

END PROCEDURE

Using EXEC_FOR_ROWS

CREATE PROCEDURE example2() RETURNING INTEGER CHAR(1)

DEFINE rs_rowdata ROW(customer_num INTEGER call_code CHAR(1))

DEFINE sql_stmt LVARCHAR(255)

LET sql_stmt = select customer_num call_code from cust_calls where

customer_num = 106

FOREACH

EXECUTE FUNCTION EXEC_FOR_ROWS(sql_stmt) INTO rs_rowdata

RETURN rs_rowdatacustomer_num rs_rowdatacall_code WITH RESUME

END FOREACH

END PROCEDURE

Using EXEC_FOR_MSET

Note the DEFINE statement for the variable rs_data Collection data types used in a SPL routine cannot be defined using the LIKE attribute in the DEFINE statement CREATE PROCEDURE example3() RETURNING INTEGER VARCHAR(8)

DEFINE v_customer_num LIKE accountscustomer_num

DEFINE v_account_cd LIKE accountsaccount_cd

DEFINE rs_data MULTISET(ROW(

r_customer_num INTEGER

r_account_cd VARCHAR(8)) NOT NULL)

DEFINE sql_stmt LVARCHAR

LET sql_stmt = select customer_num order_num from orders where

company_id = 51155

EXECUTE FUNCTION EXEC_FOR_MSET(sql_stmt) INTO rs_data

FOREACH

SELECT r_customer_num r_account_cd INTO v_customer_num

v_account_cd FROM TABLE(rs_data)

RETURN v_customer_num v_account_cd WITH RESUME

END FOREACH

END PROCEDURE

IBM Software Group IBM Information Management

Version 16 88

Date arithmetic Informix has extensive capabilities for manipulating dates and times You can add or subtract DATE and DATETIME variables from each other You can add or subtract an INTERVAL to a DATE or DATETIME

UNITS Keyword

When working with INTERVAL values sometimes it is necessary to specify the precision with which you are dealing For example suppose you have the following field defined To add 10 days to the lead time you could use a SQL statement like this

SELECT lead_time + INTERVAL(10) DAY to DAY FROM orders

-or- SELECT lead_time + 10 UNITS DAY FROM orders

Using EXTEND function

The EXTEND function allows operations between data types of different precisions SELECT

EXTEND(myvar YEAR to MINUTE) ndash INTERVAL(5) MINUTE to MINUTE

FROM member

Calculate Week Of The Year

SELECT ROUND((TODAY - DATE(0101||YEAR(TODAY))) 7 + 5) FROM DUAL

Number of days difference SELECT DATE(0106||YEAR(TODAY)) - DATE(01062005) FROM DUAL

Number of weeks difference

SELECT ROUND((DATE(0106||YEAR(TODAY)) - DATE(01062005))

7 + 5) FROM DUAL

String representation of date and time

Day and date

SELECT TO_CHAR(TODAY A B d Y) FROM dual

-returns month day and 4 digit year-

Tuesday January 03 2006

Abbreviation of day of week

SELECT SUBSTR(TO_CHAR(TODAY A B d Y R)13) FROM dual

-or-

SELECT TO_CHAR(TODAY a) FROM dual

-returns MON TUE WED THU FRI SAT SUN-

Returning the number of rows affected

IBM Software Group IBM Information Management

Version 16 89

Within SPL routines you can use the DBINFO function to find out the number of rows that have been processed in SELECT INSERT UPDATE DELETE EXECUTE PROCEDURE and EXECUTE FUNCTION statements

CREATE FUNCTION del_rows(pnumb INT) RETURNING INT

DEFINE nrows INT

DELETE FROM sec_tab WHERE part_num = pnumb

LET nrows = DBINFO(sqlcasqlerrd2)

RETURN nrows

END FUNCTION

To ensure valid results use this option after SELECT and EXECUTE PROCEDURE or EXECUTE FUNCTION statements have completed executing If you use the sqlcasqlerrd2 option within cursors make sure that all rows are fetched before the cursors are closed

Using an Informix collection data type

A collection data type as a VARRAY

In the following examples the collection data types of MULTISET and SET are used in a function to hold a collection of values You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value Informix SPL allows you to declare a cursor for a collection variable using the FOREACH statement called a collection cursor

Also demonstrated is how to utilize a variable declared with the keyword COLLECTION A variable declared as type SET MULTISET or LIST is a typed collection variable It can hold a collection of its specified data type only However a COLLECTION is an un-typed (or generic) collection variable that can hold a collection of any data type

This function will build a MULTISET list of values

CREATE FUNCTION func1() RETURNING MULTISET(INTEGER NOT NULL)

DEFINE v_array_of_ints MULTISET(INTEGER NOT NULL)

INSERT INTO TABLE (v_array_of_ints) VALUES(1)

INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(5)

INSERT INTO TABLE (v_array_of_ints) VALUES(4)

RETURN v_array_of_ints

END FUNCTION

This function will receive the COLLECTION list of values from func1

CREATE FUNCTION func2() RETURNING INTEGER

--

-- DEFINE lmset MULTISET(INTEGER NOT NULL)

--

DEFINE lmset COLLECTION

DEFINE v_int INTEGER

--

-- call func1 to populate local multiset variable

--

LET lmset = func1()

--

-- tally a count the number of elements

--

FOREACH

SELECT COUNT() INTO v_int FROM TABLE(lmset)

IBM Software Group IBM Information Management

Version 16 90

RETURN v_int WITH RESUME

END FOREACH

--

-- return the values

--

FOREACH

SELECT INTO v_int FROM TABLE(lmset)

RETURN v_int WITH RESUME

END FOREACH

END FUNCTION

NOTE In the example func2 a duplicate declaration for the ldquolmsetrdquo variable as a MULTISET data type has been commented out by declaring the variable as a COLLECTION it can accept any of the 3 types (MULTISET SET and LIST)

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

4 (row count) 1 2 5 4

By using a SET data type inserts will not permit duplicates

CREATE FUNCTION func1() RETURNING SET(INTEGER NOT NULL) DEFINE v_array_of_ints SET(INTEGER NOT NULL) INSERT INTO TABLE (v_array_of_ints) VALUES(1) INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(2) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) RETURN v_array_of_ints END FUNCTION

NOTE Because func2 is expecting a un-typed COLLECTION variable func1 does not have to be dropped and recreated It can receive a value from any Collection Data Type (MULITSET SET and LIST)

The functionrsquos return values would change to (with duplicates suppressed)

EXECUTE FUNCTION func2()

(expression)

3 (row count) 1 2 5

Using a LIST data type support for assigning values based on ordinal position

IBM Software Group IBM Information Management

Version 16 91

CREATE FUNCTION func1() RETURNING LIST(INTEGER NOT NULL)

DEFINE v_array_of_ints LIST(INTEGER NOT NULL) -- -- first insert no ordinal position can be established By default the -- database server inserts LIST elements at the end of the list -- INSERT AT 5 INTO TABLE (v_array_of_ints) VALUES(5) INSERT AT 1 INTO TABLE (v_array_of_ints) VALUES(1) INSERT AT 2 INTO TABLE (v_array_of_ints) VALUES(2) -- -- Only 3 LIST elements exist position 4 has not been instantiated -- this element will insert at the end of the list -- INSERT AT 4 INTO TABLE (v_array_of_ints) VALUES(4) INSERT AT 3 INTO TABLE (v_array_of_ints) VALUES(3) RETURN v_array_of_ints END FUNCTION

NOTE The elements of a LIST have ordinal positions with a first second and third element in a LIST To support the ordinal position of a LIST the INSERT statement provides the AT clause This clause allows you to specify the position at which you want to insert a list-element value Note the behavior of the ordinal positioning above preceded by a commented explanation

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

5 (row count) 1 2 3 5 4

Using MULTISET and ROW to replace PLSQL TABLE and RECORD types

Creating variables using Informix Collection data types SET MULTISET and LIST in combination with ROW data types can be useful when migrating applications which use Oracle REF CURSORS as arguments to functions as well as Oracle collection data types TABLE and RECORD

Typical Oracle Package specification

CREATE OR REPLACE PACKAGE MyPackage

IS

TYPE recOrders IS RECORD (

order_num ordersorder_numTYPE

order_date ordersorder_dateTYPE

customer_num orderscustomer_numTYPE

po_num orderspo_numTYPE

)

TYPE tabOrders IS TABLE OF recOrders

INDEX BY BINARY_INTEGER

TYPE ref_curtype IS REF CURSOR

Both tabOrders or ref_curtype can be converted to the following Informix SPL definition

DEFINE tabOrders MULTISET(ROW(

IBM Software Group IBM Information Management

Version 16 92

order_num INTEGER

order_date DATETIME YEAR TO FRACTION(3)

customer_num INTEGER

po_num CHAR(10)) NOT NULL)

DEFINE ref_curtype MULTISET(ROW(

define columns based on query result set

) NOT NULL)

IBM Software Group IBM Information Management

Version 16 93

A P P E N D I X E Counting system objects

Using the system catalog

System catalog

Below is a list of SQL statements that will extract most if not all of the counts of system objects owned by user lsquoXXXrsquo

select count(table_name) from all_tables

where owner=rsquoxxxrsquo

select count() from dba_indexes

where owner=rsquoxxxrsquo

select count(synonym_name) from dba_synonyms

where owner=rsquoxxxrsquo

select count() from dba_views

where owner=rsquoxxxrsquo

select count() from dba_tab_columns

where length(column_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

and owner=rsquoxxxrsquo

select count distinct() from dba_tab_columns

and owner=rsquoxxxrsquo

select count() from dba_tables

where length(table_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_synonyms

where length(synonym_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_views

where length(view_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_indexes

where length(index_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and owner=rsquoxxxrsquo

IBM Software Group IBM Information Management

Version 16 94

select data_type count(data_type) from dba_tab_columns

where owner=rsquoxxxrsquo

group by data_type

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and length(data_type)gt254

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquonumberrsquo

and data_scale=0

and owner=rsquoxxxrsquo

Using SQL code

Built-in function references

The following instructions can be used to find references to built-in functions On the UNIX machine or the NT box where your code resides please create the following file as tmpfunctionlist

convert(

hextoint(

inttohex(

getdate(

datename(

datepart(

datediff(

dateadd(

months_between(

char(

char_length(

charindex(

compute(

difference(

length(

lower(

patindex(

replicate(

reverse(

right(

soundex(

space(

str(

stuff(

substring(

upper(

abs(

atn2(

log(

ceiling(

IBM Software Group IBM Information Management

Version 16 95

cot(

degrees(

floor(

radians(

rand(

sign(

to_char(

to_date(

to_number(

exception(

pi(

raise_application_error(

raiserror(

SQLCODE

rollback

savepoint

declare

decode(

nvl(

print(

rowid

waitfor

recompile

bcp

isopen(

notfound(

rowtype(

type(

Then please run the following program with the proper subdirectories

binksh

rm ndashf somehomeoutfile

cd somesourcedatabase

export sourcebase=rdquosomepathrdquo

for functor in `cat tmpfunction_list`

do

echo before find $functor

find $sourcebasedatabase -exec grep -i $functor gtgt

somehome$functoroutfile

find $sourcebaseintfc -exec grep -i $functor gtgt

somehome$functoroutfile

echo after find $functor

done

Object types and counts

This script attempts to count the objects of each type by grepping for CREATE statements containing the object type and counts procedure definitions that are inside package bodies which are not proceeded by a CREATE keyword It is not a sophisticated parser so the results may not be perfect

binbash if [ $1 = ] then

IBM Software Group IBM Information Management

Version 16 96

echo Usage objCountssh ltFilePatterngt return 1 fi declare -a objectTypes=(CLUSTER CONTEXT CONTROLFILE DATABASE DATABASE +LINK DIMENSION DIRECTORY DISKGROUP FUNCTION INDEX INDEXTYPE JAVA LIBRARY MATERIALIZED +VIEW MATERIALIZED +VIEW +LOG OPERATOR OUTLINE PACKAGE PACKAGE +BODY PFILE PROCEDURE PROFILE RESTORE +POINT ROLE ROLLBACK +SEGMENT SCHEMA SEQUENCE SPFILE SYNONYM TABLE TABLESPACE TRIGGER TYPE TYPE +BODY USER VIEW) echo for type in $objectTypes[] do if [ $type = PROCEDURE ] then echo $type object count `cat $1 | grep -icE ^ (|CREATE +|OR REPLACE +)b$typeb` else echo $type object count `cat $1 | grep -icE ^ (CREATE +|OR +REPLACE +)b$typeb` fi done

IBM Software Group IBM Information Management

Version 16 97

A P P E N D I X F Data type mapping

Oracle built-in data types (including ANSI types) can be converted to similar data types in the Informix database according to the mapping described here This table provides default mappings based on most common usage patterns in some cases another mapping may work better

In the following table n is used to indicate length p is used to indicate precision and s is used to indicate scale

Oracle data type Informixreg Server data type

BFILE LONG RAW BLOB

BLOB

BINARY_DOUBLE DOUBLE PRECISION

BINARY_FLOAT DOUBLE PRECISION

BINARY_INTEGER

PLS_INTEGER

NATURAL

NATURALN

POSITIVE

POSITIVEN

32-bit integers only used in PLSQL NATURAL and POSITIVE are unsigned integers

INTEGER

BOOLEAN (PLSQL only) BOOLEAN

CHAR(n) or CHARACTER(n) CHAR(n)

DATE DATETIME YEAR TO SECOND

DOUBLE PRECISION DOUBLE PRECISION

IBM Software Group IBM Information Management

Version 16 98

FLOAT

See note on FLOAT below

FLOAT

INTEGER INT

A 38-digit NUMBER sub-type May want to flag with a warning on possible overflow

INTEGER

INTERVAL DAY(p) TO SECOND(s)

Note Oracle fractional seconds have 9 digits

INTERVAL DAY(p) TO FRACTION(min(5 s))

INTERVAL YEAR(p) TO MONTH

INTERVAL YEAR(p) TO MONTH

LONG CLOB

CLOB

LONG VARCHAR (xxx)

Oracle recommends not using this type

LVARCHAR

NCHAR(n) NATIONAL CHAR(n) or NATIONAL CHARACTER(n)

NCHAR(n)

See National Language Types below

NCLOB CLOB

NUMBER

NUMBER(0)

NUMBER(p) NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s lt 10

NUMBER(3-2) 12300

INTEGER

IBM Software Group IBM Information Management

Version 16 99

NUMBER(p) NUMBER (p0)

Where precision (p) is greater than or equal to 10 and lt= 18

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and 10 lt= p-s lt 19

NUMBER(9-2) 12345678900

BIGINT

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is greater than or equal to s (that is s gt 0 and p gt= s)

NUMERIC (min(p32) min(s32))

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is less than s (that is s gt 0 and p lt s)

NUMBER(35) 000123

NUMERIC (min(s32)min(s32))

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s gt 18 and p-s lt= 32

NUMERIC (min(p-s32)0)

NUMBER(p s)

Where scale (s) is greater than 32 or pInformix-s is greater than 32

NUMERIC (32)

Scale cannot be greater than precision

NUMERIC(3232) would guarantee that digits to the left of the decimal would be lost Using a floating point decimal provides the simplest best way to capture as many digits in a value as possible

IBM Software Group IBM Information Management

Version 16 100

DEC

DECIMAL

NUMERIC

DEC(p)

DECIMAL(p)

NUMERIC(p)

DEC(p s)

DECIMAL(p s) NUMERIC(p s)

There is no difference within Oracle between these types and each other and these types and NUMBER The Oracle system catalogs contain the NUMBER type id for all declarations of these types and the integer types as well Declarations of these types can be mapped using the same rules as those for NUMBER

NVARCHAR2(n) NCHAR VARYING(n) NATIONAL CHAR VARYING(n) NATIONAL CHARACTER VARYING(n)

LVARCHAR(min(n 32767))

RAW(n) BLOB

REAL DOUBLE PRECISION

Record ROWTYPE

Using a CREATE ROWTYPE statement

ROWID INTEGER

SMALLINT SMALLINT

TIMESTAMP(p)

If p is not specified precision defaults to 6

DATETIME YEAR TO FRACTION(min(5 p))

UROWID(n) INTEGER

IBM Software Group IBM Information Management

Version 16 101

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is less than or equal to 255 (that is n lt= 255)

VARCHAR(n)

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is greater than 255 (that is n gt 255)

LVARCHAR(n)

XMLType CLOB

Notes on specific types are below

DOUBLE

The range of values for the DOUBLE PRECISION data type is the same as the range of the C double data type on your computer

VARCHAR

While Oracle VARCHAR data types have a limit of 4000 bytes an Informix Server VARCHAR data types has a limit of 255 bytes An Informix Server LVARCHAR has a limit of 32739 Bytes

NUMBER

Oracle abstracts its numeric types from the hardware and operating system through the use of its NUMBER type Most numeric types like INTEGER are actually NUMBERs internally When porting to a database server like Informix which retains more of a relationship between the operating system types and the database types it is essentially a one-to-many mapping and heuristics have to be used to determine the best-fit target type No single set of type mapping rules will fit all use scenarios The converter has default rules which fit the more common user patterns When considering a number represented as mantissa and exponent

mantissa x 10exponent

precision is the number of digits in the mantissa and scale is the negative exponent how many places to the right of the decimal point the least significant digit is located Oracle NUMBERs have a maximum precision of 38 and the maximum precision available in Informix native types is 32 The first step in a type mapping is to truncate the target type precision to min(precision 32) The scale of a type can be considered its anchor point with respect to the decimal point The most

IBM Software Group IBM Information Management

Version 16 102

significant digit of a numeric type is located precision digits to the left of the decimal point and precision-scale digits to the right of the decimal point The start and end locations of the digits are used to determine the closest fitting Informix type The order of preference is INTEGER BIGINT NUMERIC(p s) and lastly NUMERIC(p) NUMERIC(p) in a non-ANSI mode database is a decimal type with a floating point type In an ANSI mode database the scale is implicitly 0 All Oracle integer declaration types such as INT INTEGER SMALLINT become NUMBER(38) type in the Oracle metadata In Oracle when precision is given but scale is not scale becomes 0 implicitly which makes the type in the set of integral types One exception to the general mapping rules is the NUMBER type specified without precision or scale Strictly speaking this has a floating point scale with 38 digits of precision but most commonly it is used where an integer is more appropriate Even if the user does specify INTEGER in a type definition when it comes out of the Oracle catalogs the type is NUMBER This is one case in particular where one type mapping will not fit well with all usage scenarios

National language types

Oracle Nchar types are allocated by number of characters where Informix is allocated by the number of bytes For Oracle the storage size of the characters varies with the encoding used and is always subject to the standard 32767 limit on maximum bytes but during declarations n always means the number of characters Oracle PLSQL supports explicit and implicit data type conversions These explicit and implicit data types are converted to syntax by using Informix Dynamic Servers explicit and implicit data type conversion mechanism

ROWID

Oracle databases support a pseudo-column named ROWID such that every row in every table is assigned an auto-generated ID Oracle also allows you to define a column of type ROWID which can be used as a foreign key to a ROWID pseudo-column Oracle ROWID columns contain data that if converted to a string are 18 characters long for example lsquoAAAQ+jAAEAAAAAeAANrsquo It is probably not advisable to migrate this data to an Informix database and instead use the Informix type which is an integer If there is a dependency on the values themselves and therefore need migrate the data then an integer type would not hold the values

TYPE

In PLSQL you can refer to the type of an existing variable field or column by using the TYPE attribute The converter replaces this reference directly by the type it refers to

ROWTYPE

In PLSQL you can refer to the record type that represents a row of a table a cursor or a cursor variable PLSQL scripts containing the ROWTYPE attribute are handled in the same way as a record type that has been previously declared

FLOAT

Oracle FLOAT type is a floating point number capable of storing up to 38 decimal digits or 126 binary digits It has a floating point scale that can exist outside the boundaries of what an Informix DECIMAL can represent A C language double or Informix float type is capable of only 16 digits so there is the chance that some data will be lost Using an Informix FLOAT type makes it so that less significant digits are lost in preference to more significant digits

IBM Software Group IBM Information Management

Version 16 103

References to subtypes declared in packages and PLSQL blocks are converted to the Informix Server equivalent base types Variables of type RECORD are not translated by the DDL Converter at the time of this writing They will be handled by the stored procedure converter

XMLType

Informix does not have a built-in type for representing XML The nearest approximation is to store it in a CLOB Another character type like LVARCHAR can be used if it can be determined that the actual data will fit in it

Page 6: Oracle to IBM Informix Server Porting Guide

IBM Software Group IBM Information Management

Version 16 6

SQLCA 59 SQLDA 60 ORACA 61

PRE-COMPILER OPTIONS 61 EMBEDDED PLSQL 61 ORACLE CALL INTERFACE 61

Database library calls 62 Global area processing 62 Fetch cycle 62 RAW binary data type processing 62 Parameter bindings 62

EMBEDDED SQL FOR C 63 VARCHAR 63 Host variables 63

EMBEDDED SQL FOR COBOL 63 VARCHAR 63 Level 88 64 SQLDA 64 REDEFINES 64 Tips 64

ODBC 64

C H A P T E R 6 APPLICATION ARCHITECTURE 65

TRANSACTION PROCESSING 65 Autonomous Transaction 66 Savepoints 67

CONCURRENCY 67 Row Level Locking 67 Transaction Isolation Level 68

C H A P T E R 7 SECURITY 70

USER AUTHENTICATION 70 Operating system security 70 Non-operating system security 70

ROLE BASED AUTHORITY 71 COLUMN-LEVEL ENCRYPTION 71

Passwords and hints 71 Encrypting a column 72 Querying an encrypted column 72 Performance impact of encryption 73 Storage considerations 73 Compliance regulations 73

C H A P T E R 8 ENVIRONMENT 74

SCRIPTS 74 SQL script substitution variables 74

UTILITIES 75 SYSTEM CATALOG 75

C H A P T E R 9 USING BLADELETS 76

WHAT IS A BLADELET 76 INFORMIX EXEC BLADELET FOR DYNAMIC SQL 77 SQLLIB DATABLADE MODULE (SQLLIBC11 SQLLIBJ11) 78

A P P E N D I X A PLANNING GUIDE 79

A P P E N D I X B SYNTAX COMPARISON 82

IBM Software Group IBM Information Management

Version 16 7

A P P E N D I X C DATABASE CONCEPTS 84

A P P E N D I X D SAMPLE CODE 85

DATE ARITHMETIC 88 UNITS Keyword 88 Using EXTEND function 88

STRING REPRESENTATION OF DATE AND TIME 88 Day and date 88 Abbreviation of day of week 88

USING AN INFORMIX COLLECTION DATA TYPE 89 A collection data type as a VARRAY 89 Using MULTISET and ROW to replace PLSQL TABLE and RECORD types 91

A P P E N D I X E COUNTING SYSTEM OBJECTS 93

USING THE SYSTEM CATALOG 93 System catalog 93

USING SQL CODE 94 Built-in function references 94 Object types and counts 95

A P P E N D I X F DATA TYPE MAPPING 97

DOUBLE 101 VARCHAR 101 NUMBER 101 National language types 102 ROWID 102 TYPE 102 ROWTYPE 102 FLOAT 102 XMLType 103

IBM Software Group IBM Information Management

Version 16 8

C H A P T E R 1 Introduction

This document is a technical document describing the differences between Oracle and Informixreg Dynamic Server (IDS) functionality and syntax This porting guide details differences between Oraclersquos 10g release 1 (101) and 10g release 2 (102) and Informix Dynamic Server (version 1110) In addition it can be a useful reference for all migrations between the two database servers regardless of version In addition to DDL DML and overall SQL syntax this document explores the differences between Oracle and Informix with regards to object technology through the use of large objects user defined types and user defined routines It also looks at the differences between Oraclersquos table partitioning and Informixrsquos table fragmentation Part of the explanation is a discussion on what needs to be changed to make an application running on an Oracle database run on an Informix database If there is more than one way to port some piece of functionality alternatives and recommendations are also discussed This document is intended to be a living document Missing items better ways of implementing Oracle functionality in Informix other than what is documented here examples to better illustrate a point and other suggestions should be sent to Chris Golledge (golledgeusibmcom) so they may be included with future revisions

Purpose This document should be used as a guide to assist in porting applications that run on an Oracle database server to run on an Informix database server Regardless of whether a porting effort will be completely manual or if tools will be utilized this document can provide value Obviously if the port is performed manually this guide will provide the most value If the port will utilize tools then analysis can be performed using this guide to determine how much of the application the tools will convert and how much must be converted manually In any case this guide is intended to be used to both visualize the scope of a porting effort and to aid in the porting effort by addressing the technical issues This document will be refined based on usersrsquo experiences to identify as many of the porting issues as possible at the beginning of a project

Product overview IBM Informix Server provides high performance and scalability with legendary reliability and nearly hands-free administration of databases of all size IDS is industry proven on UNIX Linux or Windows platforms with online transaction processing (OLTP) systems data marts data warehouses and e-business applications The IDS 11 release features significant additions over prior versions It supports the services-oriented architecture (SOA) model for application integration and offers many new features for data replication continuous availability and ldquohands freerdquo database administration

Organization This document is broken into sections to logically discuss the different database concepts Some of the sections may contain the same sub-sections for example stored procedures and triggers

IBM Software Group IBM Information Management

Version 16 9

are discussed in the DDL and DML sections This allows separate discussions on the issues facing the same item in each area For example the issues surrounding creating a stored procedure are discussed in the DDL section and the issues surrounding the stored procedure language are discussed in the DML section Among the other references the ldquoPlanning Guiderdquo appendix contains a quick reference of most of the differences between Oracle and Informix along with the degree of difficulty to port each difference This reference is intended for use in the planning process to illustrate the scope and the effort required to perform the porting project Some of the stored procedure logic used to convert Oracle functions is included in the appendix rdquoSample coderdquo

Conventions The conventions used in this document include

Courier Text Distinguishes a logic example

from regular text

Example Illustrates a point In most cases an Oracle example will be followed by an Informix example

Italicized Text Signifies a substitution in other words substitutes for the italicized word the actual object the word is describing for example table_name column_name and so on

UPPER CASE TEXT Signifies database vendor reserved words or statements such as INTEGER CREATE TABLE and so on

Bold example text highlights the item that is being explained

IBM Software Group IBM Information Management

Version 16 10

IBM Software Group IBM Information Management

Version 16 11

C H A P T E R 2 Defining the Problem Space

It is important to define the set of objects to be migrated and it is better if effort is put into this prior to beginning the actual migration This is true if you are the responsible for both the database in general and its migration from one supporting DBMS to another but it is particularly true that there be a clear agreement on the scope of what is to be migrated if the migration is to be performed by a party other than the one with long term responsibility for the database Defining the scope will involve extracting a representation of the objects to be migrated out of the Oracle system catalogs and representing them in some format that can be manipulated into constructs that can be used in Informix

Extracting the objects to be migrated It is possible to represent the objects in more than one language Using the SQL language is the most common method and it will be the only one discussed at length in this document (in its current revision) However it is also possible to express database objects in XML SQL has the advantage that the standard common grammars are widely understood in the context of defining tables indexes etc XML would have an advantage of not requiring parsing that is sensitive to the minor differences in ways of expressing essentially the same object

Working With Oracle Dump Files

There exist 3rd

-party tools for reading system catalogs but it is doubtful that any can read the Oracle catalogs more reliably than Oraclersquos own tools There are two incompatible export and import tool sets used by Oracle The older tools are imp and exp and the newer ones are impdp and expdp where dp stands for Data Pump Oracle has encouraged the use of the newer tools instead of the older ones since the newer ones were introduced at version 10 Nonetheless there are many Oracle users still using imp and exp In the discussions below only the metadata will be extracted into a dump file That is because any data in the dump file will be in a proprietary format and very likely some of the data will have to go through a type conversion process before being loaded into an Informix system Oracle exported data generally cannot be used to load a database in Informix Export and Import

If someone has given you a dump file created with the older export tool there exist tools such as The DDL Wizard by Net 2000 Limited which can be used to extract viable DDL The contents of the dump file contain the SQL for re-creating the database but they are not in a readily usable format The older export and import tools are also more sensitive to the layout of the tablespaces than impdb The ability to extract DDL from the dump file in a usable form segmented by whatever grouping you choose is limited compared to what can be achieved through the Data Pump versions

IBM Software Group IBM Information Management

Version 16 12

It may be tempting to feed the dump file into the IBM Migration Toolkit (MTK) or other tool that works on SQL flat files This will not work MTK works on flat text SQL files and the dump file is binary If you open it up you can see what may be a large number of SQL statements but there are also binary codes within the same file That binary data will prevent MTK from being able to process it Getting SQL statements

If you want to get the SQL statements out of the dump file as they would be executed on the server there is an option available from the import tool itself show=y

imp myIDmyPWD as sysdba file=myFiledmp

full=yes show=y gt dmp_showtxt

This will produce a file which contains the statements but they are wrapped in quotes The contents will look something like

ALTER SESSION SET CURRENT_SCHEMA= SYSTEM CREATE UNDO TABLESPACE TBSPC1 BLOCKSIZE 8192 DATAFILE DORACLEORADA TASCHEMA1CHUNKDBF SIZE 387973120 AUTOEXTEND ON NEXT 5242880 MAXS IZE 32767M EXTENT MANAGEMENT LOCAL

which makes them strings instead of SQL statements Fixing this is a two-step process

-- removes quotes from the start of lines

sed s^ g dmp_showtxt gt step1txt

-- removes quotes from the end of lines

sed s$g step1txt gt dmp_step2sql

The statements are still not correctly formatted because they have been truncated to a fixed length and line-endings inserted However at this point it is possible to get a count of how many of each object type there is using the script in the appendix ldquoGetting an initial count of database objectsrdquo

Data Pump Export and Import

These newer tools provide better performance and more capabilities than their predecessors Please refer to documentation on Oracle for a complete description searches for ldquoData Pump Importrdquo and ldquoData Pump Exportrdquo should return relevant results quickly Below is enough information to get started on defining and extracting the objects to be migrated Metadata can be filtered through the use of the export mode clause and INCLUDE and EXCLUDE parameters However any dependent object of an included or excluded object is likewise included or excluded For example if you include an index then the table associated with the index will also be included and if you exclude a table then any associated indexes will also be excluded The SQL that will generate all the objects in the dump file can be created by the impdp command with the SQLFILE parameter If the output file is very large you might want to break it into smaller pieces There are a couple of ways to do this and the one that is best for you somewhat depends

IBM Software Group IBM Information Management

Version 16 13

on how you intend to proceed with the conversion Data definition language (DDL) SQL for all the objects can be put into one file or the INCLUDE or EXCLUDE parameters can be added to direct Data Pump to filter on the types of objects If you put all the objects into one file then you can break that into smaller files by object type fairly easily because the objects are sorted by type in the SQL file So it is just a matter of cutting the file into smaller pieces This method may be preferred because it allows for you to do things like create all tables load the data and then create the indexes and triggers If the data set is large creating the indexes after loading the data can yield substantial performance improvements However this is less useful if you want to convert sets of objects according to dependencies in which case the filtering option is likely to be more useful Just to illustrate a difference between these two methods in one customer case the metadata dump file was about 18MB and putting all objects in one SQL file resulted in a file that was about 15MB The table definitions occupied a little under 300KB of the 15MB The output file generated by filtering on objects of type TABLE was just over 1MB The addition content was mostly GRANT INDEX and TRIGGER creation statements There were no differences in the CREATE TABLE statements themselves Examples

Prerequisite The Data Pump tools require the use of an Oracle DIRECTORY object This is basically a mapping between a name that exists within the DBMS and a system path It can be a tripping point but it provides an abstraction layer that for instance allows the same commands to work across systems with different disk layouts or different operating systems Creating a DIRECTORY on a Windows system from SQLPlus

SQLgtconnect as sysdba

SQLgtCREATE OR REPLACE DIRECTORY dumpDir AS ctemp

Note Make sure this directory is not read-only There also could be problems if the directory is a network drive on Windows these can be related to there being different users between the Oracle executable and the current user and those users having different permissions on the network drive

SQLgtGRANT read write ON DIRECTORY dumpDir TO userID

Creating a dump file of the entire database

expdp userNameuserPwd as sysdba FULL=Y dumpfile=DB_fulldmp

LOGFILE=LG_expdplog CONTENT=METADATA_ONLY DIRECTORY=dumpDir

Creating a dump file of just one schema

expdp userNameuserPwd as sysdba SCHEMAS=hr DIRECTORY=dumpDir

DUMPFILE=hr dmp LOGFILE=hr log CONTENT=METADATA_ONLY

Creating a dump of just the tables and their dependents

expdp userNameuserPwd as sysdba SCHEMAS=hr INCLUDE=TABLE

DIRECTORY=dumpDir DUMPFILE=hrdmp LOGFILE=hrlog

CONTENT=METADATA_ONLY

Creating a dump of just one table

expdp userNameuserPwd as sysdba SCHEMAS=hr

INCLUDE=TABLELIKE COUNTRIES DIRECTORY=dumpDir

DUMPFILE=hrdmp LOGFILE=hrlog CONTENT=METADATA_ONLY

IBM Software Group IBM Information Management

Version 16 14

Creatinge an SQL file from a dump file

impdp userNameuserPwd as sysdba DIRECTORY=dumpDir

DUMPFILE=hrdmp SQLFILE=dumpDirhrsql

The INCLUDE and EXCLUDE options are also valid when used with impdb so it may be easier to get a complete dump of everything to be migrated then use these options to create subsets of objects it smaller SQL files than it would be to create separate dump files It is easier to divide objects than to merge them together if they are not divided initially as wanted There is a caveat when using this impdp to generate an SQL file the object names will all be delimited identifiers Example

CREATE TABLE HRCOUNTRIES Because of differences between how Informix handles these and how Oracle handles these case-sensitivity issues could occur See the chapter on ldquoDelimited Identifiersrdquo and in particular the description of default shift problems If it can be determined that there are no name collisions if regular identifiers are used removing the quotation marks as part of the conversion might avoid many problems In other words if there are no objects whose names only differ in case like foo and FOO then changing every occurrence of ldquoFOOrdquo to FOO in the DDL could eliminate case-sensitivity issues in the application DML It depends on if the application code uses the delimited form of the name predominantly or not

IBM Software Group IBM Information Management

Version 16 15

C H A P T E R 3 Data Definition Language

Identifiers An identifier specifies the simple name of a database object such as a table name column name index name view name stored procedure name and so on The maximum length of an Oracle identifier is 30 characters and can contain letters numbers ldquo_rdquo ldquo$rdquo and ldquordquo although Oracle highly recommends that ldquo$rdquo and ldquordquo should not be used In contrast Informix identifiers have a maximum length of 128 characters and may contain letters numbers ldquo_rdquo and ldquo$rdquo (as long as ldquo$rdquo is not the first character) See the Delimited Identifiers section below for information This means that all Oracle identifiers containing a ldquordquo anywhere in the identifier or a ldquo$rdquo as the first character must be replaced or modified to remove those characters from the identifier

Delimited identifiers

Delimited identifiers are also known as quoted identifiers and sometimes as escaped identifiers They have been part of the SQL standard since SQL92 but existed in various database management systems (DBMS) prior to that time In a nutshell they are a way to preserve case sensitivity in object names as well as to allow objects to have names outside of the conventions of SQL regular identifiers Prior to the behavior of identifiers in general being standardized different DBMS vendors implemented different means of achieving case-insensitivity for object names some converted all regular identifiers to uppercase and some converted regular identifiers to lowercase By SQL99 the concept of case normal form was standardized to mean simply stated that if there exists an uppercase equivalent of any character in a name then the uppercase version is stored in the system catalogs and used for comparison purposes See the SQL99 standard chapter 5 section 2 and in particular items 21 and 22 for a formal description of case normal form and how it applies to identifier comparisons Delimited identifiers can be used to specify names for database objects that are otherwise identical to SQL reserved keywords such as TABLE WHERE DECLARE and so on The only database object for which delimited identifiers cannot be used is a database name Database administrators and application programmers do not always communicate to each other with 100 efficiency and there is no guarantee that within either of these pools every member codes by the standard practice of the other members After describing how delimited identifiers work in Informix there will be a description of how any inconsistency of usage and the differences between Oracle and Informix can introduce some migration hurdles DELIMIDENT Environment Variable

To use delimited identifiers with Informix you must set the DELIMIDENT environment variable While DELIMIDENT is set strings enclosed in quotation marks ( ldquo ) are treated as identifiers of database objects and strings enclosed in apostrophes ( rsquo ) are treated as literal strings If the

IBM Software Group IBM Information Management

Version 16 16

DELIMIDENT environment variable is not set strings enclosed in quotation marks are also treated as literal strings When you set the DELIMIDENT environment variable you cannot use quotation marks ( rdquo ) to delimit literal strings If DELIMIDENT is set the database server interprets all strings enclosed in quotation marks as SQL identifiers not string literals Commonly within Informix systems DELIMIDENT is set or not on the client side according to the design of the application However if you are converting a database and all applications accessing it from a system where every occurrence of quotation marks (ldquoobjectNamerdquo) indicates an identifier and not a string literal you may want to consider setting it in the server environment in order to avoid any inconsistency between clients where it is set and where it might not be Using Quotes in Strings The apostrophe ( rsquo ) has no special significance in string literals delimited by quotation marks Conversely double quote ( Prime ) has no special significance in strings delimited by apostrophes For example these strings are valid Nancyrsquos puppy jumped the fence

rsquoBilly told his kitten No rsquo A string delimited by quotation marks can include a double quote character by preceding it with another double quote as the following string shows Enter y to

select this row When the DELIMIDENT environment variable is set quotation marks can only delimit identifiers not strings Use of Uppercase Characters You can specify the name of a database object with uppercase characters but the Informix server shifts these to lowercase characters unless the DELIMIDENT environment variable is set and the name of the database object is enclosed in quotation marks In this case the database server treats the name of the database object as a delimited identifier and preserves the uppercase characters in the name Delimited Identifiers By default the character set of a valid SQL identifier is restricted to letters digits underscore and dollar-sign symbols If you set the DELIMIDENT environment variable however SQL identifiers can also include additional characters from the codeset implied by the setting of the DB_LOCALE environment variable See the Identifier section of the Informix Guide to SQL Syntax for more information Storage Object Names In Informix delimited identifiers can be used to specify non-alphanumeric characters in the names of database objects However delimited identifiers can not be used to specify non-alpha characters in the names of storage objects such as dbspaces and blobspaces To use delimited identifiers DELIMIDENT must be set both at compile and run times For example to set DELIMIDENT environment variable with sh or ksh issue the following at the command line prompt

export DELIMIDENT=

Note You do not need to assign a value to the environment variable and counter-intuitively setting DELIMIDENT=n has the same effect as DELIMIDENT=y Also in a Windows environment

set DELIMIDENT=

effectively undefines the variable Default shift problems

Any direct access of system catalog information involving names will cause problems when migrating from a system like Oracle where system catalog names are stored in uppercase to a system like Informix where the catalog names are stored in lowercase For example

CREATE TABLE foo (c1 int)

IBM Software Group IBM Information Management

Version 16 17

Within Oracle the following will return information about the table

select from sysall_objects where object_name = FOO

and the following will not

select from sysall_objects where object_name = foo

Conversely in Informix

select from systables where tabname = foo

will be successful and the same with FOO will not be A similar if not more common problem can occur when the table has been created without the name being delimited but is sometimes delimited when accessed by the application Per the standard foo == FOO == ldquoFOOrdquo but in Informix foo == FOO == ldquofoordquo In Oracle the following SELECT statement will be successful

SELECT FROM ldquoFOOrdquo

but within Informix this will result in an error ldquo206 The specified table (FOO) is not in the databaserdquo Likewise if the name is delimited in its definition such as

CREATE TABLE SCHEMA1TABLE1

this creates a table that can be referenced in Oracle without the name being delimited The statements

SELECT FROM schema1table1

and SELECT FROM SCHEMA1TABLE1

will be successful in the Oracle system but will fail in the Informix one In theory whether on object name is delimited or not should be the same in the database and at every occurrence within the application but this is not always the case It may be beneficial to examine whether delimited identifiers or regular identifiers are most commonly used in application code and use whichever is most common as a naming convention when translating the DDL

Explicit versus implicit schemaowner names

Another complication to keep in mind is that when the log mode is ANSI implicit and explicit owner names are treated differently between the Oracle and Informix servers In Oracle there is no difference in the case handling of an implicit owner name and an explicit one For example if connected to Oracle as scott the following CREATE TABLE statements

create table foo1(c1 int) create table scottfoo2(c1 int) create table SCOTTfoo3(c1 int)

all result in tables owned by SCOTT The following select statements in various forms that may be in application code will all run without error

select from foo1 select from scottfoo1

IBM Software Group IBM Information Management

Version 16 18

select from SCOTTfoo1 select from foo2 select from scottfoo2 select from SCOTTfoo2 select from foo3 select from scottfoo3 select from SCOTTfoo3

These statements will also run without error within a non-ANSI mode Informix database but not all of them will run successfully within an ANSI mode database This is because Informix does not uniformly fold the case of owner names and handles implicit names differently from explicit names so there will always be some combination of DDL and DML usage patterns that work within an Oracle system that do not work in an Informix one You can set ANSIOWNER before starting your Informix server but that will merely change which combinations do not work You may want to examine usage patterns within the applications and choose a naming convention when translating the DDL that matches the most common naming convention used in the applications Note This behavior of Informix forces a tradeoff between using an ANSI mode database which most closely matches the transaction behavior of Oracle and a non-ANSI mode database which has the least mismatch in identifier case sensitivity

Reserved words or keywords

Oracle and Informix both allow identifiers to be reserved words as long as they are delimited However Oracle and Informix reserved words differ In addition both systems have keywords like FROM that are not always reserved in the sense that using them as an identifier will always generate a syntax error There should be few problems with reserved words or keywords if identifiers that are delimited in the original database remain delimited in the destination database The appendix Keywords of SQL for IBM Informix in the Guide to SQL Syntax contains more information about Informix keywords Also one word non-delimited identifiers should be verified against the Informix reserved words list to ensure that they do not need to be delimited or renamed Although almost any word can be used as an identifier in Informix syntactic ambiguities can result from using reserved words as identifiers in SQL statements Delimited identifiers provide a way to use a reserved word as an identifier without causing syntactic ambiguities However doing this changes a case-insensitive name into a case-sensitive one and that means that every reference to the object has to be checked for issues related to case-sensitivity Essentially this is not much less work than changing the name of the object because in essence it is changing the name of the object Examples

The following example shows how to create an Informix table with a case sensitive table name

CREATE TABLE My_Customers (hellip)

The following example shows how to create a table whose name includes a space character If the table name were not in quotation marks () a space character or any other non-alpha character except an underscore ( _ ) or dollar sign ($) (see special conditions above) could be used in the name

CREATE TABLE My Customers (hellip)

IBM Software Group IBM Information Management

Version 16 19

The following example shows how to create a table that uses a keyword as the table name

CREATE TABLE TABLE (hellip)

To include a double-quote () within a delimited identifier the double-quote () must be preceded with another double-quote () as shown in the following example

CREATE TABLE MyGoodData (hellip)

Summary

The main points to keep in mind when deciding about any questions on how identifiers should be translated are

Oracle always has delimited identifiers enabled and Informix does not

Oracle folds regular identifiers to uppercase and Informix folds to lowercase

Informix has behavioral differences between an ANSI mode database and a non-ANSI mode one

It is beneficial to consider the most common usage patterns within the existing application code prior to deciding default identifier translation patterns

Databases

Databases database names and instances

Oracle and Informix implement databases and instances differently Oracle considers a database to be a set of data files control file(s) and log files while an instance is a set of background processes and memory structures accessing database data Oracle instances are also known as servers Each Oracle instance or server runs against one database but through the use of Oracle Parallel Server a database may have multiple instances accessing it An Oracle database is named at initialization and the name has a limit of 8 ASCII characters Informix databases are defined as ldquoa collection of information contained in tables that are useful to a particular organization or used for a specific purposerdquo Informix database names may be up to 128 characters in length An Informix instance is a set of processes memory and disk allocations that manage data and will contain at least two and in most cases many databases Informix instances are also referred to as servers Informix databases may share disk allocations (dbspaces) with other databases within an Informix instance Oracle databases cannot share disk allocations (tablespaces) Informix databases should be created in a dbspace other than the root dbspace The root dbspace holds data for the system configuration information for the engine and so on If user-defined objects are created in this dbspace then the dbspace may become unmanageably large and during backup the system information may also get backed up unnecessarily The CREATE DATABASE statements of Informix and Oracle have differences which may require modification to routines responsible for database creation Informix will accept the same minimal syntax required by Oracle (eg CREATE DATABASE myDB) however issuing the command will implicitly accept the creation of a database without transaction logging enabled and establish the default location for all database objects as the instancersquos default storage location The instancersquos default storage location or ldquorootrdquo dbspace should not contain user-defined objects The root dbspace holds data for the system and some configuration information for the engine If user-

IBM Software Group IBM Information Management

Version 16 20

defined objects are created in this dbspace it may become unmanageable and result in the system contending with user objects for the available space

ANSI vs non-ANSI

Informix supports both ANSI and non-ANSI databases Informix non-ANSI databases are most common but there are some advantages of ANSI databases when porting from Oracle

Oraclersquos transaction behavior is more or less like that of an ANSI database Applications ported on Oracle are always in a transaction In Oracle and ANSI databases transactions begin implicitly with the first of a series of SQL statements and will end immediately after a commit or rollback statement Therefore unlike a non-ANSI database a COMMIT WORK statement does not need to be preceded with a BEGIN WORK statement

In ANSI databases database object references must be prefixed by the ownerrsquos name unless the owner is the one referencing the object If Oracle applications reference database objects with a both parts of the object name prefixing the object name with schema using an ANSI database may ease modifications necessary when porting to Informix

The ldquolsquogrant to PUBLICrdquorsquo concept provide by Informix database security does not apply to ANSI databases Every database object is private and privileges must be explicitly granted to each user

If an Informix ESQLC or 4GL application was developed to run on a non-ANSI Informix database (including BEGIN WORK statements) the application could run on an ANSI Informix database in one of two ways

By placing the BEGIN WORK statement in a pre-processor directive such as IFDEF object_name and omitting the proper preprocessor compile options such as -D object_name

By compiling the application normally and ignoring the resulting warning messages

Additionally the LOG MODE ANSI clause must be added to the CREATE DATABASE statements ANSI mode databases cannot have buffered logging Applications written to use an open API like ODBC or JDBC are compiled without awareness of the database and these APIs are written with the intent to abstract specific database behavior For instance in one of these the application developer would call a function to begin or end a transaction rather than execute a BEGIN and COMMIT or ROLLBACK The API would execute these statements internally or not as necessary for the database connection See the Transaction Processing section in Application Architecture for more information on how an application running on a non-ANSI Informix database can simulate Oracle transaction behavior

Tablespaces and dbspaces Oracle tablespace names need to be replaced with Informix dbspace names Unlike the Oracle tablespace the Informix dbspace cannot be created using DDL (SQL) scripts It must be created using the Informix onspaces utility before any DDL (SQL) scripts are executed Therefore Oraclersquos CREATE TABLESPACE statements should be removed from the DDL (SQL) scripts The user interface for accomplishing these tasks is onmonitor The command line utility is onspaces Therefore the onspaces commands can be placed in shell or batch scripts After successfully executing the onspaces commands the DDL (SQL) scripts may be called through the same shell or batch scripts For example

IBM Software Group IBM Information Management

Version 16 21

onspaces hellip onspaces hellip hellip dbaccess database_name DDL_script_file_name dbaccess database_name DDL_script_file_name hellip

Tables

Attributes and general syntax

When creating tables the Oracle CREATE TABLE statement must be converted to Informix taking advantage of the Informix options IN EXTENT NEXT and LOCK MODE

IN specifies the dbspace in which the table will reside

EXTENT specifies the amount of space that will initially be allocated to the table (16K default on most platforms)

NEXT specifies the amount of space that will be allocated when additional space is needed (16K default on most platforms

Lock mode

LOCK MODE specifies whether to use row or page locks for the table In Oracle the default is row level locking in Informix the default setting is page level locking However it can be changed by using one of the following methods (resolved in the following order of precedence)

1 LOCK MODE specified using an attribute of the CREATE TABLE or ALTER TABLE command syntax

2 IFX_DEF_TABLE_LOCKMODE environment variable setting 3 DEF_TABLE_LOCKMODE parameter setting in the ONCONFIG file

NOTE If the DEF_TABLE_LOCKMODE parameter cannot be found in the ONCONFIG file it can be added to make the specification for every database within the instance The Informix instance must be restarted for this parameter to take effect The new ldquodefaultrdquo LOCK MODE will apply to all tables created after the parameter has been changed To change the LOCK MODE of existing objects use the ALTER TABLE statement

Storage

The Oracle STORAGE INITIAL and STORAGE NEXT clauses must be changed to the Informix EXTENT SIZE and NEXT SIZE clauses respectively In Oracle the STORAGE clause options MINEXTENTS MAXEXTENTS and PCTINCREASE should be removed For example Oracle

CREATE TABLE dept(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13)

)

STORAGE (INITIAL 100K NEXT 50K MINEXTENTS 1 MAXEXTENTS 50

PCTINCREASE 5)

Informix CREATE TABLE dept (

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

IBM Software Group IBM Information Management

Version 16 22

EXTENT SIZE 200 NEXT SIZE 50

When an Oracle CREATE TABLE statement does not include a STORAGE clause the table will be created using the tablespace STORAGE clause by default If an Oracle tablespace is created specifying a STORAGE INITIAL of 100KB and a STORAGE NEXT of 50KB then all tables created within that tablespace will have a default value of STORAGE INITIAL 100KB and STORAGE NEXT 50KB Oracle tables cannot be created with smaller STORAGE clause values than the tablespace default they are created in Informix dbspaces do not have storage clauses attached to them As stated earlier the default Informix EXTENT and NEXT sizes are 16KB on most platforms The minimum EXTENT and NEXT sizes are 4 times the page size

Constraints

The Oracle constraint syntax must be changed to the Informix syntax for primary keys foreign keys unique and so on For example

Oracle CONSTRAINT PK_NUMBER PRIMARY KEY(CUST_NUM)

CONSTRAINT CK_EMP_CODE CHECK (EMP_CODE gt 100)

Informix PRIMARY KEY(CUST_NUM) CONSTRAINT PK_NUMBER

CHECK (EMP_CODE gt 100) CONSTRAINT CK_EMP_CODE

An Oracle check constraint statement may contain functions that are not available in Informix In this circumstance it may be necessary to code the combination of a trigger and a stored procedure to emulate the same functionality A trigger based on an insert or update event can execute a stored procedure which tests the constraint condition and if necessary raise an exception to reject the row data which violates the constraint The Oracle PARALLEL clause which specifies parallel execution of an operation must be removed from any SQL statements (such as CREATE TABLE and ALTER TABLE) In Informix there are ways to accomplish this parallel execution depending on the context in which these SQL statements are called (shell script file batch file and so on)

ALTER TABLE

Informix offers a rich set of ALTER TABLE features adding and dropping columns (rename by using the RENAME statement) changing column data types altering the next size and changing the lock mode Informix will choose one of three algorithms when executing an ALTER TABLE statement depending upon the operation to be performed For certain conditions the database server uses either a ldquoslowrdquo ldquoin-place or ldquofastrdquo alter algorithm to modify the table Informix provides ldquoin-placerdquo alter table support for adding or dropping a column anywhere in the table changing the column length and changing the column data type without an exclusive lock on the table An ldquoin-placerdquo alter will modify the tablersquos definition without changing the existing rows or unloading and reloading the data After the ALTER TABLE operation the database server inserts rows using the latest definition Informix will not change the row structure until a data row is touched by a user operation Once a query accesses a row that is not yet converted there can be a slight degradation in the performance because the database server reformats each row in memory before it is returned Informix uses the ldquoslowrdquo alter algorithm when the ALTER TABLE statement makes column changes that it cannot perform in place This type of alter would be

Adding or drop a column created with the ROWIDS keyword

Dropping a column of the TEXT or BYTE data type

IBM Software Group IBM Information Management

Version 16 23

Converting an INT or a SMALLINT column to SERIAL or SERIAL8

Modifying the data type of a column so that some possible values of the old data type cannot be converted to the new data type

For example if you modify a column of data type INTEGER to CHAR(n) the database server uses the slow ALTER algorithm if the value of n is less than 11 An INTEGER requires 10 characters plus one for the minus sign for the lowest possible negative values

Modifying the data type of a fragmentation column in a way that value conversion might cause rows to move to another fragment

Adding dropping or modifying any column when the table contains user-defined data types or smart large objects

When the database server uses the slow alter algorithm to process an ALTER TABLE statement the table can be unavailable to other users for a long period of time because the database server will lock the table exclusively for the duration of the operation make a copy of the table to convert the table to the new definition and convert the data rows This type of ALTER TABLE processing can encounter the scenario of a statement being a long transaction and abort it if the Long Transaction High Water Mark (LTXHWM) threshold is exceeded Informix will use the ldquofastrdquo alter algorithm when the ALTER TABLE statement changes attributes of the table but does not affect the data The database server uses the fast alter algorithm when you use the ALTER TABLE statement to make the following changes

bull Change the next-extent size

bull Add or drop a constraint

bull Change the lock mode of the table

bull Change the unique index attribute without modifying the column type

With the ldquofastrdquo alter algorithm the database server holds a lock on the table for a very brief period In some cases the database server will lock the system catalog tables but only long enough to change the attribute In either case the table is unavailable for queries for only a short time

Data Partitioning

Informix Table Fragmentation is the counterpart to Oraclersquos Table Partitioning and allows the user to control where data is physically placed at the table level Table Fragmentation or Data Partitioning is typically done to large tables but Informix and Oracle implement fragmentation and partitioning for different reasons and with different results Informix recommends using table fragmentation to improve single-user response time concurrency data availability backup restore characteristics and data-load performance While Oracle does state that table partitioning may improve the performance of queries and that the Oracle optimizer takes partitioning into account the primary goal of partitioning in Oracle is improving database maintenance Partitioning strategies in Oracle include range partitioning as well as hash and composite partitioning Composite partitioning combines range and hash partitions through the use of sub-partitions Tables incorporating Oracle LOBrsquos (large objects) cannot be partitioned Informix fragmentation strategies include expression-based and round robin Basic expression-based fragmentation can replace Oracle range partitioning Unlike Oracle LOBs Informixrsquos Smart Large Objects can be fragmented Examples of creating tables with Oracle range partitioning and Informix fragmentation by expression are shown below Oracle range partitioning

CREATE TABLE dept

IBM Software Group IBM Information Management

Version 16 24

(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13) )

partition by range (deptno)

(partition PART1 values less than (11)

tablespace PART1_TS

partition PART2 values less than (21)

tablespace PART2_TS

partition PART3 values less than (31)

tablespace PART3_TS

partition PART4 values less than (MAXVALUE)

tablespace PART4_TS)

Informix expression based fragmentation CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

deptno lt 11 IN dbspace1

deptno gt= 11 AND deptno lt 21 IN dbspace2

deptno gt= 21 AND deptno lt 31 IN dbspace3

REMAINDER IN dbspace4

Oracle uses MAXVALUE for values not found in the specified range while Informix uses the REMAINDER keyword for values that fall outside the specified expression or expressions Prior to IDS version 1000 each table fragment had to go into a separate dbspace Now tables can be fragmented within a single dbspace You can create partitions within a dbspace that can each support a table fragment It is better to have one chunk per disk drive and now it is not necessary to create a dbspace just to facilitate fragmentation This feature can simplify the management of dbspaces The benefits gained through this new development include

It reduces the total number of dbspaces needed for a fragmented table

Storing multiple table fragments in a single dbspace improves query performance over storing each fragmented expression in a different dbspace

For example Informix partition fragmention in a single dbspace

CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

PARTITION part1 (deptno lt 11) IN dbspace1

PARTITION part2 (deptno lt 21) IN dbspace1

PARTITION part3 (deptno lt 31) IN dbspace1

PARTITION part4 REMAINDER IN dbspace1

Partitions of an Informix fragmented table can be manipulated using the ALTER FRAGMENT statement which supports attaching detaching adding modifying and dropping as well as initializing the distribution strategy

IBM Software Group IBM Information Management

Version 16 25

For example the following SQL removes a partition fragment and places the contents into a new table

ALTER FRAGMENT ON TABLE dept DETACH PARTITION part3 dept_part3

Making use of ALTER FRAGMENT to detach fragments can be an effective way of deleting large quantities of rows from a table quickly and easily After the above statement completes the table will no longer contain rows with a deptno greater than 21 and less than 31 Refer to the Informix Guide to SQL Syntax for a complete description on how to use the ALTER FRAGMENT statement to change the distribution strategy or the storage location of an existing table or index

Data types

Numeric

Oraclersquos NUMBER data type needs to be replaced with one of the following Informix equivalent data types depending on the size of the column The Informix numeric data types are listed below

SMALLINT (-32767 to 32767)

INTEGER (-2147483647 to 2147483647)

BIGINT (-9223372036854775807 to 9223372036854775807)

INT8 (-9223372036854775807 to 9223372036854775807)

The BIGINT type is more efficient in terms of space and speed there are few reasons to use INT8 now that BIGINT is available

DECIMAL (floating point up to 32 significant digits -10-130

to 10124

)

In an ANSI database there is an implied scale of 0 when no scale is given so this is not strictly speaking a floating point type within an ANSI database

NUMERIC (floating point up to 32 significant digits -10-130

to 10124

)

FLOAT (double precision like double data type of C)

SMALLFLOAT (single precision like float data type of C)

REAL (same as SMALLFLOAT)

DOUBLE (same as FLOAT)

LONG (same as long data type of C)

Oraclersquos NUMBER data type is used to store zero positive and negative fixed size and floating point numbers with magnitudes between 10 x 10

-130 and 999 x 10

125 (38 9s followed by 88 0s)

with 38 digits of precision A fixed-point number is specified by NUMBER(p s) where p is the precision or the total number of digits and s is the scale or the number of digits to the right of the decimal point For example a column defined as NUMBER(104) would contain numbers in the format 9999999999 In Oracle the scale can range from -84 to 127 If the scale is 0 or not mentioned then the data type can be converted into Informixrsquos SMALLINT INTEGER or BIGINT depending on the precision or FLOAT SMALLFLOAT DOUBLE or REAL depending on usage in the application When the scale is positive the data type should be converted to Informixrsquos DECIMAL or NUMERIC A floating-point data type in Oracle is declared using the type NUMBER without mentioning scale and precision In Informix this can be replaced with FLOAT SMALLFLOAT REAL DOUBLE PRECISION or DECIMAL(p) in an non-ANSI database

IBM Software Group IBM Information Management

Version 16 26

Oracle allows a negative scale If the scale is negative the actual data is rounded to the specified number of places to the left of the decimal point For example a specification of NUMBER (10 -2) means to round to the hundred If the general form for any number is

mantissa X 10exponent

then precision is the number of digits in the mantissa and scale is the negative exponent Example

select cast( 987654321 AS NUMBER(10-2) ) from dual

returns

987654300

Informix does not support a negative scale If precision - scale is less than the maximum precision of an integer type then that is the most efficient type to use Failing that and if the database is non-ANSI a floating point DECIMAL can be used If that is not sufficient then it may be necessary to define a user type and associated functions Oracle also allows the scale to be greater than the precision Precision is just the number of digits that will be preserved A NUMBER(3 5) might have the value 000123 If the Oracle scale is less than the Informix maximum precision then the Oracle scale can be used for both the Informix precision and scale A NUMERIC(55) column could also store the value 000123 You may need to take into consideration not only the minimum and maximum values but the default size for data types For example when the size of the NUMBER data type is absent Oracle will default to NUMBER(38) while Informix defaults to NUMERIC(16) Oracle and Informix support the ANSI DECIMAL data type Therefore in the case of an ANSI data type the Oracle data type can be converted to the same Informix data type There are differences between conversions based on theory versus those based on practice For instance it is very common to see an undecorated NUMBER declaration where the customer database and applications are using integer data When converting NUMBER declarations it may be necessary to consider how the data is being used in order to determine the best type mapping

CHAR VARCHAR and LVARCHAR

In Oracle the default for a CHAR column is one character and the maximum allowed is 255 characters In Informix the maximum length of CHAR and LVARCHAR columns is 32767 Therefore Oraclersquos CHAR columns can always be converted to an Informix CHAR column The CHAR data type columns can only contain printable characters tabs and spaces The CHAR columns store leading and trailing spaces In Oracle a zero-length string can be inserted into a CHAR column but the column is padded with one blank character when it is used in comparisons Also in Informix a zero-length string can be inserted into a CHAR column however the column is padded with enough spaces to fill the column In the case of inserting NULL into an Informix CHAR column no padding occurs Oraclersquos VARCHAR and VARCHAR2 are currently synonymous and have a maximum data length of 4000 bytes while the maximum length for the Informix VARCHAR data type is 255 Informixrsquos CHAR and LVARCHAR data types have a maximum length of 32767 and 32739 respectively measured in bytes These should be used to replace Oraclersquos VARCHAR VARCHAR2 LONG and LONG VARCHAR if the data length is between 256 and the maximum If the data length exceeds the maximum use Informixrsquos TEXT BYTE BLOB or CLOB data types See the Raw Data section below for more information on TEXT BYTE BLOB and CLOB data types

IBM Software Group IBM Information Management

Version 16 27

Empty Oracle VARCHAR2 strings are considered NULL Empty Informix VARCHAR and LVARCHAR strings are not considered NULL rather they contain at least one space Oracle

compares VARCHAR2 values using non-padded comparison semantics Therefore ldquoBOBrdquo ldquoBOB ldquo Informix ignores trailing blanks Therefore ldquoBOBrdquo = ldquoBOB ldquo or ldquordquo = ldquo rdquo Hence checks for NULL within the application must be replaced with checks for an empty string (such as ldquordquo or ldquo rdquo) whenever an empty string is inserted into the column If NULL is truly inserted into the column checking for NULL is appropriate (for example SELECT FROM hellip WHERE hellip IS NULL) In Oracle LONG columns store variable length character strings containing up to 2 gigabytes or 2

31-1 bytes Informix LONG columns store numeric data Oraclersquos LONG columns have many of

the characteristics of VARCHAR2 columns They can be used in a SELECT list in the SET clause of an UPDATE statement and in an INSERT statement but they cannot be used in a WHERE clause a GROUP BY clause or an ORDER BY clause and they cannot be indexed Oraclersquos LONG columns should be converted to an Informix Smart Large Object or ldquoSLOBrdquo (BLOB CLOB) column

Date and Time

Oraclersquos DATE data type contains date and time components from year down to second It can be to be replaced most directly with Informixrsquos DATETIME YEAR TO SECOND Some analysis may be necessary to determine whether the time is really necessary In other words does the application reference the date and time portions of the values If the application only references the date portion then replace Oraclersquos DATE with Informixrsquos DATE and change the host variable to X(10) or char(10) accordingly The Informix DATE default display format is MM-DD-YYYY although the DATE data type stores the calendar date The Informix DATE data type requires 4 bytes which is stored internally as an integer value equal to the number of days since December 31 1899 The default display format can be changed with the environment variable DBDATE If the application uses different date formats then using DBDATE is not a solution Sometimes it might be necessary to write small subroutines to emulate Oraclersquos DATE representations See the Informix Guide to SQL Reference manual for details on DBDATE and also DBCENTURY If the application only references the time portion of the values replace Oraclersquos DATE with Informixrsquos DATETIME using the EXTEND function to specify precision In addition Informix provides the data type INTERVAL for use while performing DATE and DATETIME calculations In Oracle the DATE data type is used to store date and time information Although date and time information can be represented in both CHAR and NUMBER data types the DATE data type has special associated properties For each DATE value the following information is stored

century

year

month

day

hour

minute

second

Also regarding the Oracle DATE data type if a date value without a time component is specified the default time is 120000am If a DATE value without a date is specified the default date is the first day of the current month

Interval

Within Informix there are two classes of interval types YEAR-MONTH and DAY-FRACTION There are different numbers if days in different months so the MONTH-DAY boundary cannot be crossed without creating ill-defined results Within each of these classes Informix allows you to declare columns or variables as any subset of the start and end fields Oracle has one INTERVAL

IBM Software Group IBM Information Management

Version 16 28

type for each of the two classes YEAR(p) TO MONTH and DAY(p) TO SECOND(s) The Oracle scale on the SECOND field is logically equivalent to the Informix scale on the FRACTION field

Raw data and Large Objects

Oraclersquos support of large blocks of raw unstructured data (such as graphic images video clips and sound waveforms) in binary or character format is provided by the large object (LOB) data types BLOB CLOB NCLOB and BFILE Traditional Oracle data types MLSLABEL (used with Trusted Oracle) RAW and LONG RAW are also used for data that is not to be interpreted by the engine and converted when moving data between different systems Informix supports two types of large objects (LOBs Simple Large Objects and Smart Large Objects Simple LOBs consist of the TEXT and BYTE data types and can be 2

31 bytes or 2

Gigabytes in size Smart LOBs include both Character Large Object (CLOB) and Binary Large Object (BLOB) data types and may be up to 42

40 bytes or 4 Terabytes in size Simple LOBs can

be stored either in-line with table data or in blobspaces while Smart LOBrsquos are stored in sbspaces Oraclersquos CLOB BLOB MLSLABEL RAW and LONG RAW data types should be replaced with Informixrsquos BYTE TEXT CLOB or BLOB depending on the columnrsquos size and usage Informixrsquos Smart BLOB data types CLOB and BLOB should be used under the following conditions and considerations

The large object needs to be referenced by multiple sources

The object size exceeds 2 GB

Fragmentation is required

Byte level locking is available making it possible to lock only a portion of the object

Logging can be specified at the object level

Updates are done in place or moved as needed

Be aware of the following restrictions for Simple Large Objects

Data can only be inserted into a BYTE or TEXT column with the dbload or onload utilities the DBACCESS load statement BYTE or TEXT host variables respectively in ESQLC or declaring a file in ESQLCOBOL

BYTE and TEXT columns cannot be inserted or updated with a literal neither quoted text string nor number

BYTE or TEXT columns cannot be used in string operations with aggregate functions with the GROUP BY ORDER BY IN LIKE or MATCHES clauses

ROWID

The implementation of ROWID differs between Oracle and Informix Oraclersquos ROWID is both a pseudo-column and a data type See the ROWID subsection in the Pseudo-Columns section in CHAPTER 3 Data Manipulation Language for more information Informix implements ROWID as a pseudo-column only Oracle stores the ROWID column and ROWID data type column values in hexadecimal format Informix stores the ROWID column values in INTEGER format The Oracle and Informix engines maintain the values of the ROWID pseudo-column Oraclersquos engine does not maintain the values of other columns of type ROWID In Informix the term rowid refers to an integer that defines the physical location of a row Informix assigns rows in a non-fragmented table a unique rowid which allows applications access to a particular row in a table Rows in fragmented tables in contrast are not assigned a rowid To access data by rowid in a fragmented table a rowid column must be explicitly created as is described in the Informix Guide to SQL Reference manual Creating a Rowid Column If applications attempt to reference a rowid in a fragmented table that does not contain a rowid that was explicitly created Informix displays an appropriate error message and execution of the application is halted

IBM Software Group IBM Information Management

Version 16 29

When used as a data type for a column Oracle does not guarantee that the values are valid ROWIDs For example if the ROWID is used as a data type on a column such as a column in a child table named parent_rowid containing the ROWID of the parent then the values are maintained by the application outside of the engine The application must read the ROWID of the parent and insert it into the parentrsquos corresponding child table rows This is usually done so the two tables can be joined on the parentrsquos ROWID and the childrsquos parent_rowid column This functionality can be duplicated in Informix by using primary and foreign keys Informix recommends that primary keys are used as a method of access in applications rather than rowids because primary keys are defined in the ANSI specification of SQL using them to access data makes applications more portable Refer to the Informix Guide to SQL Reference and the Informix Guide to SQL Syntax for a complete description on how to define and use primary keys to access data

User-defined types

Both Oracle and Informix allow the user to create and define data types Oracle refers to these as abstract data types while Informix refers to these as user-defined types In Oracle all user-defined types are referred to as abstract data types while Informix may refer to user-defined types as COLLECTION types ROW types DISTINCT types and OPAQUE types Currently the Informix ROW type is closest in form and function to the Oracle abstract data type An example of syntax for creating both an Oracle abstract data type and an Informix ROW type is shown below

Oracle abstract data type

CREATE TYPE name_type AS OBJECT

(first_name VARCHAR2(25)

middle_initial CHAR(1)

last_name VARCHAR2(30))

Informix row type

CREATE ROW TYPE name_type

(first_name VARCHAR(25)

middle_initial CHAR(1)

last_name VARCHAR(30))

Both Oracle and Informix support the use of user-defined types for table definition or column definition within a table Building on the example above the following create table example show a table definition and column definition within a table based on user-defined types Oracle table creation

CREATE TABLE name OF name_type

Informix table creation

CREATE TABLE name OF type name_type

Oracle column definition

CREATE TABLE employee

(empno NUMBER(9)

name name_type)

Informix column definition

CREATE TABLE employee

IBM Software Group IBM Information Management

Version 16 30

(empno INTEGER

name name_type)

For more information on User Defined Types see the Informix Guide to SQL Syntax

Complex data types

Informix offers users the ability to create data types from existing built-in types OPAQUE types DISTINCT types and other complex types Complex data types may either be a ROW type or a COLLECTION type Oracle treats complex data types as abstract data types For more information on Oracle abstract data types see the User Defined Types section above For more information on Complex Data Types see the Informix Guide to SQL Syntax For recommended type mappings and additional information see the appendix ldquoData type mappingsrdquo

Sequence objects

Oracle sequences

An Oracle sequence is a database object from which multiple users or transactions may generate unique integers For example sequences can be used to automatically generate primary key values When a sequence object is queried the sequence number is incremented and passed to the query independent of the transaction committing or rolling back If two applications increment the same sequence the sequence numbers each application acquires may not be sequential since sequence numbers are being generated by the other application One user or transaction can never acquire the sequence number generated by another user or transaction Once a user or transaction generates a sequence value that value will never be generated and passed to another user or transaction

Informix sequences

Informix rsquos implementation of sequence objects is identical to that of Oracle Issues regarding syntax compatibility should be negligible with the exception of some keywords which have no effect on the behavior of the sequence Informix supports DML statements (CREATE SEQUENCE ALTER SEQUENCE RENAME SEQUENCE DROP SEQUENCE) for sequence objects that multiple users can access concurrently to generate unique integers in the 8-byte integer range GRANT and REVOKE statements support access privileges on sequence objects and the CREATE SYNONYM and DROP SYNONYM statements can be used to reference synonyms for sequence objects in the local database The operators CURRVAL and NEXTVAL can read or increment the value of an existing synonym with behavior the same as Oracle

Indexes

Composite indexes

A composite index can have up to 16 key parts that are columns or up to 341 key parts that are values returned by a UDR This limit is language-dependent and applies to UDRs written in SPL or Javatrade functional indexes based on C language UDRs can have up to 102 key parts A composite index can have any of the following items as an index key

One or more columns

IBM Software Group IBM Information Management

Version 16 31

One or move values that is returned by a user-defined function (referred to as a functional index)

A combination of columns and user-defined functions

Maximum key size

The total widths of all indexed columns in a single CREATE INDEX statement have a limitation based upon the page size of the dbspace in which the index resides This limitation does not apply to functional indexes An enhancement introduced with Informix Dynamic Server Version 1110 is configurable page sizes for dbspaces Prior to this release the page size of dbspaces were restricted to that of the operating system and could not be changed thus Informix was limited to 390 byte indexes With page sizes configurable from 2K through 16K wider indexes are supported Refer to the table below 16K page sizes raises the limit on index width to over 3000 bytes Lifting the 390 byte limit also permits LVARCHAR columns larger than 387 bytes to be included in an index definition

Page Size Maximum Key Size

2 kilobytes 387 bytes

4 kilobytes 796 bytes

8 kilobytes 1615 bytes

12 kilobytes 2435 bytes

16 kilobytes 3245 bytes

In addition to aiding the porting process wider indexes have satisfied requirements for Unicode data as well as provide performance gains by reducing B-Tree index traversal costs since indexing can be built with more items on an index page and produce fewer levels

Index fragmentation

Just as Oracle and Informix support table fragmentation or partitioning in Oracle both support index fragmentation as well See the Table fragmentation section above for more information regarding Informix table fragmentation and Oracle table partitioning Oracle indexes that are partitioned in the same manner as the table they are indexing are referred to as local indexes Informix refers to these as attached indexes Oracle indexes that span partitions are known as global indexes Informix refers to these as detached indexes Informix detached indexes may also refer to indexes that do not follow the same fragmentation scheme as the table they are indexing Starting with Informix version 1110 indexes can be fragmented similarly to tables on a partition level

General index information

The Informix CLUSTER option should be used when appropriate This option orders the data within the table in the order the index requires It is important to note that the CLUSTER index is not maintained over time The primary factor determining the frequency of CLUSTER index rebuilds is the amount of DML performed against the table Frequent INSERTS UPDATES and DELETES make it necessary to closely monitor CLUSTER indexes There is only one clustered index per table since a tablersquos data can only be stored in one order Oraclersquos INITRANS and PCTFREE functionality is similar to the Informix index FILLFACTOR option of the CREATE INDEX statement or the FILLFACTOR configuration parameter in the ONCONFIG file In either case the functionality is handled by Informixrsquos engine once it is set and can be removed from the application FILLFACTOR specifies the degree of index-page

IBM Software Group IBM Information Management

Version 16 32

compactness A low value provides room for growth in the index A high value compacts the index If an index is fully compacted (100 percent) any new inserts result in splitting nodes The setting on the CREATE INDEX statement overrides the ONCONFIG file value The FILLFACTOR default value for both the CREATE INDEX statement as well as the ONCONFIG is 90 Informix has no support for bitmap indexes

Views Oraclersquos CREATE VIEW statement contains three options FORCE NO FORCE and WITH READ ONLY FORCE creates the view regardless of whether the views base tables exist or the owner of the schema containing the view has privileges on them NO FORCE creates the view only if the base tables exist and the owner of the schema containing the view has privileges on them WITH READ ONLY specifies that no deletes inserts or updates can be performed through the view These options must be removed from the Informix CREATE VIEW statements Because a view is not really a table it cannot be indexed and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE The columns of a view cannot be renamed with RENAME COLUMN To change anything about the definition of a view you must drop the view and re-create it Because it must be merged with the userrsquos query the SELECT statement on which a view is based cannot contain any of the following clauses

INTO TEMP The userrsquos query might contain INTO TEMP if the view also contains it the data would not know where to go

UNION The userrsquos query might contain UNION No meaning has been defined for nested

UNION clauses

ORDER BY The userrsquos query might contain ORDER BY If the view also contains it the choice of columns or sort directions could be in conflict

Stored procedures and triggers The ways stored procedures and triggers are created differ between Oracle and Informix Oracle allows a REPLACE clause in the CREATE statement to handle situations when the object already exists Informix does not support the REPLACE option Instead a DROP PROCEDURE or DROP TRIGGER statement must precede the CREATE PROCEDURE or CREATE TRIGGER statement respectively to handle the situation when the object already exists It should be noted a DROP statement will generate an error when the object does not exist If it is run interactively within the DBACCESS user interface the DROP statement error will terminate processing If it is run using script execution using DBACCESS at the command line processing will continue To run DBACCESS from the command line type

dbaccess db_name

To run the file containing the create statements from the command line type dbaccess db_name sql_file_name

Informix introduced an IF EXISTS clause to most of the CREATE and DROP statements at 117 but the logic is different from Oraclersquos OR REPLACE clause For example these statements

IBM Software Group IBM Information Management

Version 16 33

DROP PROCEDURE IF EXISTS hellip

CREATE PROCEDURE hellip

are logically the same as this Oracle statement

CREATE OR REPLACE PROCEDURE hellip

So it is possible to achieve the same result but not necessarily the same number of statements

Oracle extensions The Oracle CLUSTER option in CREATE statements should be removed These are not to be confused with Informix CLUSTER index statements (See Indexes section above) An Oracle cluster is a database schema object that contains one or more tables that all have one or more columns in common Rows of one or more tables that share the same value in these common columns are physically stored together within the database Removing this Oracle feature will not affect the application Other non-Informix DDL statements like CREATE DATAFILE CREATE CONTROLFILE CREATE ROLLBACK SEGMENT CREATE SNAPSHOT CREATE DATABASE and CREATE DATABASE LINK must be removed or changed (in the case of the CREATE DATABASE statement) The Oracle CREATE PROFILE statement must be removed An Oracle profile is a set of limits on database resources Profiles can be used to limit the database resources available to a user for a single SQL statement or a single session

IBM Software Group IBM Information Management

Version 16 34

C H A P T E R 4 Data Manipulation Language

SQL

Labels using keywords

Oracle displays labels in SQL statements that are Informix reserved words such as UNITS YEAR MONTH DAY HOUR and so on must be converted by using the Informix AS clause between the column name and the display label Otherwise syntactic ambiguities will cause errors

Inequality operations

In addition to the Informix supported ldquonot equal tordquo symbols ldquoltgtrdquo and ldquo=rdquo Oracle supports the symbol ldquo^=rdquo All occurrences of ^= must be replaced with one of the Informix supported symbols

Selects

Queries are executed based on how the optimizer determines the best path to the data Oracle and Informix developed their own query optimizers with their proprietary methods and rules A query that looks exactly the same in both environments may run differently in each following a different path and executing faster or slower Therefore every query in the ported application should be tested for performance regardless of whether a query had to be converted Furthermore Oracle supports optimizer hints within a SELECT statement Prior to IDS 73 and Informix Dynamic Server 92 Informix did not allow optimizer hints See the Optimizer Directives subsection below for more information on porting Oraclersquos optimizer hints to Informixrsquos optimizer directives

Optimizer directives

Informix offers optimizer directives similar to Oraclersquos optimizer hints This feature provides the query developer the flexibility to direct the optimizer to follow specific paths rather than choosing a plan through its analysis A query is processed in two steps First it is optimized and compiled to product a query plan Secondly it is executed to produce a result Optimizer directives are a method for influencing the choice of the optimizer in the creation of the plan

IBM Software Group IBM Information Management

Version 16 35

Optimizer directives address the following key issues

Reduced time for correcting performance problems Rewriting queries can be very time consuming and this allows you to have a quick way to alter a plan

Competitive pressure Users accustomed to this function were looking for it in Informix

Product development tuning This allows product development to alter plans dynamically rather than through code changes to evaluate the effect of different optimization techniques

The syntax and behavior of Informixrsquos implementation is compatible with Oraclersquos optimizer hints which eases the porting of applications from Oracle to Informix Directives are written as a comment whose first character is a lsquo+rsquo (plus sign) An example is

select + ORDERED AVOID_FULL(e) empname deptno

from employee e department d

where edept_no = ddept_no

This above example specifies that the tables should be joined in the order specified in the query and that the employee table (e) should NOT be accessed with a full table scan The Informix implementation differentiates itself significantly from Oraclersquos in one way Informix supports the notion of negative directives whereas Oracle only supports direct hints A directive that tells the optimizer what to avoid rather than what to choose is unique to Informix The query result can be realized by writing a directive to avoid certain actions known to cause performance issues but allow any new indexes or table attributes to be explored by the optimizer as they are added over the life of the table and query This allows a DBA to continue to add indexes to tables and not have to rewrite directives Additionally Informix supports full recognition of directives with SET EXPLAIN output Informix will highlight semantic and syntactic errors which Oracle does not Optimizer directives support control in the following areas of the optimization process

Access methods Index versus scans

Join Methods Forcing hash joins nested loop joins

Join Order Specify which order the tables are joined

Goal Specify first rows or all rows (response time versus throughput) See the Informix Guide to SQL Syntax or Reference for more information

External optimizer directives

External optimizer directives give the DBA the ability to specify query directives and save them in the database These directives are applied automatically to subsequent instances of the same query The SAVE EXTERNAL DIRECTIVES statement associates one or more optimizer directives with a query and stores a record of this association in the sysdirectives system catalog table for subsequent use with queries that match the specified query string The query string must be an exact match that includes case and white space positioning This statement establishes an association between the list of optimizer directives and the text of a query but it does not execute the specified query Only the DBA or user informix can execute SAVE EXTERNAL DIRECTIVES This associates AVOID_INDEX and FULL directives with the specified query

SAVE EXTERNAL DIRECTIVES

+ AVOID_INDEX (table1 index1) + FULL(table1)

ACTIVE FOR

SELECT col1 col2 FROM table1 table2

IBM Software Group IBM Information Management

Version 16 36

WHERE table1col1 = table2col1

These directives are applied automatically to subsequent instances of the same query You must include one of the ACTIVE INACTIVE or TEST ONLY keyword options to enable disable or restrict the scope of external directives When external directives are enabled and the sysdirectives system catalog table is not empty the database server compares every query with the query text of every ACTIVE external directive and for queries executed by the DBA or user informix with every TEST ONLY external directive External directives are ignored if the EXT_DIRECTIVES parameter is set to 0 in the ONCONFIG file In addition the client system can disable this feature for its current session by setting the IFX_EXTDIRECTIVES environment variable to 0 If an external directive has been applied to a query output from the SET EXPLAIN statement indicates ldquoEXTERNAL DIRECTIVES IN EFFECTrdquo for that query Any inline directive is ignored by the optimizer when the external directives are applied to a query that matches the SELECT statement Like inline optimizer directives that are embedded within a query external directives can improve performance in some queries for which the default behavior of the query optimizer is not satisfactory Unlike inline directives external directives can be applied without revising or recompiling existing applications

Inserts

Informix does not support Oraclersquos INSERT with SELECT statement utilizing an UNION clause (although a view with an UNION clause can be referenced resulting in an UNION operation) Additionally Informix does not support an INSERT statement with a VALUE clause with SELECT statements The SELECT statement within a VALUE clause can be rewritten by omitting the VALUE clause and performing an INSERT INTO table_name SELECT hellip FROM other_table_name

Temporary tables

Informix and Oracle implemented the concept of temporary tables differently Oracle implements temporary tables as a work area during batch data loads Informix implements temporary tables just like regular database tables These temporary tables can be created manipulated and dropped only within a session such as stored procedures and ESQL programs Once the session ends any remaining temporary tables are automatically dropped Temporary tables can give an application extra functionality however their use should be limited if reducing database extensions to increase database independence within an application is a priority

Outer joins

Both Oracle (starting with Oracle 9i) and Informix support ANSI standard syntax for outer join specification The syntax for left and right outer join using the plus sign (+) in the WHERE clause is only supported for backward compatibility however it is still in existence The use of ANSI outer join syntax is recommended The Oracle outer join syntax + (placed after the column which has values not matching the corresponding column in the joined table) can be replaced with the Informix equivalent OUTER The OUTER keyword is placed within the SELECT statement before the name of the subservient table Unlike Oracle in Informix multiple outer joins per SELECT statement are allowed grouped with parentheses

Sorts

In Oracle sorts NULL values are considered the highest value and are therefore ordered last in ascending sorts Informix sorts with NULLS as the lowest value ordering them first in ascending sorts First it must be determined whether this sorting difference will affect the outcome enough to warrant a work around In most cases it will not If it does then a stored procedure can be

IBM Software Group IBM Information Management

Version 16 37

written to evaluate whether a column is NULL and if so replace it with a high value so that it will sort last Once the application receives the results it must replace the high values with NULL if the column is going to be displayed or manipulated

Exceptions

Error handling using hard coded Oracle SQL codes must be replaced with the corresponding Informix SQL codes

Correlation names

Informix does not support correlation names with aliases on the main table of an UPDATE or DELETE statement Such cases must be converted For example

Oracle UPDATE customer C

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE Ccreate_date lt= Zeffective_date)

Informix UPDATE customer

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE customercreate_date lt= Zeffective_date)

-and-

Oracle DELETE customer C

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND Cstate = Tstate )

Informix DELETE customer

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND customerstate = Tstate )

Note that Informix allows correlation names with aliases on tables other than the updated or deleted table

Aliases

Unlike Oracle in Informix if an alias is used in the FROM clause of a SELECT statement it must also be used in the SELECT list and WHERE clauses The original table name should be replaced with the alias wherever aliases and original names are used together within a SELECT statement in an Oracle application

Hierarchical queries

Informix does not allow query results to be organized hierarchically in a B-tree fashion Oracle does allow it by using the clauses START WITHhellip and CONNECT BY PRIOR in the SQL

IBM Software Group IBM Information Management

Version 16 38

statement In Oracle if a table contains hierarchical data a bill of materials for example rows can be selected in a hierarchical order using the following clauses START WITH

The START WITH clause identifies the row(s) to be used as the root(s) of a hierarchical query This clause specifies a condition that the root(s) must satisfy If this clause is omitted Oracle uses all rows in the table as root rows A START WITH condition can contain a subquery

CONNECT BY

The CONNECT BY clause specifies the relationship between parent and child rows in a hierarchical query This clause contains a condition that defines this relationship The part of the condition containing the PRIOR operator must have one of the following forms

PRIOR expression comparison_operator expression -or- expression comparison_operator PRIOR expression

To find the children of a parent row Oracle first evaluates the PRIOR expression to identify the parent row(s) and the other expression for each row in the table Rows for which the other expression is true are the children of the parent The CONNECT BY clause can contain other conditions to further filter the rows selected by the query

WHERE

The WHERE clause can restrict the rows returned by the query without affecting other rows of the hierarchy

Oracle uses the information from each of the clauses mentioned above to form the hierarchy using the following steps

1 Oracle selects the root row(s) of the hierarchy These are the rows that satisfy the condition of the START WITH clause

2 Oracle selects the child rows of each root row Each child row must satisfy the condition of the CONNECT BY clause with respect to one of the root rows

3 Oracle selects successive generations of child rows Oracle first selects the children of the rows returned in step 2 and then the children of those children and so on Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row

4 If the query contains a WHERE clause Oracle removes all rows from the hierarchy that do not satisfy the condition of the WHERE clause Oracle evaluates the WHERE condition for each row individually after the row has been fetched rather than only fetching rows that satisfy the WHERE condition

5 Oracle returns the rows in the order of an in-order or left-root-right binary tree traversal

IBM Software Group IBM Information Management

Version 16 39

For example the following SQL statement returns the data in the adjacent table in hierarchical order The root row is defined to be the employee whose job is lsquoPRESIDENTrsquo The child rows of a parent row are defined to be those rows whose manager number is the employee number of the parent row

SELECT ename empno mgr job FROM emp START WITH job = lsquoPRESIDENTrsquo CONNECT BY PRIOR empno = mgr

To duplicate this hierarchical functionality in Informix stored procedures or functions can be written requiring intensive use of cursors and program arrays Informix offers the choice of creating and using a User Defined Routine or ldquoUDRrdquo See User Defined Routines section below Use of Informix global arrays will help considerably To maximize read processing at the expense of insert processing another method is to break the table into two tables one containing the data and the other containing the relationship (foreign keys) between each parent and child A parent row would have an entry in the relationship table for each of its children grandchildren great grandchildren and so on The opposite is true where a child row would have an entry in the relationship table for its parent grandparent great grandparent and so on

Truncate

Informix supports the TRUNCATE statement for deleting all active data rows from a table and associated indexes When using Informixrsquos TRUNCATE you also have the option of releasing the storage space that was occupied by the rows and index extents or keeping the space allocated to be used as the table is repopulated with new data

TRUNCATE [TABLE] table [ [ DROP | REUSE ] STORAGE ]

You may use the commandrsquos simplest usage

TRUNCATE my_table

In the example above the TRUNCATE statement drops all the data for the table and keeps only the initial extents There is a minor difference from Oracle syntax as Informix does not require the keyword TABLE Another example

TRUNCATE my_table REUSE STORAGE

ENAME EMPNO MGR JOB

KING 7839 PRESIDENT

JONES 7566 7839 MANAGER

SCOTT 7788 7566 ANALYST

ADAMS 7876 7788 CLERK

FORD 7902 7566 ANALYST

SMITH 7369 7902 CLERK

BLAKE 7698 7839 MANAGER

ALLEN 7499 7698 SALESMAN

WARD 7521 7698 SALESMAN

MARTIN 7654 7698 SALESMAN

TURNER 7844 7698 SALESMAN

JAMES 7900 7698 CLERK

CLARK 7782 7839 MANAGER

MILLER 7934 7782 CLERK

IBM Software Group IBM Information Management

Version 16 40

This example drops all the data for the table but retains all the space allocated The permissions needed for TRUNCATE TABLE depend on the existence of DELETE triggers on the table For tables with DELETE triggers ALTER permission on the table is required and RESOURCE or DBA privileges because the DELETE triggers will be bypassed For tables without DELETE triggers you need DELETE permission on the table and CONNECT privilege to the database While Oracle does not provide rollback Informix does permit TRUNCATE TABLE to execute within a transaction When you rollback a TRUNCATE statement no rows are removed from the table and the storage extents that hold the data rows and index pages continue to be allocated to the table In a database that supports transaction logging only the COMMIT WORK or ROLLBACK WORK statement is valid after the TRUNCATE statement within a transaction Any other statement will generate an error The TRUNCATE statement does not reset the serial value of SERIAL or SERIAL8 columns To reset the counter of a serial column you must do so explicitly by using the MODIFY clause of the ALTER TABLE statement either before or after you execute the TRUNCATE statement After the TRUNCATE statement successfully executes Informix automatically updates the statistics and distributions for the table and for its indexes in the system catalog to show no rows in the table nor in its dbspace partitions It is not necessary to run the UPDATE STATISTICS statement immediately after you commit the TRUNCATE statement

Host variables Host variable formats should not change during the porting process Instead data types should be converted in a manner to preserve the column and host variablersquos formats However there are times when the database schema changes in a way where the host variable format must change Any column converted to a different format in Informix than that of Oracle requires that its corresponding host variable format be changed to be consistent Alternatively if an Oracle format such as date and numeric variables is not directly supported in Informix then the conversion may require some format processing before or after the SQL statement For example the Oracle function TO_CHAR is used to format both date and numerical values A similar function or at least two functions one to handle date data types and another to handle numeric data types can be declared and used in the Informix application Informix provides two built-in functions TO_DATE which converts a character string to a DATETIME variable and TO_CHAR which converts a DATETIME variable to a character string When converting variables an optional formatting string is allowed which determines how the string is displayed (full day names partial day names full months month number and so on) There is also a function ifx_to_gl_datetime() which takes an Oracle date format and returns the corresponding Informix date format This function is supplied in genlib and is for use in ESQL programs to ease migration efforts from Oracle The syntax is as follows

TO_CHAR (source_date fmt) Returns a character string containing the date specified in source_date in the format specified by fmt if one is provided If fmt is missing the function will use the default date format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

TO_DATE (source_string fmt) Evaluates source_string as a date according to the

format fmt If fmt is missing the function will use the

IBM Software Group IBM Information Management

Version 16 41

default format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

These functions are mainly useful for simplifying migration from Oracle to Informix but are also useful for performing advanced searches on DATETIME data types and for better output presentation

Date and time functions Informix version now has built-in support for most of Oraclersquos date functions so it will not be necessary to modify or replace Oraclersquos SYSDATE or ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat)

SYSDATE

IDS 1110 will support the SYSDATE operator which returns a single value representing the current date and time from the operating system clock SYSDATE is identical to the Informixrsquos CURRENT operator except that the default precision of SYSDATE is YEAR TO FRACTION(5) while the default precision of CURRENT is YEAR TO FRACTION(3) On Windows platforms that do not support a seconds scale greater than FRACTION(3) SYSDATE is effectively a synonym for the CURRENT operator In addition to SYSDATE Informix version 1110 has support for Oraclersquos date functions ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat) Depending on the whether or not the Oracle date_format argument is supported by Informix TO_CHAR(date char_format) and TO_DATE(character_string date_format) may have to be converted to Informix date processing Date processing may be required because the Oracle application may format the date in many different ways unsupported by Informix The formats used in the Oracle functions TO_CHAR TO_NUMBER and TO_DATE are illustrated below These formats should be replaced with Informix formats wherever possible format processing functions or stored procedures written to duplicate the Oracle functionality Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

Number formats

Element Example Description 9 9999 Return value with the specified number of digits with a leading

space if positive Return value with the specified number of digits with a leading minus if negative Leading zeros are blank except for a zero value which returns a zero for the integer part of the fixed-point number

0 09999990 Return leading zeros Return trailing zeros $ $9999 Return value with a leading dollar sign B B9999 Return blanks for the integer part of a fixed-point number

when the integer part is zero (suppress leading zeros regardless of whether zeros are used in the format model ie B00999 )

MI 9999MI Return negative value with a trailing minus sign ldquo-ldquo Return positive value with a trailing blank

S S9999999 Return negative value with a leading minus sign ldquo-ldquo Return

IBM Software Group IBM Information Management

Version 16 42

Element Example Description S positive value with a leading plus sign ldquo+rdquo Return negative

value with a trailing minus sign ldquo-ldquo Return positive value with a trailing plus sign ldquo+rdquo

PR 9999PR Return negative value in ltangle bracketsgt Return positive value with a leading and trailing blank

D 99D99 Return a decimal point ldquordquo In the specified position G 9G999 Return a group separator in the specified position C C999 Return the ISO currency symbol in the specified position L L999 Return the local currency symbol in the specified position 9999 Return a comma in the specified position 9999 Return a decimal point ldquordquo In the specified position V 999V99 Return a value multiplied by 10

n (and if necessary round it

up) where n is the number of ldquo9rdquos after the ldquoVrdquo EEEE 99EEEE Return a value in scientific notation RNrn RN Return a value as Roman numerals in uppercase Return a

value as Roman numerals in lowercase Value can be an integer between 1 and 3999

FM FM909 Return a value with no leading or trailing blanks

Date formats

Element Meaning -rdquotextrdquo Punctuation and quoted text is reproduced in the result AD or AD AD indicator with or without periods AM or AM Meridian indicator with or without periods BC or BC BC indicator with or without periods CC or SCC Century ldquoSrdquo prefixes BC dates with ldquo-ldquo D Day of week (1-7) DAY Name of day padded with blanks to length of 9 characters DD Day of month (1-31) DDD Day of year (1-366) DY Abbreviated name of day IW Week of year (1-52 or 1-53) based on the ISO standard IYY or IY or I Last 3 2 or 1 digit(s) of ISO year IYYY 4-digit year based on the ISO standard HH or HH12 Hour of day (1-12) HH24 Hour of day (0-23) J Julian day the number of days since January 1 4712 BC Number

specified with lsquoJrsquo must be integers MI Minute (0-59) MM Month (01-12 JAN = 01) MONTH Name of month padded with blanks to length of 9 characters MON Abbreviated name of month RM Roman numeral month (I-XII JAN = I) Q Quarter of year (1 2 3 4 JAN-MAR = 1) RR Last 2 digits of year see below for years in other centuries WW Week of year (1-53) where week 1 starts on the first day of the year

and continues to the seventh day of the year W Week of month (1-5) where week 1 starts on the first day of the

month and ends on the seventh PM or PM Meridian indicator with and without periods SS Second (0-59) SSSSS Seconds past midnight (0-86399) YYYY Year with comma in the ldquordquo position YEAR or SYEAR Year spelled out ldquoSrdquo prefixes BC dates with ldquo-ldquo YYYY or SYYYY 4-digit year ldquoSrdquo prefixes BC dates with ldquo-ldquo

IBM Software Group IBM Information Management

Version 16 43

YYY or YY or Y Last 3 2 or 1 digit(s) of year

The RR date format element

The RR date format element is similar to the YY date format element but it provides additional flexibility for storing date values in other centuries The RR date format element allows storing the century even though only two digits are entered for the year The table below illustrates how the year is stored based on only two digits

If the year is entered as

0 ndash 49 50 - 99 If the last two digits of the

0 - 49 The return date is in the current century

The return date is in the century before the current one

current year are

50 - 99 The return date is in the century after the current one

The return date is in the current century

User-defined routines User-defined data types user defined behaviors and user defined access methods add rich functionality to Informix A user-defined routine (UDR) can be developed in C Java or Informix SPL language to vastly extend the capabilities of the database Porting applications to Informix gives the option to create UDRs for aggregate and mathematical functions or to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or you can rename an Informix function to the corresponding Oracle function name

Compatible SQL Functions Informix Dynamic Server version 1110 has added support for a number of built-in SQL functions to ease a migration effort These new functions which perform common operations and data manipulation provide compatibility with Oracle routines thus simplifying the migration of applications that have been developed for an Oracle database

Date and time functions ROUND TRUNC ADD_MONTHS LAST_DAY NEXT_DAY MONTHS_BETWEEN SYSDATE

Conversion functions ASCII TO_CHAR TO_NUMBER

String manipulation LTRIM RTRIM

Number manipulation ROUND TRUNC CEIL FLOOR POWER

Bit manipulation BITAND BITOR BITXOR BITNOT BITANDNOT

Others NULLIF FORMAT_UNITS These functions are documented with examples in the IBM Informix Guide to SQL Syntax

Aggregate functions Like Oracle the result returned by an Informix aggregate function is NULL if all of the column values are NULL with the exception of COUNT which returns 0 (zero) Like Oracle Informix aggregate functions cannot be used in a WHERE clause unless it is on a corresponding column originating from a parent query and the WHERE clause is within a sub-query that is within a HAVING clause or the aggregate function is contained within a sub-query Unlike Oracle in Informix the argument of an aggregate function cannot be another aggregate function Informix supports the SELECT COUNT (column_name) hellip statement where the number of rows containing non-null values in the specified column is returned

IBM Software Group IBM Information Management

Version 16 44

The Oracle aggregate functions STDDEV and VARIANCE are supported however the Informix standard deviation routine is named STDEV thus all references to Oraclersquos STDDEV must be changed to match Informixrsquos STDEV Informix does not support Oraclersquos greatest lower boundary (GLB ) or least upper boundary (LUB) Therefore UDRs must be written to provide equivalent functionality Informix allows users to define their own aggregate functions known as user-defined aggregates (UDA) This extension of existing aggregates can be used for new data types as well as the definition of new aggregates In Informix TEXT and BYTE columns cannot be used in aggregate functions such as COUNT AVG MAX MIN and SUM

Mathematical functions Informix does not support all of Oraclersquos mathematical functions such as SIGN COSH SINH and TANH Therefore functions or UDRs must be written in the Informix application to provide equivalent functionality In Informix the rounding factor within the ROUND function must be a value from -32 to 32 This limitation has seldom been encountered as a migration issue

String functions

LENGTH

Oraclersquos LENGTH function will return different values than Informix for strings stored in CHAR data types The numeric return value representing the string length returned by Oracle will include all trailing spaces Whereas Informixrsquos LENGTH function will ignore trailing blanks regardless of data type For example for the two CHAR strings ldquoBOBrdquo and ldquoBOB ldquo Oraclersquos LENGTH function will return different values for each string 3 and 5 respectively Whereas Informixrsquos LENGTH function will ignore trailing blanks and return the value 3 for both When the input string is NULL both database functions will return a NULL

LTRIM and RTRIM

The SQL Compatibility features of Informx has support for LTRIM and RTRIM and will return identical values to that of Oracle No modifications will be necessary to SQL statements utilizing these functions

Oracle Extensions

Informix does not support all of Oraclersquos string functions such as CHR INSTR SOUNDEX and TRANSLATE Therefore corresponding user-defined routines or UDRs (ie functions or stored procedures) must be written in the Informix application to provide equivalent functionality Please note that the VERITY and EXCALIBUR Datablades included with Informix will work with Oraclersquos string function SOUNDEX

Other Oracle Functions Informix does not support the following Oracle functions Therefore corresponding functions must be written in the Informix application to provide equivalent functionality Alternatives to some of the more common Oracle functions follow this list

CHARTOROWID CONVERT DUMP GREATEST GREATEST_LB

IBM Software Group IBM Information Management

Version 16 45

HEXTORAW LEAST LEAST_UB RAWTOHEX ROWIDTOCHAR TO_LABEL TO_MULTI_BYTE TO_SINGLE_BYTE UID USERENV(OSDBA LABEL LANGUAGE TERMINAL SESSIONID ENTRYID) VSIZE

Macros Oracle contains macros sometimes referred to as language constructs which can determine the status of an object Informix does not support Oraclersquos macros These macros must be removed from the code and the associated logic should be implemented with equivalent Informix logic where applicable

ISOPEN and NOT FOUND

The macro cursor_nameISOPEN returns a Boolean value to indicate whether the cursor is open and cursor_nameNOTFOUND indicates whether there are any more rows yet to be fetched from the cursor cursor_name These macros used in condition statements are followed by some logic to handle the true andor false conditions In the case of ISOPEN this macro and its associated logic can just be omitted since the FOREACH loop processing does not explicitly open a cursor and therefore the condition cannot be checked In the case of NOTFOUND this macro should be omitted and its associated logic converted to Informix logic within an Informix FOREACH loop

ROWTYPE

The Oracle macro prefixROWTYPE is used in the declarative section as a data type to declare variables similar to the structure construct of C or RECORD of INFORMIX The prefix can be either a table name or another structure name Structure names ultimately refer back to a table name This macro may be replaced with the Informix statement LIKE table_name The construct LIKE table_name cannot be used in SPL Instead the construct DEFINE column1 LIKE table_namecolumn1 DEFINE column2 LIKE table_namecolumn2 and so on should be used to declare variables corresponding to all the columns of the table Then operations on the whole or part of the structure should be replaced with operations on single SPL variables

TYPE

The Oracle macro prefixTYPE is used in the declarative section as a data type to declare single variables The prefix is either a table_namecolumn_name or a structure_namevariable_name A structure_namevariable_name ultimately refers back to a table_namecolumn_name This macro can be replaced with the Informix statement LIKE table_namecolumn_name

Pseudo-columns Pseudo-columns are columns that exist in tables but are not displayed from a SELECT FROM table_name query Informix pseudo-columns are generally reserved for the enginersquos use Eliminating the use of such columns increases an applicationrsquos portability and eliminates the need for future modifications if the engine is ever modified to process the column differently or not at all

IBM Software Group IBM Information Management

Version 16 46

LEVEL

In Oracle for each row returned by a hierarchical query the pseudo-column LEVEL returns 1 for a root node 2 for a child of a root 3 for a child whose parent is at level 2 and so on A root node is the highest node within an inverted tree and therefore has no parent A child node is any non-root node A parent node is any node that has children A leaf node is any node without children To define a hierarchical relationship in a query you must use the START WITH and CONNECT BY clauses Informix does not support the LEVEL clause See the Hierarchical Queries subsection in the SQL section in the ldquoData Manipulation Languagerdquo chapter for more information on how to process these queries

ROWID

Oraclersquos ROWID pseudo-column returns the rows address for each row in the database ROWID values contain the following information necessary to locate a row

Which data block in the data file

Which row in the data block (first row is 0)

Which data file (first file is 1)

Usually a ROWID value uniquely identifies a row in the database However rows in different tables that are stored together in the same cluster can have the same ROWID Values of the ROWID pseudo-column have the data type ROWID ROWID values have several important uses

They are the fastest way to access a single row

They can show you how a tables rows are stored

They are unique identifiers for rows in a table

A ROWID does not change during the lifetime of its row However you should not use ROWID as a tables primary key If a row is deleted and re-inserted its ROWID may change even when using the export and import utilities If a row is deleted Oracle may re-assign its ROWID to a new row inserted later Although you can use the ROWID pseudo-column in the SELECT and WHERE clauses of a query these pseudo-column values are not actually stored in the database The value of a ROWID pseudo-column cannot be inserted updated or deleted For example the following Oracle statement selects the address of all rows that contain data for employees in department 20

SELECT ROWID ename FROM emp WHERE deptno = 20

The equivalent pseudo-column in Informix is also known as ROWID and although the behavior is similar the data type is different from Oraclersquos See the ROWID subsection in the Data Types section in the chapter ldquoData definition languagerdquo for more information

ROWNUM

In Oracle for each row returned by a query the ROWNUM pseudo-column returns a number indicating the order in which Oracle selected the row from a table or set of joined rows The first row selected has a ROWNUM of 1 the second has 2 and so on ROWNUM can be used to limit the number of rows returned by a query as in this example to read 9 rows

SELECT

FROM emp

WHERE ROWNUM lt 10

ROWID ENAME 0000000F00000002 SMITH 0000000F00030002 JONES 0000000F00070002 SCOTT 0000000F000A0002 ADAMS 0000000F000C0002 FORD

IBM Software Group IBM Information Management

Version 16 47

You can also use ROWNUM to assign unique values to each row of a table as in this example

UPDATE tabx

SET col1 = ROWNUM

Oracle assigns a ROWNUM value to each row as it is retrieved before the rows are sorted by an ORDER BY clause Therefore the final order of the rows is in ORDER BY order not in ROWNUM order An ORDER BY clause does not affect the ROWNUM values except in the case where the ORDER BY clause causes Oracle to use an index In that case the ROWNUM values are set in the order the rows are retrieved using the index and hence in ORDER BY order This order is different than if the rows were retrieved without the index So in this case the ORDER BY can affect the ROWNUM values Conditions which test for ROWNUM values greater than zero are always false For example this query returns no rows

SELECT FROM employee WHERE ROWNUM gt 1

The first row fetched is assigned a ROWNUM of 1 thus making the condition false The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 making the condition false All rows subsequently fail to satisfy the condition so no rows are returned Although there is no ROWNUM equivalent in Informix there are solutions Beginning with IDS 73 and in Informix Dynamic Server 2000 Informix provides a feature which allows the user to limit the results of a query to the first N rows This was implemented for TPC-D compliance and to support ldquorankrdquo queries Rank queries can be assembled by using FIRST N with the ORDER BY clause Informix will return the top N rows according to some ordering criteria Therefore the following Oracle SELECT utilizing ROWNUM

SELECT FROM emp WHERE ROWNUM lt 10

can be ported to Informix as follows

SELECT FIRST 9 FROM emp

Informix does not support SELECT FIRST N in complex cases as the following

Sub-queries (SELECT within a SELECT)

View definitions (Cannot be used by a SELECT statement which references a view)

UNION queries The behavior of SELECT FIRST N depends on the presence of an ORDER BY clause If no order by clause is specified the first N rows returned may be in any order Examples are as follows

find 10 highest paid employees

SELECT FIRST 10 name salary

FROM emp

ORDER BY salary

find 10 highest salary values

SELECT FIRST 10 DISTINCT salary

FROM emp

ORDER BY salary

IBM Software Group IBM Information Management

Version 16 48

Informix supports column names of ldquofirstrdquo Thus without a positive integer following the word ldquofirstrdquo the token is parsed as a column name rather than a keyword The value of N may be between 1 and (2

31-1)

When ROWNUM is used in a WHERE clause the same results can be obtained through the use of the FIRST N and SKIP clauses but if ROWNUM is used in the select list the solution is a little more complicated Simply stated you can construct a query where the ROWNUM column in any row is the count of the rows that came before This involves creating a correlated subquery where the subquery contains a self-join This can be done for any table or set of tables which has a unique key defined on it Here is an example using the customer table of the stores7 database

select

counterrownum

basecustomer_num

basefname

baselname

from

-- There can be more than one table here and the result

-- set should thought of as a table (just not a base table)

-- The result table has to be joined to itself in the

-- subquery so if there are multiple tables in this FROM

-- clause the expansion can get messy You have to have a

-- set of columns that uniquely identify each row in the

-- result table and join across them ROWID would

-- likely work if the table is not fragmented but if it is

-- there is no guarantee the final results would be accurate

-- because ROWID is not guaranteed to be unique across

-- fragments

customer base

(select

count() as rownum

acustomer_num -- any unique key possibly multiple

-- columns

from

customer a

customer b

where

-- This is where the rownum is determined the relationship

-- here has to match the outer order-by where the rows

-- are sorted and has to create a unique sort order

--

-- Any columns to be ordered by go here

-- Also the unique key has to be used to keep rows

-- that do not have a unique sort order from being merged

(alname gt blname) -- example sorting by last name

or

(alname = blname and afname gt bfname)

-- sorting by fname where lname is equal

or

(alname = blname and afname = bfname

and acustomer_num gt= bcustomer_num)

-- sorting by unique key where all the

-- other sort columns are equal

-- The expansion above is logically the same as

-- alname || afname || to_char(acustomer_num) gt=

-- blname || bfname || to_char(bcustomer_num)

-- but it allows the server to utilize any indexes that

-- may exist

group by

-- unique key columns go here

IBM Software Group IBM Information Management

Version 16 49

acustomer_num

) counter

where

-- key columns in the base tables go here

basecustomer_num = countercustomer_num

-- if you want to limit on rownum it goes here

-- and rownum lt= 10

order by

counterrownum

If using ROWNUM as an assignment as in

UPDATE tabx

SET col1 = ROWNUM

The following Informix-ESQLC pseudo-code example would have to be used

int counter = 0

EXEC SQL declare c1 cursor for

SELECT col1 col2

INTO col1 col2

FROM table 1

WHERE col1 = XX

EXEC SQL open c1

while (SQLCODE == 0)

EXEC SQL fetch c1

counter++ Increment counter for each row

fetched

if (counter gt= 5)

break

logic

End if

End while

Update using cursors There are slight differences between the ways Informix and Oracle process cursors Unlike Oracle in Informix the WHERE CURRENT OF clause cannot be used to update tables in a SELECT statement joining multiple tables since the WHERE CURRENT OF clause requires a FOR UPDATE cursor and Informix does not support the FOR UPDATE clause in SELECT statements that join multiple tables Therefore in the multi-table join statements the Oracle options FOR UPDATE and WHERE CURRENT OF should be removed and the update of the rows should be done using a separate UPDATE statement in the same cursor loop

IBM Software Group IBM Information Management

Version 16 50

In Informix a commit or rollback statement closes all cursors open in a given transaction boundary See the Transaction Processing section in CHAPTER 5 Application Architecture for more information In situations where the intention is to commit or rollback without closing the cursor in other words where the commit or rollback is executed within a cursor fetch loop the cursor can be declared as a HOLD cursor This requires that a BEGIN WORK is issued before the cursor loop starts A HOLD cursor is not closed when a commit or rollback statement is issued In Informix the FOR UPDATE clause cannot be used when declaring a HOLD cursor Thus where an Oracle application updates a table from which it fetches data in the fetch loop or issues a commit work in the fetch loop it must be converted to Informix The cursor can be declared with HOLD and then an UPDATE statement can be issued without the WHERE CURRENT OF clause In order to uniquely identify the row to be updated in the table in other words in order to simulate the WHERE CURRENT OF clause the ROWID or unique primary key columns of the table(s) to be updated must also be fetched and the WHERE CURRENT OF clause can be replaced with WHERE ROWID = fetched rowid or WHERE unique primary key column(s) = fetched unique primary key column(s) A BEGIN WORK must follow immediately after a COMMIT WORK or ROLLBACK WORK in the fetch loops to simulate Oracle implied transaction boundaries These transaction control statements work for either Informix logged databases or Informix ANSI mode databases however ANSI mode database processing with these statements will set certain warning flags after executing the BEGIN WORK statement and continue processing without failure See the ANSI vs Non-ANSI subsection in the Databases section in the chapter ldquoData Manipulation Languagerdquo for more information

System tables References to Oracle system tables should be replaced with corresponding references to Informix system tables The information schema views provided by Informix can be used These views are created after the database is installed They are populated by data in the system catalog tables and are used for easier porting

Stored procedures Informix procedures and functions are considered to be user-defined routines (UDR) A UDR can be written in Informixrsquos Stored Procedure Language (SPL) or an external language such as C or Java A procedure is a routine written that does not return a value A function is a routine written that returns a single value a value with a complex data type or multiple values Informix SPL is an extension to Informix SQL and provides procedural flow control such as looping and branching A SPL routine is a generic term that includes both SPL procedures and SPL

functions You use SQL and SPL statements to write an SPL routine SPL statements can be used only inside the CREATE PROCEDURE CREATE PROCEDURE FROM CREATE FUNCTION and CREATE FUNCTION FROM statements SPL routines are parsed optimized and stored in the system catalog tables in executable format Like Oracle Informix stored procedures support input output and inputoutput parameters and can be used in SQL statements wherever expressions are allowed

Size limit

Informix stored procedures have a size limit of approximately 64K Oracle stored procedures greater than 64K in size can be broken into smaller Informix stored procedures communicating with each other as though they were one by passing and returning the necessary values

Parameter limit

IBM Software Group IBM Information Management

Version 16 51

Informix has a limit of 341 parameters for each stored procedure This limit also applies to UDRs written in the Java language UDRs written in the C language can have no more than 102 parameters You can define any number of SPL routine parameters but the total length of all parameters passed to an SPL routine must be less than 64 kilobytes No more than nine arguments to a UDR written in the Java language can be DECIMAL data types of SQL that the UDR declares as BigDecimal data types of the Java language Any C language UDR that returns an opaque data type must specify opaque_type in the var binary declaration of the C host variable

Packages

An Oracle package is a collection of functions procedures and variables that can be enabled and accessed as a unit There is no direct equivalent within Informix but there are ways of achieving similar capabilities Within Oracle a procedure within a package can be accessed through grammar such as package_nameprocedure_name If you create an owner or schema name within the Informix system the same as the package name then it will be easier to migrate calls to that procedure because the grammar is effectively the same although the meaning changes somewhat Using this practice a call to a migrated procedure would be ownerprocedure_name where the owner name is the same as the package name Translating package names as owner names is a way to maintain the scoping of the objects within the package Maintaining the aspect of being able to enable use of or upgrade the collection of package objects can be done by creating a datablade that contains all the objects that used to be part of the package Datablade routines can be procedures or functions written in Stored Procedure Language (SPL) C and Java In addition routines can be written in C++ on Windows platforms

Routines

Oraclersquos stored functions and stored procedures are similar in concept to Informixrsquos stored procedures Oraclersquos user defined database level functions such as stored functions stored procedures all need to be converted to Informix stored procedures using the Informix SPL C or Java Routines written in SPL have the advantage of being maintained and backed up with database backups Routines written in C are fast but are not automatically backed up when the database is and need to be compiled specifically for the operating system on which it will run Routines written in Java also not backed up by the DBMS itself but they are platform independent However probably as a result of having to convert between system memory where the objects have C structures and Java virtual machine memory where the objects have Java structures the performance of Java routines can be slow compared with the C equivalent All procedures written in an Oracle package body must be rewritten as separate Informix procedures When rewriting package bodies into separate procedures Oraclersquos variable declarations can be replaced at the package level (global) with Informixrsquos global variables The Informix global variables must be defined in the first stored procedure of the logical group

Exceptions

The method of handling exceptions is different between Informix and Oracle Oracle has many predefined and user defined exception labels such as CURSOR_ALREADY_OPEN NO_DATA_FOUND ZERO_DIVIDE and so on The labels can be used in the logic to identify errors Only one exception check is allowed per BEGIN and END block using the EXCEPTION construct and it is normally placed just before the END statement Informix also supports predefined and user defined exceptions however they are represented numerically not with labels In Informix all the exceptions checked in the stored procedure control blocks delimited with BEGIN and END statements must be declared explicitly at the top of each

IBM Software Group IBM Information Management

Version 16 52

control block with the Informix EXCEPTION construct Therefore Oracle procedure code must be restructured to manipulate these exceptions In Oracle an exception can be raised globally and acted upon globally In Informix the scope of an exception mechanism is always restricted to the block in which it is located This leads to the addition of multiple Informix exception handling mechanisms for each Oracle exception raised as well as a redesign of the overall stored procedure to a more blocked format

Error handling

In Oracle errors are processed as part of a function call return value In Informix errors are retrieved as a separate function call that has multiple structures that have to be created in order to retrieve error and status The SQLCA structure is not fully available in Informix stored procedures It is not possible to check the SQLCODE variable in the stored procedure body Instead the function DBINFO can be used to extract the value of two members of the SQLCA structure sqlcasqlerrd1 and sqlcasqlerrd2 This function should be used inside the FOREACH construct while the cursor is open Once the cursor is closed the DBINFO function cannot return proper values The sqlcasqlerrd1 option returns different values depending on the type of SQL statement For INSERT statements if the table contains a serial column then the sqlcasqlerrd1 option will return the serial value of the last row inserted into the table For SELECT DELETE and UPDATE statements the sqlcasqlerrd1 option will return the number of rows processed by the query In these cases upon each pass through the FOREACH loop sqlcasqlerrd1 is the same value the number of rows the FOREACH loop will process The sqlcasqlerrd1 value can still be interrogated during each pass through the FOREACH loop The sqlcasqlerrd2 option returns the number of rows processed by a SELECT INSERT UPDATE DELETE or EXECUTE PROCEDURE statement It should not be interrogated until after the cursor has finished processing In other words within the FOREACH loop the sqlcasqlerrd2 value can be moved to a variable which is then interrogated outside of the FOREACH loop

Cursors

Unlike Informix in Oracle cursors can be global to a package In Informix Oraclersquos global cursors can be replaced with temporary tables A temporary table can be created and populated in place of where the cursor is opened The temporary table can then be processed the same way the cursor is processed Finally the temporary table should be dropped in place of where the cursor is closed Cursors are explicitly declared opened and fetched in Oracle stored procedures In Informix cursors do not need to be explicitly declared opened and fetched in stored procedures Instead Oracle stored procedure cursors can be replaced with Informixrsquos FOREACH construct The Oracle cursor name should be used in the FOREACH statement for example FOREACH cursor_name SELECT hellip END FOREACH In order to update a cursor row in Oracle the cursor must be declared with the FOR UPDATE clause In Informix if the SELECT statement in the FOREACH construct is not a multi-table join then each fetched row can be updated using the UPDATE lttable_namegt WHERE CURRENT OF ltcursor_namegt statement See the Update Using Cursors section in ldquoData Manipulation Languagerdquo for more information Informix does not support the SELECT FOR UPDATE statement in a stored procedure Therefore the SELECT FOR UPDATE clause cannot be used in the FOREACH construct

IBM Software Group IBM Information Management

Version 16 53

Variable declaration and assignment

Oracle allows implicit variable definitions within a FOR loop The variables are defined using an assignment operator and a column name For example

out_customer_name = customername

The variable out_customer_name is defined as the same type as the column name in the customer table Informix requires that all variables be defined at the beginning of each stored procedure control block For example

DEFINE out_customer_name LIKE customername

DEFINE counter INTEGER

Therefore Oraclersquos implicit variable declaration must be replaced with Informixrsquos explicit variable declaration before the control block Additionally assignment operations will need to be ported Oracle uses a colon and an equal sign (=) for assignment while Informix utilizes the LET keyword in combination with an equal sign (=) (ie LET var = 1) Therefore assignment statements must be modified with the LET keyword and an equal sign

Boolean

Oraclersquos BOOLEAN variable type can be replaced with Informixrsquos BOOLEAN data type

Binary data types

Binary data types are very different between Oracle and Informix In Oracle the binary type is defined as a type RAW and is explicitly defined with a maximum length as part of the declaration In Informix the binary type is defined as REFERENCES BYTE which deals only with pointers to BLOBs It implicitly defines a maximum length as part of the function call in which the pointer to the BLOB and maximum length (as used in the function call) was passed as values As a result the binary type cannot be assigned a binary value in a stored procedure nor can it be inserted into a table via the SQL INSERT statement in a stored procedure These operations that initialize a binary type must be performed outside of stored procedures

Dynamic SQL

Unlike Oracle Informix does not support dynamic SQL within the Stored Procedure Language In other words a statement such as SELECT variable_name FROM variable_name WHERE variable_name is not supported This kind of processing can be achieved in Informix within an embedded SQL program This requires that either the Oracle stored procedure be converted to an embedded SQL program or just the Dynamic SQL portion be placed in an embedded SQL program and then called from within the stored procedure The latter option will have performance implications since calling an embedded SQL program from a stored procedure requires an operating system call Another option is to use the Informix EXEC Bladelet The EXEC Bladelet consists of user-defined functions that take a SQL query as an argument execute it and return a result (the format of which varies depending on the function and the kind of query) The EXEC Bladelet functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries Further details can be found in Chapter 7 Using Bladelets

Compiler

Unlike Oracle the Informix compiler was developed with the concept that developers can create stored procedures independently of the database Therefore Informixrsquos stored procedure

IBM Software Group IBM Information Management

Version 16 54

compiler has a limited set of errors that it checks compared to Oraclersquos For example the Informix stored procedure compiler does not validate database object names such as table column and view names Therefore database object naming errors will occur at runtime not compile time Additionally the error messages generated from the compiler are not very specific Identifying a problem in a stored procedure may require breaking it apart and recompiling the pieces until the problem is found This may impact the time necessary to unit test the stored procedures

Triggers Oracle supports the use of multiple trigger events for example insert update and delete within the same trigger Informix only supports one trigger event per trigger In Informix the Oracle trigger body in this example must be copied into three different triggers each with only one event Informix triggers have some constraints Oraclersquos do not In Informix if a trigger is fired due to inserting a row into a table a trigger can only act on any rows or columns within that table using the EXECUTE PROCEDURE hellip INTO syntax Similarly if a trigger is fired due to updating a row then the trigger can only act on the column that caused the trigger to fire using the EXECUTE PROCEDURE hellip INTO syntax Like Oracle if a trigger is fired due to deleting a row there are no restrictions Prior to IDS 73 when a trigger was fired on an INSERTUPDATE action no modification could be done to the columns (in the row) which just fired the trigger The reentrant UPDATEINSERT triggers feature introduced with IDS 1110 enables users to update the triggering columns by using the EXECUTE PROCEDURE INTO syntax Additionally the feature enforce that this action will not cause any additional triggers to be fired (same or different trigger) causing a cascading of triggers and potentially an infinite loop The following example demonstrates how the reentrant UPDATEINSERT trigger feature is used

create table foo

(

x int default NULL

y int default NULL

z int default NULL

)

create procedure reentrant()

returning int

return 56

end procedure

create trigger reentrant_trigger insert on foo for each row

(

execute procedure reentrant() into z

)

insert into foo values

(

1

2

3

)

The following SELECT will result in the following returned data

select from foo

x y z

1 2 56

IBM Software Group IBM Information Management

Version 16 55

Oracle allows SQL statements logical statements and stored procedure calls within a trigger body Informix allows only SQL statements and stored procedure calls within a trigger body Oracle triggers containing logical statements must be converted to Informix by moving their contents into a stored procedure The stored procedure should then be executed from the trigger

Constraints Constraints in both Oracle and Informix can be enabled and disabled within an application transaction however there are behavioral differences In Oracle the application is always executing within a transaction In Informix transaction boundaries are explicitly declared and care should be taken to ensure that this functionality is performed within the boundaries of a transaction See the Transaction Processing section in CHAPTER 5 Application Architecture for more information The constraint syntax available in Informix is

SET CONSTRAINTSINDEXESTRIGGERS FOR table_name

ENABLED|DISABLED

SET CONSTRAINTS comma_separated_constraint_names

ENABLED|DISABLED

SET INDEXES comma_separated_index_names ENABLED|DISABLED

SET TRIGGERS comma_triggers_constraint_names ENABLED|DISABLED

SET CONSTRAINTS ALLconstraint_name IMMEDIATE|DEFERRED

The first four statements must be executed with DBA privileges if placed in the application Therefore care should be taken when using them Note that the last statement contains a DEFERRED clause This is the statement used if the users of the application do not have DBA privileges When the constraint is set with the DEFERRED clause the specified constraints are not checked until the transaction is committed If a constraint violation occurs while the transaction is being committed the transaction is rolled back

DUAL table Oraclersquos DUAL table is a system table with only one row containing one column named DUMMY This table is used to complete the syntax of an SQL statement that does not involve an existing table such as

A SELECT statement which assigns some constant value (which can only be derived in an SQL statement) to a host variable

SELECT TO_CHAR(SYSDATE) INTO date_var FROM DUAL

A SELECT statement which assigns a value of another variable to a variable

SELECT source_var INTO dest_var FROM DUAL

A SELECT statement which unions application host variable values with another SELECT statement to return a result containing a row of application variable values

SELECT col1 col2 col3 FROM table_name

UNION

SELECT host_var1 host_var2 host_var3 FROM DUAL

Converting Oraclersquos DUAL table functionality to Informix depends on the way it is used Converting statements that just assign constants is as simple as replacing the DUAL statement with an Informix assignment statement The solutions below apply to Informix versions prior to 11 At 11 and above the concept of a DUAL table as well as sysdate is supported

IBM Software Group IBM Information Management

Version 16 56

SELECT sysdate FROM sysmastersysdual

If you want a dual table in your local database then create the following synonym The sysmastersysdual table is much faster than a physical table in your database because it is an in- memory pseudo table

CREATE SYNONYM dual FOR sysmastersysdual

If you are restricted to using a version of Informix prior to 11 then the following solutions can be used A dummy table can be created to mimic the behavior of simple SELECT INTO statements used to assign values to variables

CREATE TABLE dual (dummy VARCHAR(1))

INSERT INTO dual VALUES(lsquoXrsquo)

An alternate solution to widespread use of the DUAL table could be creating a permanent view that is generally accessible

CREATE VIEW dual (d) as SELECT X

FROM systables WHERE tabid = 1

The exact definition could be used or modified as needed but this would solve the problem of having DUAL be permanent usable by anyone and not modifiable

IBM Software Group IBM Information Management

Version 16 57

C H A P T E R 5 Embedded SQL

Oraclersquos embedded SQL products are ProC and ProCOBOL Informixrsquos corresponding embedded SQL products are ESQLC and ESQLCOBOL

Host variables

Declaration override

The Oracle EXEC SQL VAR declarative statement (host variable equivalency of Oracle external data types by overriding the default assignment) can be converted to an Informix explicit declaration statement For example

Oracle char char_var[20]

EXEC SQL VAR char_var IS STRING(11)

Informix

char char_var[11]

Note that the size and type used in the EXEC SQL VAR section is the final information required to declare the host variable in Informix

Arrays

Oracle arrays are not subscripted in SQL statements since it is not required to process the host arrays in a loop in the SQL statement In Informix subscripting is mandatory In Oracle if an array is defined of size 200 then an SQL statement would be

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A

VAR-B

VAR-C

END-EXEC

-or- EXEC SQL SELECT COL1 COL2 COL3

INTO VAR-A

VAR-B

VAR-C

FROM TABLE1

WHERE COL2 gt 100

END-EXEC

where VAR-A VAR-B and VAR-C are each an array of say 200

IBM Software Group IBM Information Management

Version 16 58

In Informix the first example would be converted to

PERFORM VARYING LOOP-CTR FROM 1 BY 1 UNTIL

LOOP-CTR IS GREATER THAN 200

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A(LOOP-CTR)

VAR-B(LOOP-CTR)

VAR-C(LOOP-CTR)

END-EXEC

IF SQLCODE = 100

GO TO EXIT-PERFORM

END-IF

END-PERFORM

EXIT-PERFORM

For the second Oracle example given above a cursor must be declared in Informix opened and fetched for 200 rows or less (less because there may be less than 200 qualifying rows) into the host array and then should be closed If the number of qualifying rows is more than 200 then the extra rows must be ignored to duplicate the Oracle functionality But for the first example each fetch in Oracle will return the next 200 or less number of rows Therefore each Oracle fetch needs to be replaced by another call to the Informix fetch loop Oracle also uses this method for inserts deletes and updates These array techniques are mainly used in batch SQL processing

Formatting

In Informix when a DECIMAL MONEY DATE or DATETIME value is selected into a host variable of the same data type the value must be formatted using the available Informix formatting routines before they can be printed or displayed For example

hellip

dec_t dec_host_var

char formatted_dec[40]

EXEC SQL SELECT DEC_COLUMN INTO dec_host_var FROM TABLE_NAME

rfmtdec(ampdec_host_var ldquoampampampampampampampampampamprdquo formatted_dec)

printf(ldquoThe Decimal Value is snrdquo formatted_dec)

hellip

IBM Software Group IBM Information Management

Version 16 59

Informix supplies many formatting functions and formatting strings The names of these functions are different in Informix ESQLC and ESQLCOBOL but the functionality is the same Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

SQL structures

SQLCA

Oraclersquos SQLCA structure is different from that of Informix However the components of both structures are logically the same Oraclersquos SQLCA components can be replaced with the corresponding Informix components Oraclersquos SQLCA structure

SQLCAID string containing ldquoSQLCArdquo SQLCABC length of SQLCA data structure SQLCODE Oracle error message code SQLERRM sub-record for error message

SQLERRML length of error message SQLERRMC text of error message SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) reserved for future use SQLERRD(1) reserved for future use SQLERRD(2) number of rows processed SQLERRD(3) reserved for future use SQLERRD(4) parse error offset SQLERRD(5) reserved for future use

SQLWARN array of eight warning flags SQLWARN(0) another warning flag set SQLWARN(1) character string truncated SQLWARN(2) no longer in use SQLWARN(3) SELECT list not equal to INTO list SQLWARN(4) DELETE or UPDATE without WHERE clause SQLWARN(5) reserved for future use SQLWARN(6) no longer in use SQLWARN(7) no longer in use

SQLTEXT reserved for future use

IBM Software Group IBM Information Management

Version 16 60

Informixrsquos SQLCA structure

SQLCODE Informix error code SQLERRM error message parameter SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) estimated number of rows returned SQLERRD(1) serial value of INSERT or ISAM error code SQLERRD(2) number of rows processed SQLERRD(3) estimated cost SQLERRD(4) parse error offset SQLERRD(5) ROWID after INSERT

SQLWARN structure of eight warning flags SQLWARN0 another warning flag set SQLWARN1 character string truncated or no privileges revoked SQLWARN2 NULL value returned or ANSI database SQLWARN3 SELECT list not equal to INTO list or turbo back-end SQLWARN4 DELETE or UPDATE without WHERE clause SQLWARN5 if non-ANSI statement SQLWARN6 if server is in data replication secondary mode SQLWARN7 reserved

In order to get Oracle error messages an application normally uses the SQLCA element SQLERRMC The Informix equivalent is SQLERRM On the HPUX and Solaris platforms the Informix function rgetmsg should be used instead of the element SQLERRM At the time of this writing using SQLERRM would cause an error on the HPUX and Solaris platforms

SQLDA

The implementation of Oraclersquos SQLDA structure is very different from that of Informix Significant changes are necessary to convert Oraclersquos functionality to Informix Oraclersquos sqlald function can be replaced with Informixrsquos ALLOCATE DESCRIPTOR statement Since Oraclersquos and Informixrsquos SQLDA structures are so different Oraclersquos SQLDA logic must be rewritten with the more powerful Informix SQLDA logic or alternatively the Informix system-descriptor area logic Oraclersquos SQLDA Structure

N maximum number of SELECT list items or placeholders V pointer to array of address of SELECT list items or bind variables L pointer to array of lengths of SELECT list items or bind variables T pointer to array of data types of SELECT list items or bind variables I pointer to array of addresses of indicator variable values F actual number of SELECT list items or placeholders S pointer to array of addresses of SELECT list items or placeholder names M pointer to array of max lengths of SELECT list items or placeholder names C pointer to array of current lengths of SELECT list items or placeholder names X pointer to array of addresses of indicator variable names Y pointer to array of maximum lengths of indicator variable names Z pointer to array of current lengths of indicator variable names

IBM Software Group IBM Information Management

Version 16 61

Informixrsquos SQLDA Structure SQLD count of the following SQLVAR members SQLVAR pointer to array of structures

SQLDATA pointer to actual data SQLTYPE data type of placeholder or SELECT item SQLLEN length of the placeholder or SELECT item SQLIND pointer to the indicator SQLNAME pointer to placeholder or SELECT item name SQLFORMAT reserved SQLIDATA indicator data pointer SQLITYPE indicator variable type SQLILEN length of indicator variable

If an Oracle application uses the simple dynamic SQL method using macros only not the SQLDA structure directly the value indicatorsplaceholders can be replaced with a lsquorsquo in Informix For example Oracle sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES (v1 v2)rdquo) Informix sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES ( )rdquo)

ORACA

Oraclersquos ORACA structure is not supported by Informix This structure is used to handle Oracle specific communication and more runtime information than SQLCA Oracle statements containing references to this structure should be removed from the application

Pre-compiler options The Oracle options beginning with the EXEC ORACLE OPTION statement can be removed from the application The options set after this statement do not affect the application logic They may affect some application performance only

Embedded PLSQL Oracle allows procedure language (PLSQL) blocks inside ProC and ProCOBOL code delimited by the EXEC SQL EXECUTE and END-EXEC statements In Informix these blocks must be replaced with the equivalent ESQLC or ESQLCOBOL code

Oracle Call Interface Oracle call interface (OCI) is the base layer for a variety of other application programming interfaces such as JDBC-OCI Oracle Precompilers and Oracle ODBC It is also used directly by customers who are willing to develop their code using a lower level proprietary API From a high level it can be thought of as if IBM Informix had standardized and published the function calls in the ESQLC library Although some customers have reverse engineered these calls and developed applications using them this is generally discouraged because there is no guarantee that the library of calls will not change There is no direct equivalent to this Oracle API in Informix Migrating applications written using Oracle Call Interface (OCI) will require rewriting the code from scratch OCI is native to the C language and so it should be less effort to migrate the application to an Informix API that is also native to C This could be ESQLC or CLI The following information explains differences between Oracle OCI and Informix ODBC

IBM Software Group IBM Information Management

Version 16 62

The following table is an approximate mapping of the differences between the Informix CLI and Oracle OCI function calls in which there is not a direct one-to-one mapping

Oracle Informix Buffer Areas HAD LDA CDA HENV HDBC HSTMT

Connect and allocate resources

OLOG OOPEN SQLConnect SQLAllocEnv SQLAllocConnect SQLAllocStmt

Update delete insert select OPARSE OBNDRV OEXEC SQLPrepare SQLBindParameter SQLExecute

Select ODEFIN OFETCH SQLBindCol SQLFetch

Commit Rollback OCOM OROL SQLTransact

Disconnect OLOGOF OCLOSE SQLDisconnect SQLFreeStmt SQLFreeConnect SQLFreeEnv

Database library calls

One of the first main differences between Informix CLI and Oracle OCI calls is the overall data structures and mechanisms used to process database library calls Oracle uses direct connections to the database server Informix uses an ODBC connection to the database server As a result the Informix calls will be implemented as ODBC SQL calls utilizing three tiers of increasing SQL levels of complexity

Global area processing

Another main difference between Informix CLI and Oracle OCI is Informixrsquos use of pointers to three global areas versus Oraclersquos use of pointers to three different but similar global areas Hence the Oracle OCI calls that utilize HAD (Handle Data Area) LDA (Logon Data Area) and CDA (Cursor Data Area) pointers must be translated over to Informix CLI calls that utilize HENV (Environment Area) HDBC (Database Connection Area) and HSTMT (Statement Area) pointers respectively in conjunction with an ODBC interface

Fetch cycle

Another difference between Informix CLI and Oracle OCI calls is that the overall fetch cycle is different for each and must be modified accordingly In Oracle the fetch cycle for selecting multiple rows utilizing a cursor area involves parsing binding defining fetching and then executing into a cursor data area These must be translated to a cycle that involves preparing binding executing binding and then fetching via the ldquoFor Eachrdquo cycle

RAW binary data type processing

RAW binary data types in Oracle will need to be translated to a pointer-to-BLOB REFERENCES BYTE type in Informix See the Binary Data Types subsection of the Stored Procedures section in CHAPTER 3

Parameter bindings

In Oracle multiple output bindings of parameters are declared as type ldquoOUTPUTrdquo in the ODEFIN() calls In Informix convert the calls to Informix SQLBindCol() calls and bind the output parameters as columns Differences also exist between Informix CLI and Oracle OCI in the use of inputoutput bindings In Oracle these bindings are declared as type ldquoINPUTOUTPUTrdquo in the ODEFIN() calls In Informix a ldquoround robinrdquo approach is used using three variables in the following manner A=B B=C C=A A variable (A) is declared before the SQL bindings as an input variable The function is called

IBM Software Group IBM Information Management

Version 16 63

using a second input variable (B) that is set to the first input variable (A) The function returns a third variable (C) that is bound as an output column Finally the first variable (A) is now set to the returned third variable (C) that made the first variable (A) appear as an ldquoinputoutputrdquo variable to the rest of the program

Embedded SQL for C

VARCHAR

Oraclersquos ProC VARCHAR data type is expanded after pre-compiling into a structure with two elements one is unsigned short len and the other is unsigned char arr[size] The name of the expanded structure is the same name as the VARCHAR variable and size is replaced with the size of the VARCHAR variable In Informix the VARCHAR data type is just a synonym for the C languagersquos char data type Therefore statements that use variable_namelen can be removed from the application and all occurrences of variable_namearr can be replaced with variable_name For example

Oracle VARCHAR vName[40]

strcpy(vNamearr ldquoCompany Namerdquo)

vNamelen = strlen(vNamearr)

Informix VARCHAR vName[40]

strcpy(vName ldquoCompany Namerdquo)

Host variables

The Oracle statement EXEC SQL TYPE is synonymous with the C languagersquos typedef declarative instruction It can be easily replaced with the Informix declarative instruction typedef

Embedded SQL for COBOL

VARCHAR

Oraclersquos ProCOBOL character host variable declaration statementrsquos VARYING clause is expanded after pre-compiling into a group with two elements one is variable-name-LEN PIC S9(4) COMP and the other is variable-name-ARR PIC X(size) The group name is the same as the host variable name and size is replaced with the size of the VARYING variable Informix does not support this concept Therefore statements that use variable-name-LEN must be removed from the application and all occurrences of variable-name-ARR must be replaced with variable-name Also the VARYING clause must be removed from the declarative statement For example

Oracle

05 vName PIC X(40) VARYING

hellip

MOVE ldquoCompany Namerdquo TO vName-ARR

MOVE 12 TO vName-LEN

Informix

05 vName PIC X(40)

hellip

MOVE ldquoCompany Namerdquo TO vName

IBM Software Group IBM Information Management

Version 16 64

Level 88

COBOLrsquos level 88 functionality is not supported within an Informix ESQLCOBOL host variable declaration section in versions prior to 72 Level 88 functionality is supported in Informix ESQLCOBOL 72

SQLDA

In Informix ESQLCOBOL the SQLDA structure is not available The Informix macros such as ALLOCATE DESCRIPTOR DESCRIBE GET DESCRIPTOR and SET DESCRIPTOR must be used to retrieve and manipulate the SQLDA data

REDEFINES

Oracle supports the use of the REDEFINES clause at the elementary level in the host variable declaration section In other words the redefined item cannot be a group item but the redefining item may be a group item Informix does not support the use of the REDEFINES clause in the host variable declaration section in versions prior to 72 The REDEFINES clause is supported in Informix ESQLCOBOL 72

Tips

If the Informix pre-compiler finds an SQL statement within an IF [ELSE IF hellip ] END-IF or EVALUATE END-EVALUATE or PERFORM END-PERFORM block then the pre-compiler adds a period after the generated COBOL statements regardless of whether there is a period at the end of the SQL statement This is a violation of COBOL rules for such blocks and the code may cause syntax errors during compilation or may behave unexpectedly To avoid these problems each SQL statement group should be moved to a new paragraph and these paragraphs should be performed from the block from which they were moved

ODBC Although the Open Database Connectivity (ODBC) API is designed to make it possible to write and compile an application once and use it with any ODBC driver on the same platform there are frequently differences between the underlying DBMSs that can expose problems to the applications For instance there can be differences between how unspecified parts of a date-time value are filled Most of these kinds of differences that get exposed through ODBC have their origins in the differences between the DBMSs themselves There are also cases where there are gaps in the ODBC standard for example there is a standard ODBC call that allows the application to ask the driver if it can support scrollable cursors and there is another call to ask if it can support updateable cursors There is no call to ask if it can support both at the same time With Informix you can have a scrollable cursor and you can have an updateable cursor but you can not have one cursor that is both scrollable and updateable A more complete description of ODBC application migration issues is beyond the scope of this article

IBM Software Group IBM Information Management

Version 16 65

C H A P T E R 6 Application Architecture

Transaction processing Transaction boundaries are defined differently in Oracle and Informix Oraclersquos transactions begin implicitly in one of two ways either by issuing a CONNECT statement or issuing a COMMIT or ROLLBACK statement A CONNECT statement marks the beginning of a transaction and a COMMIT or ROLLBACK statement commits or rolls back the previous transaction respectively and then implicitly begins a new transaction CONNECT statements are usually issued once at the beginning of a program however they may be nested or issued more than once serially to connect to the same or a different database When using more than one CONNECT statement within a program each CONNECT statement must be named This marks the beginning of named transactions Every SQL statement within a named transaction must also be named with the same transaction name as the CONNECT statement at where the SQL is to be executed SQL is named using the EXEC SQL statementrsquos AT clause Informixrsquos transaction boundaries are explicitly marked with the reserved words BEGIN WORK and COMMIT WORK or ROLLBACK WORK Note that once a transaction has begun for a given connection it stays open until a COMMIT or ROLLBACK is executed In other words if an ESQL program begins a transaction and then calls a stored procedure the stored procedure executes within the same transaction If the stored procedure issues a COMMIT then the whole transaction is committed and the calling ESQL program should not issue a COMMIT or ROLLBACK Informix transactions can be written to behave the same way as Oraclersquos To simulate Oraclersquos CONNECT statement behavior an Informix CONNECT should also be issued followed by a BEGIN WORK statement If more than one CONNECT statement is used in a program Informix also requires that the CONNECT and SQL statements be named To simulate Oraclersquos COMMIT and ROLLBACK statement behavior an Informix COMMIT WORK or ROLLBACK WORK statement should be issued followed by a BEGIN WORK statement Nested transactions can be simulated in Informix with the CONNECT statement and naming the transactions Then the Informix SET CONNECTION connection_name statement can be used to switch between transactions Committing or rolling back each named transaction does not commit or roll back other active transactions The Oracle statement EXEC SQL COMMITROLLBACK RELEASE should be replaced with the Informix statements EXEC SQL COMMITROLLBACK [WORK] followed by EXEC SQL DISCONNECT CURRENT In the following examples ws-dbenviron is the database name ws-connect-nm is the user name and ws-identity-nm is the password set in the program enp and connection-name are the connection names For Informix the user name and password information should correspond to the entries in the etcpasswd file on the UNIX system See the User Authentication section later in this chapter for more information The default server name is automatically obtained from the environment variable INFORMIXSERVER The following examples illustrate how Oracle and Informix implement the CONNECT functionality

IBM Software Group IBM Information Management

Version 16 66

Simple Connect

Oracle

CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm

Informix

CONNECT ws-dbenviron USER ws-connect-nm USING ws-identity-nm

Named Connect with Literal

Oracle

DECLARE enp DATABASE hellip CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm AT enp USING ws-dbenviron hellip AT enp SELECT col1 col2 INTO var1 var2

FROM table_name

Informix

CONNECT TO ws-dbenviron AS ldquoenprdquo USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION ldquoenprdquo hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Named Connect with Variable

Oracle

CONNECT ws-connect-nm

IDENTIFIED BY ws-identity-nm AT connection-name USING ws-dbenviron hellip AT connection-name SELECT col1 col2 INTO var1 var2 FROM table_name

Informix

CONNECT TO ws-dbenviron AS connection-name USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION connection-name hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Autonomous Transaction

An autonomous transaction is an independent transaction that is initiated by another transaction (the parent transaction) An autonomous transaction can modify data and commit or rollback independent of the state of the parent transaction The autonomous transaction must commit or roll back before the autonomous transaction is ended and the parent transaction continues

IBM Software Group IBM Information Management

Version 16 67

An autonomous transactions has been available since the release of Oracle 8i An autonomous transaction is defined in the declaration of a PLSQL block This can be an anonymous block function procedure object method or triggerThis is done by adding the statement PRAGMA AUTONOMOUS_TRANSACTION anywhere in the declaration block There isnt much involved in defining a PLSQL block as an autonomous transaction You simply include the following statement in your declaration section PRAGMA AUTONOMOUS_TRANSACTION Sample code

PROCEDURE test_autonomous

IS

PRAGMA AUTONOMOUS_TRANSACTION

BEGIN

insert

commit

END test_autonomous

Autonomous transactions can be used for logging in the database independent of the rollbackcommit of the parent transaction

Savepoints

Oracle allows savepoints within its PLSQL For example a PLSQL block can be structured so that SAVEPOINT A is issued upon entry and SAVEPOINT B is issued after some processing Then after some more processing a COMMIT or ROLLBACK can be issued against all the logic since the last COMMIT point which is before the PLSQL block or up to any of the savepoints by naming the COMMIT or ROLLBACK with the savepoint name In other words a savepoint can be issued at the beginning of a stored procedure and then only the stored procedure logic can be committed without committing the changes pending before the stored procedure was executed Those changes can be committed or rolled back once processing is returned from the stored procedure Informix does not support savepoint processing within a stored procedure

Concurrency Database concurrency can be managed through the combination of two configurable settings one specifies the lock granularity on database objects while the other influences how the application behaves in regards to the presence and placement of locks using a transaction isolation level

Row Level Locking

Oracle and Informix implement locking differently on database objects Oracle defaults to row level locking whereas Informix defaults to page level In most cases row level locking is preferred to improve concurrency Informix supports row level locking however it must be either explicitly requested specified by an environment variable or permanently changed in the instancersquos configuration Having three methods for establishing the lock level there is an order of precedence

1 To be explicitly requested the CREATE TABLE statement must include the specification of the LOCK MODE attribute

CREATE TABLE emp (

name CHAR(40)

salary MONEY

ssn LVARCHAR(64)

) LOCK MODE ROW

IBM Software Group IBM Information Management

Version 16 68

2 The environment variable IFX_DEF_TABLE_LOCKMODE will establish the default for CREATE TABLE statements issued without the LOCK MODE attribute and will override the Instancersquos configuration setting The variable setting on the client will override the server environment setting

set IFX_DEF_TABLE_LOCKMODE=ROW -or- export IFX_DEF_TABLE_LOCKMODE=ROW

3 Informix allows the instancersquos lock level default to be changed using a configuration parameter Row level locking can be as the default by adding the parameter DEF_TABLE_LOCKMODE to the instancersquos ONCONFIG file This parameter may not be found in the existing file and if not present can be added using an editor and establish a new default setting of ROW

DEF_TABLE_LOCKMODE ROW

None of the steps will apply a change to existing tables only establish the lock level for the CREATE TABLE statement

Transaction Isolation Level

Oracle databases incorporate a feature known as ldquoread consistencyrdquo which allows a query return a result based on the state of the data when the query started regardless of other processes updating or deleting the same data while the query is running Informix facilitates this type of behavior differently by providing control of the applicationrsquos placement of locks as well as how it reacts to those placed by other processes through the use of the transactionrsquos isolation level If Oraclersquos technique of ldquoreaders not blocking writersrdquo is a requirement then in many circumstance Informixrsquos DIRTY READ isolation level can be used The readers will not block the writers with dirty read processing however the query result may contain updates performed while the query was running which may be uncommitted If the emulation of Oraclersquos ldquoread consistencyrdquo is desired the LAST COMMITTED option of Informixrsquos COMMITTED READ isolation level can reduce the risk of locking conflicts when two or more sessions attempt to access the same row in a table whose locking granularity is row-level When an application attempts to read a row on which another session holds an exclusive lock these keywords instruct the database server to return the most recently committed version of the row rather than wait for the lock to be released This isolation level attribute could be preferable to executing queries using DIRTY READ since it will return only the most recently committed versions of the data The LAST COMMITTED option can be enabled in the following ways

1 Setting the USELASTCOMMITTED parameter in the Instancersquos configuration (ONCONFIG) will apply this feature as the default isolation level to all database transactions The parameterlsquos values will designate the scope of applying the LAST COMMITED option to either ALL NONE or only COMMITED READ and DIRTY READ isolation levels

USELASTCOMMITTED [ALL | NONE | COMMITTED READ | DIRTY READ]

2 The SET ENVIRONMENT statement can override the USELASTCOMMITTED configuration parameter setting for the duration of the current session The same semantics apply as the parameter within the ONCONFIG file with the setting value enclosed in quotes (lsquo)

SET ENVIRONMENT USELASTCOMMITTED lsquoALLrsquo

IBM Software Group IBM Information Management

Version 16 69

3 The SET ISOLATION statement can be used to override the instance configuration and session environment setting The SET ISOLATION statement is an Informix extension to the ANSI SQL-92 standard and provides the same functionality as the ISOANSI-compliant SET TRANSACTION statement There is no support for the LAST COMMITTED option with the SET TRANSACTION statement SET TRANSACTION complies with ANSI SQL-92 and only ANSI supported isolation levels are supported

SET ISOLATION TO COMMITTED READ LAST COMMITTED

4 PREPARE statements in ODBCJDBC applications

This feature is primarily documented in the Guide to SQL Syntax Guide to SQL Reference Administrators Reference and Administrators Guide

IBM Software Group IBM Information Management

Version 16 70

C H A P T E R 7 Security

User authentication In Oracle security information is stored in the database Up until recently Informix has used only the operating system security subsystem to check security For security purposes Oracle connects to the server and passes the user ID and password information to the database for verification

Operating system security

Informix does not store user ID and password information in the database Instead they are validated against the operating systemrsquos security mechanism on the server for example the etcpasswd file in UNIX Therefore either every database user must have an entry in the serverrsquos password file or the application must handle a level of security where user IDs are converted into a group id based on database permissions and only those group IDs are entered into the password file Note that if the second alternative is chosen then auditing capabilities based on user ID are lost Also if the application performs security functions then those functions are not applicable to third party applications such as report writers application development tools and so on when they access the database The home directory of all the users should point to the same physical directory where the application executable resides The Informix method of using the operating system for security checking allows external programs to be called from within stored procedures This capability is not allowed in Oracle In Oracle the OPS$User_name is sometimes used to connect to the database where OPS$User_name is a valid Oracle user and User_name is a valid operating system level user In this case the connection is made to the database using just the lsquorsquo character without the user id and password Informixrsquos technique of using the etcpasswd file for security works fine for this type of connection

Non-operating system security

In previous releases each user who needed to access the database server also needed an operating system account on the host computer Now you can configure Informix so that users who are authenticated by an external authentication service (such as Kerberos or Microsoft Active Directory) can connect to Informix The new USERMAPPING configuration parameter specifies whether or not such users can access the database server and whether any of those users can have administrative privileges When Informix is configured to allow user mapping you can still control which externally authenticated users are allowed to connect to Informix and their privileges Please refer to the IBM Informix documentation on connection security for more information

IBM Software Group IBM Information Management

Version 16 71

Informix supports for the pluggable authentication module (PAM) framework which lets an administrator customize authentication for individual applications and permits column-level encryption

Role based authority Role based authority can help you manage your database permissions As of version 1110 you can create a role and assign that as a default role for individual users (or to PUBLIC) A role is a work-task classification such as ldquopayrollrdquo or ldquomanagerrdquo Each defined role has privileges on the database object granted to the role You use the CREATE ROLE statement to define a role and GRANT DEFAULT ROLE to establish the userrsquos initial setting when connecting to the database A userrsquos role can be changed after connecting by using the SET ROLE statement

Column-level encryption You can use column-level encryption to improve the confidentiality of your data IDS Version 1110 has new built-in SQL scalar functions provide methods for data in columns to be stored in an encrypted format Use the ENCRYPT_AES or the ENCRYPT_TDES function to define encrypted data Use the DECRYPT_BINARY() and DECRYPT_CHAR() functions to query encrypted data When using the routines the encryption of data is under application control and the DBMS is not aware that data is encrypted Informixrsquos support of column level encryption is analogous to Oraclersquos DBMS Obfuscation Tool Kit Built-in ENCRYPT functions provide methods for encrypting and decrypting the following character data types or smart large object data types

CHAR

NCHAR

VARCHAR

NVARCHAR

LVARCHAR

BLOB

CLOB

Passwords and hints

Passwords are necessary when using the encryption functions Only users who can provide a secret password can view copy or modify encrypted data The password must be a minimum of 6 bytes and can be a maximum of 128 bytes When you set an encryption password you have the option of specifying a password hint Hints can be up to 32 bytes of text If you specify a hint you can store the hint with the encrypted password or in another location Passwords (and hints) to be used by default can be set for a session using the SET ENCRYPTION PASSWORD statement

SET ENCRYPTION PASSWORD lsquopasswordrsquo [ WITH HINT lsquohint stringrsquo ]

Hence the password and hint parameters can be optional when calling the encryption function Explicit values override the session default values The password or hint can be a single word or several words The hint should be a word or phrase that helps you to remember the password but does not include the password You can subsequently execute the built-in GETHINT function (with an encrypted value as its argument) to return the plain text of hint Calling the GETHINT function with an argument of encrypted data will return the hint (if any) from the encrypted data or an empty string (NULL) is no hint was provided There is no privilege needed anybody can get any hint at any time When you set a password Informix transfers the password and any hint to 128-bit key that is used to encrypt the password and hint Passwords and hints are not stored as plain text any table of the system catalog The key is a time-based random value per instance The database server

IBM Software Group IBM Information Management

Version 16 72

initializes the key when the server starts the key is destroyed when the database server shuts down

Encrypting a column

Column data can be encrypted through the use of two functions ENCRYPT_TDES and ENCRYPT_AES corresponding to the two data encryption standards Triple Data Encryption Standard (Triple-DES) and Advanced Encryption Standard (AES) which describes the cipher algorithm used to protect data from unauthorized viewing AES encryption (also known as Rijndael) uses a 128-bit key size and Triple-DES encryption uses two 56-bit keys for 112-bits overall Both functions are variant functions and will return a different result every time it is used The following example demonstrates how to use the encryption functions with a column that contains a social security number

CREATE TABLE emp (name CHAR (40) salary MONEY ssn LVARCHAR(64))

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890one two

three 123))

-or-

CREATE TABLE emp (name CHAR(40) salary MONEY ssn LVARCHAR(64))

SET ENCRYPTION PASSWORD one two three 123

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890))

Querying an encrypted column

Encrypted data can be translated using Informixrsquos DECRYPT_CHAR and DECRYPT_BINARY scalar functions Encrypted data contains information about the encryption method and all the other data needed to decrypt it except the password The encrypted data value is passed as the first argument and a password as the second unless the SET ENCRYPTION statement has specified for this session with the same session password by which the first argument was encrypted If the data is not encrypted the function call will return an error The DECRYPT_CHAR function is used to invoke a decryption routine on character data types (ie CHAR LVARCHAR NCHAR NVARCHAR and VARCHAR) while the DECRYPT_BINARY function accepts an encrypted large object of type BLOB or CLOB If the first argument to DECRYPT_CHAR or DECRYPT_BINARY is not an encrypted value or if the second argument (or the default password specified by SET ENCRYPTION) is not the password that was used when the first argument was encrypted Informix will issue an error and the call fails If the call to the decryption function is successful it returns the plain text version of the encrypted data argument The following example demonstrates how to use the decrypt function to query encrypted data

SELECT name salary DECRYPT_CHAR(ssn lsquoone two three 123rsquo)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

-or-

SET ENCRYPTION PASSWORD lsquoone two three 123rsquo

SELECT name salary DECRYPT_CHAR(ssn)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

The first argument to DECRYPT_BINARY is expected to be an encrypted value of a large object data type however if it is called with a character data type Informix invokes the DECRYPT_CHAR function and attempts to decrypt the specified value

IBM Software Group IBM Information Management

Version 16 73

Do not use either decryption function to create a functional index on an encrypted column This would store the decrypted values as plain text data in the database defeating the purpose of encryption

Performance impact of encryption

The performance impact of encryption is significant Encryption by its nature will slow down most SQL statements If some care and discretion are used the amount of extra overhead should be minimal Also encrypted data will have a significant impact on your database design In general you want to encrypt a few very sensitive data elements in a schema like social security numbers credit card numbers patient names and so on The effect on performance depends on direction encrypting is slower than decrypting It does not depend measurably on which algorithm is used AES performs at the same speed as Triple-DES It does depend on data size the relative overhead is less when there is more data to encrypt

Storage considerations

An encrypted value uses more storage space than the corresponding plain text value Data encrypted using AES can be bigger than Triple-DES but not by a significant amount This occurs because all of the information needed to decrypt the value except the encryption key is stored with the value Therefore before you set the encryption password and encrypt the data you must be sure the encrypted data can fit in the column A chart of the expected sizes can be found in the IBM Informix Administrator Guide

Compliance regulations

Informixrsquos encryption routines comply with the United Statesrsquo regulations of Health Insurance Portability and Accountability Act (HIPAA) Sarbanes-Oxley Gramm-Leach-Bliley and California Personal Information Privacy (SB 1386) as well as the international requirements of Basel II Also they comply with the latest cryptographic standards (OpenSSL 097c)

IBM Software Group IBM Information Management

Version 16 74

C H A P T E R 8 Environment

Scripts Oracle make files used to build the application should be modified to invoke the appropriate Informix ESQLCOBOL ESQLC MF COBOL and other application language commands The shell scripts shell startup scripts and command files should be modified for Informix compliant statements

SQL script substitution variables

In Oracle a substitution variable is a user variable name preceded by one or two ampersands (amp) When Oracle (SQLPlus) encounters a substitution variable in a command Oracle executes the command as though it contained the value of the substitution variable rather than the variable itself In Oracle the substitution variables can be used anywhere in SQL and SQLPlus commands except as the first word entered at the command prompt When SQLPlus encounters an undefined substitution variable in a command SQLPlus prompts the user for the value SQLPlus reads the responses from the keyboard even if terminal input or output has been redirected to a file If a terminal is not available (if for example the command file is run in batch mode) SQLPlus uses the redirected file Informixrsquos dbaccess does not provide this functionality however a work-around for the redirected file type of substitution is a follows (no user prompting) Create the following shell script (named subvalsksh in this case)

binkshif [[ $ -ne 2 ]]

then

echo nUsage $0 ltdfilegt ltcfilegtn

echo Desc This script accepts two files - dfile the decode

file

echo and cfile the change file It modifies the

change file

echo using the values listed in the decode file

echo The decode file should contain two columns - old

value

echo and new value

echo Ex

echo changethis tothis

echo

echo In this case every occurance of changethis

would be

echo replaced with tothisn

exit 1

fi

IBM Software Group IBM Information Management

Version 16 75

-----------------------

Declare variables

-----------------------

dfile=$1

cfile=$2

awk print s$1$2 $dfile gt $dfile_sed

sed -f $dfile_sed $cfile

The preceding script is used by creating a ldquodecoderdquo file (named decodefile in this case) which holds two columns in the form which may contain multiple rows

oldval newval

Executing the following command

subvalsksh decodefile chgfile

will replace every occurrence of oldval with newval in the file chgfile The shell script (subvalsksh) writes to standard output therefore the output should be redirected The redirected file will then be able to run with dbaccess

Utilities To improve performance the Informix EXPLAIN utility should be used by executing the SET EXPLAIN ON command to see how an SQL statement accesses the database From that point forward the access path for every SQL statement is written in the SQEXPLAINOUT file in the current working directory or the home directory of the process that initiated the request on the host machine The Informix SET EXPLAIN OFF should be executed to turn off this feature when finished The overall system performance should be monitored using the Informix ONSTAT utility

System catalog The following items discuss how Informix implements the system catalog differently than Oracle Each item refers to the Informix implementation only Object names are stored in lower case The system catalog tables are owned by lsquoinformixrsquo To query the systables table use SELECT from lsquoinformixrsquosystables Each table in systables is assigned a tabid by the system It is used as the primary key and therefore the foreign key for the other catalog tables The identifier information is stored in sysindexes Columns part1 - part16 each contain a column component of a composite index They are integers positive for ascending order negative for descending order In syscolumns collength and coltype have special meanings depending on the data type of the column See the Informix Guide to SQL Reference Version for details

IBM Software Group IBM Information Management

Version 16 76

C H A P T E R 9 Using Bladelets

What is a Bladelet

A Bladelet is a small informal Informix Datablade module Its meant to be useful out of the box and is offered complete with source code at no cost -- and no support or warranty In the context of this document the term Datablade refers to an extension to the standard IBM Informix database engine These generally take the form of new data types (for example timeseries or video) andor new routines that execute inside the server The new routines might operate on new data types or on existing ones A Datablade module is usually a formal product available for sale In addition a Datablade is

Developed either by IBM Informix or by a third-party developer

Rigorously tested

Packaged and sold for profit

May or may not be formally certified by IBM Informix as having been developed according to approved Datablade coding practices

In contrast a Bladelet is

Not rigorously tested

Not sold for profit

Not certified by IBM Informix A Bladelet is an extension to the database engine that is narrow in scope and thought to be generally useful being offered at no cost complete with source Just remember before you use any of this code in mission-critical applications its up to you to thoroughly test it and fix any problems you find Please review the disclaimer which applies to any sample code you find on this site httpwwwibmcomdeveloperworksdb2zonesinformixlibrarysamplesdb_downloadshtml Note The bladelets at this link have not been updated for some time (at the time of this writing) some of the capabilities especially simple function call that increase compatibility may have been introduced into the Informix server itself since they were written

Useful Bladelets

Bladelet Description

Exec Defines two user-defined functions that provide dynamic SQL functionality within a SPL procedure

Flat File Access Method A complete access method that lets you build virtual tables based on operating system files

IUtil Implements a collection of other database vendor functions for Informix

IBM Software Group IBM Information Management

Version 16 77

JPEG Image Bladelet Provides a user-defined type for JPEG images that allows you to manipulate images and to extract and search on image properties

Multirepresentational lvarchar Opaque Type

Creates the idn_mrLvarchar opaque type which stores character data up to 2 gigabytes

Node Datablade Module Creates the node opaque type which is intended to solve one of the hardest problems in relational databases transitive closure

Regexp Creates routines that let you manipulate character and clob data using regular expressions

Shapes DataBlade Module Creates several opaque types for managing spatial data including R-tree index support

Smart Blob Information DataBlade Module

Includes a variety of useful routines for working with smart blobs

SqlLib C SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

SqlLib Java SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

Versioning Table Access Method

Permits users to create and manage versioned tables

We will look closer at two bladelets which could assist with migration the Exec datablade and SQLLib

Informix Exec bladelet for Dynamic SQL Often it is desirable to execute a SQL query that is generated at run-time within the RDBMS For example a developer may not know the name of the temporary table they wish to run the query against or they might want to append predicates to a query In external programs this can be accomplished using the ESQLC SQLCA and DESCRIPTOR facilities Unfortunately the INFORMIX Stored Procedure Language (SPL) does not support Dynamic SQL Queries must be hard-coded into the SPL logic The objective of the Exec bladelet is to remedy this situation Exec consists of user-defined functions that take an SQL query as an argument execute it and return the result (the format of which varies depending on which function is called and the kind of query) The Exec functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries For more details and download refer to

httpwwwibmcomdeveloperworksdb2zonesinformixlibrarydemoids_exechtml

There are three User Defined Routines (UDRs) in the Exec bladelet Two of them are external C functions that use the Server API (SAPI) These must be compiled into shared libraries on the target machine and you need to declare them to the server using CREATE FUNCTION statements The third UDR is a routine written in Informix Stored Procedure Language (SPL) that uses the first two UDRs to return a collection of items The Exec bladelet module consists of the following

1 EXEC The EXEC() function takes an LVARCHAR that it treats as a SQL query executes the query and returns a single LVARCHAR result string Depending on what kind of SQL statement is submitted Exec() returns a different result format

IBM Software Group IBM Information Management

Version 16 78

2 EXEC_FOR_ROWS The EXEC_FOR_ROWS() UDR is an iterator function which means it can return more than one result row Of course it only does so when it is asked to execute a SELECT Otherwise it behaves exactly as the EXEC() UDR Being an iterator function limits the ways in which such a UDR can be used It cannot be used in another SQL query The only place it can be used effectively is inside a SPL routine

3 EXEC_FOR_MSET EXEC_FOR_MSET() is a SPL routine that uses the EXEC_FOR_ROWS() routine introduced above Instead of returning a set of rows as an iterator or a single row as the EXEC() UDF does this UDR collects the results of the SQL query together into a single object a multi-set

Refer to Appendix E Sample Code for examples on using the EXEC bladelet functions

SqlLib DataBlade module (SqlLibC11 SqlLibJ11) The SqlLib DataBlade module implements SQL routines that the Informix does not support natively but that are supported by some other database vendors Source code is freely available for download and includes two implementations one in C (SqlLibC) and the other in Java (SqlLibJ)

The following routines are included

ascii - takes a single character as input and returns the ASCII value in decimal that corresponds to that character

ceil - takes a single numeric value as input and returns the smallest integer that is either equal to or greater than the input value

chr - takes an integer value and returns the character that is represented by the ASCII value (in decimal) of that integer

instr - searches for a value in a string and returns the position where it was found It

returns 0 if the search value was not found instrb - provides the exact same functionality as instr() but for single-byte character sets

sign - takes a numeric argument and returns an integer that indicates if the input value is

positive (1) negative (-1) or zero (0) to_decimal - converts the input character argument into a decimal type

to_float - converts the input character argument into a float type

to_integer - converts the input character argument into an integer type For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

IBM Software Group IBM Information Management

Version 16 79

A P P E N D I X A Planning guide

The checklist below will help an analyst determine which Oracle features which need to be converted to Informix and give some guidance on the effort involved Each porting task is listed They are followed by a quantity field used to determine how prevalent the item the difficulty or amount of effort involved 1 (low) to 5 (high) is used to estimate the amount of time needed to perform the task when the associated item exists in the application a moderate number of times What is moderate depends on the size of the application If there are an unusually large number of occurrences of an item then the effort should be increased Conversely if there are a small number of occurrences of an item then the effort should be decreased Each of these items is discussed in detail within this document Each heading corresponds to a section heading within the document

Tasks Quantity Effort

DDL

Identifiers Delimit identifiers named with Informix reserved words 2 Databases Determine database names and create databases 3 Replace Oracle tablespace names with Informix dbspace names 1 ANSI vs Non-ANSI considerations 3 Tables Convert create table statements 2 Convert DDL syntax 3 Reduce primary key length to 390 bytes 5 Data Types Convert Oraclersquos NUMBER data type 3 Convert VARCHAR columns 2 Convert Oraclersquos DATE data type 5 Convert raw data types 2 Convert Rowids 2 Indexes Convert Indexes 2 Views Remove CREATE VIEW statement options 1 Stored Procedures and Triggers Convert CREATE and REPLACE Stored Procedure and Trigger syntax 1 Oracle Extensions Remove non-supported Oracle extensions from DDL 1

Tasks Quantity Effort

DML

SQL Add the Informix AS clause to display labels 1 Replace non-supported DML syntax ^= hellip = ELSE IF 2 Convert Optimizer DirectiveHints 2 Convert InsertSelectUnion and InsertValueSelect statements 3

IBM Software Group IBM Information Management

Version 16 80

Convert Delete statement syntax 1 Convert temporary table processing 2 Convert Join statements + MINUS INTERSECT different data types 2 Convert sorts 4 Convert hard coded SQL error messages 3 Remove correlation names on the main table of Update and Delete statements

2

Replace original table names in SELECT statements using aliases 1 Convert hierarchical implementation (CONNECT BY PRIOR) 5 Host Variables Convert host variable format or add conversion processing 5 Functions Convert date and time functions 5 Convert aggregate functions 3 Convert mathematical functions 5 Convert string function syntax 1 Convert other unsupported Oracle functions 5 Macros Convert ISOPEN NOT FOUND ROWTYPE and TYPE macros 3 Pseudo-Columns Convert Level processing 3 Convert Rownum processing 2 Update Using Cursors Convert WHERE CURRENT OF processing for multiple table joins 5 Convert FOR UPDATE with a HOLD cursor processing 2 Convert concurrency processing from Oraclersquos implicit to Informixrsquos explicit

4

System Tables Convert system table references 1

Tasks Quantity Effort

Stored procedures Break stored procedures greater than 64K in size into smaller ones 2 Convert Oraclersquos stored procedure packages 3 Convert exception processing 5 Convert error handling (SQLCA) 2 Convert Oraclersquos global cursor processing 5 Convert Oraclersquos explicit cursor processing 2 Convert flow control processing 5 Convert Oraclersquos implicit variable declaration and assignment 3 Convert Oraclersquos BOOLEAN variable type 1 Convert binary data type processing Convert Oraclersquos dynamic SQL processing 5 Triggers Convert multi-functional triggers 3 Convert Insert and Update triggers which are not supported in Informix 5 Place logical statements in a stored procedure 5 Constraints Convert constraint enabling and disabling processing 5 DUAL table Convert Dual table processing 4

Embedded SQL

Host variables

IBM Software Group IBM Information Management

Version 16 81

Convert declaration overrides 1 Convert array processing 5 Convert Oraclersquos formatting functions 4 SQL structures Convert SQLDA processing 5 Convert ORACA processing 1 Pre-compiler options Convert Oracle pre-compiler options 1 Embedded PLSQL Convert Oraclersquos Embedded PLSQL 5 ODBC Convert Oraclersquos OCI 5 Convert database library calls Convert global area processing Convert fetch cycle Convert RAW data type processing Convert parameter bindings Embedded SQL for C Convert VARCHAR processing 2 Embedded SQL for COBOL Convert VARCHAR processing 2 Convert 88 Level processing in COBOL 2 Convert Redefine processing in COBOL 4

Tasks Quantity Effort

Application architecture

Transaction processing Convert application to Informix transaction processing 5 Convert multiple connect processing 5 Convert savepoints Concurrency Address Informix locking processing na 2 User authentication Address Informix security processing na 4

Environment

Convert make files 2 Convert shell scripts shell startup scripts and command files 2 Convert script substitution variables

IBM Software Group IBM Information Management

Version 16 82

A P P E N D I X B Syntax comparison

See the Informix Guide to SQL Syntax for more information on each item

Oracle Informix Boolean AND AND AND NOT NOT NOT OR OR OR Greater Than or Equal To gt= gt= Less Than or Equal TO lt= lt= Not Equal ltgt = or ^= ltgt or = Identifiers letters numbersrdquo_rdquordquo$rdquordquordquo letters numbers and ldquo_rdquo Data types Character CHAR CHAR Long Character VARCHAR (2000) if lt= 2000

LONG VARCHAR if gt 2000 CHAR or TEXT

Number (2 bytes) NUMBER SMALLINT Number (4 bytes) NUMBER INTEGER Number (gt 4 bytes) NUMBER DECIMAL Image LONG RAW CLOB BLOB BYTE TEXT CLOB BLOB DML Comments -- hellip -- hellip Assignment var1 = expression LET var1 = expression Condition ELSE IF ELSE or ELIF

IF Aggregate functions Average AVG(expression) AVG(ALL

expression) AVG(DISTINCT expression)

AVG(expression) AVG(ALL expression) AVG(DISTINCT column_name) AVG(UNIQUE column_name)

Count COUNT() COUNT (expression) COUNT(ALL expression) COUNT (DISTINCT expression)

COUNT() COUNT(DISTINCT column_name) COUNT (UNIQUE column_name)

Maximum MAX(expression) MAX(ALL expression) MAX(DISTINCT expression)

MAX(expression) MAX(ALL expression) MAX(DISTINCT column_name) MAX(UNIQUE column_name)

Minimum MIN(expression) MIN(ALL expression) MIN(DISTINCT expression)

MIN(expression) MIN(ALL expression) MIN(DISTINCT column_name) MIN(UNIQUE column_name)

Sum SUM(expression) SUM(ALL expression) SUM(DISTINCT expression)

SUM(expression) SUM(ALL expression) SUM(DISTINCT column_name) SUM(UNIQUE column_name)

Algebraic functions Round ROUND(expressionrounding

factor) ROUND(expressionrounding factor)

Statistical functions Standard Deviation STDEV(expression) STDDEV(expression) Variance VARIANCE(expression) VARIANCE(expression) Range RANGE(expression)

IBM Software Group IBM Information Management

Version 16 83

String functions

Trim LTRIM(expression) RTRIM(expression)

LTRIM(expression) RTRIM(expression)

Length LENGTH(string) LENGTH(string) Like LIKE(string) LIKE(string) Like (single character) _ _ Like (wildcard) String Delimiter lsquo or ldquo lsquo or ldquo Escape Character set within LIKE clause using

ESCAPE ldquordquo to make ldquordquo the escape character

or set within LIKE clause using ESCAPE ldquordquo to make ldquordquo the escape character

Stored procedures Create CREATE OR REPLACE

PROCEDURE procedure_name (var1 IN CHAR(1) var2 OUT DATE var3 IN OUT NUMBER)

DROP PROCEDURE procedure_name CREATE PROCEDURE procedure_name (var1 CHAR(1) var3 INTEGER) RETURNING DATE INTEGER

Arguments EXECUTE PROCEDURE procedure_name (var1 IN var2 OUT var3 IN OUT)

EXECUTE PROCEDURE procedure_name (var1 var3) RETURNING var2 var3

IBM Software Group IBM Information Management

Version 16 84

A P P E N D I X C Database concepts

The table below illustrates the relationship between each database vendorrsquos database objects

Oracle Informix

Database name attached to a group of files Specific database name

Data file Chunk

Tablespace (logical partition) or Segments (Index Segment Table Segment and so on)

Dbspace

Extent Extent

Rollback Segment Physical Log

Redo Log Logical Log

System tablespace Root dbspace

Temporary tablespace Temporary dbspaces dbspacetemp environment variable or dbspacetemp onconfig parameter

Pointer Blobspace Sbspace

Table partitioning table fragmentation

Database link Not supported

Snapshot Not supported

oerr utility finderr utility

sqldba and svrmgrl - monitor utilities onstat and oncheck utilities

SQLPlus utility dbaccess utility

ProC ESQLC

ProCOBOL ESQLCOBOL

SQLNET INet

OCI Like the ESQL function library after pre-compiling if they were publically documented

Read Consistency COMMITTED READ LAST COMMITTED

IBM Software Group IBM Information Management

Version 16 85

A P P E N D I X D Sample code

User defined functions User Defined Routines (UDR) can be developed to extend the capabilities of the database and provides the option to create UDRs to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or rename an Informix function to the corresponding Oracle function name

CONCAT

CREATE PROCEDURE concat (str1 VARCHAR(255) str2 VARCHAR(255)) RETURNING VARCHAR(255) RETURN str1 || str2

END PROCEDURE

INSTR

CREATE PROCEDURE instr( str VARCHAR(255) mask VARCHAR(255) strt SMALLINT DEFAULT 1 occur SMALLINT DEFAULT 1 ) RETURNING INT DEFINE slen SMALLINT DEFINE mlen SMALLINT DEFINE tempstr VARCHAR(255) DEFINE tempmask VARCHAR(255)

DEFINE nomatch SMALLINT DEFINE count SMALLINT DEFINE pos SMALLINT DEFINE retpos SMALLINT DEFINE i SMALLINT DEFINE j SMALLINT DEFINE srchstrt SMALLINT LET slen = LENGTH(str) LET mlen = LENGTH(mask) LET count = 0 LET nomatch = 0 LET pos = 1 LET retpos = 1 LET tempstr = LET tempmask = LET srchstrt = strt

IF (strt lt 0) THEN - reverse the str FOR i = 1 TO slen LET tempstr = str[11] || tempstr LET str = str[2255] END FOR -- reverse the mask FOR i = 1 TO mlen LET tempmask = mask[11] || tempmask LET mask = mask[2255] END FOR

IBM Software Group IBM Information Management

Version 16 86

LET srchstrt = strt -1 LET str = tempstr LET mask = tempmask END IF FOR j = 1 TO slen LET tempstr = str LET tempmask = mask FOR i = 1 TO mlen IF (tempmask[11] = tempstr[11]) THEN LET nomatch = 1 EXIT FOR END IF LET tempmask = tempmask[2255] LET tempstr = tempstr[2255]

END FOR IF (nomatch = 0) THEN IF (pos gt= srchstrt) THEN LET count = count + 1 END IF IF (count = occur) THEN IF (strt lt 0) THEN RETURN slen - pos + 1 ELSE RETURN pos END IF END IF END IF LET str = str[2255] LET nomatch = 0

LET pos = pos + 1 END FOR RETURN 0 END PROCEDURE

YYYYMMDD

CREATE PROCEDURE yyyymmdd (str VARCHAR(10)) RETURNING varchar(8)

DEFINE retstr VARCHAR(8)

IF str IS NULL THEN

RETURN NULL

ELSE

LET retstr = str[710] || str[12] || str[45]

RETURN retstr

END IF

END PROCEDURE

Using EXEC bladelet functions

IBM Software Group IBM Information Management

Version 16 87

Using EXEC

Note the ROW data type variable can be referenced using table and column syntax CREATE PROCEDURE example1() RETURNING INTEGER

DEFINE sql_stmt LVARCHAR(255)

DEFINE rcnt ROW(val INTEGER)

LET sql_stmt = select count() from items where manu_code = lsquoANZrsquo

EXECUTE FUNCTION EXEC(sql_stmt) INTO rcnt

RETURN rcntval

END PROCEDURE

Using EXEC_FOR_ROWS

CREATE PROCEDURE example2() RETURNING INTEGER CHAR(1)

DEFINE rs_rowdata ROW(customer_num INTEGER call_code CHAR(1))

DEFINE sql_stmt LVARCHAR(255)

LET sql_stmt = select customer_num call_code from cust_calls where

customer_num = 106

FOREACH

EXECUTE FUNCTION EXEC_FOR_ROWS(sql_stmt) INTO rs_rowdata

RETURN rs_rowdatacustomer_num rs_rowdatacall_code WITH RESUME

END FOREACH

END PROCEDURE

Using EXEC_FOR_MSET

Note the DEFINE statement for the variable rs_data Collection data types used in a SPL routine cannot be defined using the LIKE attribute in the DEFINE statement CREATE PROCEDURE example3() RETURNING INTEGER VARCHAR(8)

DEFINE v_customer_num LIKE accountscustomer_num

DEFINE v_account_cd LIKE accountsaccount_cd

DEFINE rs_data MULTISET(ROW(

r_customer_num INTEGER

r_account_cd VARCHAR(8)) NOT NULL)

DEFINE sql_stmt LVARCHAR

LET sql_stmt = select customer_num order_num from orders where

company_id = 51155

EXECUTE FUNCTION EXEC_FOR_MSET(sql_stmt) INTO rs_data

FOREACH

SELECT r_customer_num r_account_cd INTO v_customer_num

v_account_cd FROM TABLE(rs_data)

RETURN v_customer_num v_account_cd WITH RESUME

END FOREACH

END PROCEDURE

IBM Software Group IBM Information Management

Version 16 88

Date arithmetic Informix has extensive capabilities for manipulating dates and times You can add or subtract DATE and DATETIME variables from each other You can add or subtract an INTERVAL to a DATE or DATETIME

UNITS Keyword

When working with INTERVAL values sometimes it is necessary to specify the precision with which you are dealing For example suppose you have the following field defined To add 10 days to the lead time you could use a SQL statement like this

SELECT lead_time + INTERVAL(10) DAY to DAY FROM orders

-or- SELECT lead_time + 10 UNITS DAY FROM orders

Using EXTEND function

The EXTEND function allows operations between data types of different precisions SELECT

EXTEND(myvar YEAR to MINUTE) ndash INTERVAL(5) MINUTE to MINUTE

FROM member

Calculate Week Of The Year

SELECT ROUND((TODAY - DATE(0101||YEAR(TODAY))) 7 + 5) FROM DUAL

Number of days difference SELECT DATE(0106||YEAR(TODAY)) - DATE(01062005) FROM DUAL

Number of weeks difference

SELECT ROUND((DATE(0106||YEAR(TODAY)) - DATE(01062005))

7 + 5) FROM DUAL

String representation of date and time

Day and date

SELECT TO_CHAR(TODAY A B d Y) FROM dual

-returns month day and 4 digit year-

Tuesday January 03 2006

Abbreviation of day of week

SELECT SUBSTR(TO_CHAR(TODAY A B d Y R)13) FROM dual

-or-

SELECT TO_CHAR(TODAY a) FROM dual

-returns MON TUE WED THU FRI SAT SUN-

Returning the number of rows affected

IBM Software Group IBM Information Management

Version 16 89

Within SPL routines you can use the DBINFO function to find out the number of rows that have been processed in SELECT INSERT UPDATE DELETE EXECUTE PROCEDURE and EXECUTE FUNCTION statements

CREATE FUNCTION del_rows(pnumb INT) RETURNING INT

DEFINE nrows INT

DELETE FROM sec_tab WHERE part_num = pnumb

LET nrows = DBINFO(sqlcasqlerrd2)

RETURN nrows

END FUNCTION

To ensure valid results use this option after SELECT and EXECUTE PROCEDURE or EXECUTE FUNCTION statements have completed executing If you use the sqlcasqlerrd2 option within cursors make sure that all rows are fetched before the cursors are closed

Using an Informix collection data type

A collection data type as a VARRAY

In the following examples the collection data types of MULTISET and SET are used in a function to hold a collection of values You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value Informix SPL allows you to declare a cursor for a collection variable using the FOREACH statement called a collection cursor

Also demonstrated is how to utilize a variable declared with the keyword COLLECTION A variable declared as type SET MULTISET or LIST is a typed collection variable It can hold a collection of its specified data type only However a COLLECTION is an un-typed (or generic) collection variable that can hold a collection of any data type

This function will build a MULTISET list of values

CREATE FUNCTION func1() RETURNING MULTISET(INTEGER NOT NULL)

DEFINE v_array_of_ints MULTISET(INTEGER NOT NULL)

INSERT INTO TABLE (v_array_of_ints) VALUES(1)

INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(5)

INSERT INTO TABLE (v_array_of_ints) VALUES(4)

RETURN v_array_of_ints

END FUNCTION

This function will receive the COLLECTION list of values from func1

CREATE FUNCTION func2() RETURNING INTEGER

--

-- DEFINE lmset MULTISET(INTEGER NOT NULL)

--

DEFINE lmset COLLECTION

DEFINE v_int INTEGER

--

-- call func1 to populate local multiset variable

--

LET lmset = func1()

--

-- tally a count the number of elements

--

FOREACH

SELECT COUNT() INTO v_int FROM TABLE(lmset)

IBM Software Group IBM Information Management

Version 16 90

RETURN v_int WITH RESUME

END FOREACH

--

-- return the values

--

FOREACH

SELECT INTO v_int FROM TABLE(lmset)

RETURN v_int WITH RESUME

END FOREACH

END FUNCTION

NOTE In the example func2 a duplicate declaration for the ldquolmsetrdquo variable as a MULTISET data type has been commented out by declaring the variable as a COLLECTION it can accept any of the 3 types (MULTISET SET and LIST)

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

4 (row count) 1 2 5 4

By using a SET data type inserts will not permit duplicates

CREATE FUNCTION func1() RETURNING SET(INTEGER NOT NULL) DEFINE v_array_of_ints SET(INTEGER NOT NULL) INSERT INTO TABLE (v_array_of_ints) VALUES(1) INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(2) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) RETURN v_array_of_ints END FUNCTION

NOTE Because func2 is expecting a un-typed COLLECTION variable func1 does not have to be dropped and recreated It can receive a value from any Collection Data Type (MULITSET SET and LIST)

The functionrsquos return values would change to (with duplicates suppressed)

EXECUTE FUNCTION func2()

(expression)

3 (row count) 1 2 5

Using a LIST data type support for assigning values based on ordinal position

IBM Software Group IBM Information Management

Version 16 91

CREATE FUNCTION func1() RETURNING LIST(INTEGER NOT NULL)

DEFINE v_array_of_ints LIST(INTEGER NOT NULL) -- -- first insert no ordinal position can be established By default the -- database server inserts LIST elements at the end of the list -- INSERT AT 5 INTO TABLE (v_array_of_ints) VALUES(5) INSERT AT 1 INTO TABLE (v_array_of_ints) VALUES(1) INSERT AT 2 INTO TABLE (v_array_of_ints) VALUES(2) -- -- Only 3 LIST elements exist position 4 has not been instantiated -- this element will insert at the end of the list -- INSERT AT 4 INTO TABLE (v_array_of_ints) VALUES(4) INSERT AT 3 INTO TABLE (v_array_of_ints) VALUES(3) RETURN v_array_of_ints END FUNCTION

NOTE The elements of a LIST have ordinal positions with a first second and third element in a LIST To support the ordinal position of a LIST the INSERT statement provides the AT clause This clause allows you to specify the position at which you want to insert a list-element value Note the behavior of the ordinal positioning above preceded by a commented explanation

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

5 (row count) 1 2 3 5 4

Using MULTISET and ROW to replace PLSQL TABLE and RECORD types

Creating variables using Informix Collection data types SET MULTISET and LIST in combination with ROW data types can be useful when migrating applications which use Oracle REF CURSORS as arguments to functions as well as Oracle collection data types TABLE and RECORD

Typical Oracle Package specification

CREATE OR REPLACE PACKAGE MyPackage

IS

TYPE recOrders IS RECORD (

order_num ordersorder_numTYPE

order_date ordersorder_dateTYPE

customer_num orderscustomer_numTYPE

po_num orderspo_numTYPE

)

TYPE tabOrders IS TABLE OF recOrders

INDEX BY BINARY_INTEGER

TYPE ref_curtype IS REF CURSOR

Both tabOrders or ref_curtype can be converted to the following Informix SPL definition

DEFINE tabOrders MULTISET(ROW(

IBM Software Group IBM Information Management

Version 16 92

order_num INTEGER

order_date DATETIME YEAR TO FRACTION(3)

customer_num INTEGER

po_num CHAR(10)) NOT NULL)

DEFINE ref_curtype MULTISET(ROW(

define columns based on query result set

) NOT NULL)

IBM Software Group IBM Information Management

Version 16 93

A P P E N D I X E Counting system objects

Using the system catalog

System catalog

Below is a list of SQL statements that will extract most if not all of the counts of system objects owned by user lsquoXXXrsquo

select count(table_name) from all_tables

where owner=rsquoxxxrsquo

select count() from dba_indexes

where owner=rsquoxxxrsquo

select count(synonym_name) from dba_synonyms

where owner=rsquoxxxrsquo

select count() from dba_views

where owner=rsquoxxxrsquo

select count() from dba_tab_columns

where length(column_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

and owner=rsquoxxxrsquo

select count distinct() from dba_tab_columns

and owner=rsquoxxxrsquo

select count() from dba_tables

where length(table_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_synonyms

where length(synonym_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_views

where length(view_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_indexes

where length(index_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and owner=rsquoxxxrsquo

IBM Software Group IBM Information Management

Version 16 94

select data_type count(data_type) from dba_tab_columns

where owner=rsquoxxxrsquo

group by data_type

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and length(data_type)gt254

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquonumberrsquo

and data_scale=0

and owner=rsquoxxxrsquo

Using SQL code

Built-in function references

The following instructions can be used to find references to built-in functions On the UNIX machine or the NT box where your code resides please create the following file as tmpfunctionlist

convert(

hextoint(

inttohex(

getdate(

datename(

datepart(

datediff(

dateadd(

months_between(

char(

char_length(

charindex(

compute(

difference(

length(

lower(

patindex(

replicate(

reverse(

right(

soundex(

space(

str(

stuff(

substring(

upper(

abs(

atn2(

log(

ceiling(

IBM Software Group IBM Information Management

Version 16 95

cot(

degrees(

floor(

radians(

rand(

sign(

to_char(

to_date(

to_number(

exception(

pi(

raise_application_error(

raiserror(

SQLCODE

rollback

savepoint

declare

decode(

nvl(

print(

rowid

waitfor

recompile

bcp

isopen(

notfound(

rowtype(

type(

Then please run the following program with the proper subdirectories

binksh

rm ndashf somehomeoutfile

cd somesourcedatabase

export sourcebase=rdquosomepathrdquo

for functor in `cat tmpfunction_list`

do

echo before find $functor

find $sourcebasedatabase -exec grep -i $functor gtgt

somehome$functoroutfile

find $sourcebaseintfc -exec grep -i $functor gtgt

somehome$functoroutfile

echo after find $functor

done

Object types and counts

This script attempts to count the objects of each type by grepping for CREATE statements containing the object type and counts procedure definitions that are inside package bodies which are not proceeded by a CREATE keyword It is not a sophisticated parser so the results may not be perfect

binbash if [ $1 = ] then

IBM Software Group IBM Information Management

Version 16 96

echo Usage objCountssh ltFilePatterngt return 1 fi declare -a objectTypes=(CLUSTER CONTEXT CONTROLFILE DATABASE DATABASE +LINK DIMENSION DIRECTORY DISKGROUP FUNCTION INDEX INDEXTYPE JAVA LIBRARY MATERIALIZED +VIEW MATERIALIZED +VIEW +LOG OPERATOR OUTLINE PACKAGE PACKAGE +BODY PFILE PROCEDURE PROFILE RESTORE +POINT ROLE ROLLBACK +SEGMENT SCHEMA SEQUENCE SPFILE SYNONYM TABLE TABLESPACE TRIGGER TYPE TYPE +BODY USER VIEW) echo for type in $objectTypes[] do if [ $type = PROCEDURE ] then echo $type object count `cat $1 | grep -icE ^ (|CREATE +|OR REPLACE +)b$typeb` else echo $type object count `cat $1 | grep -icE ^ (CREATE +|OR +REPLACE +)b$typeb` fi done

IBM Software Group IBM Information Management

Version 16 97

A P P E N D I X F Data type mapping

Oracle built-in data types (including ANSI types) can be converted to similar data types in the Informix database according to the mapping described here This table provides default mappings based on most common usage patterns in some cases another mapping may work better

In the following table n is used to indicate length p is used to indicate precision and s is used to indicate scale

Oracle data type Informixreg Server data type

BFILE LONG RAW BLOB

BLOB

BINARY_DOUBLE DOUBLE PRECISION

BINARY_FLOAT DOUBLE PRECISION

BINARY_INTEGER

PLS_INTEGER

NATURAL

NATURALN

POSITIVE

POSITIVEN

32-bit integers only used in PLSQL NATURAL and POSITIVE are unsigned integers

INTEGER

BOOLEAN (PLSQL only) BOOLEAN

CHAR(n) or CHARACTER(n) CHAR(n)

DATE DATETIME YEAR TO SECOND

DOUBLE PRECISION DOUBLE PRECISION

IBM Software Group IBM Information Management

Version 16 98

FLOAT

See note on FLOAT below

FLOAT

INTEGER INT

A 38-digit NUMBER sub-type May want to flag with a warning on possible overflow

INTEGER

INTERVAL DAY(p) TO SECOND(s)

Note Oracle fractional seconds have 9 digits

INTERVAL DAY(p) TO FRACTION(min(5 s))

INTERVAL YEAR(p) TO MONTH

INTERVAL YEAR(p) TO MONTH

LONG CLOB

CLOB

LONG VARCHAR (xxx)

Oracle recommends not using this type

LVARCHAR

NCHAR(n) NATIONAL CHAR(n) or NATIONAL CHARACTER(n)

NCHAR(n)

See National Language Types below

NCLOB CLOB

NUMBER

NUMBER(0)

NUMBER(p) NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s lt 10

NUMBER(3-2) 12300

INTEGER

IBM Software Group IBM Information Management

Version 16 99

NUMBER(p) NUMBER (p0)

Where precision (p) is greater than or equal to 10 and lt= 18

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and 10 lt= p-s lt 19

NUMBER(9-2) 12345678900

BIGINT

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is greater than or equal to s (that is s gt 0 and p gt= s)

NUMERIC (min(p32) min(s32))

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is less than s (that is s gt 0 and p lt s)

NUMBER(35) 000123

NUMERIC (min(s32)min(s32))

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s gt 18 and p-s lt= 32

NUMERIC (min(p-s32)0)

NUMBER(p s)

Where scale (s) is greater than 32 or pInformix-s is greater than 32

NUMERIC (32)

Scale cannot be greater than precision

NUMERIC(3232) would guarantee that digits to the left of the decimal would be lost Using a floating point decimal provides the simplest best way to capture as many digits in a value as possible

IBM Software Group IBM Information Management

Version 16 100

DEC

DECIMAL

NUMERIC

DEC(p)

DECIMAL(p)

NUMERIC(p)

DEC(p s)

DECIMAL(p s) NUMERIC(p s)

There is no difference within Oracle between these types and each other and these types and NUMBER The Oracle system catalogs contain the NUMBER type id for all declarations of these types and the integer types as well Declarations of these types can be mapped using the same rules as those for NUMBER

NVARCHAR2(n) NCHAR VARYING(n) NATIONAL CHAR VARYING(n) NATIONAL CHARACTER VARYING(n)

LVARCHAR(min(n 32767))

RAW(n) BLOB

REAL DOUBLE PRECISION

Record ROWTYPE

Using a CREATE ROWTYPE statement

ROWID INTEGER

SMALLINT SMALLINT

TIMESTAMP(p)

If p is not specified precision defaults to 6

DATETIME YEAR TO FRACTION(min(5 p))

UROWID(n) INTEGER

IBM Software Group IBM Information Management

Version 16 101

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is less than or equal to 255 (that is n lt= 255)

VARCHAR(n)

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is greater than 255 (that is n gt 255)

LVARCHAR(n)

XMLType CLOB

Notes on specific types are below

DOUBLE

The range of values for the DOUBLE PRECISION data type is the same as the range of the C double data type on your computer

VARCHAR

While Oracle VARCHAR data types have a limit of 4000 bytes an Informix Server VARCHAR data types has a limit of 255 bytes An Informix Server LVARCHAR has a limit of 32739 Bytes

NUMBER

Oracle abstracts its numeric types from the hardware and operating system through the use of its NUMBER type Most numeric types like INTEGER are actually NUMBERs internally When porting to a database server like Informix which retains more of a relationship between the operating system types and the database types it is essentially a one-to-many mapping and heuristics have to be used to determine the best-fit target type No single set of type mapping rules will fit all use scenarios The converter has default rules which fit the more common user patterns When considering a number represented as mantissa and exponent

mantissa x 10exponent

precision is the number of digits in the mantissa and scale is the negative exponent how many places to the right of the decimal point the least significant digit is located Oracle NUMBERs have a maximum precision of 38 and the maximum precision available in Informix native types is 32 The first step in a type mapping is to truncate the target type precision to min(precision 32) The scale of a type can be considered its anchor point with respect to the decimal point The most

IBM Software Group IBM Information Management

Version 16 102

significant digit of a numeric type is located precision digits to the left of the decimal point and precision-scale digits to the right of the decimal point The start and end locations of the digits are used to determine the closest fitting Informix type The order of preference is INTEGER BIGINT NUMERIC(p s) and lastly NUMERIC(p) NUMERIC(p) in a non-ANSI mode database is a decimal type with a floating point type In an ANSI mode database the scale is implicitly 0 All Oracle integer declaration types such as INT INTEGER SMALLINT become NUMBER(38) type in the Oracle metadata In Oracle when precision is given but scale is not scale becomes 0 implicitly which makes the type in the set of integral types One exception to the general mapping rules is the NUMBER type specified without precision or scale Strictly speaking this has a floating point scale with 38 digits of precision but most commonly it is used where an integer is more appropriate Even if the user does specify INTEGER in a type definition when it comes out of the Oracle catalogs the type is NUMBER This is one case in particular where one type mapping will not fit well with all usage scenarios

National language types

Oracle Nchar types are allocated by number of characters where Informix is allocated by the number of bytes For Oracle the storage size of the characters varies with the encoding used and is always subject to the standard 32767 limit on maximum bytes but during declarations n always means the number of characters Oracle PLSQL supports explicit and implicit data type conversions These explicit and implicit data types are converted to syntax by using Informix Dynamic Servers explicit and implicit data type conversion mechanism

ROWID

Oracle databases support a pseudo-column named ROWID such that every row in every table is assigned an auto-generated ID Oracle also allows you to define a column of type ROWID which can be used as a foreign key to a ROWID pseudo-column Oracle ROWID columns contain data that if converted to a string are 18 characters long for example lsquoAAAQ+jAAEAAAAAeAANrsquo It is probably not advisable to migrate this data to an Informix database and instead use the Informix type which is an integer If there is a dependency on the values themselves and therefore need migrate the data then an integer type would not hold the values

TYPE

In PLSQL you can refer to the type of an existing variable field or column by using the TYPE attribute The converter replaces this reference directly by the type it refers to

ROWTYPE

In PLSQL you can refer to the record type that represents a row of a table a cursor or a cursor variable PLSQL scripts containing the ROWTYPE attribute are handled in the same way as a record type that has been previously declared

FLOAT

Oracle FLOAT type is a floating point number capable of storing up to 38 decimal digits or 126 binary digits It has a floating point scale that can exist outside the boundaries of what an Informix DECIMAL can represent A C language double or Informix float type is capable of only 16 digits so there is the chance that some data will be lost Using an Informix FLOAT type makes it so that less significant digits are lost in preference to more significant digits

IBM Software Group IBM Information Management

Version 16 103

References to subtypes declared in packages and PLSQL blocks are converted to the Informix Server equivalent base types Variables of type RECORD are not translated by the DDL Converter at the time of this writing They will be handled by the stored procedure converter

XMLType

Informix does not have a built-in type for representing XML The nearest approximation is to store it in a CLOB Another character type like LVARCHAR can be used if it can be determined that the actual data will fit in it

Page 7: Oracle to IBM Informix Server Porting Guide

IBM Software Group IBM Information Management

Version 16 7

A P P E N D I X C DATABASE CONCEPTS 84

A P P E N D I X D SAMPLE CODE 85

DATE ARITHMETIC 88 UNITS Keyword 88 Using EXTEND function 88

STRING REPRESENTATION OF DATE AND TIME 88 Day and date 88 Abbreviation of day of week 88

USING AN INFORMIX COLLECTION DATA TYPE 89 A collection data type as a VARRAY 89 Using MULTISET and ROW to replace PLSQL TABLE and RECORD types 91

A P P E N D I X E COUNTING SYSTEM OBJECTS 93

USING THE SYSTEM CATALOG 93 System catalog 93

USING SQL CODE 94 Built-in function references 94 Object types and counts 95

A P P E N D I X F DATA TYPE MAPPING 97

DOUBLE 101 VARCHAR 101 NUMBER 101 National language types 102 ROWID 102 TYPE 102 ROWTYPE 102 FLOAT 102 XMLType 103

IBM Software Group IBM Information Management

Version 16 8

C H A P T E R 1 Introduction

This document is a technical document describing the differences between Oracle and Informixreg Dynamic Server (IDS) functionality and syntax This porting guide details differences between Oraclersquos 10g release 1 (101) and 10g release 2 (102) and Informix Dynamic Server (version 1110) In addition it can be a useful reference for all migrations between the two database servers regardless of version In addition to DDL DML and overall SQL syntax this document explores the differences between Oracle and Informix with regards to object technology through the use of large objects user defined types and user defined routines It also looks at the differences between Oraclersquos table partitioning and Informixrsquos table fragmentation Part of the explanation is a discussion on what needs to be changed to make an application running on an Oracle database run on an Informix database If there is more than one way to port some piece of functionality alternatives and recommendations are also discussed This document is intended to be a living document Missing items better ways of implementing Oracle functionality in Informix other than what is documented here examples to better illustrate a point and other suggestions should be sent to Chris Golledge (golledgeusibmcom) so they may be included with future revisions

Purpose This document should be used as a guide to assist in porting applications that run on an Oracle database server to run on an Informix database server Regardless of whether a porting effort will be completely manual or if tools will be utilized this document can provide value Obviously if the port is performed manually this guide will provide the most value If the port will utilize tools then analysis can be performed using this guide to determine how much of the application the tools will convert and how much must be converted manually In any case this guide is intended to be used to both visualize the scope of a porting effort and to aid in the porting effort by addressing the technical issues This document will be refined based on usersrsquo experiences to identify as many of the porting issues as possible at the beginning of a project

Product overview IBM Informix Server provides high performance and scalability with legendary reliability and nearly hands-free administration of databases of all size IDS is industry proven on UNIX Linux or Windows platforms with online transaction processing (OLTP) systems data marts data warehouses and e-business applications The IDS 11 release features significant additions over prior versions It supports the services-oriented architecture (SOA) model for application integration and offers many new features for data replication continuous availability and ldquohands freerdquo database administration

Organization This document is broken into sections to logically discuss the different database concepts Some of the sections may contain the same sub-sections for example stored procedures and triggers

IBM Software Group IBM Information Management

Version 16 9

are discussed in the DDL and DML sections This allows separate discussions on the issues facing the same item in each area For example the issues surrounding creating a stored procedure are discussed in the DDL section and the issues surrounding the stored procedure language are discussed in the DML section Among the other references the ldquoPlanning Guiderdquo appendix contains a quick reference of most of the differences between Oracle and Informix along with the degree of difficulty to port each difference This reference is intended for use in the planning process to illustrate the scope and the effort required to perform the porting project Some of the stored procedure logic used to convert Oracle functions is included in the appendix rdquoSample coderdquo

Conventions The conventions used in this document include

Courier Text Distinguishes a logic example

from regular text

Example Illustrates a point In most cases an Oracle example will be followed by an Informix example

Italicized Text Signifies a substitution in other words substitutes for the italicized word the actual object the word is describing for example table_name column_name and so on

UPPER CASE TEXT Signifies database vendor reserved words or statements such as INTEGER CREATE TABLE and so on

Bold example text highlights the item that is being explained

IBM Software Group IBM Information Management

Version 16 10

IBM Software Group IBM Information Management

Version 16 11

C H A P T E R 2 Defining the Problem Space

It is important to define the set of objects to be migrated and it is better if effort is put into this prior to beginning the actual migration This is true if you are the responsible for both the database in general and its migration from one supporting DBMS to another but it is particularly true that there be a clear agreement on the scope of what is to be migrated if the migration is to be performed by a party other than the one with long term responsibility for the database Defining the scope will involve extracting a representation of the objects to be migrated out of the Oracle system catalogs and representing them in some format that can be manipulated into constructs that can be used in Informix

Extracting the objects to be migrated It is possible to represent the objects in more than one language Using the SQL language is the most common method and it will be the only one discussed at length in this document (in its current revision) However it is also possible to express database objects in XML SQL has the advantage that the standard common grammars are widely understood in the context of defining tables indexes etc XML would have an advantage of not requiring parsing that is sensitive to the minor differences in ways of expressing essentially the same object

Working With Oracle Dump Files

There exist 3rd

-party tools for reading system catalogs but it is doubtful that any can read the Oracle catalogs more reliably than Oraclersquos own tools There are two incompatible export and import tool sets used by Oracle The older tools are imp and exp and the newer ones are impdp and expdp where dp stands for Data Pump Oracle has encouraged the use of the newer tools instead of the older ones since the newer ones were introduced at version 10 Nonetheless there are many Oracle users still using imp and exp In the discussions below only the metadata will be extracted into a dump file That is because any data in the dump file will be in a proprietary format and very likely some of the data will have to go through a type conversion process before being loaded into an Informix system Oracle exported data generally cannot be used to load a database in Informix Export and Import

If someone has given you a dump file created with the older export tool there exist tools such as The DDL Wizard by Net 2000 Limited which can be used to extract viable DDL The contents of the dump file contain the SQL for re-creating the database but they are not in a readily usable format The older export and import tools are also more sensitive to the layout of the tablespaces than impdb The ability to extract DDL from the dump file in a usable form segmented by whatever grouping you choose is limited compared to what can be achieved through the Data Pump versions

IBM Software Group IBM Information Management

Version 16 12

It may be tempting to feed the dump file into the IBM Migration Toolkit (MTK) or other tool that works on SQL flat files This will not work MTK works on flat text SQL files and the dump file is binary If you open it up you can see what may be a large number of SQL statements but there are also binary codes within the same file That binary data will prevent MTK from being able to process it Getting SQL statements

If you want to get the SQL statements out of the dump file as they would be executed on the server there is an option available from the import tool itself show=y

imp myIDmyPWD as sysdba file=myFiledmp

full=yes show=y gt dmp_showtxt

This will produce a file which contains the statements but they are wrapped in quotes The contents will look something like

ALTER SESSION SET CURRENT_SCHEMA= SYSTEM CREATE UNDO TABLESPACE TBSPC1 BLOCKSIZE 8192 DATAFILE DORACLEORADA TASCHEMA1CHUNKDBF SIZE 387973120 AUTOEXTEND ON NEXT 5242880 MAXS IZE 32767M EXTENT MANAGEMENT LOCAL

which makes them strings instead of SQL statements Fixing this is a two-step process

-- removes quotes from the start of lines

sed s^ g dmp_showtxt gt step1txt

-- removes quotes from the end of lines

sed s$g step1txt gt dmp_step2sql

The statements are still not correctly formatted because they have been truncated to a fixed length and line-endings inserted However at this point it is possible to get a count of how many of each object type there is using the script in the appendix ldquoGetting an initial count of database objectsrdquo

Data Pump Export and Import

These newer tools provide better performance and more capabilities than their predecessors Please refer to documentation on Oracle for a complete description searches for ldquoData Pump Importrdquo and ldquoData Pump Exportrdquo should return relevant results quickly Below is enough information to get started on defining and extracting the objects to be migrated Metadata can be filtered through the use of the export mode clause and INCLUDE and EXCLUDE parameters However any dependent object of an included or excluded object is likewise included or excluded For example if you include an index then the table associated with the index will also be included and if you exclude a table then any associated indexes will also be excluded The SQL that will generate all the objects in the dump file can be created by the impdp command with the SQLFILE parameter If the output file is very large you might want to break it into smaller pieces There are a couple of ways to do this and the one that is best for you somewhat depends

IBM Software Group IBM Information Management

Version 16 13

on how you intend to proceed with the conversion Data definition language (DDL) SQL for all the objects can be put into one file or the INCLUDE or EXCLUDE parameters can be added to direct Data Pump to filter on the types of objects If you put all the objects into one file then you can break that into smaller files by object type fairly easily because the objects are sorted by type in the SQL file So it is just a matter of cutting the file into smaller pieces This method may be preferred because it allows for you to do things like create all tables load the data and then create the indexes and triggers If the data set is large creating the indexes after loading the data can yield substantial performance improvements However this is less useful if you want to convert sets of objects according to dependencies in which case the filtering option is likely to be more useful Just to illustrate a difference between these two methods in one customer case the metadata dump file was about 18MB and putting all objects in one SQL file resulted in a file that was about 15MB The table definitions occupied a little under 300KB of the 15MB The output file generated by filtering on objects of type TABLE was just over 1MB The addition content was mostly GRANT INDEX and TRIGGER creation statements There were no differences in the CREATE TABLE statements themselves Examples

Prerequisite The Data Pump tools require the use of an Oracle DIRECTORY object This is basically a mapping between a name that exists within the DBMS and a system path It can be a tripping point but it provides an abstraction layer that for instance allows the same commands to work across systems with different disk layouts or different operating systems Creating a DIRECTORY on a Windows system from SQLPlus

SQLgtconnect as sysdba

SQLgtCREATE OR REPLACE DIRECTORY dumpDir AS ctemp

Note Make sure this directory is not read-only There also could be problems if the directory is a network drive on Windows these can be related to there being different users between the Oracle executable and the current user and those users having different permissions on the network drive

SQLgtGRANT read write ON DIRECTORY dumpDir TO userID

Creating a dump file of the entire database

expdp userNameuserPwd as sysdba FULL=Y dumpfile=DB_fulldmp

LOGFILE=LG_expdplog CONTENT=METADATA_ONLY DIRECTORY=dumpDir

Creating a dump file of just one schema

expdp userNameuserPwd as sysdba SCHEMAS=hr DIRECTORY=dumpDir

DUMPFILE=hr dmp LOGFILE=hr log CONTENT=METADATA_ONLY

Creating a dump of just the tables and their dependents

expdp userNameuserPwd as sysdba SCHEMAS=hr INCLUDE=TABLE

DIRECTORY=dumpDir DUMPFILE=hrdmp LOGFILE=hrlog

CONTENT=METADATA_ONLY

Creating a dump of just one table

expdp userNameuserPwd as sysdba SCHEMAS=hr

INCLUDE=TABLELIKE COUNTRIES DIRECTORY=dumpDir

DUMPFILE=hrdmp LOGFILE=hrlog CONTENT=METADATA_ONLY

IBM Software Group IBM Information Management

Version 16 14

Creatinge an SQL file from a dump file

impdp userNameuserPwd as sysdba DIRECTORY=dumpDir

DUMPFILE=hrdmp SQLFILE=dumpDirhrsql

The INCLUDE and EXCLUDE options are also valid when used with impdb so it may be easier to get a complete dump of everything to be migrated then use these options to create subsets of objects it smaller SQL files than it would be to create separate dump files It is easier to divide objects than to merge them together if they are not divided initially as wanted There is a caveat when using this impdp to generate an SQL file the object names will all be delimited identifiers Example

CREATE TABLE HRCOUNTRIES Because of differences between how Informix handles these and how Oracle handles these case-sensitivity issues could occur See the chapter on ldquoDelimited Identifiersrdquo and in particular the description of default shift problems If it can be determined that there are no name collisions if regular identifiers are used removing the quotation marks as part of the conversion might avoid many problems In other words if there are no objects whose names only differ in case like foo and FOO then changing every occurrence of ldquoFOOrdquo to FOO in the DDL could eliminate case-sensitivity issues in the application DML It depends on if the application code uses the delimited form of the name predominantly or not

IBM Software Group IBM Information Management

Version 16 15

C H A P T E R 3 Data Definition Language

Identifiers An identifier specifies the simple name of a database object such as a table name column name index name view name stored procedure name and so on The maximum length of an Oracle identifier is 30 characters and can contain letters numbers ldquo_rdquo ldquo$rdquo and ldquordquo although Oracle highly recommends that ldquo$rdquo and ldquordquo should not be used In contrast Informix identifiers have a maximum length of 128 characters and may contain letters numbers ldquo_rdquo and ldquo$rdquo (as long as ldquo$rdquo is not the first character) See the Delimited Identifiers section below for information This means that all Oracle identifiers containing a ldquordquo anywhere in the identifier or a ldquo$rdquo as the first character must be replaced or modified to remove those characters from the identifier

Delimited identifiers

Delimited identifiers are also known as quoted identifiers and sometimes as escaped identifiers They have been part of the SQL standard since SQL92 but existed in various database management systems (DBMS) prior to that time In a nutshell they are a way to preserve case sensitivity in object names as well as to allow objects to have names outside of the conventions of SQL regular identifiers Prior to the behavior of identifiers in general being standardized different DBMS vendors implemented different means of achieving case-insensitivity for object names some converted all regular identifiers to uppercase and some converted regular identifiers to lowercase By SQL99 the concept of case normal form was standardized to mean simply stated that if there exists an uppercase equivalent of any character in a name then the uppercase version is stored in the system catalogs and used for comparison purposes See the SQL99 standard chapter 5 section 2 and in particular items 21 and 22 for a formal description of case normal form and how it applies to identifier comparisons Delimited identifiers can be used to specify names for database objects that are otherwise identical to SQL reserved keywords such as TABLE WHERE DECLARE and so on The only database object for which delimited identifiers cannot be used is a database name Database administrators and application programmers do not always communicate to each other with 100 efficiency and there is no guarantee that within either of these pools every member codes by the standard practice of the other members After describing how delimited identifiers work in Informix there will be a description of how any inconsistency of usage and the differences between Oracle and Informix can introduce some migration hurdles DELIMIDENT Environment Variable

To use delimited identifiers with Informix you must set the DELIMIDENT environment variable While DELIMIDENT is set strings enclosed in quotation marks ( ldquo ) are treated as identifiers of database objects and strings enclosed in apostrophes ( rsquo ) are treated as literal strings If the

IBM Software Group IBM Information Management

Version 16 16

DELIMIDENT environment variable is not set strings enclosed in quotation marks are also treated as literal strings When you set the DELIMIDENT environment variable you cannot use quotation marks ( rdquo ) to delimit literal strings If DELIMIDENT is set the database server interprets all strings enclosed in quotation marks as SQL identifiers not string literals Commonly within Informix systems DELIMIDENT is set or not on the client side according to the design of the application However if you are converting a database and all applications accessing it from a system where every occurrence of quotation marks (ldquoobjectNamerdquo) indicates an identifier and not a string literal you may want to consider setting it in the server environment in order to avoid any inconsistency between clients where it is set and where it might not be Using Quotes in Strings The apostrophe ( rsquo ) has no special significance in string literals delimited by quotation marks Conversely double quote ( Prime ) has no special significance in strings delimited by apostrophes For example these strings are valid Nancyrsquos puppy jumped the fence

rsquoBilly told his kitten No rsquo A string delimited by quotation marks can include a double quote character by preceding it with another double quote as the following string shows Enter y to

select this row When the DELIMIDENT environment variable is set quotation marks can only delimit identifiers not strings Use of Uppercase Characters You can specify the name of a database object with uppercase characters but the Informix server shifts these to lowercase characters unless the DELIMIDENT environment variable is set and the name of the database object is enclosed in quotation marks In this case the database server treats the name of the database object as a delimited identifier and preserves the uppercase characters in the name Delimited Identifiers By default the character set of a valid SQL identifier is restricted to letters digits underscore and dollar-sign symbols If you set the DELIMIDENT environment variable however SQL identifiers can also include additional characters from the codeset implied by the setting of the DB_LOCALE environment variable See the Identifier section of the Informix Guide to SQL Syntax for more information Storage Object Names In Informix delimited identifiers can be used to specify non-alphanumeric characters in the names of database objects However delimited identifiers can not be used to specify non-alpha characters in the names of storage objects such as dbspaces and blobspaces To use delimited identifiers DELIMIDENT must be set both at compile and run times For example to set DELIMIDENT environment variable with sh or ksh issue the following at the command line prompt

export DELIMIDENT=

Note You do not need to assign a value to the environment variable and counter-intuitively setting DELIMIDENT=n has the same effect as DELIMIDENT=y Also in a Windows environment

set DELIMIDENT=

effectively undefines the variable Default shift problems

Any direct access of system catalog information involving names will cause problems when migrating from a system like Oracle where system catalog names are stored in uppercase to a system like Informix where the catalog names are stored in lowercase For example

CREATE TABLE foo (c1 int)

IBM Software Group IBM Information Management

Version 16 17

Within Oracle the following will return information about the table

select from sysall_objects where object_name = FOO

and the following will not

select from sysall_objects where object_name = foo

Conversely in Informix

select from systables where tabname = foo

will be successful and the same with FOO will not be A similar if not more common problem can occur when the table has been created without the name being delimited but is sometimes delimited when accessed by the application Per the standard foo == FOO == ldquoFOOrdquo but in Informix foo == FOO == ldquofoordquo In Oracle the following SELECT statement will be successful

SELECT FROM ldquoFOOrdquo

but within Informix this will result in an error ldquo206 The specified table (FOO) is not in the databaserdquo Likewise if the name is delimited in its definition such as

CREATE TABLE SCHEMA1TABLE1

this creates a table that can be referenced in Oracle without the name being delimited The statements

SELECT FROM schema1table1

and SELECT FROM SCHEMA1TABLE1

will be successful in the Oracle system but will fail in the Informix one In theory whether on object name is delimited or not should be the same in the database and at every occurrence within the application but this is not always the case It may be beneficial to examine whether delimited identifiers or regular identifiers are most commonly used in application code and use whichever is most common as a naming convention when translating the DDL

Explicit versus implicit schemaowner names

Another complication to keep in mind is that when the log mode is ANSI implicit and explicit owner names are treated differently between the Oracle and Informix servers In Oracle there is no difference in the case handling of an implicit owner name and an explicit one For example if connected to Oracle as scott the following CREATE TABLE statements

create table foo1(c1 int) create table scottfoo2(c1 int) create table SCOTTfoo3(c1 int)

all result in tables owned by SCOTT The following select statements in various forms that may be in application code will all run without error

select from foo1 select from scottfoo1

IBM Software Group IBM Information Management

Version 16 18

select from SCOTTfoo1 select from foo2 select from scottfoo2 select from SCOTTfoo2 select from foo3 select from scottfoo3 select from SCOTTfoo3

These statements will also run without error within a non-ANSI mode Informix database but not all of them will run successfully within an ANSI mode database This is because Informix does not uniformly fold the case of owner names and handles implicit names differently from explicit names so there will always be some combination of DDL and DML usage patterns that work within an Oracle system that do not work in an Informix one You can set ANSIOWNER before starting your Informix server but that will merely change which combinations do not work You may want to examine usage patterns within the applications and choose a naming convention when translating the DDL that matches the most common naming convention used in the applications Note This behavior of Informix forces a tradeoff between using an ANSI mode database which most closely matches the transaction behavior of Oracle and a non-ANSI mode database which has the least mismatch in identifier case sensitivity

Reserved words or keywords

Oracle and Informix both allow identifiers to be reserved words as long as they are delimited However Oracle and Informix reserved words differ In addition both systems have keywords like FROM that are not always reserved in the sense that using them as an identifier will always generate a syntax error There should be few problems with reserved words or keywords if identifiers that are delimited in the original database remain delimited in the destination database The appendix Keywords of SQL for IBM Informix in the Guide to SQL Syntax contains more information about Informix keywords Also one word non-delimited identifiers should be verified against the Informix reserved words list to ensure that they do not need to be delimited or renamed Although almost any word can be used as an identifier in Informix syntactic ambiguities can result from using reserved words as identifiers in SQL statements Delimited identifiers provide a way to use a reserved word as an identifier without causing syntactic ambiguities However doing this changes a case-insensitive name into a case-sensitive one and that means that every reference to the object has to be checked for issues related to case-sensitivity Essentially this is not much less work than changing the name of the object because in essence it is changing the name of the object Examples

The following example shows how to create an Informix table with a case sensitive table name

CREATE TABLE My_Customers (hellip)

The following example shows how to create a table whose name includes a space character If the table name were not in quotation marks () a space character or any other non-alpha character except an underscore ( _ ) or dollar sign ($) (see special conditions above) could be used in the name

CREATE TABLE My Customers (hellip)

IBM Software Group IBM Information Management

Version 16 19

The following example shows how to create a table that uses a keyword as the table name

CREATE TABLE TABLE (hellip)

To include a double-quote () within a delimited identifier the double-quote () must be preceded with another double-quote () as shown in the following example

CREATE TABLE MyGoodData (hellip)

Summary

The main points to keep in mind when deciding about any questions on how identifiers should be translated are

Oracle always has delimited identifiers enabled and Informix does not

Oracle folds regular identifiers to uppercase and Informix folds to lowercase

Informix has behavioral differences between an ANSI mode database and a non-ANSI mode one

It is beneficial to consider the most common usage patterns within the existing application code prior to deciding default identifier translation patterns

Databases

Databases database names and instances

Oracle and Informix implement databases and instances differently Oracle considers a database to be a set of data files control file(s) and log files while an instance is a set of background processes and memory structures accessing database data Oracle instances are also known as servers Each Oracle instance or server runs against one database but through the use of Oracle Parallel Server a database may have multiple instances accessing it An Oracle database is named at initialization and the name has a limit of 8 ASCII characters Informix databases are defined as ldquoa collection of information contained in tables that are useful to a particular organization or used for a specific purposerdquo Informix database names may be up to 128 characters in length An Informix instance is a set of processes memory and disk allocations that manage data and will contain at least two and in most cases many databases Informix instances are also referred to as servers Informix databases may share disk allocations (dbspaces) with other databases within an Informix instance Oracle databases cannot share disk allocations (tablespaces) Informix databases should be created in a dbspace other than the root dbspace The root dbspace holds data for the system configuration information for the engine and so on If user-defined objects are created in this dbspace then the dbspace may become unmanageably large and during backup the system information may also get backed up unnecessarily The CREATE DATABASE statements of Informix and Oracle have differences which may require modification to routines responsible for database creation Informix will accept the same minimal syntax required by Oracle (eg CREATE DATABASE myDB) however issuing the command will implicitly accept the creation of a database without transaction logging enabled and establish the default location for all database objects as the instancersquos default storage location The instancersquos default storage location or ldquorootrdquo dbspace should not contain user-defined objects The root dbspace holds data for the system and some configuration information for the engine If user-

IBM Software Group IBM Information Management

Version 16 20

defined objects are created in this dbspace it may become unmanageable and result in the system contending with user objects for the available space

ANSI vs non-ANSI

Informix supports both ANSI and non-ANSI databases Informix non-ANSI databases are most common but there are some advantages of ANSI databases when porting from Oracle

Oraclersquos transaction behavior is more or less like that of an ANSI database Applications ported on Oracle are always in a transaction In Oracle and ANSI databases transactions begin implicitly with the first of a series of SQL statements and will end immediately after a commit or rollback statement Therefore unlike a non-ANSI database a COMMIT WORK statement does not need to be preceded with a BEGIN WORK statement

In ANSI databases database object references must be prefixed by the ownerrsquos name unless the owner is the one referencing the object If Oracle applications reference database objects with a both parts of the object name prefixing the object name with schema using an ANSI database may ease modifications necessary when porting to Informix

The ldquolsquogrant to PUBLICrdquorsquo concept provide by Informix database security does not apply to ANSI databases Every database object is private and privileges must be explicitly granted to each user

If an Informix ESQLC or 4GL application was developed to run on a non-ANSI Informix database (including BEGIN WORK statements) the application could run on an ANSI Informix database in one of two ways

By placing the BEGIN WORK statement in a pre-processor directive such as IFDEF object_name and omitting the proper preprocessor compile options such as -D object_name

By compiling the application normally and ignoring the resulting warning messages

Additionally the LOG MODE ANSI clause must be added to the CREATE DATABASE statements ANSI mode databases cannot have buffered logging Applications written to use an open API like ODBC or JDBC are compiled without awareness of the database and these APIs are written with the intent to abstract specific database behavior For instance in one of these the application developer would call a function to begin or end a transaction rather than execute a BEGIN and COMMIT or ROLLBACK The API would execute these statements internally or not as necessary for the database connection See the Transaction Processing section in Application Architecture for more information on how an application running on a non-ANSI Informix database can simulate Oracle transaction behavior

Tablespaces and dbspaces Oracle tablespace names need to be replaced with Informix dbspace names Unlike the Oracle tablespace the Informix dbspace cannot be created using DDL (SQL) scripts It must be created using the Informix onspaces utility before any DDL (SQL) scripts are executed Therefore Oraclersquos CREATE TABLESPACE statements should be removed from the DDL (SQL) scripts The user interface for accomplishing these tasks is onmonitor The command line utility is onspaces Therefore the onspaces commands can be placed in shell or batch scripts After successfully executing the onspaces commands the DDL (SQL) scripts may be called through the same shell or batch scripts For example

IBM Software Group IBM Information Management

Version 16 21

onspaces hellip onspaces hellip hellip dbaccess database_name DDL_script_file_name dbaccess database_name DDL_script_file_name hellip

Tables

Attributes and general syntax

When creating tables the Oracle CREATE TABLE statement must be converted to Informix taking advantage of the Informix options IN EXTENT NEXT and LOCK MODE

IN specifies the dbspace in which the table will reside

EXTENT specifies the amount of space that will initially be allocated to the table (16K default on most platforms)

NEXT specifies the amount of space that will be allocated when additional space is needed (16K default on most platforms

Lock mode

LOCK MODE specifies whether to use row or page locks for the table In Oracle the default is row level locking in Informix the default setting is page level locking However it can be changed by using one of the following methods (resolved in the following order of precedence)

1 LOCK MODE specified using an attribute of the CREATE TABLE or ALTER TABLE command syntax

2 IFX_DEF_TABLE_LOCKMODE environment variable setting 3 DEF_TABLE_LOCKMODE parameter setting in the ONCONFIG file

NOTE If the DEF_TABLE_LOCKMODE parameter cannot be found in the ONCONFIG file it can be added to make the specification for every database within the instance The Informix instance must be restarted for this parameter to take effect The new ldquodefaultrdquo LOCK MODE will apply to all tables created after the parameter has been changed To change the LOCK MODE of existing objects use the ALTER TABLE statement

Storage

The Oracle STORAGE INITIAL and STORAGE NEXT clauses must be changed to the Informix EXTENT SIZE and NEXT SIZE clauses respectively In Oracle the STORAGE clause options MINEXTENTS MAXEXTENTS and PCTINCREASE should be removed For example Oracle

CREATE TABLE dept(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13)

)

STORAGE (INITIAL 100K NEXT 50K MINEXTENTS 1 MAXEXTENTS 50

PCTINCREASE 5)

Informix CREATE TABLE dept (

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

IBM Software Group IBM Information Management

Version 16 22

EXTENT SIZE 200 NEXT SIZE 50

When an Oracle CREATE TABLE statement does not include a STORAGE clause the table will be created using the tablespace STORAGE clause by default If an Oracle tablespace is created specifying a STORAGE INITIAL of 100KB and a STORAGE NEXT of 50KB then all tables created within that tablespace will have a default value of STORAGE INITIAL 100KB and STORAGE NEXT 50KB Oracle tables cannot be created with smaller STORAGE clause values than the tablespace default they are created in Informix dbspaces do not have storage clauses attached to them As stated earlier the default Informix EXTENT and NEXT sizes are 16KB on most platforms The minimum EXTENT and NEXT sizes are 4 times the page size

Constraints

The Oracle constraint syntax must be changed to the Informix syntax for primary keys foreign keys unique and so on For example

Oracle CONSTRAINT PK_NUMBER PRIMARY KEY(CUST_NUM)

CONSTRAINT CK_EMP_CODE CHECK (EMP_CODE gt 100)

Informix PRIMARY KEY(CUST_NUM) CONSTRAINT PK_NUMBER

CHECK (EMP_CODE gt 100) CONSTRAINT CK_EMP_CODE

An Oracle check constraint statement may contain functions that are not available in Informix In this circumstance it may be necessary to code the combination of a trigger and a stored procedure to emulate the same functionality A trigger based on an insert or update event can execute a stored procedure which tests the constraint condition and if necessary raise an exception to reject the row data which violates the constraint The Oracle PARALLEL clause which specifies parallel execution of an operation must be removed from any SQL statements (such as CREATE TABLE and ALTER TABLE) In Informix there are ways to accomplish this parallel execution depending on the context in which these SQL statements are called (shell script file batch file and so on)

ALTER TABLE

Informix offers a rich set of ALTER TABLE features adding and dropping columns (rename by using the RENAME statement) changing column data types altering the next size and changing the lock mode Informix will choose one of three algorithms when executing an ALTER TABLE statement depending upon the operation to be performed For certain conditions the database server uses either a ldquoslowrdquo ldquoin-place or ldquofastrdquo alter algorithm to modify the table Informix provides ldquoin-placerdquo alter table support for adding or dropping a column anywhere in the table changing the column length and changing the column data type without an exclusive lock on the table An ldquoin-placerdquo alter will modify the tablersquos definition without changing the existing rows or unloading and reloading the data After the ALTER TABLE operation the database server inserts rows using the latest definition Informix will not change the row structure until a data row is touched by a user operation Once a query accesses a row that is not yet converted there can be a slight degradation in the performance because the database server reformats each row in memory before it is returned Informix uses the ldquoslowrdquo alter algorithm when the ALTER TABLE statement makes column changes that it cannot perform in place This type of alter would be

Adding or drop a column created with the ROWIDS keyword

Dropping a column of the TEXT or BYTE data type

IBM Software Group IBM Information Management

Version 16 23

Converting an INT or a SMALLINT column to SERIAL or SERIAL8

Modifying the data type of a column so that some possible values of the old data type cannot be converted to the new data type

For example if you modify a column of data type INTEGER to CHAR(n) the database server uses the slow ALTER algorithm if the value of n is less than 11 An INTEGER requires 10 characters plus one for the minus sign for the lowest possible negative values

Modifying the data type of a fragmentation column in a way that value conversion might cause rows to move to another fragment

Adding dropping or modifying any column when the table contains user-defined data types or smart large objects

When the database server uses the slow alter algorithm to process an ALTER TABLE statement the table can be unavailable to other users for a long period of time because the database server will lock the table exclusively for the duration of the operation make a copy of the table to convert the table to the new definition and convert the data rows This type of ALTER TABLE processing can encounter the scenario of a statement being a long transaction and abort it if the Long Transaction High Water Mark (LTXHWM) threshold is exceeded Informix will use the ldquofastrdquo alter algorithm when the ALTER TABLE statement changes attributes of the table but does not affect the data The database server uses the fast alter algorithm when you use the ALTER TABLE statement to make the following changes

bull Change the next-extent size

bull Add or drop a constraint

bull Change the lock mode of the table

bull Change the unique index attribute without modifying the column type

With the ldquofastrdquo alter algorithm the database server holds a lock on the table for a very brief period In some cases the database server will lock the system catalog tables but only long enough to change the attribute In either case the table is unavailable for queries for only a short time

Data Partitioning

Informix Table Fragmentation is the counterpart to Oraclersquos Table Partitioning and allows the user to control where data is physically placed at the table level Table Fragmentation or Data Partitioning is typically done to large tables but Informix and Oracle implement fragmentation and partitioning for different reasons and with different results Informix recommends using table fragmentation to improve single-user response time concurrency data availability backup restore characteristics and data-load performance While Oracle does state that table partitioning may improve the performance of queries and that the Oracle optimizer takes partitioning into account the primary goal of partitioning in Oracle is improving database maintenance Partitioning strategies in Oracle include range partitioning as well as hash and composite partitioning Composite partitioning combines range and hash partitions through the use of sub-partitions Tables incorporating Oracle LOBrsquos (large objects) cannot be partitioned Informix fragmentation strategies include expression-based and round robin Basic expression-based fragmentation can replace Oracle range partitioning Unlike Oracle LOBs Informixrsquos Smart Large Objects can be fragmented Examples of creating tables with Oracle range partitioning and Informix fragmentation by expression are shown below Oracle range partitioning

CREATE TABLE dept

IBM Software Group IBM Information Management

Version 16 24

(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13) )

partition by range (deptno)

(partition PART1 values less than (11)

tablespace PART1_TS

partition PART2 values less than (21)

tablespace PART2_TS

partition PART3 values less than (31)

tablespace PART3_TS

partition PART4 values less than (MAXVALUE)

tablespace PART4_TS)

Informix expression based fragmentation CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

deptno lt 11 IN dbspace1

deptno gt= 11 AND deptno lt 21 IN dbspace2

deptno gt= 21 AND deptno lt 31 IN dbspace3

REMAINDER IN dbspace4

Oracle uses MAXVALUE for values not found in the specified range while Informix uses the REMAINDER keyword for values that fall outside the specified expression or expressions Prior to IDS version 1000 each table fragment had to go into a separate dbspace Now tables can be fragmented within a single dbspace You can create partitions within a dbspace that can each support a table fragment It is better to have one chunk per disk drive and now it is not necessary to create a dbspace just to facilitate fragmentation This feature can simplify the management of dbspaces The benefits gained through this new development include

It reduces the total number of dbspaces needed for a fragmented table

Storing multiple table fragments in a single dbspace improves query performance over storing each fragmented expression in a different dbspace

For example Informix partition fragmention in a single dbspace

CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

PARTITION part1 (deptno lt 11) IN dbspace1

PARTITION part2 (deptno lt 21) IN dbspace1

PARTITION part3 (deptno lt 31) IN dbspace1

PARTITION part4 REMAINDER IN dbspace1

Partitions of an Informix fragmented table can be manipulated using the ALTER FRAGMENT statement which supports attaching detaching adding modifying and dropping as well as initializing the distribution strategy

IBM Software Group IBM Information Management

Version 16 25

For example the following SQL removes a partition fragment and places the contents into a new table

ALTER FRAGMENT ON TABLE dept DETACH PARTITION part3 dept_part3

Making use of ALTER FRAGMENT to detach fragments can be an effective way of deleting large quantities of rows from a table quickly and easily After the above statement completes the table will no longer contain rows with a deptno greater than 21 and less than 31 Refer to the Informix Guide to SQL Syntax for a complete description on how to use the ALTER FRAGMENT statement to change the distribution strategy or the storage location of an existing table or index

Data types

Numeric

Oraclersquos NUMBER data type needs to be replaced with one of the following Informix equivalent data types depending on the size of the column The Informix numeric data types are listed below

SMALLINT (-32767 to 32767)

INTEGER (-2147483647 to 2147483647)

BIGINT (-9223372036854775807 to 9223372036854775807)

INT8 (-9223372036854775807 to 9223372036854775807)

The BIGINT type is more efficient in terms of space and speed there are few reasons to use INT8 now that BIGINT is available

DECIMAL (floating point up to 32 significant digits -10-130

to 10124

)

In an ANSI database there is an implied scale of 0 when no scale is given so this is not strictly speaking a floating point type within an ANSI database

NUMERIC (floating point up to 32 significant digits -10-130

to 10124

)

FLOAT (double precision like double data type of C)

SMALLFLOAT (single precision like float data type of C)

REAL (same as SMALLFLOAT)

DOUBLE (same as FLOAT)

LONG (same as long data type of C)

Oraclersquos NUMBER data type is used to store zero positive and negative fixed size and floating point numbers with magnitudes between 10 x 10

-130 and 999 x 10

125 (38 9s followed by 88 0s)

with 38 digits of precision A fixed-point number is specified by NUMBER(p s) where p is the precision or the total number of digits and s is the scale or the number of digits to the right of the decimal point For example a column defined as NUMBER(104) would contain numbers in the format 9999999999 In Oracle the scale can range from -84 to 127 If the scale is 0 or not mentioned then the data type can be converted into Informixrsquos SMALLINT INTEGER or BIGINT depending on the precision or FLOAT SMALLFLOAT DOUBLE or REAL depending on usage in the application When the scale is positive the data type should be converted to Informixrsquos DECIMAL or NUMERIC A floating-point data type in Oracle is declared using the type NUMBER without mentioning scale and precision In Informix this can be replaced with FLOAT SMALLFLOAT REAL DOUBLE PRECISION or DECIMAL(p) in an non-ANSI database

IBM Software Group IBM Information Management

Version 16 26

Oracle allows a negative scale If the scale is negative the actual data is rounded to the specified number of places to the left of the decimal point For example a specification of NUMBER (10 -2) means to round to the hundred If the general form for any number is

mantissa X 10exponent

then precision is the number of digits in the mantissa and scale is the negative exponent Example

select cast( 987654321 AS NUMBER(10-2) ) from dual

returns

987654300

Informix does not support a negative scale If precision - scale is less than the maximum precision of an integer type then that is the most efficient type to use Failing that and if the database is non-ANSI a floating point DECIMAL can be used If that is not sufficient then it may be necessary to define a user type and associated functions Oracle also allows the scale to be greater than the precision Precision is just the number of digits that will be preserved A NUMBER(3 5) might have the value 000123 If the Oracle scale is less than the Informix maximum precision then the Oracle scale can be used for both the Informix precision and scale A NUMERIC(55) column could also store the value 000123 You may need to take into consideration not only the minimum and maximum values but the default size for data types For example when the size of the NUMBER data type is absent Oracle will default to NUMBER(38) while Informix defaults to NUMERIC(16) Oracle and Informix support the ANSI DECIMAL data type Therefore in the case of an ANSI data type the Oracle data type can be converted to the same Informix data type There are differences between conversions based on theory versus those based on practice For instance it is very common to see an undecorated NUMBER declaration where the customer database and applications are using integer data When converting NUMBER declarations it may be necessary to consider how the data is being used in order to determine the best type mapping

CHAR VARCHAR and LVARCHAR

In Oracle the default for a CHAR column is one character and the maximum allowed is 255 characters In Informix the maximum length of CHAR and LVARCHAR columns is 32767 Therefore Oraclersquos CHAR columns can always be converted to an Informix CHAR column The CHAR data type columns can only contain printable characters tabs and spaces The CHAR columns store leading and trailing spaces In Oracle a zero-length string can be inserted into a CHAR column but the column is padded with one blank character when it is used in comparisons Also in Informix a zero-length string can be inserted into a CHAR column however the column is padded with enough spaces to fill the column In the case of inserting NULL into an Informix CHAR column no padding occurs Oraclersquos VARCHAR and VARCHAR2 are currently synonymous and have a maximum data length of 4000 bytes while the maximum length for the Informix VARCHAR data type is 255 Informixrsquos CHAR and LVARCHAR data types have a maximum length of 32767 and 32739 respectively measured in bytes These should be used to replace Oraclersquos VARCHAR VARCHAR2 LONG and LONG VARCHAR if the data length is between 256 and the maximum If the data length exceeds the maximum use Informixrsquos TEXT BYTE BLOB or CLOB data types See the Raw Data section below for more information on TEXT BYTE BLOB and CLOB data types

IBM Software Group IBM Information Management

Version 16 27

Empty Oracle VARCHAR2 strings are considered NULL Empty Informix VARCHAR and LVARCHAR strings are not considered NULL rather they contain at least one space Oracle

compares VARCHAR2 values using non-padded comparison semantics Therefore ldquoBOBrdquo ldquoBOB ldquo Informix ignores trailing blanks Therefore ldquoBOBrdquo = ldquoBOB ldquo or ldquordquo = ldquo rdquo Hence checks for NULL within the application must be replaced with checks for an empty string (such as ldquordquo or ldquo rdquo) whenever an empty string is inserted into the column If NULL is truly inserted into the column checking for NULL is appropriate (for example SELECT FROM hellip WHERE hellip IS NULL) In Oracle LONG columns store variable length character strings containing up to 2 gigabytes or 2

31-1 bytes Informix LONG columns store numeric data Oraclersquos LONG columns have many of

the characteristics of VARCHAR2 columns They can be used in a SELECT list in the SET clause of an UPDATE statement and in an INSERT statement but they cannot be used in a WHERE clause a GROUP BY clause or an ORDER BY clause and they cannot be indexed Oraclersquos LONG columns should be converted to an Informix Smart Large Object or ldquoSLOBrdquo (BLOB CLOB) column

Date and Time

Oraclersquos DATE data type contains date and time components from year down to second It can be to be replaced most directly with Informixrsquos DATETIME YEAR TO SECOND Some analysis may be necessary to determine whether the time is really necessary In other words does the application reference the date and time portions of the values If the application only references the date portion then replace Oraclersquos DATE with Informixrsquos DATE and change the host variable to X(10) or char(10) accordingly The Informix DATE default display format is MM-DD-YYYY although the DATE data type stores the calendar date The Informix DATE data type requires 4 bytes which is stored internally as an integer value equal to the number of days since December 31 1899 The default display format can be changed with the environment variable DBDATE If the application uses different date formats then using DBDATE is not a solution Sometimes it might be necessary to write small subroutines to emulate Oraclersquos DATE representations See the Informix Guide to SQL Reference manual for details on DBDATE and also DBCENTURY If the application only references the time portion of the values replace Oraclersquos DATE with Informixrsquos DATETIME using the EXTEND function to specify precision In addition Informix provides the data type INTERVAL for use while performing DATE and DATETIME calculations In Oracle the DATE data type is used to store date and time information Although date and time information can be represented in both CHAR and NUMBER data types the DATE data type has special associated properties For each DATE value the following information is stored

century

year

month

day

hour

minute

second

Also regarding the Oracle DATE data type if a date value without a time component is specified the default time is 120000am If a DATE value without a date is specified the default date is the first day of the current month

Interval

Within Informix there are two classes of interval types YEAR-MONTH and DAY-FRACTION There are different numbers if days in different months so the MONTH-DAY boundary cannot be crossed without creating ill-defined results Within each of these classes Informix allows you to declare columns or variables as any subset of the start and end fields Oracle has one INTERVAL

IBM Software Group IBM Information Management

Version 16 28

type for each of the two classes YEAR(p) TO MONTH and DAY(p) TO SECOND(s) The Oracle scale on the SECOND field is logically equivalent to the Informix scale on the FRACTION field

Raw data and Large Objects

Oraclersquos support of large blocks of raw unstructured data (such as graphic images video clips and sound waveforms) in binary or character format is provided by the large object (LOB) data types BLOB CLOB NCLOB and BFILE Traditional Oracle data types MLSLABEL (used with Trusted Oracle) RAW and LONG RAW are also used for data that is not to be interpreted by the engine and converted when moving data between different systems Informix supports two types of large objects (LOBs Simple Large Objects and Smart Large Objects Simple LOBs consist of the TEXT and BYTE data types and can be 2

31 bytes or 2

Gigabytes in size Smart LOBs include both Character Large Object (CLOB) and Binary Large Object (BLOB) data types and may be up to 42

40 bytes or 4 Terabytes in size Simple LOBs can

be stored either in-line with table data or in blobspaces while Smart LOBrsquos are stored in sbspaces Oraclersquos CLOB BLOB MLSLABEL RAW and LONG RAW data types should be replaced with Informixrsquos BYTE TEXT CLOB or BLOB depending on the columnrsquos size and usage Informixrsquos Smart BLOB data types CLOB and BLOB should be used under the following conditions and considerations

The large object needs to be referenced by multiple sources

The object size exceeds 2 GB

Fragmentation is required

Byte level locking is available making it possible to lock only a portion of the object

Logging can be specified at the object level

Updates are done in place or moved as needed

Be aware of the following restrictions for Simple Large Objects

Data can only be inserted into a BYTE or TEXT column with the dbload or onload utilities the DBACCESS load statement BYTE or TEXT host variables respectively in ESQLC or declaring a file in ESQLCOBOL

BYTE and TEXT columns cannot be inserted or updated with a literal neither quoted text string nor number

BYTE or TEXT columns cannot be used in string operations with aggregate functions with the GROUP BY ORDER BY IN LIKE or MATCHES clauses

ROWID

The implementation of ROWID differs between Oracle and Informix Oraclersquos ROWID is both a pseudo-column and a data type See the ROWID subsection in the Pseudo-Columns section in CHAPTER 3 Data Manipulation Language for more information Informix implements ROWID as a pseudo-column only Oracle stores the ROWID column and ROWID data type column values in hexadecimal format Informix stores the ROWID column values in INTEGER format The Oracle and Informix engines maintain the values of the ROWID pseudo-column Oraclersquos engine does not maintain the values of other columns of type ROWID In Informix the term rowid refers to an integer that defines the physical location of a row Informix assigns rows in a non-fragmented table a unique rowid which allows applications access to a particular row in a table Rows in fragmented tables in contrast are not assigned a rowid To access data by rowid in a fragmented table a rowid column must be explicitly created as is described in the Informix Guide to SQL Reference manual Creating a Rowid Column If applications attempt to reference a rowid in a fragmented table that does not contain a rowid that was explicitly created Informix displays an appropriate error message and execution of the application is halted

IBM Software Group IBM Information Management

Version 16 29

When used as a data type for a column Oracle does not guarantee that the values are valid ROWIDs For example if the ROWID is used as a data type on a column such as a column in a child table named parent_rowid containing the ROWID of the parent then the values are maintained by the application outside of the engine The application must read the ROWID of the parent and insert it into the parentrsquos corresponding child table rows This is usually done so the two tables can be joined on the parentrsquos ROWID and the childrsquos parent_rowid column This functionality can be duplicated in Informix by using primary and foreign keys Informix recommends that primary keys are used as a method of access in applications rather than rowids because primary keys are defined in the ANSI specification of SQL using them to access data makes applications more portable Refer to the Informix Guide to SQL Reference and the Informix Guide to SQL Syntax for a complete description on how to define and use primary keys to access data

User-defined types

Both Oracle and Informix allow the user to create and define data types Oracle refers to these as abstract data types while Informix refers to these as user-defined types In Oracle all user-defined types are referred to as abstract data types while Informix may refer to user-defined types as COLLECTION types ROW types DISTINCT types and OPAQUE types Currently the Informix ROW type is closest in form and function to the Oracle abstract data type An example of syntax for creating both an Oracle abstract data type and an Informix ROW type is shown below

Oracle abstract data type

CREATE TYPE name_type AS OBJECT

(first_name VARCHAR2(25)

middle_initial CHAR(1)

last_name VARCHAR2(30))

Informix row type

CREATE ROW TYPE name_type

(first_name VARCHAR(25)

middle_initial CHAR(1)

last_name VARCHAR(30))

Both Oracle and Informix support the use of user-defined types for table definition or column definition within a table Building on the example above the following create table example show a table definition and column definition within a table based on user-defined types Oracle table creation

CREATE TABLE name OF name_type

Informix table creation

CREATE TABLE name OF type name_type

Oracle column definition

CREATE TABLE employee

(empno NUMBER(9)

name name_type)

Informix column definition

CREATE TABLE employee

IBM Software Group IBM Information Management

Version 16 30

(empno INTEGER

name name_type)

For more information on User Defined Types see the Informix Guide to SQL Syntax

Complex data types

Informix offers users the ability to create data types from existing built-in types OPAQUE types DISTINCT types and other complex types Complex data types may either be a ROW type or a COLLECTION type Oracle treats complex data types as abstract data types For more information on Oracle abstract data types see the User Defined Types section above For more information on Complex Data Types see the Informix Guide to SQL Syntax For recommended type mappings and additional information see the appendix ldquoData type mappingsrdquo

Sequence objects

Oracle sequences

An Oracle sequence is a database object from which multiple users or transactions may generate unique integers For example sequences can be used to automatically generate primary key values When a sequence object is queried the sequence number is incremented and passed to the query independent of the transaction committing or rolling back If two applications increment the same sequence the sequence numbers each application acquires may not be sequential since sequence numbers are being generated by the other application One user or transaction can never acquire the sequence number generated by another user or transaction Once a user or transaction generates a sequence value that value will never be generated and passed to another user or transaction

Informix sequences

Informix rsquos implementation of sequence objects is identical to that of Oracle Issues regarding syntax compatibility should be negligible with the exception of some keywords which have no effect on the behavior of the sequence Informix supports DML statements (CREATE SEQUENCE ALTER SEQUENCE RENAME SEQUENCE DROP SEQUENCE) for sequence objects that multiple users can access concurrently to generate unique integers in the 8-byte integer range GRANT and REVOKE statements support access privileges on sequence objects and the CREATE SYNONYM and DROP SYNONYM statements can be used to reference synonyms for sequence objects in the local database The operators CURRVAL and NEXTVAL can read or increment the value of an existing synonym with behavior the same as Oracle

Indexes

Composite indexes

A composite index can have up to 16 key parts that are columns or up to 341 key parts that are values returned by a UDR This limit is language-dependent and applies to UDRs written in SPL or Javatrade functional indexes based on C language UDRs can have up to 102 key parts A composite index can have any of the following items as an index key

One or more columns

IBM Software Group IBM Information Management

Version 16 31

One or move values that is returned by a user-defined function (referred to as a functional index)

A combination of columns and user-defined functions

Maximum key size

The total widths of all indexed columns in a single CREATE INDEX statement have a limitation based upon the page size of the dbspace in which the index resides This limitation does not apply to functional indexes An enhancement introduced with Informix Dynamic Server Version 1110 is configurable page sizes for dbspaces Prior to this release the page size of dbspaces were restricted to that of the operating system and could not be changed thus Informix was limited to 390 byte indexes With page sizes configurable from 2K through 16K wider indexes are supported Refer to the table below 16K page sizes raises the limit on index width to over 3000 bytes Lifting the 390 byte limit also permits LVARCHAR columns larger than 387 bytes to be included in an index definition

Page Size Maximum Key Size

2 kilobytes 387 bytes

4 kilobytes 796 bytes

8 kilobytes 1615 bytes

12 kilobytes 2435 bytes

16 kilobytes 3245 bytes

In addition to aiding the porting process wider indexes have satisfied requirements for Unicode data as well as provide performance gains by reducing B-Tree index traversal costs since indexing can be built with more items on an index page and produce fewer levels

Index fragmentation

Just as Oracle and Informix support table fragmentation or partitioning in Oracle both support index fragmentation as well See the Table fragmentation section above for more information regarding Informix table fragmentation and Oracle table partitioning Oracle indexes that are partitioned in the same manner as the table they are indexing are referred to as local indexes Informix refers to these as attached indexes Oracle indexes that span partitions are known as global indexes Informix refers to these as detached indexes Informix detached indexes may also refer to indexes that do not follow the same fragmentation scheme as the table they are indexing Starting with Informix version 1110 indexes can be fragmented similarly to tables on a partition level

General index information

The Informix CLUSTER option should be used when appropriate This option orders the data within the table in the order the index requires It is important to note that the CLUSTER index is not maintained over time The primary factor determining the frequency of CLUSTER index rebuilds is the amount of DML performed against the table Frequent INSERTS UPDATES and DELETES make it necessary to closely monitor CLUSTER indexes There is only one clustered index per table since a tablersquos data can only be stored in one order Oraclersquos INITRANS and PCTFREE functionality is similar to the Informix index FILLFACTOR option of the CREATE INDEX statement or the FILLFACTOR configuration parameter in the ONCONFIG file In either case the functionality is handled by Informixrsquos engine once it is set and can be removed from the application FILLFACTOR specifies the degree of index-page

IBM Software Group IBM Information Management

Version 16 32

compactness A low value provides room for growth in the index A high value compacts the index If an index is fully compacted (100 percent) any new inserts result in splitting nodes The setting on the CREATE INDEX statement overrides the ONCONFIG file value The FILLFACTOR default value for both the CREATE INDEX statement as well as the ONCONFIG is 90 Informix has no support for bitmap indexes

Views Oraclersquos CREATE VIEW statement contains three options FORCE NO FORCE and WITH READ ONLY FORCE creates the view regardless of whether the views base tables exist or the owner of the schema containing the view has privileges on them NO FORCE creates the view only if the base tables exist and the owner of the schema containing the view has privileges on them WITH READ ONLY specifies that no deletes inserts or updates can be performed through the view These options must be removed from the Informix CREATE VIEW statements Because a view is not really a table it cannot be indexed and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE The columns of a view cannot be renamed with RENAME COLUMN To change anything about the definition of a view you must drop the view and re-create it Because it must be merged with the userrsquos query the SELECT statement on which a view is based cannot contain any of the following clauses

INTO TEMP The userrsquos query might contain INTO TEMP if the view also contains it the data would not know where to go

UNION The userrsquos query might contain UNION No meaning has been defined for nested

UNION clauses

ORDER BY The userrsquos query might contain ORDER BY If the view also contains it the choice of columns or sort directions could be in conflict

Stored procedures and triggers The ways stored procedures and triggers are created differ between Oracle and Informix Oracle allows a REPLACE clause in the CREATE statement to handle situations when the object already exists Informix does not support the REPLACE option Instead a DROP PROCEDURE or DROP TRIGGER statement must precede the CREATE PROCEDURE or CREATE TRIGGER statement respectively to handle the situation when the object already exists It should be noted a DROP statement will generate an error when the object does not exist If it is run interactively within the DBACCESS user interface the DROP statement error will terminate processing If it is run using script execution using DBACCESS at the command line processing will continue To run DBACCESS from the command line type

dbaccess db_name

To run the file containing the create statements from the command line type dbaccess db_name sql_file_name

Informix introduced an IF EXISTS clause to most of the CREATE and DROP statements at 117 but the logic is different from Oraclersquos OR REPLACE clause For example these statements

IBM Software Group IBM Information Management

Version 16 33

DROP PROCEDURE IF EXISTS hellip

CREATE PROCEDURE hellip

are logically the same as this Oracle statement

CREATE OR REPLACE PROCEDURE hellip

So it is possible to achieve the same result but not necessarily the same number of statements

Oracle extensions The Oracle CLUSTER option in CREATE statements should be removed These are not to be confused with Informix CLUSTER index statements (See Indexes section above) An Oracle cluster is a database schema object that contains one or more tables that all have one or more columns in common Rows of one or more tables that share the same value in these common columns are physically stored together within the database Removing this Oracle feature will not affect the application Other non-Informix DDL statements like CREATE DATAFILE CREATE CONTROLFILE CREATE ROLLBACK SEGMENT CREATE SNAPSHOT CREATE DATABASE and CREATE DATABASE LINK must be removed or changed (in the case of the CREATE DATABASE statement) The Oracle CREATE PROFILE statement must be removed An Oracle profile is a set of limits on database resources Profiles can be used to limit the database resources available to a user for a single SQL statement or a single session

IBM Software Group IBM Information Management

Version 16 34

C H A P T E R 4 Data Manipulation Language

SQL

Labels using keywords

Oracle displays labels in SQL statements that are Informix reserved words such as UNITS YEAR MONTH DAY HOUR and so on must be converted by using the Informix AS clause between the column name and the display label Otherwise syntactic ambiguities will cause errors

Inequality operations

In addition to the Informix supported ldquonot equal tordquo symbols ldquoltgtrdquo and ldquo=rdquo Oracle supports the symbol ldquo^=rdquo All occurrences of ^= must be replaced with one of the Informix supported symbols

Selects

Queries are executed based on how the optimizer determines the best path to the data Oracle and Informix developed their own query optimizers with their proprietary methods and rules A query that looks exactly the same in both environments may run differently in each following a different path and executing faster or slower Therefore every query in the ported application should be tested for performance regardless of whether a query had to be converted Furthermore Oracle supports optimizer hints within a SELECT statement Prior to IDS 73 and Informix Dynamic Server 92 Informix did not allow optimizer hints See the Optimizer Directives subsection below for more information on porting Oraclersquos optimizer hints to Informixrsquos optimizer directives

Optimizer directives

Informix offers optimizer directives similar to Oraclersquos optimizer hints This feature provides the query developer the flexibility to direct the optimizer to follow specific paths rather than choosing a plan through its analysis A query is processed in two steps First it is optimized and compiled to product a query plan Secondly it is executed to produce a result Optimizer directives are a method for influencing the choice of the optimizer in the creation of the plan

IBM Software Group IBM Information Management

Version 16 35

Optimizer directives address the following key issues

Reduced time for correcting performance problems Rewriting queries can be very time consuming and this allows you to have a quick way to alter a plan

Competitive pressure Users accustomed to this function were looking for it in Informix

Product development tuning This allows product development to alter plans dynamically rather than through code changes to evaluate the effect of different optimization techniques

The syntax and behavior of Informixrsquos implementation is compatible with Oraclersquos optimizer hints which eases the porting of applications from Oracle to Informix Directives are written as a comment whose first character is a lsquo+rsquo (plus sign) An example is

select + ORDERED AVOID_FULL(e) empname deptno

from employee e department d

where edept_no = ddept_no

This above example specifies that the tables should be joined in the order specified in the query and that the employee table (e) should NOT be accessed with a full table scan The Informix implementation differentiates itself significantly from Oraclersquos in one way Informix supports the notion of negative directives whereas Oracle only supports direct hints A directive that tells the optimizer what to avoid rather than what to choose is unique to Informix The query result can be realized by writing a directive to avoid certain actions known to cause performance issues but allow any new indexes or table attributes to be explored by the optimizer as they are added over the life of the table and query This allows a DBA to continue to add indexes to tables and not have to rewrite directives Additionally Informix supports full recognition of directives with SET EXPLAIN output Informix will highlight semantic and syntactic errors which Oracle does not Optimizer directives support control in the following areas of the optimization process

Access methods Index versus scans

Join Methods Forcing hash joins nested loop joins

Join Order Specify which order the tables are joined

Goal Specify first rows or all rows (response time versus throughput) See the Informix Guide to SQL Syntax or Reference for more information

External optimizer directives

External optimizer directives give the DBA the ability to specify query directives and save them in the database These directives are applied automatically to subsequent instances of the same query The SAVE EXTERNAL DIRECTIVES statement associates one or more optimizer directives with a query and stores a record of this association in the sysdirectives system catalog table for subsequent use with queries that match the specified query string The query string must be an exact match that includes case and white space positioning This statement establishes an association between the list of optimizer directives and the text of a query but it does not execute the specified query Only the DBA or user informix can execute SAVE EXTERNAL DIRECTIVES This associates AVOID_INDEX and FULL directives with the specified query

SAVE EXTERNAL DIRECTIVES

+ AVOID_INDEX (table1 index1) + FULL(table1)

ACTIVE FOR

SELECT col1 col2 FROM table1 table2

IBM Software Group IBM Information Management

Version 16 36

WHERE table1col1 = table2col1

These directives are applied automatically to subsequent instances of the same query You must include one of the ACTIVE INACTIVE or TEST ONLY keyword options to enable disable or restrict the scope of external directives When external directives are enabled and the sysdirectives system catalog table is not empty the database server compares every query with the query text of every ACTIVE external directive and for queries executed by the DBA or user informix with every TEST ONLY external directive External directives are ignored if the EXT_DIRECTIVES parameter is set to 0 in the ONCONFIG file In addition the client system can disable this feature for its current session by setting the IFX_EXTDIRECTIVES environment variable to 0 If an external directive has been applied to a query output from the SET EXPLAIN statement indicates ldquoEXTERNAL DIRECTIVES IN EFFECTrdquo for that query Any inline directive is ignored by the optimizer when the external directives are applied to a query that matches the SELECT statement Like inline optimizer directives that are embedded within a query external directives can improve performance in some queries for which the default behavior of the query optimizer is not satisfactory Unlike inline directives external directives can be applied without revising or recompiling existing applications

Inserts

Informix does not support Oraclersquos INSERT with SELECT statement utilizing an UNION clause (although a view with an UNION clause can be referenced resulting in an UNION operation) Additionally Informix does not support an INSERT statement with a VALUE clause with SELECT statements The SELECT statement within a VALUE clause can be rewritten by omitting the VALUE clause and performing an INSERT INTO table_name SELECT hellip FROM other_table_name

Temporary tables

Informix and Oracle implemented the concept of temporary tables differently Oracle implements temporary tables as a work area during batch data loads Informix implements temporary tables just like regular database tables These temporary tables can be created manipulated and dropped only within a session such as stored procedures and ESQL programs Once the session ends any remaining temporary tables are automatically dropped Temporary tables can give an application extra functionality however their use should be limited if reducing database extensions to increase database independence within an application is a priority

Outer joins

Both Oracle (starting with Oracle 9i) and Informix support ANSI standard syntax for outer join specification The syntax for left and right outer join using the plus sign (+) in the WHERE clause is only supported for backward compatibility however it is still in existence The use of ANSI outer join syntax is recommended The Oracle outer join syntax + (placed after the column which has values not matching the corresponding column in the joined table) can be replaced with the Informix equivalent OUTER The OUTER keyword is placed within the SELECT statement before the name of the subservient table Unlike Oracle in Informix multiple outer joins per SELECT statement are allowed grouped with parentheses

Sorts

In Oracle sorts NULL values are considered the highest value and are therefore ordered last in ascending sorts Informix sorts with NULLS as the lowest value ordering them first in ascending sorts First it must be determined whether this sorting difference will affect the outcome enough to warrant a work around In most cases it will not If it does then a stored procedure can be

IBM Software Group IBM Information Management

Version 16 37

written to evaluate whether a column is NULL and if so replace it with a high value so that it will sort last Once the application receives the results it must replace the high values with NULL if the column is going to be displayed or manipulated

Exceptions

Error handling using hard coded Oracle SQL codes must be replaced with the corresponding Informix SQL codes

Correlation names

Informix does not support correlation names with aliases on the main table of an UPDATE or DELETE statement Such cases must be converted For example

Oracle UPDATE customer C

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE Ccreate_date lt= Zeffective_date)

Informix UPDATE customer

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE customercreate_date lt= Zeffective_date)

-and-

Oracle DELETE customer C

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND Cstate = Tstate )

Informix DELETE customer

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND customerstate = Tstate )

Note that Informix allows correlation names with aliases on tables other than the updated or deleted table

Aliases

Unlike Oracle in Informix if an alias is used in the FROM clause of a SELECT statement it must also be used in the SELECT list and WHERE clauses The original table name should be replaced with the alias wherever aliases and original names are used together within a SELECT statement in an Oracle application

Hierarchical queries

Informix does not allow query results to be organized hierarchically in a B-tree fashion Oracle does allow it by using the clauses START WITHhellip and CONNECT BY PRIOR in the SQL

IBM Software Group IBM Information Management

Version 16 38

statement In Oracle if a table contains hierarchical data a bill of materials for example rows can be selected in a hierarchical order using the following clauses START WITH

The START WITH clause identifies the row(s) to be used as the root(s) of a hierarchical query This clause specifies a condition that the root(s) must satisfy If this clause is omitted Oracle uses all rows in the table as root rows A START WITH condition can contain a subquery

CONNECT BY

The CONNECT BY clause specifies the relationship between parent and child rows in a hierarchical query This clause contains a condition that defines this relationship The part of the condition containing the PRIOR operator must have one of the following forms

PRIOR expression comparison_operator expression -or- expression comparison_operator PRIOR expression

To find the children of a parent row Oracle first evaluates the PRIOR expression to identify the parent row(s) and the other expression for each row in the table Rows for which the other expression is true are the children of the parent The CONNECT BY clause can contain other conditions to further filter the rows selected by the query

WHERE

The WHERE clause can restrict the rows returned by the query without affecting other rows of the hierarchy

Oracle uses the information from each of the clauses mentioned above to form the hierarchy using the following steps

1 Oracle selects the root row(s) of the hierarchy These are the rows that satisfy the condition of the START WITH clause

2 Oracle selects the child rows of each root row Each child row must satisfy the condition of the CONNECT BY clause with respect to one of the root rows

3 Oracle selects successive generations of child rows Oracle first selects the children of the rows returned in step 2 and then the children of those children and so on Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row

4 If the query contains a WHERE clause Oracle removes all rows from the hierarchy that do not satisfy the condition of the WHERE clause Oracle evaluates the WHERE condition for each row individually after the row has been fetched rather than only fetching rows that satisfy the WHERE condition

5 Oracle returns the rows in the order of an in-order or left-root-right binary tree traversal

IBM Software Group IBM Information Management

Version 16 39

For example the following SQL statement returns the data in the adjacent table in hierarchical order The root row is defined to be the employee whose job is lsquoPRESIDENTrsquo The child rows of a parent row are defined to be those rows whose manager number is the employee number of the parent row

SELECT ename empno mgr job FROM emp START WITH job = lsquoPRESIDENTrsquo CONNECT BY PRIOR empno = mgr

To duplicate this hierarchical functionality in Informix stored procedures or functions can be written requiring intensive use of cursors and program arrays Informix offers the choice of creating and using a User Defined Routine or ldquoUDRrdquo See User Defined Routines section below Use of Informix global arrays will help considerably To maximize read processing at the expense of insert processing another method is to break the table into two tables one containing the data and the other containing the relationship (foreign keys) between each parent and child A parent row would have an entry in the relationship table for each of its children grandchildren great grandchildren and so on The opposite is true where a child row would have an entry in the relationship table for its parent grandparent great grandparent and so on

Truncate

Informix supports the TRUNCATE statement for deleting all active data rows from a table and associated indexes When using Informixrsquos TRUNCATE you also have the option of releasing the storage space that was occupied by the rows and index extents or keeping the space allocated to be used as the table is repopulated with new data

TRUNCATE [TABLE] table [ [ DROP | REUSE ] STORAGE ]

You may use the commandrsquos simplest usage

TRUNCATE my_table

In the example above the TRUNCATE statement drops all the data for the table and keeps only the initial extents There is a minor difference from Oracle syntax as Informix does not require the keyword TABLE Another example

TRUNCATE my_table REUSE STORAGE

ENAME EMPNO MGR JOB

KING 7839 PRESIDENT

JONES 7566 7839 MANAGER

SCOTT 7788 7566 ANALYST

ADAMS 7876 7788 CLERK

FORD 7902 7566 ANALYST

SMITH 7369 7902 CLERK

BLAKE 7698 7839 MANAGER

ALLEN 7499 7698 SALESMAN

WARD 7521 7698 SALESMAN

MARTIN 7654 7698 SALESMAN

TURNER 7844 7698 SALESMAN

JAMES 7900 7698 CLERK

CLARK 7782 7839 MANAGER

MILLER 7934 7782 CLERK

IBM Software Group IBM Information Management

Version 16 40

This example drops all the data for the table but retains all the space allocated The permissions needed for TRUNCATE TABLE depend on the existence of DELETE triggers on the table For tables with DELETE triggers ALTER permission on the table is required and RESOURCE or DBA privileges because the DELETE triggers will be bypassed For tables without DELETE triggers you need DELETE permission on the table and CONNECT privilege to the database While Oracle does not provide rollback Informix does permit TRUNCATE TABLE to execute within a transaction When you rollback a TRUNCATE statement no rows are removed from the table and the storage extents that hold the data rows and index pages continue to be allocated to the table In a database that supports transaction logging only the COMMIT WORK or ROLLBACK WORK statement is valid after the TRUNCATE statement within a transaction Any other statement will generate an error The TRUNCATE statement does not reset the serial value of SERIAL or SERIAL8 columns To reset the counter of a serial column you must do so explicitly by using the MODIFY clause of the ALTER TABLE statement either before or after you execute the TRUNCATE statement After the TRUNCATE statement successfully executes Informix automatically updates the statistics and distributions for the table and for its indexes in the system catalog to show no rows in the table nor in its dbspace partitions It is not necessary to run the UPDATE STATISTICS statement immediately after you commit the TRUNCATE statement

Host variables Host variable formats should not change during the porting process Instead data types should be converted in a manner to preserve the column and host variablersquos formats However there are times when the database schema changes in a way where the host variable format must change Any column converted to a different format in Informix than that of Oracle requires that its corresponding host variable format be changed to be consistent Alternatively if an Oracle format such as date and numeric variables is not directly supported in Informix then the conversion may require some format processing before or after the SQL statement For example the Oracle function TO_CHAR is used to format both date and numerical values A similar function or at least two functions one to handle date data types and another to handle numeric data types can be declared and used in the Informix application Informix provides two built-in functions TO_DATE which converts a character string to a DATETIME variable and TO_CHAR which converts a DATETIME variable to a character string When converting variables an optional formatting string is allowed which determines how the string is displayed (full day names partial day names full months month number and so on) There is also a function ifx_to_gl_datetime() which takes an Oracle date format and returns the corresponding Informix date format This function is supplied in genlib and is for use in ESQL programs to ease migration efforts from Oracle The syntax is as follows

TO_CHAR (source_date fmt) Returns a character string containing the date specified in source_date in the format specified by fmt if one is provided If fmt is missing the function will use the default date format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

TO_DATE (source_string fmt) Evaluates source_string as a date according to the

format fmt If fmt is missing the function will use the

IBM Software Group IBM Information Management

Version 16 41

default format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

These functions are mainly useful for simplifying migration from Oracle to Informix but are also useful for performing advanced searches on DATETIME data types and for better output presentation

Date and time functions Informix version now has built-in support for most of Oraclersquos date functions so it will not be necessary to modify or replace Oraclersquos SYSDATE or ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat)

SYSDATE

IDS 1110 will support the SYSDATE operator which returns a single value representing the current date and time from the operating system clock SYSDATE is identical to the Informixrsquos CURRENT operator except that the default precision of SYSDATE is YEAR TO FRACTION(5) while the default precision of CURRENT is YEAR TO FRACTION(3) On Windows platforms that do not support a seconds scale greater than FRACTION(3) SYSDATE is effectively a synonym for the CURRENT operator In addition to SYSDATE Informix version 1110 has support for Oraclersquos date functions ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat) Depending on the whether or not the Oracle date_format argument is supported by Informix TO_CHAR(date char_format) and TO_DATE(character_string date_format) may have to be converted to Informix date processing Date processing may be required because the Oracle application may format the date in many different ways unsupported by Informix The formats used in the Oracle functions TO_CHAR TO_NUMBER and TO_DATE are illustrated below These formats should be replaced with Informix formats wherever possible format processing functions or stored procedures written to duplicate the Oracle functionality Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

Number formats

Element Example Description 9 9999 Return value with the specified number of digits with a leading

space if positive Return value with the specified number of digits with a leading minus if negative Leading zeros are blank except for a zero value which returns a zero for the integer part of the fixed-point number

0 09999990 Return leading zeros Return trailing zeros $ $9999 Return value with a leading dollar sign B B9999 Return blanks for the integer part of a fixed-point number

when the integer part is zero (suppress leading zeros regardless of whether zeros are used in the format model ie B00999 )

MI 9999MI Return negative value with a trailing minus sign ldquo-ldquo Return positive value with a trailing blank

S S9999999 Return negative value with a leading minus sign ldquo-ldquo Return

IBM Software Group IBM Information Management

Version 16 42

Element Example Description S positive value with a leading plus sign ldquo+rdquo Return negative

value with a trailing minus sign ldquo-ldquo Return positive value with a trailing plus sign ldquo+rdquo

PR 9999PR Return negative value in ltangle bracketsgt Return positive value with a leading and trailing blank

D 99D99 Return a decimal point ldquordquo In the specified position G 9G999 Return a group separator in the specified position C C999 Return the ISO currency symbol in the specified position L L999 Return the local currency symbol in the specified position 9999 Return a comma in the specified position 9999 Return a decimal point ldquordquo In the specified position V 999V99 Return a value multiplied by 10

n (and if necessary round it

up) where n is the number of ldquo9rdquos after the ldquoVrdquo EEEE 99EEEE Return a value in scientific notation RNrn RN Return a value as Roman numerals in uppercase Return a

value as Roman numerals in lowercase Value can be an integer between 1 and 3999

FM FM909 Return a value with no leading or trailing blanks

Date formats

Element Meaning -rdquotextrdquo Punctuation and quoted text is reproduced in the result AD or AD AD indicator with or without periods AM or AM Meridian indicator with or without periods BC or BC BC indicator with or without periods CC or SCC Century ldquoSrdquo prefixes BC dates with ldquo-ldquo D Day of week (1-7) DAY Name of day padded with blanks to length of 9 characters DD Day of month (1-31) DDD Day of year (1-366) DY Abbreviated name of day IW Week of year (1-52 or 1-53) based on the ISO standard IYY or IY or I Last 3 2 or 1 digit(s) of ISO year IYYY 4-digit year based on the ISO standard HH or HH12 Hour of day (1-12) HH24 Hour of day (0-23) J Julian day the number of days since January 1 4712 BC Number

specified with lsquoJrsquo must be integers MI Minute (0-59) MM Month (01-12 JAN = 01) MONTH Name of month padded with blanks to length of 9 characters MON Abbreviated name of month RM Roman numeral month (I-XII JAN = I) Q Quarter of year (1 2 3 4 JAN-MAR = 1) RR Last 2 digits of year see below for years in other centuries WW Week of year (1-53) where week 1 starts on the first day of the year

and continues to the seventh day of the year W Week of month (1-5) where week 1 starts on the first day of the

month and ends on the seventh PM or PM Meridian indicator with and without periods SS Second (0-59) SSSSS Seconds past midnight (0-86399) YYYY Year with comma in the ldquordquo position YEAR or SYEAR Year spelled out ldquoSrdquo prefixes BC dates with ldquo-ldquo YYYY or SYYYY 4-digit year ldquoSrdquo prefixes BC dates with ldquo-ldquo

IBM Software Group IBM Information Management

Version 16 43

YYY or YY or Y Last 3 2 or 1 digit(s) of year

The RR date format element

The RR date format element is similar to the YY date format element but it provides additional flexibility for storing date values in other centuries The RR date format element allows storing the century even though only two digits are entered for the year The table below illustrates how the year is stored based on only two digits

If the year is entered as

0 ndash 49 50 - 99 If the last two digits of the

0 - 49 The return date is in the current century

The return date is in the century before the current one

current year are

50 - 99 The return date is in the century after the current one

The return date is in the current century

User-defined routines User-defined data types user defined behaviors and user defined access methods add rich functionality to Informix A user-defined routine (UDR) can be developed in C Java or Informix SPL language to vastly extend the capabilities of the database Porting applications to Informix gives the option to create UDRs for aggregate and mathematical functions or to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or you can rename an Informix function to the corresponding Oracle function name

Compatible SQL Functions Informix Dynamic Server version 1110 has added support for a number of built-in SQL functions to ease a migration effort These new functions which perform common operations and data manipulation provide compatibility with Oracle routines thus simplifying the migration of applications that have been developed for an Oracle database

Date and time functions ROUND TRUNC ADD_MONTHS LAST_DAY NEXT_DAY MONTHS_BETWEEN SYSDATE

Conversion functions ASCII TO_CHAR TO_NUMBER

String manipulation LTRIM RTRIM

Number manipulation ROUND TRUNC CEIL FLOOR POWER

Bit manipulation BITAND BITOR BITXOR BITNOT BITANDNOT

Others NULLIF FORMAT_UNITS These functions are documented with examples in the IBM Informix Guide to SQL Syntax

Aggregate functions Like Oracle the result returned by an Informix aggregate function is NULL if all of the column values are NULL with the exception of COUNT which returns 0 (zero) Like Oracle Informix aggregate functions cannot be used in a WHERE clause unless it is on a corresponding column originating from a parent query and the WHERE clause is within a sub-query that is within a HAVING clause or the aggregate function is contained within a sub-query Unlike Oracle in Informix the argument of an aggregate function cannot be another aggregate function Informix supports the SELECT COUNT (column_name) hellip statement where the number of rows containing non-null values in the specified column is returned

IBM Software Group IBM Information Management

Version 16 44

The Oracle aggregate functions STDDEV and VARIANCE are supported however the Informix standard deviation routine is named STDEV thus all references to Oraclersquos STDDEV must be changed to match Informixrsquos STDEV Informix does not support Oraclersquos greatest lower boundary (GLB ) or least upper boundary (LUB) Therefore UDRs must be written to provide equivalent functionality Informix allows users to define their own aggregate functions known as user-defined aggregates (UDA) This extension of existing aggregates can be used for new data types as well as the definition of new aggregates In Informix TEXT and BYTE columns cannot be used in aggregate functions such as COUNT AVG MAX MIN and SUM

Mathematical functions Informix does not support all of Oraclersquos mathematical functions such as SIGN COSH SINH and TANH Therefore functions or UDRs must be written in the Informix application to provide equivalent functionality In Informix the rounding factor within the ROUND function must be a value from -32 to 32 This limitation has seldom been encountered as a migration issue

String functions

LENGTH

Oraclersquos LENGTH function will return different values than Informix for strings stored in CHAR data types The numeric return value representing the string length returned by Oracle will include all trailing spaces Whereas Informixrsquos LENGTH function will ignore trailing blanks regardless of data type For example for the two CHAR strings ldquoBOBrdquo and ldquoBOB ldquo Oraclersquos LENGTH function will return different values for each string 3 and 5 respectively Whereas Informixrsquos LENGTH function will ignore trailing blanks and return the value 3 for both When the input string is NULL both database functions will return a NULL

LTRIM and RTRIM

The SQL Compatibility features of Informx has support for LTRIM and RTRIM and will return identical values to that of Oracle No modifications will be necessary to SQL statements utilizing these functions

Oracle Extensions

Informix does not support all of Oraclersquos string functions such as CHR INSTR SOUNDEX and TRANSLATE Therefore corresponding user-defined routines or UDRs (ie functions or stored procedures) must be written in the Informix application to provide equivalent functionality Please note that the VERITY and EXCALIBUR Datablades included with Informix will work with Oraclersquos string function SOUNDEX

Other Oracle Functions Informix does not support the following Oracle functions Therefore corresponding functions must be written in the Informix application to provide equivalent functionality Alternatives to some of the more common Oracle functions follow this list

CHARTOROWID CONVERT DUMP GREATEST GREATEST_LB

IBM Software Group IBM Information Management

Version 16 45

HEXTORAW LEAST LEAST_UB RAWTOHEX ROWIDTOCHAR TO_LABEL TO_MULTI_BYTE TO_SINGLE_BYTE UID USERENV(OSDBA LABEL LANGUAGE TERMINAL SESSIONID ENTRYID) VSIZE

Macros Oracle contains macros sometimes referred to as language constructs which can determine the status of an object Informix does not support Oraclersquos macros These macros must be removed from the code and the associated logic should be implemented with equivalent Informix logic where applicable

ISOPEN and NOT FOUND

The macro cursor_nameISOPEN returns a Boolean value to indicate whether the cursor is open and cursor_nameNOTFOUND indicates whether there are any more rows yet to be fetched from the cursor cursor_name These macros used in condition statements are followed by some logic to handle the true andor false conditions In the case of ISOPEN this macro and its associated logic can just be omitted since the FOREACH loop processing does not explicitly open a cursor and therefore the condition cannot be checked In the case of NOTFOUND this macro should be omitted and its associated logic converted to Informix logic within an Informix FOREACH loop

ROWTYPE

The Oracle macro prefixROWTYPE is used in the declarative section as a data type to declare variables similar to the structure construct of C or RECORD of INFORMIX The prefix can be either a table name or another structure name Structure names ultimately refer back to a table name This macro may be replaced with the Informix statement LIKE table_name The construct LIKE table_name cannot be used in SPL Instead the construct DEFINE column1 LIKE table_namecolumn1 DEFINE column2 LIKE table_namecolumn2 and so on should be used to declare variables corresponding to all the columns of the table Then operations on the whole or part of the structure should be replaced with operations on single SPL variables

TYPE

The Oracle macro prefixTYPE is used in the declarative section as a data type to declare single variables The prefix is either a table_namecolumn_name or a structure_namevariable_name A structure_namevariable_name ultimately refers back to a table_namecolumn_name This macro can be replaced with the Informix statement LIKE table_namecolumn_name

Pseudo-columns Pseudo-columns are columns that exist in tables but are not displayed from a SELECT FROM table_name query Informix pseudo-columns are generally reserved for the enginersquos use Eliminating the use of such columns increases an applicationrsquos portability and eliminates the need for future modifications if the engine is ever modified to process the column differently or not at all

IBM Software Group IBM Information Management

Version 16 46

LEVEL

In Oracle for each row returned by a hierarchical query the pseudo-column LEVEL returns 1 for a root node 2 for a child of a root 3 for a child whose parent is at level 2 and so on A root node is the highest node within an inverted tree and therefore has no parent A child node is any non-root node A parent node is any node that has children A leaf node is any node without children To define a hierarchical relationship in a query you must use the START WITH and CONNECT BY clauses Informix does not support the LEVEL clause See the Hierarchical Queries subsection in the SQL section in the ldquoData Manipulation Languagerdquo chapter for more information on how to process these queries

ROWID

Oraclersquos ROWID pseudo-column returns the rows address for each row in the database ROWID values contain the following information necessary to locate a row

Which data block in the data file

Which row in the data block (first row is 0)

Which data file (first file is 1)

Usually a ROWID value uniquely identifies a row in the database However rows in different tables that are stored together in the same cluster can have the same ROWID Values of the ROWID pseudo-column have the data type ROWID ROWID values have several important uses

They are the fastest way to access a single row

They can show you how a tables rows are stored

They are unique identifiers for rows in a table

A ROWID does not change during the lifetime of its row However you should not use ROWID as a tables primary key If a row is deleted and re-inserted its ROWID may change even when using the export and import utilities If a row is deleted Oracle may re-assign its ROWID to a new row inserted later Although you can use the ROWID pseudo-column in the SELECT and WHERE clauses of a query these pseudo-column values are not actually stored in the database The value of a ROWID pseudo-column cannot be inserted updated or deleted For example the following Oracle statement selects the address of all rows that contain data for employees in department 20

SELECT ROWID ename FROM emp WHERE deptno = 20

The equivalent pseudo-column in Informix is also known as ROWID and although the behavior is similar the data type is different from Oraclersquos See the ROWID subsection in the Data Types section in the chapter ldquoData definition languagerdquo for more information

ROWNUM

In Oracle for each row returned by a query the ROWNUM pseudo-column returns a number indicating the order in which Oracle selected the row from a table or set of joined rows The first row selected has a ROWNUM of 1 the second has 2 and so on ROWNUM can be used to limit the number of rows returned by a query as in this example to read 9 rows

SELECT

FROM emp

WHERE ROWNUM lt 10

ROWID ENAME 0000000F00000002 SMITH 0000000F00030002 JONES 0000000F00070002 SCOTT 0000000F000A0002 ADAMS 0000000F000C0002 FORD

IBM Software Group IBM Information Management

Version 16 47

You can also use ROWNUM to assign unique values to each row of a table as in this example

UPDATE tabx

SET col1 = ROWNUM

Oracle assigns a ROWNUM value to each row as it is retrieved before the rows are sorted by an ORDER BY clause Therefore the final order of the rows is in ORDER BY order not in ROWNUM order An ORDER BY clause does not affect the ROWNUM values except in the case where the ORDER BY clause causes Oracle to use an index In that case the ROWNUM values are set in the order the rows are retrieved using the index and hence in ORDER BY order This order is different than if the rows were retrieved without the index So in this case the ORDER BY can affect the ROWNUM values Conditions which test for ROWNUM values greater than zero are always false For example this query returns no rows

SELECT FROM employee WHERE ROWNUM gt 1

The first row fetched is assigned a ROWNUM of 1 thus making the condition false The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 making the condition false All rows subsequently fail to satisfy the condition so no rows are returned Although there is no ROWNUM equivalent in Informix there are solutions Beginning with IDS 73 and in Informix Dynamic Server 2000 Informix provides a feature which allows the user to limit the results of a query to the first N rows This was implemented for TPC-D compliance and to support ldquorankrdquo queries Rank queries can be assembled by using FIRST N with the ORDER BY clause Informix will return the top N rows according to some ordering criteria Therefore the following Oracle SELECT utilizing ROWNUM

SELECT FROM emp WHERE ROWNUM lt 10

can be ported to Informix as follows

SELECT FIRST 9 FROM emp

Informix does not support SELECT FIRST N in complex cases as the following

Sub-queries (SELECT within a SELECT)

View definitions (Cannot be used by a SELECT statement which references a view)

UNION queries The behavior of SELECT FIRST N depends on the presence of an ORDER BY clause If no order by clause is specified the first N rows returned may be in any order Examples are as follows

find 10 highest paid employees

SELECT FIRST 10 name salary

FROM emp

ORDER BY salary

find 10 highest salary values

SELECT FIRST 10 DISTINCT salary

FROM emp

ORDER BY salary

IBM Software Group IBM Information Management

Version 16 48

Informix supports column names of ldquofirstrdquo Thus without a positive integer following the word ldquofirstrdquo the token is parsed as a column name rather than a keyword The value of N may be between 1 and (2

31-1)

When ROWNUM is used in a WHERE clause the same results can be obtained through the use of the FIRST N and SKIP clauses but if ROWNUM is used in the select list the solution is a little more complicated Simply stated you can construct a query where the ROWNUM column in any row is the count of the rows that came before This involves creating a correlated subquery where the subquery contains a self-join This can be done for any table or set of tables which has a unique key defined on it Here is an example using the customer table of the stores7 database

select

counterrownum

basecustomer_num

basefname

baselname

from

-- There can be more than one table here and the result

-- set should thought of as a table (just not a base table)

-- The result table has to be joined to itself in the

-- subquery so if there are multiple tables in this FROM

-- clause the expansion can get messy You have to have a

-- set of columns that uniquely identify each row in the

-- result table and join across them ROWID would

-- likely work if the table is not fragmented but if it is

-- there is no guarantee the final results would be accurate

-- because ROWID is not guaranteed to be unique across

-- fragments

customer base

(select

count() as rownum

acustomer_num -- any unique key possibly multiple

-- columns

from

customer a

customer b

where

-- This is where the rownum is determined the relationship

-- here has to match the outer order-by where the rows

-- are sorted and has to create a unique sort order

--

-- Any columns to be ordered by go here

-- Also the unique key has to be used to keep rows

-- that do not have a unique sort order from being merged

(alname gt blname) -- example sorting by last name

or

(alname = blname and afname gt bfname)

-- sorting by fname where lname is equal

or

(alname = blname and afname = bfname

and acustomer_num gt= bcustomer_num)

-- sorting by unique key where all the

-- other sort columns are equal

-- The expansion above is logically the same as

-- alname || afname || to_char(acustomer_num) gt=

-- blname || bfname || to_char(bcustomer_num)

-- but it allows the server to utilize any indexes that

-- may exist

group by

-- unique key columns go here

IBM Software Group IBM Information Management

Version 16 49

acustomer_num

) counter

where

-- key columns in the base tables go here

basecustomer_num = countercustomer_num

-- if you want to limit on rownum it goes here

-- and rownum lt= 10

order by

counterrownum

If using ROWNUM as an assignment as in

UPDATE tabx

SET col1 = ROWNUM

The following Informix-ESQLC pseudo-code example would have to be used

int counter = 0

EXEC SQL declare c1 cursor for

SELECT col1 col2

INTO col1 col2

FROM table 1

WHERE col1 = XX

EXEC SQL open c1

while (SQLCODE == 0)

EXEC SQL fetch c1

counter++ Increment counter for each row

fetched

if (counter gt= 5)

break

logic

End if

End while

Update using cursors There are slight differences between the ways Informix and Oracle process cursors Unlike Oracle in Informix the WHERE CURRENT OF clause cannot be used to update tables in a SELECT statement joining multiple tables since the WHERE CURRENT OF clause requires a FOR UPDATE cursor and Informix does not support the FOR UPDATE clause in SELECT statements that join multiple tables Therefore in the multi-table join statements the Oracle options FOR UPDATE and WHERE CURRENT OF should be removed and the update of the rows should be done using a separate UPDATE statement in the same cursor loop

IBM Software Group IBM Information Management

Version 16 50

In Informix a commit or rollback statement closes all cursors open in a given transaction boundary See the Transaction Processing section in CHAPTER 5 Application Architecture for more information In situations where the intention is to commit or rollback without closing the cursor in other words where the commit or rollback is executed within a cursor fetch loop the cursor can be declared as a HOLD cursor This requires that a BEGIN WORK is issued before the cursor loop starts A HOLD cursor is not closed when a commit or rollback statement is issued In Informix the FOR UPDATE clause cannot be used when declaring a HOLD cursor Thus where an Oracle application updates a table from which it fetches data in the fetch loop or issues a commit work in the fetch loop it must be converted to Informix The cursor can be declared with HOLD and then an UPDATE statement can be issued without the WHERE CURRENT OF clause In order to uniquely identify the row to be updated in the table in other words in order to simulate the WHERE CURRENT OF clause the ROWID or unique primary key columns of the table(s) to be updated must also be fetched and the WHERE CURRENT OF clause can be replaced with WHERE ROWID = fetched rowid or WHERE unique primary key column(s) = fetched unique primary key column(s) A BEGIN WORK must follow immediately after a COMMIT WORK or ROLLBACK WORK in the fetch loops to simulate Oracle implied transaction boundaries These transaction control statements work for either Informix logged databases or Informix ANSI mode databases however ANSI mode database processing with these statements will set certain warning flags after executing the BEGIN WORK statement and continue processing without failure See the ANSI vs Non-ANSI subsection in the Databases section in the chapter ldquoData Manipulation Languagerdquo for more information

System tables References to Oracle system tables should be replaced with corresponding references to Informix system tables The information schema views provided by Informix can be used These views are created after the database is installed They are populated by data in the system catalog tables and are used for easier porting

Stored procedures Informix procedures and functions are considered to be user-defined routines (UDR) A UDR can be written in Informixrsquos Stored Procedure Language (SPL) or an external language such as C or Java A procedure is a routine written that does not return a value A function is a routine written that returns a single value a value with a complex data type or multiple values Informix SPL is an extension to Informix SQL and provides procedural flow control such as looping and branching A SPL routine is a generic term that includes both SPL procedures and SPL

functions You use SQL and SPL statements to write an SPL routine SPL statements can be used only inside the CREATE PROCEDURE CREATE PROCEDURE FROM CREATE FUNCTION and CREATE FUNCTION FROM statements SPL routines are parsed optimized and stored in the system catalog tables in executable format Like Oracle Informix stored procedures support input output and inputoutput parameters and can be used in SQL statements wherever expressions are allowed

Size limit

Informix stored procedures have a size limit of approximately 64K Oracle stored procedures greater than 64K in size can be broken into smaller Informix stored procedures communicating with each other as though they were one by passing and returning the necessary values

Parameter limit

IBM Software Group IBM Information Management

Version 16 51

Informix has a limit of 341 parameters for each stored procedure This limit also applies to UDRs written in the Java language UDRs written in the C language can have no more than 102 parameters You can define any number of SPL routine parameters but the total length of all parameters passed to an SPL routine must be less than 64 kilobytes No more than nine arguments to a UDR written in the Java language can be DECIMAL data types of SQL that the UDR declares as BigDecimal data types of the Java language Any C language UDR that returns an opaque data type must specify opaque_type in the var binary declaration of the C host variable

Packages

An Oracle package is a collection of functions procedures and variables that can be enabled and accessed as a unit There is no direct equivalent within Informix but there are ways of achieving similar capabilities Within Oracle a procedure within a package can be accessed through grammar such as package_nameprocedure_name If you create an owner or schema name within the Informix system the same as the package name then it will be easier to migrate calls to that procedure because the grammar is effectively the same although the meaning changes somewhat Using this practice a call to a migrated procedure would be ownerprocedure_name where the owner name is the same as the package name Translating package names as owner names is a way to maintain the scoping of the objects within the package Maintaining the aspect of being able to enable use of or upgrade the collection of package objects can be done by creating a datablade that contains all the objects that used to be part of the package Datablade routines can be procedures or functions written in Stored Procedure Language (SPL) C and Java In addition routines can be written in C++ on Windows platforms

Routines

Oraclersquos stored functions and stored procedures are similar in concept to Informixrsquos stored procedures Oraclersquos user defined database level functions such as stored functions stored procedures all need to be converted to Informix stored procedures using the Informix SPL C or Java Routines written in SPL have the advantage of being maintained and backed up with database backups Routines written in C are fast but are not automatically backed up when the database is and need to be compiled specifically for the operating system on which it will run Routines written in Java also not backed up by the DBMS itself but they are platform independent However probably as a result of having to convert between system memory where the objects have C structures and Java virtual machine memory where the objects have Java structures the performance of Java routines can be slow compared with the C equivalent All procedures written in an Oracle package body must be rewritten as separate Informix procedures When rewriting package bodies into separate procedures Oraclersquos variable declarations can be replaced at the package level (global) with Informixrsquos global variables The Informix global variables must be defined in the first stored procedure of the logical group

Exceptions

The method of handling exceptions is different between Informix and Oracle Oracle has many predefined and user defined exception labels such as CURSOR_ALREADY_OPEN NO_DATA_FOUND ZERO_DIVIDE and so on The labels can be used in the logic to identify errors Only one exception check is allowed per BEGIN and END block using the EXCEPTION construct and it is normally placed just before the END statement Informix also supports predefined and user defined exceptions however they are represented numerically not with labels In Informix all the exceptions checked in the stored procedure control blocks delimited with BEGIN and END statements must be declared explicitly at the top of each

IBM Software Group IBM Information Management

Version 16 52

control block with the Informix EXCEPTION construct Therefore Oracle procedure code must be restructured to manipulate these exceptions In Oracle an exception can be raised globally and acted upon globally In Informix the scope of an exception mechanism is always restricted to the block in which it is located This leads to the addition of multiple Informix exception handling mechanisms for each Oracle exception raised as well as a redesign of the overall stored procedure to a more blocked format

Error handling

In Oracle errors are processed as part of a function call return value In Informix errors are retrieved as a separate function call that has multiple structures that have to be created in order to retrieve error and status The SQLCA structure is not fully available in Informix stored procedures It is not possible to check the SQLCODE variable in the stored procedure body Instead the function DBINFO can be used to extract the value of two members of the SQLCA structure sqlcasqlerrd1 and sqlcasqlerrd2 This function should be used inside the FOREACH construct while the cursor is open Once the cursor is closed the DBINFO function cannot return proper values The sqlcasqlerrd1 option returns different values depending on the type of SQL statement For INSERT statements if the table contains a serial column then the sqlcasqlerrd1 option will return the serial value of the last row inserted into the table For SELECT DELETE and UPDATE statements the sqlcasqlerrd1 option will return the number of rows processed by the query In these cases upon each pass through the FOREACH loop sqlcasqlerrd1 is the same value the number of rows the FOREACH loop will process The sqlcasqlerrd1 value can still be interrogated during each pass through the FOREACH loop The sqlcasqlerrd2 option returns the number of rows processed by a SELECT INSERT UPDATE DELETE or EXECUTE PROCEDURE statement It should not be interrogated until after the cursor has finished processing In other words within the FOREACH loop the sqlcasqlerrd2 value can be moved to a variable which is then interrogated outside of the FOREACH loop

Cursors

Unlike Informix in Oracle cursors can be global to a package In Informix Oraclersquos global cursors can be replaced with temporary tables A temporary table can be created and populated in place of where the cursor is opened The temporary table can then be processed the same way the cursor is processed Finally the temporary table should be dropped in place of where the cursor is closed Cursors are explicitly declared opened and fetched in Oracle stored procedures In Informix cursors do not need to be explicitly declared opened and fetched in stored procedures Instead Oracle stored procedure cursors can be replaced with Informixrsquos FOREACH construct The Oracle cursor name should be used in the FOREACH statement for example FOREACH cursor_name SELECT hellip END FOREACH In order to update a cursor row in Oracle the cursor must be declared with the FOR UPDATE clause In Informix if the SELECT statement in the FOREACH construct is not a multi-table join then each fetched row can be updated using the UPDATE lttable_namegt WHERE CURRENT OF ltcursor_namegt statement See the Update Using Cursors section in ldquoData Manipulation Languagerdquo for more information Informix does not support the SELECT FOR UPDATE statement in a stored procedure Therefore the SELECT FOR UPDATE clause cannot be used in the FOREACH construct

IBM Software Group IBM Information Management

Version 16 53

Variable declaration and assignment

Oracle allows implicit variable definitions within a FOR loop The variables are defined using an assignment operator and a column name For example

out_customer_name = customername

The variable out_customer_name is defined as the same type as the column name in the customer table Informix requires that all variables be defined at the beginning of each stored procedure control block For example

DEFINE out_customer_name LIKE customername

DEFINE counter INTEGER

Therefore Oraclersquos implicit variable declaration must be replaced with Informixrsquos explicit variable declaration before the control block Additionally assignment operations will need to be ported Oracle uses a colon and an equal sign (=) for assignment while Informix utilizes the LET keyword in combination with an equal sign (=) (ie LET var = 1) Therefore assignment statements must be modified with the LET keyword and an equal sign

Boolean

Oraclersquos BOOLEAN variable type can be replaced with Informixrsquos BOOLEAN data type

Binary data types

Binary data types are very different between Oracle and Informix In Oracle the binary type is defined as a type RAW and is explicitly defined with a maximum length as part of the declaration In Informix the binary type is defined as REFERENCES BYTE which deals only with pointers to BLOBs It implicitly defines a maximum length as part of the function call in which the pointer to the BLOB and maximum length (as used in the function call) was passed as values As a result the binary type cannot be assigned a binary value in a stored procedure nor can it be inserted into a table via the SQL INSERT statement in a stored procedure These operations that initialize a binary type must be performed outside of stored procedures

Dynamic SQL

Unlike Oracle Informix does not support dynamic SQL within the Stored Procedure Language In other words a statement such as SELECT variable_name FROM variable_name WHERE variable_name is not supported This kind of processing can be achieved in Informix within an embedded SQL program This requires that either the Oracle stored procedure be converted to an embedded SQL program or just the Dynamic SQL portion be placed in an embedded SQL program and then called from within the stored procedure The latter option will have performance implications since calling an embedded SQL program from a stored procedure requires an operating system call Another option is to use the Informix EXEC Bladelet The EXEC Bladelet consists of user-defined functions that take a SQL query as an argument execute it and return a result (the format of which varies depending on the function and the kind of query) The EXEC Bladelet functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries Further details can be found in Chapter 7 Using Bladelets

Compiler

Unlike Oracle the Informix compiler was developed with the concept that developers can create stored procedures independently of the database Therefore Informixrsquos stored procedure

IBM Software Group IBM Information Management

Version 16 54

compiler has a limited set of errors that it checks compared to Oraclersquos For example the Informix stored procedure compiler does not validate database object names such as table column and view names Therefore database object naming errors will occur at runtime not compile time Additionally the error messages generated from the compiler are not very specific Identifying a problem in a stored procedure may require breaking it apart and recompiling the pieces until the problem is found This may impact the time necessary to unit test the stored procedures

Triggers Oracle supports the use of multiple trigger events for example insert update and delete within the same trigger Informix only supports one trigger event per trigger In Informix the Oracle trigger body in this example must be copied into three different triggers each with only one event Informix triggers have some constraints Oraclersquos do not In Informix if a trigger is fired due to inserting a row into a table a trigger can only act on any rows or columns within that table using the EXECUTE PROCEDURE hellip INTO syntax Similarly if a trigger is fired due to updating a row then the trigger can only act on the column that caused the trigger to fire using the EXECUTE PROCEDURE hellip INTO syntax Like Oracle if a trigger is fired due to deleting a row there are no restrictions Prior to IDS 73 when a trigger was fired on an INSERTUPDATE action no modification could be done to the columns (in the row) which just fired the trigger The reentrant UPDATEINSERT triggers feature introduced with IDS 1110 enables users to update the triggering columns by using the EXECUTE PROCEDURE INTO syntax Additionally the feature enforce that this action will not cause any additional triggers to be fired (same or different trigger) causing a cascading of triggers and potentially an infinite loop The following example demonstrates how the reentrant UPDATEINSERT trigger feature is used

create table foo

(

x int default NULL

y int default NULL

z int default NULL

)

create procedure reentrant()

returning int

return 56

end procedure

create trigger reentrant_trigger insert on foo for each row

(

execute procedure reentrant() into z

)

insert into foo values

(

1

2

3

)

The following SELECT will result in the following returned data

select from foo

x y z

1 2 56

IBM Software Group IBM Information Management

Version 16 55

Oracle allows SQL statements logical statements and stored procedure calls within a trigger body Informix allows only SQL statements and stored procedure calls within a trigger body Oracle triggers containing logical statements must be converted to Informix by moving their contents into a stored procedure The stored procedure should then be executed from the trigger

Constraints Constraints in both Oracle and Informix can be enabled and disabled within an application transaction however there are behavioral differences In Oracle the application is always executing within a transaction In Informix transaction boundaries are explicitly declared and care should be taken to ensure that this functionality is performed within the boundaries of a transaction See the Transaction Processing section in CHAPTER 5 Application Architecture for more information The constraint syntax available in Informix is

SET CONSTRAINTSINDEXESTRIGGERS FOR table_name

ENABLED|DISABLED

SET CONSTRAINTS comma_separated_constraint_names

ENABLED|DISABLED

SET INDEXES comma_separated_index_names ENABLED|DISABLED

SET TRIGGERS comma_triggers_constraint_names ENABLED|DISABLED

SET CONSTRAINTS ALLconstraint_name IMMEDIATE|DEFERRED

The first four statements must be executed with DBA privileges if placed in the application Therefore care should be taken when using them Note that the last statement contains a DEFERRED clause This is the statement used if the users of the application do not have DBA privileges When the constraint is set with the DEFERRED clause the specified constraints are not checked until the transaction is committed If a constraint violation occurs while the transaction is being committed the transaction is rolled back

DUAL table Oraclersquos DUAL table is a system table with only one row containing one column named DUMMY This table is used to complete the syntax of an SQL statement that does not involve an existing table such as

A SELECT statement which assigns some constant value (which can only be derived in an SQL statement) to a host variable

SELECT TO_CHAR(SYSDATE) INTO date_var FROM DUAL

A SELECT statement which assigns a value of another variable to a variable

SELECT source_var INTO dest_var FROM DUAL

A SELECT statement which unions application host variable values with another SELECT statement to return a result containing a row of application variable values

SELECT col1 col2 col3 FROM table_name

UNION

SELECT host_var1 host_var2 host_var3 FROM DUAL

Converting Oraclersquos DUAL table functionality to Informix depends on the way it is used Converting statements that just assign constants is as simple as replacing the DUAL statement with an Informix assignment statement The solutions below apply to Informix versions prior to 11 At 11 and above the concept of a DUAL table as well as sysdate is supported

IBM Software Group IBM Information Management

Version 16 56

SELECT sysdate FROM sysmastersysdual

If you want a dual table in your local database then create the following synonym The sysmastersysdual table is much faster than a physical table in your database because it is an in- memory pseudo table

CREATE SYNONYM dual FOR sysmastersysdual

If you are restricted to using a version of Informix prior to 11 then the following solutions can be used A dummy table can be created to mimic the behavior of simple SELECT INTO statements used to assign values to variables

CREATE TABLE dual (dummy VARCHAR(1))

INSERT INTO dual VALUES(lsquoXrsquo)

An alternate solution to widespread use of the DUAL table could be creating a permanent view that is generally accessible

CREATE VIEW dual (d) as SELECT X

FROM systables WHERE tabid = 1

The exact definition could be used or modified as needed but this would solve the problem of having DUAL be permanent usable by anyone and not modifiable

IBM Software Group IBM Information Management

Version 16 57

C H A P T E R 5 Embedded SQL

Oraclersquos embedded SQL products are ProC and ProCOBOL Informixrsquos corresponding embedded SQL products are ESQLC and ESQLCOBOL

Host variables

Declaration override

The Oracle EXEC SQL VAR declarative statement (host variable equivalency of Oracle external data types by overriding the default assignment) can be converted to an Informix explicit declaration statement For example

Oracle char char_var[20]

EXEC SQL VAR char_var IS STRING(11)

Informix

char char_var[11]

Note that the size and type used in the EXEC SQL VAR section is the final information required to declare the host variable in Informix

Arrays

Oracle arrays are not subscripted in SQL statements since it is not required to process the host arrays in a loop in the SQL statement In Informix subscripting is mandatory In Oracle if an array is defined of size 200 then an SQL statement would be

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A

VAR-B

VAR-C

END-EXEC

-or- EXEC SQL SELECT COL1 COL2 COL3

INTO VAR-A

VAR-B

VAR-C

FROM TABLE1

WHERE COL2 gt 100

END-EXEC

where VAR-A VAR-B and VAR-C are each an array of say 200

IBM Software Group IBM Information Management

Version 16 58

In Informix the first example would be converted to

PERFORM VARYING LOOP-CTR FROM 1 BY 1 UNTIL

LOOP-CTR IS GREATER THAN 200

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A(LOOP-CTR)

VAR-B(LOOP-CTR)

VAR-C(LOOP-CTR)

END-EXEC

IF SQLCODE = 100

GO TO EXIT-PERFORM

END-IF

END-PERFORM

EXIT-PERFORM

For the second Oracle example given above a cursor must be declared in Informix opened and fetched for 200 rows or less (less because there may be less than 200 qualifying rows) into the host array and then should be closed If the number of qualifying rows is more than 200 then the extra rows must be ignored to duplicate the Oracle functionality But for the first example each fetch in Oracle will return the next 200 or less number of rows Therefore each Oracle fetch needs to be replaced by another call to the Informix fetch loop Oracle also uses this method for inserts deletes and updates These array techniques are mainly used in batch SQL processing

Formatting

In Informix when a DECIMAL MONEY DATE or DATETIME value is selected into a host variable of the same data type the value must be formatted using the available Informix formatting routines before they can be printed or displayed For example

hellip

dec_t dec_host_var

char formatted_dec[40]

EXEC SQL SELECT DEC_COLUMN INTO dec_host_var FROM TABLE_NAME

rfmtdec(ampdec_host_var ldquoampampampampampampampampampamprdquo formatted_dec)

printf(ldquoThe Decimal Value is snrdquo formatted_dec)

hellip

IBM Software Group IBM Information Management

Version 16 59

Informix supplies many formatting functions and formatting strings The names of these functions are different in Informix ESQLC and ESQLCOBOL but the functionality is the same Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

SQL structures

SQLCA

Oraclersquos SQLCA structure is different from that of Informix However the components of both structures are logically the same Oraclersquos SQLCA components can be replaced with the corresponding Informix components Oraclersquos SQLCA structure

SQLCAID string containing ldquoSQLCArdquo SQLCABC length of SQLCA data structure SQLCODE Oracle error message code SQLERRM sub-record for error message

SQLERRML length of error message SQLERRMC text of error message SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) reserved for future use SQLERRD(1) reserved for future use SQLERRD(2) number of rows processed SQLERRD(3) reserved for future use SQLERRD(4) parse error offset SQLERRD(5) reserved for future use

SQLWARN array of eight warning flags SQLWARN(0) another warning flag set SQLWARN(1) character string truncated SQLWARN(2) no longer in use SQLWARN(3) SELECT list not equal to INTO list SQLWARN(4) DELETE or UPDATE without WHERE clause SQLWARN(5) reserved for future use SQLWARN(6) no longer in use SQLWARN(7) no longer in use

SQLTEXT reserved for future use

IBM Software Group IBM Information Management

Version 16 60

Informixrsquos SQLCA structure

SQLCODE Informix error code SQLERRM error message parameter SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) estimated number of rows returned SQLERRD(1) serial value of INSERT or ISAM error code SQLERRD(2) number of rows processed SQLERRD(3) estimated cost SQLERRD(4) parse error offset SQLERRD(5) ROWID after INSERT

SQLWARN structure of eight warning flags SQLWARN0 another warning flag set SQLWARN1 character string truncated or no privileges revoked SQLWARN2 NULL value returned or ANSI database SQLWARN3 SELECT list not equal to INTO list or turbo back-end SQLWARN4 DELETE or UPDATE without WHERE clause SQLWARN5 if non-ANSI statement SQLWARN6 if server is in data replication secondary mode SQLWARN7 reserved

In order to get Oracle error messages an application normally uses the SQLCA element SQLERRMC The Informix equivalent is SQLERRM On the HPUX and Solaris platforms the Informix function rgetmsg should be used instead of the element SQLERRM At the time of this writing using SQLERRM would cause an error on the HPUX and Solaris platforms

SQLDA

The implementation of Oraclersquos SQLDA structure is very different from that of Informix Significant changes are necessary to convert Oraclersquos functionality to Informix Oraclersquos sqlald function can be replaced with Informixrsquos ALLOCATE DESCRIPTOR statement Since Oraclersquos and Informixrsquos SQLDA structures are so different Oraclersquos SQLDA logic must be rewritten with the more powerful Informix SQLDA logic or alternatively the Informix system-descriptor area logic Oraclersquos SQLDA Structure

N maximum number of SELECT list items or placeholders V pointer to array of address of SELECT list items or bind variables L pointer to array of lengths of SELECT list items or bind variables T pointer to array of data types of SELECT list items or bind variables I pointer to array of addresses of indicator variable values F actual number of SELECT list items or placeholders S pointer to array of addresses of SELECT list items or placeholder names M pointer to array of max lengths of SELECT list items or placeholder names C pointer to array of current lengths of SELECT list items or placeholder names X pointer to array of addresses of indicator variable names Y pointer to array of maximum lengths of indicator variable names Z pointer to array of current lengths of indicator variable names

IBM Software Group IBM Information Management

Version 16 61

Informixrsquos SQLDA Structure SQLD count of the following SQLVAR members SQLVAR pointer to array of structures

SQLDATA pointer to actual data SQLTYPE data type of placeholder or SELECT item SQLLEN length of the placeholder or SELECT item SQLIND pointer to the indicator SQLNAME pointer to placeholder or SELECT item name SQLFORMAT reserved SQLIDATA indicator data pointer SQLITYPE indicator variable type SQLILEN length of indicator variable

If an Oracle application uses the simple dynamic SQL method using macros only not the SQLDA structure directly the value indicatorsplaceholders can be replaced with a lsquorsquo in Informix For example Oracle sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES (v1 v2)rdquo) Informix sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES ( )rdquo)

ORACA

Oraclersquos ORACA structure is not supported by Informix This structure is used to handle Oracle specific communication and more runtime information than SQLCA Oracle statements containing references to this structure should be removed from the application

Pre-compiler options The Oracle options beginning with the EXEC ORACLE OPTION statement can be removed from the application The options set after this statement do not affect the application logic They may affect some application performance only

Embedded PLSQL Oracle allows procedure language (PLSQL) blocks inside ProC and ProCOBOL code delimited by the EXEC SQL EXECUTE and END-EXEC statements In Informix these blocks must be replaced with the equivalent ESQLC or ESQLCOBOL code

Oracle Call Interface Oracle call interface (OCI) is the base layer for a variety of other application programming interfaces such as JDBC-OCI Oracle Precompilers and Oracle ODBC It is also used directly by customers who are willing to develop their code using a lower level proprietary API From a high level it can be thought of as if IBM Informix had standardized and published the function calls in the ESQLC library Although some customers have reverse engineered these calls and developed applications using them this is generally discouraged because there is no guarantee that the library of calls will not change There is no direct equivalent to this Oracle API in Informix Migrating applications written using Oracle Call Interface (OCI) will require rewriting the code from scratch OCI is native to the C language and so it should be less effort to migrate the application to an Informix API that is also native to C This could be ESQLC or CLI The following information explains differences between Oracle OCI and Informix ODBC

IBM Software Group IBM Information Management

Version 16 62

The following table is an approximate mapping of the differences between the Informix CLI and Oracle OCI function calls in which there is not a direct one-to-one mapping

Oracle Informix Buffer Areas HAD LDA CDA HENV HDBC HSTMT

Connect and allocate resources

OLOG OOPEN SQLConnect SQLAllocEnv SQLAllocConnect SQLAllocStmt

Update delete insert select OPARSE OBNDRV OEXEC SQLPrepare SQLBindParameter SQLExecute

Select ODEFIN OFETCH SQLBindCol SQLFetch

Commit Rollback OCOM OROL SQLTransact

Disconnect OLOGOF OCLOSE SQLDisconnect SQLFreeStmt SQLFreeConnect SQLFreeEnv

Database library calls

One of the first main differences between Informix CLI and Oracle OCI calls is the overall data structures and mechanisms used to process database library calls Oracle uses direct connections to the database server Informix uses an ODBC connection to the database server As a result the Informix calls will be implemented as ODBC SQL calls utilizing three tiers of increasing SQL levels of complexity

Global area processing

Another main difference between Informix CLI and Oracle OCI is Informixrsquos use of pointers to three global areas versus Oraclersquos use of pointers to three different but similar global areas Hence the Oracle OCI calls that utilize HAD (Handle Data Area) LDA (Logon Data Area) and CDA (Cursor Data Area) pointers must be translated over to Informix CLI calls that utilize HENV (Environment Area) HDBC (Database Connection Area) and HSTMT (Statement Area) pointers respectively in conjunction with an ODBC interface

Fetch cycle

Another difference between Informix CLI and Oracle OCI calls is that the overall fetch cycle is different for each and must be modified accordingly In Oracle the fetch cycle for selecting multiple rows utilizing a cursor area involves parsing binding defining fetching and then executing into a cursor data area These must be translated to a cycle that involves preparing binding executing binding and then fetching via the ldquoFor Eachrdquo cycle

RAW binary data type processing

RAW binary data types in Oracle will need to be translated to a pointer-to-BLOB REFERENCES BYTE type in Informix See the Binary Data Types subsection of the Stored Procedures section in CHAPTER 3

Parameter bindings

In Oracle multiple output bindings of parameters are declared as type ldquoOUTPUTrdquo in the ODEFIN() calls In Informix convert the calls to Informix SQLBindCol() calls and bind the output parameters as columns Differences also exist between Informix CLI and Oracle OCI in the use of inputoutput bindings In Oracle these bindings are declared as type ldquoINPUTOUTPUTrdquo in the ODEFIN() calls In Informix a ldquoround robinrdquo approach is used using three variables in the following manner A=B B=C C=A A variable (A) is declared before the SQL bindings as an input variable The function is called

IBM Software Group IBM Information Management

Version 16 63

using a second input variable (B) that is set to the first input variable (A) The function returns a third variable (C) that is bound as an output column Finally the first variable (A) is now set to the returned third variable (C) that made the first variable (A) appear as an ldquoinputoutputrdquo variable to the rest of the program

Embedded SQL for C

VARCHAR

Oraclersquos ProC VARCHAR data type is expanded after pre-compiling into a structure with two elements one is unsigned short len and the other is unsigned char arr[size] The name of the expanded structure is the same name as the VARCHAR variable and size is replaced with the size of the VARCHAR variable In Informix the VARCHAR data type is just a synonym for the C languagersquos char data type Therefore statements that use variable_namelen can be removed from the application and all occurrences of variable_namearr can be replaced with variable_name For example

Oracle VARCHAR vName[40]

strcpy(vNamearr ldquoCompany Namerdquo)

vNamelen = strlen(vNamearr)

Informix VARCHAR vName[40]

strcpy(vName ldquoCompany Namerdquo)

Host variables

The Oracle statement EXEC SQL TYPE is synonymous with the C languagersquos typedef declarative instruction It can be easily replaced with the Informix declarative instruction typedef

Embedded SQL for COBOL

VARCHAR

Oraclersquos ProCOBOL character host variable declaration statementrsquos VARYING clause is expanded after pre-compiling into a group with two elements one is variable-name-LEN PIC S9(4) COMP and the other is variable-name-ARR PIC X(size) The group name is the same as the host variable name and size is replaced with the size of the VARYING variable Informix does not support this concept Therefore statements that use variable-name-LEN must be removed from the application and all occurrences of variable-name-ARR must be replaced with variable-name Also the VARYING clause must be removed from the declarative statement For example

Oracle

05 vName PIC X(40) VARYING

hellip

MOVE ldquoCompany Namerdquo TO vName-ARR

MOVE 12 TO vName-LEN

Informix

05 vName PIC X(40)

hellip

MOVE ldquoCompany Namerdquo TO vName

IBM Software Group IBM Information Management

Version 16 64

Level 88

COBOLrsquos level 88 functionality is not supported within an Informix ESQLCOBOL host variable declaration section in versions prior to 72 Level 88 functionality is supported in Informix ESQLCOBOL 72

SQLDA

In Informix ESQLCOBOL the SQLDA structure is not available The Informix macros such as ALLOCATE DESCRIPTOR DESCRIBE GET DESCRIPTOR and SET DESCRIPTOR must be used to retrieve and manipulate the SQLDA data

REDEFINES

Oracle supports the use of the REDEFINES clause at the elementary level in the host variable declaration section In other words the redefined item cannot be a group item but the redefining item may be a group item Informix does not support the use of the REDEFINES clause in the host variable declaration section in versions prior to 72 The REDEFINES clause is supported in Informix ESQLCOBOL 72

Tips

If the Informix pre-compiler finds an SQL statement within an IF [ELSE IF hellip ] END-IF or EVALUATE END-EVALUATE or PERFORM END-PERFORM block then the pre-compiler adds a period after the generated COBOL statements regardless of whether there is a period at the end of the SQL statement This is a violation of COBOL rules for such blocks and the code may cause syntax errors during compilation or may behave unexpectedly To avoid these problems each SQL statement group should be moved to a new paragraph and these paragraphs should be performed from the block from which they were moved

ODBC Although the Open Database Connectivity (ODBC) API is designed to make it possible to write and compile an application once and use it with any ODBC driver on the same platform there are frequently differences between the underlying DBMSs that can expose problems to the applications For instance there can be differences between how unspecified parts of a date-time value are filled Most of these kinds of differences that get exposed through ODBC have their origins in the differences between the DBMSs themselves There are also cases where there are gaps in the ODBC standard for example there is a standard ODBC call that allows the application to ask the driver if it can support scrollable cursors and there is another call to ask if it can support updateable cursors There is no call to ask if it can support both at the same time With Informix you can have a scrollable cursor and you can have an updateable cursor but you can not have one cursor that is both scrollable and updateable A more complete description of ODBC application migration issues is beyond the scope of this article

IBM Software Group IBM Information Management

Version 16 65

C H A P T E R 6 Application Architecture

Transaction processing Transaction boundaries are defined differently in Oracle and Informix Oraclersquos transactions begin implicitly in one of two ways either by issuing a CONNECT statement or issuing a COMMIT or ROLLBACK statement A CONNECT statement marks the beginning of a transaction and a COMMIT or ROLLBACK statement commits or rolls back the previous transaction respectively and then implicitly begins a new transaction CONNECT statements are usually issued once at the beginning of a program however they may be nested or issued more than once serially to connect to the same or a different database When using more than one CONNECT statement within a program each CONNECT statement must be named This marks the beginning of named transactions Every SQL statement within a named transaction must also be named with the same transaction name as the CONNECT statement at where the SQL is to be executed SQL is named using the EXEC SQL statementrsquos AT clause Informixrsquos transaction boundaries are explicitly marked with the reserved words BEGIN WORK and COMMIT WORK or ROLLBACK WORK Note that once a transaction has begun for a given connection it stays open until a COMMIT or ROLLBACK is executed In other words if an ESQL program begins a transaction and then calls a stored procedure the stored procedure executes within the same transaction If the stored procedure issues a COMMIT then the whole transaction is committed and the calling ESQL program should not issue a COMMIT or ROLLBACK Informix transactions can be written to behave the same way as Oraclersquos To simulate Oraclersquos CONNECT statement behavior an Informix CONNECT should also be issued followed by a BEGIN WORK statement If more than one CONNECT statement is used in a program Informix also requires that the CONNECT and SQL statements be named To simulate Oraclersquos COMMIT and ROLLBACK statement behavior an Informix COMMIT WORK or ROLLBACK WORK statement should be issued followed by a BEGIN WORK statement Nested transactions can be simulated in Informix with the CONNECT statement and naming the transactions Then the Informix SET CONNECTION connection_name statement can be used to switch between transactions Committing or rolling back each named transaction does not commit or roll back other active transactions The Oracle statement EXEC SQL COMMITROLLBACK RELEASE should be replaced with the Informix statements EXEC SQL COMMITROLLBACK [WORK] followed by EXEC SQL DISCONNECT CURRENT In the following examples ws-dbenviron is the database name ws-connect-nm is the user name and ws-identity-nm is the password set in the program enp and connection-name are the connection names For Informix the user name and password information should correspond to the entries in the etcpasswd file on the UNIX system See the User Authentication section later in this chapter for more information The default server name is automatically obtained from the environment variable INFORMIXSERVER The following examples illustrate how Oracle and Informix implement the CONNECT functionality

IBM Software Group IBM Information Management

Version 16 66

Simple Connect

Oracle

CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm

Informix

CONNECT ws-dbenviron USER ws-connect-nm USING ws-identity-nm

Named Connect with Literal

Oracle

DECLARE enp DATABASE hellip CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm AT enp USING ws-dbenviron hellip AT enp SELECT col1 col2 INTO var1 var2

FROM table_name

Informix

CONNECT TO ws-dbenviron AS ldquoenprdquo USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION ldquoenprdquo hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Named Connect with Variable

Oracle

CONNECT ws-connect-nm

IDENTIFIED BY ws-identity-nm AT connection-name USING ws-dbenviron hellip AT connection-name SELECT col1 col2 INTO var1 var2 FROM table_name

Informix

CONNECT TO ws-dbenviron AS connection-name USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION connection-name hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Autonomous Transaction

An autonomous transaction is an independent transaction that is initiated by another transaction (the parent transaction) An autonomous transaction can modify data and commit or rollback independent of the state of the parent transaction The autonomous transaction must commit or roll back before the autonomous transaction is ended and the parent transaction continues

IBM Software Group IBM Information Management

Version 16 67

An autonomous transactions has been available since the release of Oracle 8i An autonomous transaction is defined in the declaration of a PLSQL block This can be an anonymous block function procedure object method or triggerThis is done by adding the statement PRAGMA AUTONOMOUS_TRANSACTION anywhere in the declaration block There isnt much involved in defining a PLSQL block as an autonomous transaction You simply include the following statement in your declaration section PRAGMA AUTONOMOUS_TRANSACTION Sample code

PROCEDURE test_autonomous

IS

PRAGMA AUTONOMOUS_TRANSACTION

BEGIN

insert

commit

END test_autonomous

Autonomous transactions can be used for logging in the database independent of the rollbackcommit of the parent transaction

Savepoints

Oracle allows savepoints within its PLSQL For example a PLSQL block can be structured so that SAVEPOINT A is issued upon entry and SAVEPOINT B is issued after some processing Then after some more processing a COMMIT or ROLLBACK can be issued against all the logic since the last COMMIT point which is before the PLSQL block or up to any of the savepoints by naming the COMMIT or ROLLBACK with the savepoint name In other words a savepoint can be issued at the beginning of a stored procedure and then only the stored procedure logic can be committed without committing the changes pending before the stored procedure was executed Those changes can be committed or rolled back once processing is returned from the stored procedure Informix does not support savepoint processing within a stored procedure

Concurrency Database concurrency can be managed through the combination of two configurable settings one specifies the lock granularity on database objects while the other influences how the application behaves in regards to the presence and placement of locks using a transaction isolation level

Row Level Locking

Oracle and Informix implement locking differently on database objects Oracle defaults to row level locking whereas Informix defaults to page level In most cases row level locking is preferred to improve concurrency Informix supports row level locking however it must be either explicitly requested specified by an environment variable or permanently changed in the instancersquos configuration Having three methods for establishing the lock level there is an order of precedence

1 To be explicitly requested the CREATE TABLE statement must include the specification of the LOCK MODE attribute

CREATE TABLE emp (

name CHAR(40)

salary MONEY

ssn LVARCHAR(64)

) LOCK MODE ROW

IBM Software Group IBM Information Management

Version 16 68

2 The environment variable IFX_DEF_TABLE_LOCKMODE will establish the default for CREATE TABLE statements issued without the LOCK MODE attribute and will override the Instancersquos configuration setting The variable setting on the client will override the server environment setting

set IFX_DEF_TABLE_LOCKMODE=ROW -or- export IFX_DEF_TABLE_LOCKMODE=ROW

3 Informix allows the instancersquos lock level default to be changed using a configuration parameter Row level locking can be as the default by adding the parameter DEF_TABLE_LOCKMODE to the instancersquos ONCONFIG file This parameter may not be found in the existing file and if not present can be added using an editor and establish a new default setting of ROW

DEF_TABLE_LOCKMODE ROW

None of the steps will apply a change to existing tables only establish the lock level for the CREATE TABLE statement

Transaction Isolation Level

Oracle databases incorporate a feature known as ldquoread consistencyrdquo which allows a query return a result based on the state of the data when the query started regardless of other processes updating or deleting the same data while the query is running Informix facilitates this type of behavior differently by providing control of the applicationrsquos placement of locks as well as how it reacts to those placed by other processes through the use of the transactionrsquos isolation level If Oraclersquos technique of ldquoreaders not blocking writersrdquo is a requirement then in many circumstance Informixrsquos DIRTY READ isolation level can be used The readers will not block the writers with dirty read processing however the query result may contain updates performed while the query was running which may be uncommitted If the emulation of Oraclersquos ldquoread consistencyrdquo is desired the LAST COMMITTED option of Informixrsquos COMMITTED READ isolation level can reduce the risk of locking conflicts when two or more sessions attempt to access the same row in a table whose locking granularity is row-level When an application attempts to read a row on which another session holds an exclusive lock these keywords instruct the database server to return the most recently committed version of the row rather than wait for the lock to be released This isolation level attribute could be preferable to executing queries using DIRTY READ since it will return only the most recently committed versions of the data The LAST COMMITTED option can be enabled in the following ways

1 Setting the USELASTCOMMITTED parameter in the Instancersquos configuration (ONCONFIG) will apply this feature as the default isolation level to all database transactions The parameterlsquos values will designate the scope of applying the LAST COMMITED option to either ALL NONE or only COMMITED READ and DIRTY READ isolation levels

USELASTCOMMITTED [ALL | NONE | COMMITTED READ | DIRTY READ]

2 The SET ENVIRONMENT statement can override the USELASTCOMMITTED configuration parameter setting for the duration of the current session The same semantics apply as the parameter within the ONCONFIG file with the setting value enclosed in quotes (lsquo)

SET ENVIRONMENT USELASTCOMMITTED lsquoALLrsquo

IBM Software Group IBM Information Management

Version 16 69

3 The SET ISOLATION statement can be used to override the instance configuration and session environment setting The SET ISOLATION statement is an Informix extension to the ANSI SQL-92 standard and provides the same functionality as the ISOANSI-compliant SET TRANSACTION statement There is no support for the LAST COMMITTED option with the SET TRANSACTION statement SET TRANSACTION complies with ANSI SQL-92 and only ANSI supported isolation levels are supported

SET ISOLATION TO COMMITTED READ LAST COMMITTED

4 PREPARE statements in ODBCJDBC applications

This feature is primarily documented in the Guide to SQL Syntax Guide to SQL Reference Administrators Reference and Administrators Guide

IBM Software Group IBM Information Management

Version 16 70

C H A P T E R 7 Security

User authentication In Oracle security information is stored in the database Up until recently Informix has used only the operating system security subsystem to check security For security purposes Oracle connects to the server and passes the user ID and password information to the database for verification

Operating system security

Informix does not store user ID and password information in the database Instead they are validated against the operating systemrsquos security mechanism on the server for example the etcpasswd file in UNIX Therefore either every database user must have an entry in the serverrsquos password file or the application must handle a level of security where user IDs are converted into a group id based on database permissions and only those group IDs are entered into the password file Note that if the second alternative is chosen then auditing capabilities based on user ID are lost Also if the application performs security functions then those functions are not applicable to third party applications such as report writers application development tools and so on when they access the database The home directory of all the users should point to the same physical directory where the application executable resides The Informix method of using the operating system for security checking allows external programs to be called from within stored procedures This capability is not allowed in Oracle In Oracle the OPS$User_name is sometimes used to connect to the database where OPS$User_name is a valid Oracle user and User_name is a valid operating system level user In this case the connection is made to the database using just the lsquorsquo character without the user id and password Informixrsquos technique of using the etcpasswd file for security works fine for this type of connection

Non-operating system security

In previous releases each user who needed to access the database server also needed an operating system account on the host computer Now you can configure Informix so that users who are authenticated by an external authentication service (such as Kerberos or Microsoft Active Directory) can connect to Informix The new USERMAPPING configuration parameter specifies whether or not such users can access the database server and whether any of those users can have administrative privileges When Informix is configured to allow user mapping you can still control which externally authenticated users are allowed to connect to Informix and their privileges Please refer to the IBM Informix documentation on connection security for more information

IBM Software Group IBM Information Management

Version 16 71

Informix supports for the pluggable authentication module (PAM) framework which lets an administrator customize authentication for individual applications and permits column-level encryption

Role based authority Role based authority can help you manage your database permissions As of version 1110 you can create a role and assign that as a default role for individual users (or to PUBLIC) A role is a work-task classification such as ldquopayrollrdquo or ldquomanagerrdquo Each defined role has privileges on the database object granted to the role You use the CREATE ROLE statement to define a role and GRANT DEFAULT ROLE to establish the userrsquos initial setting when connecting to the database A userrsquos role can be changed after connecting by using the SET ROLE statement

Column-level encryption You can use column-level encryption to improve the confidentiality of your data IDS Version 1110 has new built-in SQL scalar functions provide methods for data in columns to be stored in an encrypted format Use the ENCRYPT_AES or the ENCRYPT_TDES function to define encrypted data Use the DECRYPT_BINARY() and DECRYPT_CHAR() functions to query encrypted data When using the routines the encryption of data is under application control and the DBMS is not aware that data is encrypted Informixrsquos support of column level encryption is analogous to Oraclersquos DBMS Obfuscation Tool Kit Built-in ENCRYPT functions provide methods for encrypting and decrypting the following character data types or smart large object data types

CHAR

NCHAR

VARCHAR

NVARCHAR

LVARCHAR

BLOB

CLOB

Passwords and hints

Passwords are necessary when using the encryption functions Only users who can provide a secret password can view copy or modify encrypted data The password must be a minimum of 6 bytes and can be a maximum of 128 bytes When you set an encryption password you have the option of specifying a password hint Hints can be up to 32 bytes of text If you specify a hint you can store the hint with the encrypted password or in another location Passwords (and hints) to be used by default can be set for a session using the SET ENCRYPTION PASSWORD statement

SET ENCRYPTION PASSWORD lsquopasswordrsquo [ WITH HINT lsquohint stringrsquo ]

Hence the password and hint parameters can be optional when calling the encryption function Explicit values override the session default values The password or hint can be a single word or several words The hint should be a word or phrase that helps you to remember the password but does not include the password You can subsequently execute the built-in GETHINT function (with an encrypted value as its argument) to return the plain text of hint Calling the GETHINT function with an argument of encrypted data will return the hint (if any) from the encrypted data or an empty string (NULL) is no hint was provided There is no privilege needed anybody can get any hint at any time When you set a password Informix transfers the password and any hint to 128-bit key that is used to encrypt the password and hint Passwords and hints are not stored as plain text any table of the system catalog The key is a time-based random value per instance The database server

IBM Software Group IBM Information Management

Version 16 72

initializes the key when the server starts the key is destroyed when the database server shuts down

Encrypting a column

Column data can be encrypted through the use of two functions ENCRYPT_TDES and ENCRYPT_AES corresponding to the two data encryption standards Triple Data Encryption Standard (Triple-DES) and Advanced Encryption Standard (AES) which describes the cipher algorithm used to protect data from unauthorized viewing AES encryption (also known as Rijndael) uses a 128-bit key size and Triple-DES encryption uses two 56-bit keys for 112-bits overall Both functions are variant functions and will return a different result every time it is used The following example demonstrates how to use the encryption functions with a column that contains a social security number

CREATE TABLE emp (name CHAR (40) salary MONEY ssn LVARCHAR(64))

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890one two

three 123))

-or-

CREATE TABLE emp (name CHAR(40) salary MONEY ssn LVARCHAR(64))

SET ENCRYPTION PASSWORD one two three 123

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890))

Querying an encrypted column

Encrypted data can be translated using Informixrsquos DECRYPT_CHAR and DECRYPT_BINARY scalar functions Encrypted data contains information about the encryption method and all the other data needed to decrypt it except the password The encrypted data value is passed as the first argument and a password as the second unless the SET ENCRYPTION statement has specified for this session with the same session password by which the first argument was encrypted If the data is not encrypted the function call will return an error The DECRYPT_CHAR function is used to invoke a decryption routine on character data types (ie CHAR LVARCHAR NCHAR NVARCHAR and VARCHAR) while the DECRYPT_BINARY function accepts an encrypted large object of type BLOB or CLOB If the first argument to DECRYPT_CHAR or DECRYPT_BINARY is not an encrypted value or if the second argument (or the default password specified by SET ENCRYPTION) is not the password that was used when the first argument was encrypted Informix will issue an error and the call fails If the call to the decryption function is successful it returns the plain text version of the encrypted data argument The following example demonstrates how to use the decrypt function to query encrypted data

SELECT name salary DECRYPT_CHAR(ssn lsquoone two three 123rsquo)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

-or-

SET ENCRYPTION PASSWORD lsquoone two three 123rsquo

SELECT name salary DECRYPT_CHAR(ssn)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

The first argument to DECRYPT_BINARY is expected to be an encrypted value of a large object data type however if it is called with a character data type Informix invokes the DECRYPT_CHAR function and attempts to decrypt the specified value

IBM Software Group IBM Information Management

Version 16 73

Do not use either decryption function to create a functional index on an encrypted column This would store the decrypted values as plain text data in the database defeating the purpose of encryption

Performance impact of encryption

The performance impact of encryption is significant Encryption by its nature will slow down most SQL statements If some care and discretion are used the amount of extra overhead should be minimal Also encrypted data will have a significant impact on your database design In general you want to encrypt a few very sensitive data elements in a schema like social security numbers credit card numbers patient names and so on The effect on performance depends on direction encrypting is slower than decrypting It does not depend measurably on which algorithm is used AES performs at the same speed as Triple-DES It does depend on data size the relative overhead is less when there is more data to encrypt

Storage considerations

An encrypted value uses more storage space than the corresponding plain text value Data encrypted using AES can be bigger than Triple-DES but not by a significant amount This occurs because all of the information needed to decrypt the value except the encryption key is stored with the value Therefore before you set the encryption password and encrypt the data you must be sure the encrypted data can fit in the column A chart of the expected sizes can be found in the IBM Informix Administrator Guide

Compliance regulations

Informixrsquos encryption routines comply with the United Statesrsquo regulations of Health Insurance Portability and Accountability Act (HIPAA) Sarbanes-Oxley Gramm-Leach-Bliley and California Personal Information Privacy (SB 1386) as well as the international requirements of Basel II Also they comply with the latest cryptographic standards (OpenSSL 097c)

IBM Software Group IBM Information Management

Version 16 74

C H A P T E R 8 Environment

Scripts Oracle make files used to build the application should be modified to invoke the appropriate Informix ESQLCOBOL ESQLC MF COBOL and other application language commands The shell scripts shell startup scripts and command files should be modified for Informix compliant statements

SQL script substitution variables

In Oracle a substitution variable is a user variable name preceded by one or two ampersands (amp) When Oracle (SQLPlus) encounters a substitution variable in a command Oracle executes the command as though it contained the value of the substitution variable rather than the variable itself In Oracle the substitution variables can be used anywhere in SQL and SQLPlus commands except as the first word entered at the command prompt When SQLPlus encounters an undefined substitution variable in a command SQLPlus prompts the user for the value SQLPlus reads the responses from the keyboard even if terminal input or output has been redirected to a file If a terminal is not available (if for example the command file is run in batch mode) SQLPlus uses the redirected file Informixrsquos dbaccess does not provide this functionality however a work-around for the redirected file type of substitution is a follows (no user prompting) Create the following shell script (named subvalsksh in this case)

binkshif [[ $ -ne 2 ]]

then

echo nUsage $0 ltdfilegt ltcfilegtn

echo Desc This script accepts two files - dfile the decode

file

echo and cfile the change file It modifies the

change file

echo using the values listed in the decode file

echo The decode file should contain two columns - old

value

echo and new value

echo Ex

echo changethis tothis

echo

echo In this case every occurance of changethis

would be

echo replaced with tothisn

exit 1

fi

IBM Software Group IBM Information Management

Version 16 75

-----------------------

Declare variables

-----------------------

dfile=$1

cfile=$2

awk print s$1$2 $dfile gt $dfile_sed

sed -f $dfile_sed $cfile

The preceding script is used by creating a ldquodecoderdquo file (named decodefile in this case) which holds two columns in the form which may contain multiple rows

oldval newval

Executing the following command

subvalsksh decodefile chgfile

will replace every occurrence of oldval with newval in the file chgfile The shell script (subvalsksh) writes to standard output therefore the output should be redirected The redirected file will then be able to run with dbaccess

Utilities To improve performance the Informix EXPLAIN utility should be used by executing the SET EXPLAIN ON command to see how an SQL statement accesses the database From that point forward the access path for every SQL statement is written in the SQEXPLAINOUT file in the current working directory or the home directory of the process that initiated the request on the host machine The Informix SET EXPLAIN OFF should be executed to turn off this feature when finished The overall system performance should be monitored using the Informix ONSTAT utility

System catalog The following items discuss how Informix implements the system catalog differently than Oracle Each item refers to the Informix implementation only Object names are stored in lower case The system catalog tables are owned by lsquoinformixrsquo To query the systables table use SELECT from lsquoinformixrsquosystables Each table in systables is assigned a tabid by the system It is used as the primary key and therefore the foreign key for the other catalog tables The identifier information is stored in sysindexes Columns part1 - part16 each contain a column component of a composite index They are integers positive for ascending order negative for descending order In syscolumns collength and coltype have special meanings depending on the data type of the column See the Informix Guide to SQL Reference Version for details

IBM Software Group IBM Information Management

Version 16 76

C H A P T E R 9 Using Bladelets

What is a Bladelet

A Bladelet is a small informal Informix Datablade module Its meant to be useful out of the box and is offered complete with source code at no cost -- and no support or warranty In the context of this document the term Datablade refers to an extension to the standard IBM Informix database engine These generally take the form of new data types (for example timeseries or video) andor new routines that execute inside the server The new routines might operate on new data types or on existing ones A Datablade module is usually a formal product available for sale In addition a Datablade is

Developed either by IBM Informix or by a third-party developer

Rigorously tested

Packaged and sold for profit

May or may not be formally certified by IBM Informix as having been developed according to approved Datablade coding practices

In contrast a Bladelet is

Not rigorously tested

Not sold for profit

Not certified by IBM Informix A Bladelet is an extension to the database engine that is narrow in scope and thought to be generally useful being offered at no cost complete with source Just remember before you use any of this code in mission-critical applications its up to you to thoroughly test it and fix any problems you find Please review the disclaimer which applies to any sample code you find on this site httpwwwibmcomdeveloperworksdb2zonesinformixlibrarysamplesdb_downloadshtml Note The bladelets at this link have not been updated for some time (at the time of this writing) some of the capabilities especially simple function call that increase compatibility may have been introduced into the Informix server itself since they were written

Useful Bladelets

Bladelet Description

Exec Defines two user-defined functions that provide dynamic SQL functionality within a SPL procedure

Flat File Access Method A complete access method that lets you build virtual tables based on operating system files

IUtil Implements a collection of other database vendor functions for Informix

IBM Software Group IBM Information Management

Version 16 77

JPEG Image Bladelet Provides a user-defined type for JPEG images that allows you to manipulate images and to extract and search on image properties

Multirepresentational lvarchar Opaque Type

Creates the idn_mrLvarchar opaque type which stores character data up to 2 gigabytes

Node Datablade Module Creates the node opaque type which is intended to solve one of the hardest problems in relational databases transitive closure

Regexp Creates routines that let you manipulate character and clob data using regular expressions

Shapes DataBlade Module Creates several opaque types for managing spatial data including R-tree index support

Smart Blob Information DataBlade Module

Includes a variety of useful routines for working with smart blobs

SqlLib C SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

SqlLib Java SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

Versioning Table Access Method

Permits users to create and manage versioned tables

We will look closer at two bladelets which could assist with migration the Exec datablade and SQLLib

Informix Exec bladelet for Dynamic SQL Often it is desirable to execute a SQL query that is generated at run-time within the RDBMS For example a developer may not know the name of the temporary table they wish to run the query against or they might want to append predicates to a query In external programs this can be accomplished using the ESQLC SQLCA and DESCRIPTOR facilities Unfortunately the INFORMIX Stored Procedure Language (SPL) does not support Dynamic SQL Queries must be hard-coded into the SPL logic The objective of the Exec bladelet is to remedy this situation Exec consists of user-defined functions that take an SQL query as an argument execute it and return the result (the format of which varies depending on which function is called and the kind of query) The Exec functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries For more details and download refer to

httpwwwibmcomdeveloperworksdb2zonesinformixlibrarydemoids_exechtml

There are three User Defined Routines (UDRs) in the Exec bladelet Two of them are external C functions that use the Server API (SAPI) These must be compiled into shared libraries on the target machine and you need to declare them to the server using CREATE FUNCTION statements The third UDR is a routine written in Informix Stored Procedure Language (SPL) that uses the first two UDRs to return a collection of items The Exec bladelet module consists of the following

1 EXEC The EXEC() function takes an LVARCHAR that it treats as a SQL query executes the query and returns a single LVARCHAR result string Depending on what kind of SQL statement is submitted Exec() returns a different result format

IBM Software Group IBM Information Management

Version 16 78

2 EXEC_FOR_ROWS The EXEC_FOR_ROWS() UDR is an iterator function which means it can return more than one result row Of course it only does so when it is asked to execute a SELECT Otherwise it behaves exactly as the EXEC() UDR Being an iterator function limits the ways in which such a UDR can be used It cannot be used in another SQL query The only place it can be used effectively is inside a SPL routine

3 EXEC_FOR_MSET EXEC_FOR_MSET() is a SPL routine that uses the EXEC_FOR_ROWS() routine introduced above Instead of returning a set of rows as an iterator or a single row as the EXEC() UDF does this UDR collects the results of the SQL query together into a single object a multi-set

Refer to Appendix E Sample Code for examples on using the EXEC bladelet functions

SqlLib DataBlade module (SqlLibC11 SqlLibJ11) The SqlLib DataBlade module implements SQL routines that the Informix does not support natively but that are supported by some other database vendors Source code is freely available for download and includes two implementations one in C (SqlLibC) and the other in Java (SqlLibJ)

The following routines are included

ascii - takes a single character as input and returns the ASCII value in decimal that corresponds to that character

ceil - takes a single numeric value as input and returns the smallest integer that is either equal to or greater than the input value

chr - takes an integer value and returns the character that is represented by the ASCII value (in decimal) of that integer

instr - searches for a value in a string and returns the position where it was found It

returns 0 if the search value was not found instrb - provides the exact same functionality as instr() but for single-byte character sets

sign - takes a numeric argument and returns an integer that indicates if the input value is

positive (1) negative (-1) or zero (0) to_decimal - converts the input character argument into a decimal type

to_float - converts the input character argument into a float type

to_integer - converts the input character argument into an integer type For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

IBM Software Group IBM Information Management

Version 16 79

A P P E N D I X A Planning guide

The checklist below will help an analyst determine which Oracle features which need to be converted to Informix and give some guidance on the effort involved Each porting task is listed They are followed by a quantity field used to determine how prevalent the item the difficulty or amount of effort involved 1 (low) to 5 (high) is used to estimate the amount of time needed to perform the task when the associated item exists in the application a moderate number of times What is moderate depends on the size of the application If there are an unusually large number of occurrences of an item then the effort should be increased Conversely if there are a small number of occurrences of an item then the effort should be decreased Each of these items is discussed in detail within this document Each heading corresponds to a section heading within the document

Tasks Quantity Effort

DDL

Identifiers Delimit identifiers named with Informix reserved words 2 Databases Determine database names and create databases 3 Replace Oracle tablespace names with Informix dbspace names 1 ANSI vs Non-ANSI considerations 3 Tables Convert create table statements 2 Convert DDL syntax 3 Reduce primary key length to 390 bytes 5 Data Types Convert Oraclersquos NUMBER data type 3 Convert VARCHAR columns 2 Convert Oraclersquos DATE data type 5 Convert raw data types 2 Convert Rowids 2 Indexes Convert Indexes 2 Views Remove CREATE VIEW statement options 1 Stored Procedures and Triggers Convert CREATE and REPLACE Stored Procedure and Trigger syntax 1 Oracle Extensions Remove non-supported Oracle extensions from DDL 1

Tasks Quantity Effort

DML

SQL Add the Informix AS clause to display labels 1 Replace non-supported DML syntax ^= hellip = ELSE IF 2 Convert Optimizer DirectiveHints 2 Convert InsertSelectUnion and InsertValueSelect statements 3

IBM Software Group IBM Information Management

Version 16 80

Convert Delete statement syntax 1 Convert temporary table processing 2 Convert Join statements + MINUS INTERSECT different data types 2 Convert sorts 4 Convert hard coded SQL error messages 3 Remove correlation names on the main table of Update and Delete statements

2

Replace original table names in SELECT statements using aliases 1 Convert hierarchical implementation (CONNECT BY PRIOR) 5 Host Variables Convert host variable format or add conversion processing 5 Functions Convert date and time functions 5 Convert aggregate functions 3 Convert mathematical functions 5 Convert string function syntax 1 Convert other unsupported Oracle functions 5 Macros Convert ISOPEN NOT FOUND ROWTYPE and TYPE macros 3 Pseudo-Columns Convert Level processing 3 Convert Rownum processing 2 Update Using Cursors Convert WHERE CURRENT OF processing for multiple table joins 5 Convert FOR UPDATE with a HOLD cursor processing 2 Convert concurrency processing from Oraclersquos implicit to Informixrsquos explicit

4

System Tables Convert system table references 1

Tasks Quantity Effort

Stored procedures Break stored procedures greater than 64K in size into smaller ones 2 Convert Oraclersquos stored procedure packages 3 Convert exception processing 5 Convert error handling (SQLCA) 2 Convert Oraclersquos global cursor processing 5 Convert Oraclersquos explicit cursor processing 2 Convert flow control processing 5 Convert Oraclersquos implicit variable declaration and assignment 3 Convert Oraclersquos BOOLEAN variable type 1 Convert binary data type processing Convert Oraclersquos dynamic SQL processing 5 Triggers Convert multi-functional triggers 3 Convert Insert and Update triggers which are not supported in Informix 5 Place logical statements in a stored procedure 5 Constraints Convert constraint enabling and disabling processing 5 DUAL table Convert Dual table processing 4

Embedded SQL

Host variables

IBM Software Group IBM Information Management

Version 16 81

Convert declaration overrides 1 Convert array processing 5 Convert Oraclersquos formatting functions 4 SQL structures Convert SQLDA processing 5 Convert ORACA processing 1 Pre-compiler options Convert Oracle pre-compiler options 1 Embedded PLSQL Convert Oraclersquos Embedded PLSQL 5 ODBC Convert Oraclersquos OCI 5 Convert database library calls Convert global area processing Convert fetch cycle Convert RAW data type processing Convert parameter bindings Embedded SQL for C Convert VARCHAR processing 2 Embedded SQL for COBOL Convert VARCHAR processing 2 Convert 88 Level processing in COBOL 2 Convert Redefine processing in COBOL 4

Tasks Quantity Effort

Application architecture

Transaction processing Convert application to Informix transaction processing 5 Convert multiple connect processing 5 Convert savepoints Concurrency Address Informix locking processing na 2 User authentication Address Informix security processing na 4

Environment

Convert make files 2 Convert shell scripts shell startup scripts and command files 2 Convert script substitution variables

IBM Software Group IBM Information Management

Version 16 82

A P P E N D I X B Syntax comparison

See the Informix Guide to SQL Syntax for more information on each item

Oracle Informix Boolean AND AND AND NOT NOT NOT OR OR OR Greater Than or Equal To gt= gt= Less Than or Equal TO lt= lt= Not Equal ltgt = or ^= ltgt or = Identifiers letters numbersrdquo_rdquordquo$rdquordquordquo letters numbers and ldquo_rdquo Data types Character CHAR CHAR Long Character VARCHAR (2000) if lt= 2000

LONG VARCHAR if gt 2000 CHAR or TEXT

Number (2 bytes) NUMBER SMALLINT Number (4 bytes) NUMBER INTEGER Number (gt 4 bytes) NUMBER DECIMAL Image LONG RAW CLOB BLOB BYTE TEXT CLOB BLOB DML Comments -- hellip -- hellip Assignment var1 = expression LET var1 = expression Condition ELSE IF ELSE or ELIF

IF Aggregate functions Average AVG(expression) AVG(ALL

expression) AVG(DISTINCT expression)

AVG(expression) AVG(ALL expression) AVG(DISTINCT column_name) AVG(UNIQUE column_name)

Count COUNT() COUNT (expression) COUNT(ALL expression) COUNT (DISTINCT expression)

COUNT() COUNT(DISTINCT column_name) COUNT (UNIQUE column_name)

Maximum MAX(expression) MAX(ALL expression) MAX(DISTINCT expression)

MAX(expression) MAX(ALL expression) MAX(DISTINCT column_name) MAX(UNIQUE column_name)

Minimum MIN(expression) MIN(ALL expression) MIN(DISTINCT expression)

MIN(expression) MIN(ALL expression) MIN(DISTINCT column_name) MIN(UNIQUE column_name)

Sum SUM(expression) SUM(ALL expression) SUM(DISTINCT expression)

SUM(expression) SUM(ALL expression) SUM(DISTINCT column_name) SUM(UNIQUE column_name)

Algebraic functions Round ROUND(expressionrounding

factor) ROUND(expressionrounding factor)

Statistical functions Standard Deviation STDEV(expression) STDDEV(expression) Variance VARIANCE(expression) VARIANCE(expression) Range RANGE(expression)

IBM Software Group IBM Information Management

Version 16 83

String functions

Trim LTRIM(expression) RTRIM(expression)

LTRIM(expression) RTRIM(expression)

Length LENGTH(string) LENGTH(string) Like LIKE(string) LIKE(string) Like (single character) _ _ Like (wildcard) String Delimiter lsquo or ldquo lsquo or ldquo Escape Character set within LIKE clause using

ESCAPE ldquordquo to make ldquordquo the escape character

or set within LIKE clause using ESCAPE ldquordquo to make ldquordquo the escape character

Stored procedures Create CREATE OR REPLACE

PROCEDURE procedure_name (var1 IN CHAR(1) var2 OUT DATE var3 IN OUT NUMBER)

DROP PROCEDURE procedure_name CREATE PROCEDURE procedure_name (var1 CHAR(1) var3 INTEGER) RETURNING DATE INTEGER

Arguments EXECUTE PROCEDURE procedure_name (var1 IN var2 OUT var3 IN OUT)

EXECUTE PROCEDURE procedure_name (var1 var3) RETURNING var2 var3

IBM Software Group IBM Information Management

Version 16 84

A P P E N D I X C Database concepts

The table below illustrates the relationship between each database vendorrsquos database objects

Oracle Informix

Database name attached to a group of files Specific database name

Data file Chunk

Tablespace (logical partition) or Segments (Index Segment Table Segment and so on)

Dbspace

Extent Extent

Rollback Segment Physical Log

Redo Log Logical Log

System tablespace Root dbspace

Temporary tablespace Temporary dbspaces dbspacetemp environment variable or dbspacetemp onconfig parameter

Pointer Blobspace Sbspace

Table partitioning table fragmentation

Database link Not supported

Snapshot Not supported

oerr utility finderr utility

sqldba and svrmgrl - monitor utilities onstat and oncheck utilities

SQLPlus utility dbaccess utility

ProC ESQLC

ProCOBOL ESQLCOBOL

SQLNET INet

OCI Like the ESQL function library after pre-compiling if they were publically documented

Read Consistency COMMITTED READ LAST COMMITTED

IBM Software Group IBM Information Management

Version 16 85

A P P E N D I X D Sample code

User defined functions User Defined Routines (UDR) can be developed to extend the capabilities of the database and provides the option to create UDRs to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or rename an Informix function to the corresponding Oracle function name

CONCAT

CREATE PROCEDURE concat (str1 VARCHAR(255) str2 VARCHAR(255)) RETURNING VARCHAR(255) RETURN str1 || str2

END PROCEDURE

INSTR

CREATE PROCEDURE instr( str VARCHAR(255) mask VARCHAR(255) strt SMALLINT DEFAULT 1 occur SMALLINT DEFAULT 1 ) RETURNING INT DEFINE slen SMALLINT DEFINE mlen SMALLINT DEFINE tempstr VARCHAR(255) DEFINE tempmask VARCHAR(255)

DEFINE nomatch SMALLINT DEFINE count SMALLINT DEFINE pos SMALLINT DEFINE retpos SMALLINT DEFINE i SMALLINT DEFINE j SMALLINT DEFINE srchstrt SMALLINT LET slen = LENGTH(str) LET mlen = LENGTH(mask) LET count = 0 LET nomatch = 0 LET pos = 1 LET retpos = 1 LET tempstr = LET tempmask = LET srchstrt = strt

IF (strt lt 0) THEN - reverse the str FOR i = 1 TO slen LET tempstr = str[11] || tempstr LET str = str[2255] END FOR -- reverse the mask FOR i = 1 TO mlen LET tempmask = mask[11] || tempmask LET mask = mask[2255] END FOR

IBM Software Group IBM Information Management

Version 16 86

LET srchstrt = strt -1 LET str = tempstr LET mask = tempmask END IF FOR j = 1 TO slen LET tempstr = str LET tempmask = mask FOR i = 1 TO mlen IF (tempmask[11] = tempstr[11]) THEN LET nomatch = 1 EXIT FOR END IF LET tempmask = tempmask[2255] LET tempstr = tempstr[2255]

END FOR IF (nomatch = 0) THEN IF (pos gt= srchstrt) THEN LET count = count + 1 END IF IF (count = occur) THEN IF (strt lt 0) THEN RETURN slen - pos + 1 ELSE RETURN pos END IF END IF END IF LET str = str[2255] LET nomatch = 0

LET pos = pos + 1 END FOR RETURN 0 END PROCEDURE

YYYYMMDD

CREATE PROCEDURE yyyymmdd (str VARCHAR(10)) RETURNING varchar(8)

DEFINE retstr VARCHAR(8)

IF str IS NULL THEN

RETURN NULL

ELSE

LET retstr = str[710] || str[12] || str[45]

RETURN retstr

END IF

END PROCEDURE

Using EXEC bladelet functions

IBM Software Group IBM Information Management

Version 16 87

Using EXEC

Note the ROW data type variable can be referenced using table and column syntax CREATE PROCEDURE example1() RETURNING INTEGER

DEFINE sql_stmt LVARCHAR(255)

DEFINE rcnt ROW(val INTEGER)

LET sql_stmt = select count() from items where manu_code = lsquoANZrsquo

EXECUTE FUNCTION EXEC(sql_stmt) INTO rcnt

RETURN rcntval

END PROCEDURE

Using EXEC_FOR_ROWS

CREATE PROCEDURE example2() RETURNING INTEGER CHAR(1)

DEFINE rs_rowdata ROW(customer_num INTEGER call_code CHAR(1))

DEFINE sql_stmt LVARCHAR(255)

LET sql_stmt = select customer_num call_code from cust_calls where

customer_num = 106

FOREACH

EXECUTE FUNCTION EXEC_FOR_ROWS(sql_stmt) INTO rs_rowdata

RETURN rs_rowdatacustomer_num rs_rowdatacall_code WITH RESUME

END FOREACH

END PROCEDURE

Using EXEC_FOR_MSET

Note the DEFINE statement for the variable rs_data Collection data types used in a SPL routine cannot be defined using the LIKE attribute in the DEFINE statement CREATE PROCEDURE example3() RETURNING INTEGER VARCHAR(8)

DEFINE v_customer_num LIKE accountscustomer_num

DEFINE v_account_cd LIKE accountsaccount_cd

DEFINE rs_data MULTISET(ROW(

r_customer_num INTEGER

r_account_cd VARCHAR(8)) NOT NULL)

DEFINE sql_stmt LVARCHAR

LET sql_stmt = select customer_num order_num from orders where

company_id = 51155

EXECUTE FUNCTION EXEC_FOR_MSET(sql_stmt) INTO rs_data

FOREACH

SELECT r_customer_num r_account_cd INTO v_customer_num

v_account_cd FROM TABLE(rs_data)

RETURN v_customer_num v_account_cd WITH RESUME

END FOREACH

END PROCEDURE

IBM Software Group IBM Information Management

Version 16 88

Date arithmetic Informix has extensive capabilities for manipulating dates and times You can add or subtract DATE and DATETIME variables from each other You can add or subtract an INTERVAL to a DATE or DATETIME

UNITS Keyword

When working with INTERVAL values sometimes it is necessary to specify the precision with which you are dealing For example suppose you have the following field defined To add 10 days to the lead time you could use a SQL statement like this

SELECT lead_time + INTERVAL(10) DAY to DAY FROM orders

-or- SELECT lead_time + 10 UNITS DAY FROM orders

Using EXTEND function

The EXTEND function allows operations between data types of different precisions SELECT

EXTEND(myvar YEAR to MINUTE) ndash INTERVAL(5) MINUTE to MINUTE

FROM member

Calculate Week Of The Year

SELECT ROUND((TODAY - DATE(0101||YEAR(TODAY))) 7 + 5) FROM DUAL

Number of days difference SELECT DATE(0106||YEAR(TODAY)) - DATE(01062005) FROM DUAL

Number of weeks difference

SELECT ROUND((DATE(0106||YEAR(TODAY)) - DATE(01062005))

7 + 5) FROM DUAL

String representation of date and time

Day and date

SELECT TO_CHAR(TODAY A B d Y) FROM dual

-returns month day and 4 digit year-

Tuesday January 03 2006

Abbreviation of day of week

SELECT SUBSTR(TO_CHAR(TODAY A B d Y R)13) FROM dual

-or-

SELECT TO_CHAR(TODAY a) FROM dual

-returns MON TUE WED THU FRI SAT SUN-

Returning the number of rows affected

IBM Software Group IBM Information Management

Version 16 89

Within SPL routines you can use the DBINFO function to find out the number of rows that have been processed in SELECT INSERT UPDATE DELETE EXECUTE PROCEDURE and EXECUTE FUNCTION statements

CREATE FUNCTION del_rows(pnumb INT) RETURNING INT

DEFINE nrows INT

DELETE FROM sec_tab WHERE part_num = pnumb

LET nrows = DBINFO(sqlcasqlerrd2)

RETURN nrows

END FUNCTION

To ensure valid results use this option after SELECT and EXECUTE PROCEDURE or EXECUTE FUNCTION statements have completed executing If you use the sqlcasqlerrd2 option within cursors make sure that all rows are fetched before the cursors are closed

Using an Informix collection data type

A collection data type as a VARRAY

In the following examples the collection data types of MULTISET and SET are used in a function to hold a collection of values You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value Informix SPL allows you to declare a cursor for a collection variable using the FOREACH statement called a collection cursor

Also demonstrated is how to utilize a variable declared with the keyword COLLECTION A variable declared as type SET MULTISET or LIST is a typed collection variable It can hold a collection of its specified data type only However a COLLECTION is an un-typed (or generic) collection variable that can hold a collection of any data type

This function will build a MULTISET list of values

CREATE FUNCTION func1() RETURNING MULTISET(INTEGER NOT NULL)

DEFINE v_array_of_ints MULTISET(INTEGER NOT NULL)

INSERT INTO TABLE (v_array_of_ints) VALUES(1)

INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(5)

INSERT INTO TABLE (v_array_of_ints) VALUES(4)

RETURN v_array_of_ints

END FUNCTION

This function will receive the COLLECTION list of values from func1

CREATE FUNCTION func2() RETURNING INTEGER

--

-- DEFINE lmset MULTISET(INTEGER NOT NULL)

--

DEFINE lmset COLLECTION

DEFINE v_int INTEGER

--

-- call func1 to populate local multiset variable

--

LET lmset = func1()

--

-- tally a count the number of elements

--

FOREACH

SELECT COUNT() INTO v_int FROM TABLE(lmset)

IBM Software Group IBM Information Management

Version 16 90

RETURN v_int WITH RESUME

END FOREACH

--

-- return the values

--

FOREACH

SELECT INTO v_int FROM TABLE(lmset)

RETURN v_int WITH RESUME

END FOREACH

END FUNCTION

NOTE In the example func2 a duplicate declaration for the ldquolmsetrdquo variable as a MULTISET data type has been commented out by declaring the variable as a COLLECTION it can accept any of the 3 types (MULTISET SET and LIST)

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

4 (row count) 1 2 5 4

By using a SET data type inserts will not permit duplicates

CREATE FUNCTION func1() RETURNING SET(INTEGER NOT NULL) DEFINE v_array_of_ints SET(INTEGER NOT NULL) INSERT INTO TABLE (v_array_of_ints) VALUES(1) INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(2) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) RETURN v_array_of_ints END FUNCTION

NOTE Because func2 is expecting a un-typed COLLECTION variable func1 does not have to be dropped and recreated It can receive a value from any Collection Data Type (MULITSET SET and LIST)

The functionrsquos return values would change to (with duplicates suppressed)

EXECUTE FUNCTION func2()

(expression)

3 (row count) 1 2 5

Using a LIST data type support for assigning values based on ordinal position

IBM Software Group IBM Information Management

Version 16 91

CREATE FUNCTION func1() RETURNING LIST(INTEGER NOT NULL)

DEFINE v_array_of_ints LIST(INTEGER NOT NULL) -- -- first insert no ordinal position can be established By default the -- database server inserts LIST elements at the end of the list -- INSERT AT 5 INTO TABLE (v_array_of_ints) VALUES(5) INSERT AT 1 INTO TABLE (v_array_of_ints) VALUES(1) INSERT AT 2 INTO TABLE (v_array_of_ints) VALUES(2) -- -- Only 3 LIST elements exist position 4 has not been instantiated -- this element will insert at the end of the list -- INSERT AT 4 INTO TABLE (v_array_of_ints) VALUES(4) INSERT AT 3 INTO TABLE (v_array_of_ints) VALUES(3) RETURN v_array_of_ints END FUNCTION

NOTE The elements of a LIST have ordinal positions with a first second and third element in a LIST To support the ordinal position of a LIST the INSERT statement provides the AT clause This clause allows you to specify the position at which you want to insert a list-element value Note the behavior of the ordinal positioning above preceded by a commented explanation

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

5 (row count) 1 2 3 5 4

Using MULTISET and ROW to replace PLSQL TABLE and RECORD types

Creating variables using Informix Collection data types SET MULTISET and LIST in combination with ROW data types can be useful when migrating applications which use Oracle REF CURSORS as arguments to functions as well as Oracle collection data types TABLE and RECORD

Typical Oracle Package specification

CREATE OR REPLACE PACKAGE MyPackage

IS

TYPE recOrders IS RECORD (

order_num ordersorder_numTYPE

order_date ordersorder_dateTYPE

customer_num orderscustomer_numTYPE

po_num orderspo_numTYPE

)

TYPE tabOrders IS TABLE OF recOrders

INDEX BY BINARY_INTEGER

TYPE ref_curtype IS REF CURSOR

Both tabOrders or ref_curtype can be converted to the following Informix SPL definition

DEFINE tabOrders MULTISET(ROW(

IBM Software Group IBM Information Management

Version 16 92

order_num INTEGER

order_date DATETIME YEAR TO FRACTION(3)

customer_num INTEGER

po_num CHAR(10)) NOT NULL)

DEFINE ref_curtype MULTISET(ROW(

define columns based on query result set

) NOT NULL)

IBM Software Group IBM Information Management

Version 16 93

A P P E N D I X E Counting system objects

Using the system catalog

System catalog

Below is a list of SQL statements that will extract most if not all of the counts of system objects owned by user lsquoXXXrsquo

select count(table_name) from all_tables

where owner=rsquoxxxrsquo

select count() from dba_indexes

where owner=rsquoxxxrsquo

select count(synonym_name) from dba_synonyms

where owner=rsquoxxxrsquo

select count() from dba_views

where owner=rsquoxxxrsquo

select count() from dba_tab_columns

where length(column_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

and owner=rsquoxxxrsquo

select count distinct() from dba_tab_columns

and owner=rsquoxxxrsquo

select count() from dba_tables

where length(table_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_synonyms

where length(synonym_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_views

where length(view_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_indexes

where length(index_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and owner=rsquoxxxrsquo

IBM Software Group IBM Information Management

Version 16 94

select data_type count(data_type) from dba_tab_columns

where owner=rsquoxxxrsquo

group by data_type

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and length(data_type)gt254

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquonumberrsquo

and data_scale=0

and owner=rsquoxxxrsquo

Using SQL code

Built-in function references

The following instructions can be used to find references to built-in functions On the UNIX machine or the NT box where your code resides please create the following file as tmpfunctionlist

convert(

hextoint(

inttohex(

getdate(

datename(

datepart(

datediff(

dateadd(

months_between(

char(

char_length(

charindex(

compute(

difference(

length(

lower(

patindex(

replicate(

reverse(

right(

soundex(

space(

str(

stuff(

substring(

upper(

abs(

atn2(

log(

ceiling(

IBM Software Group IBM Information Management

Version 16 95

cot(

degrees(

floor(

radians(

rand(

sign(

to_char(

to_date(

to_number(

exception(

pi(

raise_application_error(

raiserror(

SQLCODE

rollback

savepoint

declare

decode(

nvl(

print(

rowid

waitfor

recompile

bcp

isopen(

notfound(

rowtype(

type(

Then please run the following program with the proper subdirectories

binksh

rm ndashf somehomeoutfile

cd somesourcedatabase

export sourcebase=rdquosomepathrdquo

for functor in `cat tmpfunction_list`

do

echo before find $functor

find $sourcebasedatabase -exec grep -i $functor gtgt

somehome$functoroutfile

find $sourcebaseintfc -exec grep -i $functor gtgt

somehome$functoroutfile

echo after find $functor

done

Object types and counts

This script attempts to count the objects of each type by grepping for CREATE statements containing the object type and counts procedure definitions that are inside package bodies which are not proceeded by a CREATE keyword It is not a sophisticated parser so the results may not be perfect

binbash if [ $1 = ] then

IBM Software Group IBM Information Management

Version 16 96

echo Usage objCountssh ltFilePatterngt return 1 fi declare -a objectTypes=(CLUSTER CONTEXT CONTROLFILE DATABASE DATABASE +LINK DIMENSION DIRECTORY DISKGROUP FUNCTION INDEX INDEXTYPE JAVA LIBRARY MATERIALIZED +VIEW MATERIALIZED +VIEW +LOG OPERATOR OUTLINE PACKAGE PACKAGE +BODY PFILE PROCEDURE PROFILE RESTORE +POINT ROLE ROLLBACK +SEGMENT SCHEMA SEQUENCE SPFILE SYNONYM TABLE TABLESPACE TRIGGER TYPE TYPE +BODY USER VIEW) echo for type in $objectTypes[] do if [ $type = PROCEDURE ] then echo $type object count `cat $1 | grep -icE ^ (|CREATE +|OR REPLACE +)b$typeb` else echo $type object count `cat $1 | grep -icE ^ (CREATE +|OR +REPLACE +)b$typeb` fi done

IBM Software Group IBM Information Management

Version 16 97

A P P E N D I X F Data type mapping

Oracle built-in data types (including ANSI types) can be converted to similar data types in the Informix database according to the mapping described here This table provides default mappings based on most common usage patterns in some cases another mapping may work better

In the following table n is used to indicate length p is used to indicate precision and s is used to indicate scale

Oracle data type Informixreg Server data type

BFILE LONG RAW BLOB

BLOB

BINARY_DOUBLE DOUBLE PRECISION

BINARY_FLOAT DOUBLE PRECISION

BINARY_INTEGER

PLS_INTEGER

NATURAL

NATURALN

POSITIVE

POSITIVEN

32-bit integers only used in PLSQL NATURAL and POSITIVE are unsigned integers

INTEGER

BOOLEAN (PLSQL only) BOOLEAN

CHAR(n) or CHARACTER(n) CHAR(n)

DATE DATETIME YEAR TO SECOND

DOUBLE PRECISION DOUBLE PRECISION

IBM Software Group IBM Information Management

Version 16 98

FLOAT

See note on FLOAT below

FLOAT

INTEGER INT

A 38-digit NUMBER sub-type May want to flag with a warning on possible overflow

INTEGER

INTERVAL DAY(p) TO SECOND(s)

Note Oracle fractional seconds have 9 digits

INTERVAL DAY(p) TO FRACTION(min(5 s))

INTERVAL YEAR(p) TO MONTH

INTERVAL YEAR(p) TO MONTH

LONG CLOB

CLOB

LONG VARCHAR (xxx)

Oracle recommends not using this type

LVARCHAR

NCHAR(n) NATIONAL CHAR(n) or NATIONAL CHARACTER(n)

NCHAR(n)

See National Language Types below

NCLOB CLOB

NUMBER

NUMBER(0)

NUMBER(p) NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s lt 10

NUMBER(3-2) 12300

INTEGER

IBM Software Group IBM Information Management

Version 16 99

NUMBER(p) NUMBER (p0)

Where precision (p) is greater than or equal to 10 and lt= 18

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and 10 lt= p-s lt 19

NUMBER(9-2) 12345678900

BIGINT

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is greater than or equal to s (that is s gt 0 and p gt= s)

NUMERIC (min(p32) min(s32))

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is less than s (that is s gt 0 and p lt s)

NUMBER(35) 000123

NUMERIC (min(s32)min(s32))

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s gt 18 and p-s lt= 32

NUMERIC (min(p-s32)0)

NUMBER(p s)

Where scale (s) is greater than 32 or pInformix-s is greater than 32

NUMERIC (32)

Scale cannot be greater than precision

NUMERIC(3232) would guarantee that digits to the left of the decimal would be lost Using a floating point decimal provides the simplest best way to capture as many digits in a value as possible

IBM Software Group IBM Information Management

Version 16 100

DEC

DECIMAL

NUMERIC

DEC(p)

DECIMAL(p)

NUMERIC(p)

DEC(p s)

DECIMAL(p s) NUMERIC(p s)

There is no difference within Oracle between these types and each other and these types and NUMBER The Oracle system catalogs contain the NUMBER type id for all declarations of these types and the integer types as well Declarations of these types can be mapped using the same rules as those for NUMBER

NVARCHAR2(n) NCHAR VARYING(n) NATIONAL CHAR VARYING(n) NATIONAL CHARACTER VARYING(n)

LVARCHAR(min(n 32767))

RAW(n) BLOB

REAL DOUBLE PRECISION

Record ROWTYPE

Using a CREATE ROWTYPE statement

ROWID INTEGER

SMALLINT SMALLINT

TIMESTAMP(p)

If p is not specified precision defaults to 6

DATETIME YEAR TO FRACTION(min(5 p))

UROWID(n) INTEGER

IBM Software Group IBM Information Management

Version 16 101

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is less than or equal to 255 (that is n lt= 255)

VARCHAR(n)

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is greater than 255 (that is n gt 255)

LVARCHAR(n)

XMLType CLOB

Notes on specific types are below

DOUBLE

The range of values for the DOUBLE PRECISION data type is the same as the range of the C double data type on your computer

VARCHAR

While Oracle VARCHAR data types have a limit of 4000 bytes an Informix Server VARCHAR data types has a limit of 255 bytes An Informix Server LVARCHAR has a limit of 32739 Bytes

NUMBER

Oracle abstracts its numeric types from the hardware and operating system through the use of its NUMBER type Most numeric types like INTEGER are actually NUMBERs internally When porting to a database server like Informix which retains more of a relationship between the operating system types and the database types it is essentially a one-to-many mapping and heuristics have to be used to determine the best-fit target type No single set of type mapping rules will fit all use scenarios The converter has default rules which fit the more common user patterns When considering a number represented as mantissa and exponent

mantissa x 10exponent

precision is the number of digits in the mantissa and scale is the negative exponent how many places to the right of the decimal point the least significant digit is located Oracle NUMBERs have a maximum precision of 38 and the maximum precision available in Informix native types is 32 The first step in a type mapping is to truncate the target type precision to min(precision 32) The scale of a type can be considered its anchor point with respect to the decimal point The most

IBM Software Group IBM Information Management

Version 16 102

significant digit of a numeric type is located precision digits to the left of the decimal point and precision-scale digits to the right of the decimal point The start and end locations of the digits are used to determine the closest fitting Informix type The order of preference is INTEGER BIGINT NUMERIC(p s) and lastly NUMERIC(p) NUMERIC(p) in a non-ANSI mode database is a decimal type with a floating point type In an ANSI mode database the scale is implicitly 0 All Oracle integer declaration types such as INT INTEGER SMALLINT become NUMBER(38) type in the Oracle metadata In Oracle when precision is given but scale is not scale becomes 0 implicitly which makes the type in the set of integral types One exception to the general mapping rules is the NUMBER type specified without precision or scale Strictly speaking this has a floating point scale with 38 digits of precision but most commonly it is used where an integer is more appropriate Even if the user does specify INTEGER in a type definition when it comes out of the Oracle catalogs the type is NUMBER This is one case in particular where one type mapping will not fit well with all usage scenarios

National language types

Oracle Nchar types are allocated by number of characters where Informix is allocated by the number of bytes For Oracle the storage size of the characters varies with the encoding used and is always subject to the standard 32767 limit on maximum bytes but during declarations n always means the number of characters Oracle PLSQL supports explicit and implicit data type conversions These explicit and implicit data types are converted to syntax by using Informix Dynamic Servers explicit and implicit data type conversion mechanism

ROWID

Oracle databases support a pseudo-column named ROWID such that every row in every table is assigned an auto-generated ID Oracle also allows you to define a column of type ROWID which can be used as a foreign key to a ROWID pseudo-column Oracle ROWID columns contain data that if converted to a string are 18 characters long for example lsquoAAAQ+jAAEAAAAAeAANrsquo It is probably not advisable to migrate this data to an Informix database and instead use the Informix type which is an integer If there is a dependency on the values themselves and therefore need migrate the data then an integer type would not hold the values

TYPE

In PLSQL you can refer to the type of an existing variable field or column by using the TYPE attribute The converter replaces this reference directly by the type it refers to

ROWTYPE

In PLSQL you can refer to the record type that represents a row of a table a cursor or a cursor variable PLSQL scripts containing the ROWTYPE attribute are handled in the same way as a record type that has been previously declared

FLOAT

Oracle FLOAT type is a floating point number capable of storing up to 38 decimal digits or 126 binary digits It has a floating point scale that can exist outside the boundaries of what an Informix DECIMAL can represent A C language double or Informix float type is capable of only 16 digits so there is the chance that some data will be lost Using an Informix FLOAT type makes it so that less significant digits are lost in preference to more significant digits

IBM Software Group IBM Information Management

Version 16 103

References to subtypes declared in packages and PLSQL blocks are converted to the Informix Server equivalent base types Variables of type RECORD are not translated by the DDL Converter at the time of this writing They will be handled by the stored procedure converter

XMLType

Informix does not have a built-in type for representing XML The nearest approximation is to store it in a CLOB Another character type like LVARCHAR can be used if it can be determined that the actual data will fit in it

Page 8: Oracle to IBM Informix Server Porting Guide

IBM Software Group IBM Information Management

Version 16 8

C H A P T E R 1 Introduction

This document is a technical document describing the differences between Oracle and Informixreg Dynamic Server (IDS) functionality and syntax This porting guide details differences between Oraclersquos 10g release 1 (101) and 10g release 2 (102) and Informix Dynamic Server (version 1110) In addition it can be a useful reference for all migrations between the two database servers regardless of version In addition to DDL DML and overall SQL syntax this document explores the differences between Oracle and Informix with regards to object technology through the use of large objects user defined types and user defined routines It also looks at the differences between Oraclersquos table partitioning and Informixrsquos table fragmentation Part of the explanation is a discussion on what needs to be changed to make an application running on an Oracle database run on an Informix database If there is more than one way to port some piece of functionality alternatives and recommendations are also discussed This document is intended to be a living document Missing items better ways of implementing Oracle functionality in Informix other than what is documented here examples to better illustrate a point and other suggestions should be sent to Chris Golledge (golledgeusibmcom) so they may be included with future revisions

Purpose This document should be used as a guide to assist in porting applications that run on an Oracle database server to run on an Informix database server Regardless of whether a porting effort will be completely manual or if tools will be utilized this document can provide value Obviously if the port is performed manually this guide will provide the most value If the port will utilize tools then analysis can be performed using this guide to determine how much of the application the tools will convert and how much must be converted manually In any case this guide is intended to be used to both visualize the scope of a porting effort and to aid in the porting effort by addressing the technical issues This document will be refined based on usersrsquo experiences to identify as many of the porting issues as possible at the beginning of a project

Product overview IBM Informix Server provides high performance and scalability with legendary reliability and nearly hands-free administration of databases of all size IDS is industry proven on UNIX Linux or Windows platforms with online transaction processing (OLTP) systems data marts data warehouses and e-business applications The IDS 11 release features significant additions over prior versions It supports the services-oriented architecture (SOA) model for application integration and offers many new features for data replication continuous availability and ldquohands freerdquo database administration

Organization This document is broken into sections to logically discuss the different database concepts Some of the sections may contain the same sub-sections for example stored procedures and triggers

IBM Software Group IBM Information Management

Version 16 9

are discussed in the DDL and DML sections This allows separate discussions on the issues facing the same item in each area For example the issues surrounding creating a stored procedure are discussed in the DDL section and the issues surrounding the stored procedure language are discussed in the DML section Among the other references the ldquoPlanning Guiderdquo appendix contains a quick reference of most of the differences between Oracle and Informix along with the degree of difficulty to port each difference This reference is intended for use in the planning process to illustrate the scope and the effort required to perform the porting project Some of the stored procedure logic used to convert Oracle functions is included in the appendix rdquoSample coderdquo

Conventions The conventions used in this document include

Courier Text Distinguishes a logic example

from regular text

Example Illustrates a point In most cases an Oracle example will be followed by an Informix example

Italicized Text Signifies a substitution in other words substitutes for the italicized word the actual object the word is describing for example table_name column_name and so on

UPPER CASE TEXT Signifies database vendor reserved words or statements such as INTEGER CREATE TABLE and so on

Bold example text highlights the item that is being explained

IBM Software Group IBM Information Management

Version 16 10

IBM Software Group IBM Information Management

Version 16 11

C H A P T E R 2 Defining the Problem Space

It is important to define the set of objects to be migrated and it is better if effort is put into this prior to beginning the actual migration This is true if you are the responsible for both the database in general and its migration from one supporting DBMS to another but it is particularly true that there be a clear agreement on the scope of what is to be migrated if the migration is to be performed by a party other than the one with long term responsibility for the database Defining the scope will involve extracting a representation of the objects to be migrated out of the Oracle system catalogs and representing them in some format that can be manipulated into constructs that can be used in Informix

Extracting the objects to be migrated It is possible to represent the objects in more than one language Using the SQL language is the most common method and it will be the only one discussed at length in this document (in its current revision) However it is also possible to express database objects in XML SQL has the advantage that the standard common grammars are widely understood in the context of defining tables indexes etc XML would have an advantage of not requiring parsing that is sensitive to the minor differences in ways of expressing essentially the same object

Working With Oracle Dump Files

There exist 3rd

-party tools for reading system catalogs but it is doubtful that any can read the Oracle catalogs more reliably than Oraclersquos own tools There are two incompatible export and import tool sets used by Oracle The older tools are imp and exp and the newer ones are impdp and expdp where dp stands for Data Pump Oracle has encouraged the use of the newer tools instead of the older ones since the newer ones were introduced at version 10 Nonetheless there are many Oracle users still using imp and exp In the discussions below only the metadata will be extracted into a dump file That is because any data in the dump file will be in a proprietary format and very likely some of the data will have to go through a type conversion process before being loaded into an Informix system Oracle exported data generally cannot be used to load a database in Informix Export and Import

If someone has given you a dump file created with the older export tool there exist tools such as The DDL Wizard by Net 2000 Limited which can be used to extract viable DDL The contents of the dump file contain the SQL for re-creating the database but they are not in a readily usable format The older export and import tools are also more sensitive to the layout of the tablespaces than impdb The ability to extract DDL from the dump file in a usable form segmented by whatever grouping you choose is limited compared to what can be achieved through the Data Pump versions

IBM Software Group IBM Information Management

Version 16 12

It may be tempting to feed the dump file into the IBM Migration Toolkit (MTK) or other tool that works on SQL flat files This will not work MTK works on flat text SQL files and the dump file is binary If you open it up you can see what may be a large number of SQL statements but there are also binary codes within the same file That binary data will prevent MTK from being able to process it Getting SQL statements

If you want to get the SQL statements out of the dump file as they would be executed on the server there is an option available from the import tool itself show=y

imp myIDmyPWD as sysdba file=myFiledmp

full=yes show=y gt dmp_showtxt

This will produce a file which contains the statements but they are wrapped in quotes The contents will look something like

ALTER SESSION SET CURRENT_SCHEMA= SYSTEM CREATE UNDO TABLESPACE TBSPC1 BLOCKSIZE 8192 DATAFILE DORACLEORADA TASCHEMA1CHUNKDBF SIZE 387973120 AUTOEXTEND ON NEXT 5242880 MAXS IZE 32767M EXTENT MANAGEMENT LOCAL

which makes them strings instead of SQL statements Fixing this is a two-step process

-- removes quotes from the start of lines

sed s^ g dmp_showtxt gt step1txt

-- removes quotes from the end of lines

sed s$g step1txt gt dmp_step2sql

The statements are still not correctly formatted because they have been truncated to a fixed length and line-endings inserted However at this point it is possible to get a count of how many of each object type there is using the script in the appendix ldquoGetting an initial count of database objectsrdquo

Data Pump Export and Import

These newer tools provide better performance and more capabilities than their predecessors Please refer to documentation on Oracle for a complete description searches for ldquoData Pump Importrdquo and ldquoData Pump Exportrdquo should return relevant results quickly Below is enough information to get started on defining and extracting the objects to be migrated Metadata can be filtered through the use of the export mode clause and INCLUDE and EXCLUDE parameters However any dependent object of an included or excluded object is likewise included or excluded For example if you include an index then the table associated with the index will also be included and if you exclude a table then any associated indexes will also be excluded The SQL that will generate all the objects in the dump file can be created by the impdp command with the SQLFILE parameter If the output file is very large you might want to break it into smaller pieces There are a couple of ways to do this and the one that is best for you somewhat depends

IBM Software Group IBM Information Management

Version 16 13

on how you intend to proceed with the conversion Data definition language (DDL) SQL for all the objects can be put into one file or the INCLUDE or EXCLUDE parameters can be added to direct Data Pump to filter on the types of objects If you put all the objects into one file then you can break that into smaller files by object type fairly easily because the objects are sorted by type in the SQL file So it is just a matter of cutting the file into smaller pieces This method may be preferred because it allows for you to do things like create all tables load the data and then create the indexes and triggers If the data set is large creating the indexes after loading the data can yield substantial performance improvements However this is less useful if you want to convert sets of objects according to dependencies in which case the filtering option is likely to be more useful Just to illustrate a difference between these two methods in one customer case the metadata dump file was about 18MB and putting all objects in one SQL file resulted in a file that was about 15MB The table definitions occupied a little under 300KB of the 15MB The output file generated by filtering on objects of type TABLE was just over 1MB The addition content was mostly GRANT INDEX and TRIGGER creation statements There were no differences in the CREATE TABLE statements themselves Examples

Prerequisite The Data Pump tools require the use of an Oracle DIRECTORY object This is basically a mapping between a name that exists within the DBMS and a system path It can be a tripping point but it provides an abstraction layer that for instance allows the same commands to work across systems with different disk layouts or different operating systems Creating a DIRECTORY on a Windows system from SQLPlus

SQLgtconnect as sysdba

SQLgtCREATE OR REPLACE DIRECTORY dumpDir AS ctemp

Note Make sure this directory is not read-only There also could be problems if the directory is a network drive on Windows these can be related to there being different users between the Oracle executable and the current user and those users having different permissions on the network drive

SQLgtGRANT read write ON DIRECTORY dumpDir TO userID

Creating a dump file of the entire database

expdp userNameuserPwd as sysdba FULL=Y dumpfile=DB_fulldmp

LOGFILE=LG_expdplog CONTENT=METADATA_ONLY DIRECTORY=dumpDir

Creating a dump file of just one schema

expdp userNameuserPwd as sysdba SCHEMAS=hr DIRECTORY=dumpDir

DUMPFILE=hr dmp LOGFILE=hr log CONTENT=METADATA_ONLY

Creating a dump of just the tables and their dependents

expdp userNameuserPwd as sysdba SCHEMAS=hr INCLUDE=TABLE

DIRECTORY=dumpDir DUMPFILE=hrdmp LOGFILE=hrlog

CONTENT=METADATA_ONLY

Creating a dump of just one table

expdp userNameuserPwd as sysdba SCHEMAS=hr

INCLUDE=TABLELIKE COUNTRIES DIRECTORY=dumpDir

DUMPFILE=hrdmp LOGFILE=hrlog CONTENT=METADATA_ONLY

IBM Software Group IBM Information Management

Version 16 14

Creatinge an SQL file from a dump file

impdp userNameuserPwd as sysdba DIRECTORY=dumpDir

DUMPFILE=hrdmp SQLFILE=dumpDirhrsql

The INCLUDE and EXCLUDE options are also valid when used with impdb so it may be easier to get a complete dump of everything to be migrated then use these options to create subsets of objects it smaller SQL files than it would be to create separate dump files It is easier to divide objects than to merge them together if they are not divided initially as wanted There is a caveat when using this impdp to generate an SQL file the object names will all be delimited identifiers Example

CREATE TABLE HRCOUNTRIES Because of differences between how Informix handles these and how Oracle handles these case-sensitivity issues could occur See the chapter on ldquoDelimited Identifiersrdquo and in particular the description of default shift problems If it can be determined that there are no name collisions if regular identifiers are used removing the quotation marks as part of the conversion might avoid many problems In other words if there are no objects whose names only differ in case like foo and FOO then changing every occurrence of ldquoFOOrdquo to FOO in the DDL could eliminate case-sensitivity issues in the application DML It depends on if the application code uses the delimited form of the name predominantly or not

IBM Software Group IBM Information Management

Version 16 15

C H A P T E R 3 Data Definition Language

Identifiers An identifier specifies the simple name of a database object such as a table name column name index name view name stored procedure name and so on The maximum length of an Oracle identifier is 30 characters and can contain letters numbers ldquo_rdquo ldquo$rdquo and ldquordquo although Oracle highly recommends that ldquo$rdquo and ldquordquo should not be used In contrast Informix identifiers have a maximum length of 128 characters and may contain letters numbers ldquo_rdquo and ldquo$rdquo (as long as ldquo$rdquo is not the first character) See the Delimited Identifiers section below for information This means that all Oracle identifiers containing a ldquordquo anywhere in the identifier or a ldquo$rdquo as the first character must be replaced or modified to remove those characters from the identifier

Delimited identifiers

Delimited identifiers are also known as quoted identifiers and sometimes as escaped identifiers They have been part of the SQL standard since SQL92 but existed in various database management systems (DBMS) prior to that time In a nutshell they are a way to preserve case sensitivity in object names as well as to allow objects to have names outside of the conventions of SQL regular identifiers Prior to the behavior of identifiers in general being standardized different DBMS vendors implemented different means of achieving case-insensitivity for object names some converted all regular identifiers to uppercase and some converted regular identifiers to lowercase By SQL99 the concept of case normal form was standardized to mean simply stated that if there exists an uppercase equivalent of any character in a name then the uppercase version is stored in the system catalogs and used for comparison purposes See the SQL99 standard chapter 5 section 2 and in particular items 21 and 22 for a formal description of case normal form and how it applies to identifier comparisons Delimited identifiers can be used to specify names for database objects that are otherwise identical to SQL reserved keywords such as TABLE WHERE DECLARE and so on The only database object for which delimited identifiers cannot be used is a database name Database administrators and application programmers do not always communicate to each other with 100 efficiency and there is no guarantee that within either of these pools every member codes by the standard practice of the other members After describing how delimited identifiers work in Informix there will be a description of how any inconsistency of usage and the differences between Oracle and Informix can introduce some migration hurdles DELIMIDENT Environment Variable

To use delimited identifiers with Informix you must set the DELIMIDENT environment variable While DELIMIDENT is set strings enclosed in quotation marks ( ldquo ) are treated as identifiers of database objects and strings enclosed in apostrophes ( rsquo ) are treated as literal strings If the

IBM Software Group IBM Information Management

Version 16 16

DELIMIDENT environment variable is not set strings enclosed in quotation marks are also treated as literal strings When you set the DELIMIDENT environment variable you cannot use quotation marks ( rdquo ) to delimit literal strings If DELIMIDENT is set the database server interprets all strings enclosed in quotation marks as SQL identifiers not string literals Commonly within Informix systems DELIMIDENT is set or not on the client side according to the design of the application However if you are converting a database and all applications accessing it from a system where every occurrence of quotation marks (ldquoobjectNamerdquo) indicates an identifier and not a string literal you may want to consider setting it in the server environment in order to avoid any inconsistency between clients where it is set and where it might not be Using Quotes in Strings The apostrophe ( rsquo ) has no special significance in string literals delimited by quotation marks Conversely double quote ( Prime ) has no special significance in strings delimited by apostrophes For example these strings are valid Nancyrsquos puppy jumped the fence

rsquoBilly told his kitten No rsquo A string delimited by quotation marks can include a double quote character by preceding it with another double quote as the following string shows Enter y to

select this row When the DELIMIDENT environment variable is set quotation marks can only delimit identifiers not strings Use of Uppercase Characters You can specify the name of a database object with uppercase characters but the Informix server shifts these to lowercase characters unless the DELIMIDENT environment variable is set and the name of the database object is enclosed in quotation marks In this case the database server treats the name of the database object as a delimited identifier and preserves the uppercase characters in the name Delimited Identifiers By default the character set of a valid SQL identifier is restricted to letters digits underscore and dollar-sign symbols If you set the DELIMIDENT environment variable however SQL identifiers can also include additional characters from the codeset implied by the setting of the DB_LOCALE environment variable See the Identifier section of the Informix Guide to SQL Syntax for more information Storage Object Names In Informix delimited identifiers can be used to specify non-alphanumeric characters in the names of database objects However delimited identifiers can not be used to specify non-alpha characters in the names of storage objects such as dbspaces and blobspaces To use delimited identifiers DELIMIDENT must be set both at compile and run times For example to set DELIMIDENT environment variable with sh or ksh issue the following at the command line prompt

export DELIMIDENT=

Note You do not need to assign a value to the environment variable and counter-intuitively setting DELIMIDENT=n has the same effect as DELIMIDENT=y Also in a Windows environment

set DELIMIDENT=

effectively undefines the variable Default shift problems

Any direct access of system catalog information involving names will cause problems when migrating from a system like Oracle where system catalog names are stored in uppercase to a system like Informix where the catalog names are stored in lowercase For example

CREATE TABLE foo (c1 int)

IBM Software Group IBM Information Management

Version 16 17

Within Oracle the following will return information about the table

select from sysall_objects where object_name = FOO

and the following will not

select from sysall_objects where object_name = foo

Conversely in Informix

select from systables where tabname = foo

will be successful and the same with FOO will not be A similar if not more common problem can occur when the table has been created without the name being delimited but is sometimes delimited when accessed by the application Per the standard foo == FOO == ldquoFOOrdquo but in Informix foo == FOO == ldquofoordquo In Oracle the following SELECT statement will be successful

SELECT FROM ldquoFOOrdquo

but within Informix this will result in an error ldquo206 The specified table (FOO) is not in the databaserdquo Likewise if the name is delimited in its definition such as

CREATE TABLE SCHEMA1TABLE1

this creates a table that can be referenced in Oracle without the name being delimited The statements

SELECT FROM schema1table1

and SELECT FROM SCHEMA1TABLE1

will be successful in the Oracle system but will fail in the Informix one In theory whether on object name is delimited or not should be the same in the database and at every occurrence within the application but this is not always the case It may be beneficial to examine whether delimited identifiers or regular identifiers are most commonly used in application code and use whichever is most common as a naming convention when translating the DDL

Explicit versus implicit schemaowner names

Another complication to keep in mind is that when the log mode is ANSI implicit and explicit owner names are treated differently between the Oracle and Informix servers In Oracle there is no difference in the case handling of an implicit owner name and an explicit one For example if connected to Oracle as scott the following CREATE TABLE statements

create table foo1(c1 int) create table scottfoo2(c1 int) create table SCOTTfoo3(c1 int)

all result in tables owned by SCOTT The following select statements in various forms that may be in application code will all run without error

select from foo1 select from scottfoo1

IBM Software Group IBM Information Management

Version 16 18

select from SCOTTfoo1 select from foo2 select from scottfoo2 select from SCOTTfoo2 select from foo3 select from scottfoo3 select from SCOTTfoo3

These statements will also run without error within a non-ANSI mode Informix database but not all of them will run successfully within an ANSI mode database This is because Informix does not uniformly fold the case of owner names and handles implicit names differently from explicit names so there will always be some combination of DDL and DML usage patterns that work within an Oracle system that do not work in an Informix one You can set ANSIOWNER before starting your Informix server but that will merely change which combinations do not work You may want to examine usage patterns within the applications and choose a naming convention when translating the DDL that matches the most common naming convention used in the applications Note This behavior of Informix forces a tradeoff between using an ANSI mode database which most closely matches the transaction behavior of Oracle and a non-ANSI mode database which has the least mismatch in identifier case sensitivity

Reserved words or keywords

Oracle and Informix both allow identifiers to be reserved words as long as they are delimited However Oracle and Informix reserved words differ In addition both systems have keywords like FROM that are not always reserved in the sense that using them as an identifier will always generate a syntax error There should be few problems with reserved words or keywords if identifiers that are delimited in the original database remain delimited in the destination database The appendix Keywords of SQL for IBM Informix in the Guide to SQL Syntax contains more information about Informix keywords Also one word non-delimited identifiers should be verified against the Informix reserved words list to ensure that they do not need to be delimited or renamed Although almost any word can be used as an identifier in Informix syntactic ambiguities can result from using reserved words as identifiers in SQL statements Delimited identifiers provide a way to use a reserved word as an identifier without causing syntactic ambiguities However doing this changes a case-insensitive name into a case-sensitive one and that means that every reference to the object has to be checked for issues related to case-sensitivity Essentially this is not much less work than changing the name of the object because in essence it is changing the name of the object Examples

The following example shows how to create an Informix table with a case sensitive table name

CREATE TABLE My_Customers (hellip)

The following example shows how to create a table whose name includes a space character If the table name were not in quotation marks () a space character or any other non-alpha character except an underscore ( _ ) or dollar sign ($) (see special conditions above) could be used in the name

CREATE TABLE My Customers (hellip)

IBM Software Group IBM Information Management

Version 16 19

The following example shows how to create a table that uses a keyword as the table name

CREATE TABLE TABLE (hellip)

To include a double-quote () within a delimited identifier the double-quote () must be preceded with another double-quote () as shown in the following example

CREATE TABLE MyGoodData (hellip)

Summary

The main points to keep in mind when deciding about any questions on how identifiers should be translated are

Oracle always has delimited identifiers enabled and Informix does not

Oracle folds regular identifiers to uppercase and Informix folds to lowercase

Informix has behavioral differences between an ANSI mode database and a non-ANSI mode one

It is beneficial to consider the most common usage patterns within the existing application code prior to deciding default identifier translation patterns

Databases

Databases database names and instances

Oracle and Informix implement databases and instances differently Oracle considers a database to be a set of data files control file(s) and log files while an instance is a set of background processes and memory structures accessing database data Oracle instances are also known as servers Each Oracle instance or server runs against one database but through the use of Oracle Parallel Server a database may have multiple instances accessing it An Oracle database is named at initialization and the name has a limit of 8 ASCII characters Informix databases are defined as ldquoa collection of information contained in tables that are useful to a particular organization or used for a specific purposerdquo Informix database names may be up to 128 characters in length An Informix instance is a set of processes memory and disk allocations that manage data and will contain at least two and in most cases many databases Informix instances are also referred to as servers Informix databases may share disk allocations (dbspaces) with other databases within an Informix instance Oracle databases cannot share disk allocations (tablespaces) Informix databases should be created in a dbspace other than the root dbspace The root dbspace holds data for the system configuration information for the engine and so on If user-defined objects are created in this dbspace then the dbspace may become unmanageably large and during backup the system information may also get backed up unnecessarily The CREATE DATABASE statements of Informix and Oracle have differences which may require modification to routines responsible for database creation Informix will accept the same minimal syntax required by Oracle (eg CREATE DATABASE myDB) however issuing the command will implicitly accept the creation of a database without transaction logging enabled and establish the default location for all database objects as the instancersquos default storage location The instancersquos default storage location or ldquorootrdquo dbspace should not contain user-defined objects The root dbspace holds data for the system and some configuration information for the engine If user-

IBM Software Group IBM Information Management

Version 16 20

defined objects are created in this dbspace it may become unmanageable and result in the system contending with user objects for the available space

ANSI vs non-ANSI

Informix supports both ANSI and non-ANSI databases Informix non-ANSI databases are most common but there are some advantages of ANSI databases when porting from Oracle

Oraclersquos transaction behavior is more or less like that of an ANSI database Applications ported on Oracle are always in a transaction In Oracle and ANSI databases transactions begin implicitly with the first of a series of SQL statements and will end immediately after a commit or rollback statement Therefore unlike a non-ANSI database a COMMIT WORK statement does not need to be preceded with a BEGIN WORK statement

In ANSI databases database object references must be prefixed by the ownerrsquos name unless the owner is the one referencing the object If Oracle applications reference database objects with a both parts of the object name prefixing the object name with schema using an ANSI database may ease modifications necessary when porting to Informix

The ldquolsquogrant to PUBLICrdquorsquo concept provide by Informix database security does not apply to ANSI databases Every database object is private and privileges must be explicitly granted to each user

If an Informix ESQLC or 4GL application was developed to run on a non-ANSI Informix database (including BEGIN WORK statements) the application could run on an ANSI Informix database in one of two ways

By placing the BEGIN WORK statement in a pre-processor directive such as IFDEF object_name and omitting the proper preprocessor compile options such as -D object_name

By compiling the application normally and ignoring the resulting warning messages

Additionally the LOG MODE ANSI clause must be added to the CREATE DATABASE statements ANSI mode databases cannot have buffered logging Applications written to use an open API like ODBC or JDBC are compiled without awareness of the database and these APIs are written with the intent to abstract specific database behavior For instance in one of these the application developer would call a function to begin or end a transaction rather than execute a BEGIN and COMMIT or ROLLBACK The API would execute these statements internally or not as necessary for the database connection See the Transaction Processing section in Application Architecture for more information on how an application running on a non-ANSI Informix database can simulate Oracle transaction behavior

Tablespaces and dbspaces Oracle tablespace names need to be replaced with Informix dbspace names Unlike the Oracle tablespace the Informix dbspace cannot be created using DDL (SQL) scripts It must be created using the Informix onspaces utility before any DDL (SQL) scripts are executed Therefore Oraclersquos CREATE TABLESPACE statements should be removed from the DDL (SQL) scripts The user interface for accomplishing these tasks is onmonitor The command line utility is onspaces Therefore the onspaces commands can be placed in shell or batch scripts After successfully executing the onspaces commands the DDL (SQL) scripts may be called through the same shell or batch scripts For example

IBM Software Group IBM Information Management

Version 16 21

onspaces hellip onspaces hellip hellip dbaccess database_name DDL_script_file_name dbaccess database_name DDL_script_file_name hellip

Tables

Attributes and general syntax

When creating tables the Oracle CREATE TABLE statement must be converted to Informix taking advantage of the Informix options IN EXTENT NEXT and LOCK MODE

IN specifies the dbspace in which the table will reside

EXTENT specifies the amount of space that will initially be allocated to the table (16K default on most platforms)

NEXT specifies the amount of space that will be allocated when additional space is needed (16K default on most platforms

Lock mode

LOCK MODE specifies whether to use row or page locks for the table In Oracle the default is row level locking in Informix the default setting is page level locking However it can be changed by using one of the following methods (resolved in the following order of precedence)

1 LOCK MODE specified using an attribute of the CREATE TABLE or ALTER TABLE command syntax

2 IFX_DEF_TABLE_LOCKMODE environment variable setting 3 DEF_TABLE_LOCKMODE parameter setting in the ONCONFIG file

NOTE If the DEF_TABLE_LOCKMODE parameter cannot be found in the ONCONFIG file it can be added to make the specification for every database within the instance The Informix instance must be restarted for this parameter to take effect The new ldquodefaultrdquo LOCK MODE will apply to all tables created after the parameter has been changed To change the LOCK MODE of existing objects use the ALTER TABLE statement

Storage

The Oracle STORAGE INITIAL and STORAGE NEXT clauses must be changed to the Informix EXTENT SIZE and NEXT SIZE clauses respectively In Oracle the STORAGE clause options MINEXTENTS MAXEXTENTS and PCTINCREASE should be removed For example Oracle

CREATE TABLE dept(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13)

)

STORAGE (INITIAL 100K NEXT 50K MINEXTENTS 1 MAXEXTENTS 50

PCTINCREASE 5)

Informix CREATE TABLE dept (

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

IBM Software Group IBM Information Management

Version 16 22

EXTENT SIZE 200 NEXT SIZE 50

When an Oracle CREATE TABLE statement does not include a STORAGE clause the table will be created using the tablespace STORAGE clause by default If an Oracle tablespace is created specifying a STORAGE INITIAL of 100KB and a STORAGE NEXT of 50KB then all tables created within that tablespace will have a default value of STORAGE INITIAL 100KB and STORAGE NEXT 50KB Oracle tables cannot be created with smaller STORAGE clause values than the tablespace default they are created in Informix dbspaces do not have storage clauses attached to them As stated earlier the default Informix EXTENT and NEXT sizes are 16KB on most platforms The minimum EXTENT and NEXT sizes are 4 times the page size

Constraints

The Oracle constraint syntax must be changed to the Informix syntax for primary keys foreign keys unique and so on For example

Oracle CONSTRAINT PK_NUMBER PRIMARY KEY(CUST_NUM)

CONSTRAINT CK_EMP_CODE CHECK (EMP_CODE gt 100)

Informix PRIMARY KEY(CUST_NUM) CONSTRAINT PK_NUMBER

CHECK (EMP_CODE gt 100) CONSTRAINT CK_EMP_CODE

An Oracle check constraint statement may contain functions that are not available in Informix In this circumstance it may be necessary to code the combination of a trigger and a stored procedure to emulate the same functionality A trigger based on an insert or update event can execute a stored procedure which tests the constraint condition and if necessary raise an exception to reject the row data which violates the constraint The Oracle PARALLEL clause which specifies parallel execution of an operation must be removed from any SQL statements (such as CREATE TABLE and ALTER TABLE) In Informix there are ways to accomplish this parallel execution depending on the context in which these SQL statements are called (shell script file batch file and so on)

ALTER TABLE

Informix offers a rich set of ALTER TABLE features adding and dropping columns (rename by using the RENAME statement) changing column data types altering the next size and changing the lock mode Informix will choose one of three algorithms when executing an ALTER TABLE statement depending upon the operation to be performed For certain conditions the database server uses either a ldquoslowrdquo ldquoin-place or ldquofastrdquo alter algorithm to modify the table Informix provides ldquoin-placerdquo alter table support for adding or dropping a column anywhere in the table changing the column length and changing the column data type without an exclusive lock on the table An ldquoin-placerdquo alter will modify the tablersquos definition without changing the existing rows or unloading and reloading the data After the ALTER TABLE operation the database server inserts rows using the latest definition Informix will not change the row structure until a data row is touched by a user operation Once a query accesses a row that is not yet converted there can be a slight degradation in the performance because the database server reformats each row in memory before it is returned Informix uses the ldquoslowrdquo alter algorithm when the ALTER TABLE statement makes column changes that it cannot perform in place This type of alter would be

Adding or drop a column created with the ROWIDS keyword

Dropping a column of the TEXT or BYTE data type

IBM Software Group IBM Information Management

Version 16 23

Converting an INT or a SMALLINT column to SERIAL or SERIAL8

Modifying the data type of a column so that some possible values of the old data type cannot be converted to the new data type

For example if you modify a column of data type INTEGER to CHAR(n) the database server uses the slow ALTER algorithm if the value of n is less than 11 An INTEGER requires 10 characters plus one for the minus sign for the lowest possible negative values

Modifying the data type of a fragmentation column in a way that value conversion might cause rows to move to another fragment

Adding dropping or modifying any column when the table contains user-defined data types or smart large objects

When the database server uses the slow alter algorithm to process an ALTER TABLE statement the table can be unavailable to other users for a long period of time because the database server will lock the table exclusively for the duration of the operation make a copy of the table to convert the table to the new definition and convert the data rows This type of ALTER TABLE processing can encounter the scenario of a statement being a long transaction and abort it if the Long Transaction High Water Mark (LTXHWM) threshold is exceeded Informix will use the ldquofastrdquo alter algorithm when the ALTER TABLE statement changes attributes of the table but does not affect the data The database server uses the fast alter algorithm when you use the ALTER TABLE statement to make the following changes

bull Change the next-extent size

bull Add or drop a constraint

bull Change the lock mode of the table

bull Change the unique index attribute without modifying the column type

With the ldquofastrdquo alter algorithm the database server holds a lock on the table for a very brief period In some cases the database server will lock the system catalog tables but only long enough to change the attribute In either case the table is unavailable for queries for only a short time

Data Partitioning

Informix Table Fragmentation is the counterpart to Oraclersquos Table Partitioning and allows the user to control where data is physically placed at the table level Table Fragmentation or Data Partitioning is typically done to large tables but Informix and Oracle implement fragmentation and partitioning for different reasons and with different results Informix recommends using table fragmentation to improve single-user response time concurrency data availability backup restore characteristics and data-load performance While Oracle does state that table partitioning may improve the performance of queries and that the Oracle optimizer takes partitioning into account the primary goal of partitioning in Oracle is improving database maintenance Partitioning strategies in Oracle include range partitioning as well as hash and composite partitioning Composite partitioning combines range and hash partitions through the use of sub-partitions Tables incorporating Oracle LOBrsquos (large objects) cannot be partitioned Informix fragmentation strategies include expression-based and round robin Basic expression-based fragmentation can replace Oracle range partitioning Unlike Oracle LOBs Informixrsquos Smart Large Objects can be fragmented Examples of creating tables with Oracle range partitioning and Informix fragmentation by expression are shown below Oracle range partitioning

CREATE TABLE dept

IBM Software Group IBM Information Management

Version 16 24

(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13) )

partition by range (deptno)

(partition PART1 values less than (11)

tablespace PART1_TS

partition PART2 values less than (21)

tablespace PART2_TS

partition PART3 values less than (31)

tablespace PART3_TS

partition PART4 values less than (MAXVALUE)

tablespace PART4_TS)

Informix expression based fragmentation CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

deptno lt 11 IN dbspace1

deptno gt= 11 AND deptno lt 21 IN dbspace2

deptno gt= 21 AND deptno lt 31 IN dbspace3

REMAINDER IN dbspace4

Oracle uses MAXVALUE for values not found in the specified range while Informix uses the REMAINDER keyword for values that fall outside the specified expression or expressions Prior to IDS version 1000 each table fragment had to go into a separate dbspace Now tables can be fragmented within a single dbspace You can create partitions within a dbspace that can each support a table fragment It is better to have one chunk per disk drive and now it is not necessary to create a dbspace just to facilitate fragmentation This feature can simplify the management of dbspaces The benefits gained through this new development include

It reduces the total number of dbspaces needed for a fragmented table

Storing multiple table fragments in a single dbspace improves query performance over storing each fragmented expression in a different dbspace

For example Informix partition fragmention in a single dbspace

CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

PARTITION part1 (deptno lt 11) IN dbspace1

PARTITION part2 (deptno lt 21) IN dbspace1

PARTITION part3 (deptno lt 31) IN dbspace1

PARTITION part4 REMAINDER IN dbspace1

Partitions of an Informix fragmented table can be manipulated using the ALTER FRAGMENT statement which supports attaching detaching adding modifying and dropping as well as initializing the distribution strategy

IBM Software Group IBM Information Management

Version 16 25

For example the following SQL removes a partition fragment and places the contents into a new table

ALTER FRAGMENT ON TABLE dept DETACH PARTITION part3 dept_part3

Making use of ALTER FRAGMENT to detach fragments can be an effective way of deleting large quantities of rows from a table quickly and easily After the above statement completes the table will no longer contain rows with a deptno greater than 21 and less than 31 Refer to the Informix Guide to SQL Syntax for a complete description on how to use the ALTER FRAGMENT statement to change the distribution strategy or the storage location of an existing table or index

Data types

Numeric

Oraclersquos NUMBER data type needs to be replaced with one of the following Informix equivalent data types depending on the size of the column The Informix numeric data types are listed below

SMALLINT (-32767 to 32767)

INTEGER (-2147483647 to 2147483647)

BIGINT (-9223372036854775807 to 9223372036854775807)

INT8 (-9223372036854775807 to 9223372036854775807)

The BIGINT type is more efficient in terms of space and speed there are few reasons to use INT8 now that BIGINT is available

DECIMAL (floating point up to 32 significant digits -10-130

to 10124

)

In an ANSI database there is an implied scale of 0 when no scale is given so this is not strictly speaking a floating point type within an ANSI database

NUMERIC (floating point up to 32 significant digits -10-130

to 10124

)

FLOAT (double precision like double data type of C)

SMALLFLOAT (single precision like float data type of C)

REAL (same as SMALLFLOAT)

DOUBLE (same as FLOAT)

LONG (same as long data type of C)

Oraclersquos NUMBER data type is used to store zero positive and negative fixed size and floating point numbers with magnitudes between 10 x 10

-130 and 999 x 10

125 (38 9s followed by 88 0s)

with 38 digits of precision A fixed-point number is specified by NUMBER(p s) where p is the precision or the total number of digits and s is the scale or the number of digits to the right of the decimal point For example a column defined as NUMBER(104) would contain numbers in the format 9999999999 In Oracle the scale can range from -84 to 127 If the scale is 0 or not mentioned then the data type can be converted into Informixrsquos SMALLINT INTEGER or BIGINT depending on the precision or FLOAT SMALLFLOAT DOUBLE or REAL depending on usage in the application When the scale is positive the data type should be converted to Informixrsquos DECIMAL or NUMERIC A floating-point data type in Oracle is declared using the type NUMBER without mentioning scale and precision In Informix this can be replaced with FLOAT SMALLFLOAT REAL DOUBLE PRECISION or DECIMAL(p) in an non-ANSI database

IBM Software Group IBM Information Management

Version 16 26

Oracle allows a negative scale If the scale is negative the actual data is rounded to the specified number of places to the left of the decimal point For example a specification of NUMBER (10 -2) means to round to the hundred If the general form for any number is

mantissa X 10exponent

then precision is the number of digits in the mantissa and scale is the negative exponent Example

select cast( 987654321 AS NUMBER(10-2) ) from dual

returns

987654300

Informix does not support a negative scale If precision - scale is less than the maximum precision of an integer type then that is the most efficient type to use Failing that and if the database is non-ANSI a floating point DECIMAL can be used If that is not sufficient then it may be necessary to define a user type and associated functions Oracle also allows the scale to be greater than the precision Precision is just the number of digits that will be preserved A NUMBER(3 5) might have the value 000123 If the Oracle scale is less than the Informix maximum precision then the Oracle scale can be used for both the Informix precision and scale A NUMERIC(55) column could also store the value 000123 You may need to take into consideration not only the minimum and maximum values but the default size for data types For example when the size of the NUMBER data type is absent Oracle will default to NUMBER(38) while Informix defaults to NUMERIC(16) Oracle and Informix support the ANSI DECIMAL data type Therefore in the case of an ANSI data type the Oracle data type can be converted to the same Informix data type There are differences between conversions based on theory versus those based on practice For instance it is very common to see an undecorated NUMBER declaration where the customer database and applications are using integer data When converting NUMBER declarations it may be necessary to consider how the data is being used in order to determine the best type mapping

CHAR VARCHAR and LVARCHAR

In Oracle the default for a CHAR column is one character and the maximum allowed is 255 characters In Informix the maximum length of CHAR and LVARCHAR columns is 32767 Therefore Oraclersquos CHAR columns can always be converted to an Informix CHAR column The CHAR data type columns can only contain printable characters tabs and spaces The CHAR columns store leading and trailing spaces In Oracle a zero-length string can be inserted into a CHAR column but the column is padded with one blank character when it is used in comparisons Also in Informix a zero-length string can be inserted into a CHAR column however the column is padded with enough spaces to fill the column In the case of inserting NULL into an Informix CHAR column no padding occurs Oraclersquos VARCHAR and VARCHAR2 are currently synonymous and have a maximum data length of 4000 bytes while the maximum length for the Informix VARCHAR data type is 255 Informixrsquos CHAR and LVARCHAR data types have a maximum length of 32767 and 32739 respectively measured in bytes These should be used to replace Oraclersquos VARCHAR VARCHAR2 LONG and LONG VARCHAR if the data length is between 256 and the maximum If the data length exceeds the maximum use Informixrsquos TEXT BYTE BLOB or CLOB data types See the Raw Data section below for more information on TEXT BYTE BLOB and CLOB data types

IBM Software Group IBM Information Management

Version 16 27

Empty Oracle VARCHAR2 strings are considered NULL Empty Informix VARCHAR and LVARCHAR strings are not considered NULL rather they contain at least one space Oracle

compares VARCHAR2 values using non-padded comparison semantics Therefore ldquoBOBrdquo ldquoBOB ldquo Informix ignores trailing blanks Therefore ldquoBOBrdquo = ldquoBOB ldquo or ldquordquo = ldquo rdquo Hence checks for NULL within the application must be replaced with checks for an empty string (such as ldquordquo or ldquo rdquo) whenever an empty string is inserted into the column If NULL is truly inserted into the column checking for NULL is appropriate (for example SELECT FROM hellip WHERE hellip IS NULL) In Oracle LONG columns store variable length character strings containing up to 2 gigabytes or 2

31-1 bytes Informix LONG columns store numeric data Oraclersquos LONG columns have many of

the characteristics of VARCHAR2 columns They can be used in a SELECT list in the SET clause of an UPDATE statement and in an INSERT statement but they cannot be used in a WHERE clause a GROUP BY clause or an ORDER BY clause and they cannot be indexed Oraclersquos LONG columns should be converted to an Informix Smart Large Object or ldquoSLOBrdquo (BLOB CLOB) column

Date and Time

Oraclersquos DATE data type contains date and time components from year down to second It can be to be replaced most directly with Informixrsquos DATETIME YEAR TO SECOND Some analysis may be necessary to determine whether the time is really necessary In other words does the application reference the date and time portions of the values If the application only references the date portion then replace Oraclersquos DATE with Informixrsquos DATE and change the host variable to X(10) or char(10) accordingly The Informix DATE default display format is MM-DD-YYYY although the DATE data type stores the calendar date The Informix DATE data type requires 4 bytes which is stored internally as an integer value equal to the number of days since December 31 1899 The default display format can be changed with the environment variable DBDATE If the application uses different date formats then using DBDATE is not a solution Sometimes it might be necessary to write small subroutines to emulate Oraclersquos DATE representations See the Informix Guide to SQL Reference manual for details on DBDATE and also DBCENTURY If the application only references the time portion of the values replace Oraclersquos DATE with Informixrsquos DATETIME using the EXTEND function to specify precision In addition Informix provides the data type INTERVAL for use while performing DATE and DATETIME calculations In Oracle the DATE data type is used to store date and time information Although date and time information can be represented in both CHAR and NUMBER data types the DATE data type has special associated properties For each DATE value the following information is stored

century

year

month

day

hour

minute

second

Also regarding the Oracle DATE data type if a date value without a time component is specified the default time is 120000am If a DATE value without a date is specified the default date is the first day of the current month

Interval

Within Informix there are two classes of interval types YEAR-MONTH and DAY-FRACTION There are different numbers if days in different months so the MONTH-DAY boundary cannot be crossed without creating ill-defined results Within each of these classes Informix allows you to declare columns or variables as any subset of the start and end fields Oracle has one INTERVAL

IBM Software Group IBM Information Management

Version 16 28

type for each of the two classes YEAR(p) TO MONTH and DAY(p) TO SECOND(s) The Oracle scale on the SECOND field is logically equivalent to the Informix scale on the FRACTION field

Raw data and Large Objects

Oraclersquos support of large blocks of raw unstructured data (such as graphic images video clips and sound waveforms) in binary or character format is provided by the large object (LOB) data types BLOB CLOB NCLOB and BFILE Traditional Oracle data types MLSLABEL (used with Trusted Oracle) RAW and LONG RAW are also used for data that is not to be interpreted by the engine and converted when moving data between different systems Informix supports two types of large objects (LOBs Simple Large Objects and Smart Large Objects Simple LOBs consist of the TEXT and BYTE data types and can be 2

31 bytes or 2

Gigabytes in size Smart LOBs include both Character Large Object (CLOB) and Binary Large Object (BLOB) data types and may be up to 42

40 bytes or 4 Terabytes in size Simple LOBs can

be stored either in-line with table data or in blobspaces while Smart LOBrsquos are stored in sbspaces Oraclersquos CLOB BLOB MLSLABEL RAW and LONG RAW data types should be replaced with Informixrsquos BYTE TEXT CLOB or BLOB depending on the columnrsquos size and usage Informixrsquos Smart BLOB data types CLOB and BLOB should be used under the following conditions and considerations

The large object needs to be referenced by multiple sources

The object size exceeds 2 GB

Fragmentation is required

Byte level locking is available making it possible to lock only a portion of the object

Logging can be specified at the object level

Updates are done in place or moved as needed

Be aware of the following restrictions for Simple Large Objects

Data can only be inserted into a BYTE or TEXT column with the dbload or onload utilities the DBACCESS load statement BYTE or TEXT host variables respectively in ESQLC or declaring a file in ESQLCOBOL

BYTE and TEXT columns cannot be inserted or updated with a literal neither quoted text string nor number

BYTE or TEXT columns cannot be used in string operations with aggregate functions with the GROUP BY ORDER BY IN LIKE or MATCHES clauses

ROWID

The implementation of ROWID differs between Oracle and Informix Oraclersquos ROWID is both a pseudo-column and a data type See the ROWID subsection in the Pseudo-Columns section in CHAPTER 3 Data Manipulation Language for more information Informix implements ROWID as a pseudo-column only Oracle stores the ROWID column and ROWID data type column values in hexadecimal format Informix stores the ROWID column values in INTEGER format The Oracle and Informix engines maintain the values of the ROWID pseudo-column Oraclersquos engine does not maintain the values of other columns of type ROWID In Informix the term rowid refers to an integer that defines the physical location of a row Informix assigns rows in a non-fragmented table a unique rowid which allows applications access to a particular row in a table Rows in fragmented tables in contrast are not assigned a rowid To access data by rowid in a fragmented table a rowid column must be explicitly created as is described in the Informix Guide to SQL Reference manual Creating a Rowid Column If applications attempt to reference a rowid in a fragmented table that does not contain a rowid that was explicitly created Informix displays an appropriate error message and execution of the application is halted

IBM Software Group IBM Information Management

Version 16 29

When used as a data type for a column Oracle does not guarantee that the values are valid ROWIDs For example if the ROWID is used as a data type on a column such as a column in a child table named parent_rowid containing the ROWID of the parent then the values are maintained by the application outside of the engine The application must read the ROWID of the parent and insert it into the parentrsquos corresponding child table rows This is usually done so the two tables can be joined on the parentrsquos ROWID and the childrsquos parent_rowid column This functionality can be duplicated in Informix by using primary and foreign keys Informix recommends that primary keys are used as a method of access in applications rather than rowids because primary keys are defined in the ANSI specification of SQL using them to access data makes applications more portable Refer to the Informix Guide to SQL Reference and the Informix Guide to SQL Syntax for a complete description on how to define and use primary keys to access data

User-defined types

Both Oracle and Informix allow the user to create and define data types Oracle refers to these as abstract data types while Informix refers to these as user-defined types In Oracle all user-defined types are referred to as abstract data types while Informix may refer to user-defined types as COLLECTION types ROW types DISTINCT types and OPAQUE types Currently the Informix ROW type is closest in form and function to the Oracle abstract data type An example of syntax for creating both an Oracle abstract data type and an Informix ROW type is shown below

Oracle abstract data type

CREATE TYPE name_type AS OBJECT

(first_name VARCHAR2(25)

middle_initial CHAR(1)

last_name VARCHAR2(30))

Informix row type

CREATE ROW TYPE name_type

(first_name VARCHAR(25)

middle_initial CHAR(1)

last_name VARCHAR(30))

Both Oracle and Informix support the use of user-defined types for table definition or column definition within a table Building on the example above the following create table example show a table definition and column definition within a table based on user-defined types Oracle table creation

CREATE TABLE name OF name_type

Informix table creation

CREATE TABLE name OF type name_type

Oracle column definition

CREATE TABLE employee

(empno NUMBER(9)

name name_type)

Informix column definition

CREATE TABLE employee

IBM Software Group IBM Information Management

Version 16 30

(empno INTEGER

name name_type)

For more information on User Defined Types see the Informix Guide to SQL Syntax

Complex data types

Informix offers users the ability to create data types from existing built-in types OPAQUE types DISTINCT types and other complex types Complex data types may either be a ROW type or a COLLECTION type Oracle treats complex data types as abstract data types For more information on Oracle abstract data types see the User Defined Types section above For more information on Complex Data Types see the Informix Guide to SQL Syntax For recommended type mappings and additional information see the appendix ldquoData type mappingsrdquo

Sequence objects

Oracle sequences

An Oracle sequence is a database object from which multiple users or transactions may generate unique integers For example sequences can be used to automatically generate primary key values When a sequence object is queried the sequence number is incremented and passed to the query independent of the transaction committing or rolling back If two applications increment the same sequence the sequence numbers each application acquires may not be sequential since sequence numbers are being generated by the other application One user or transaction can never acquire the sequence number generated by another user or transaction Once a user or transaction generates a sequence value that value will never be generated and passed to another user or transaction

Informix sequences

Informix rsquos implementation of sequence objects is identical to that of Oracle Issues regarding syntax compatibility should be negligible with the exception of some keywords which have no effect on the behavior of the sequence Informix supports DML statements (CREATE SEQUENCE ALTER SEQUENCE RENAME SEQUENCE DROP SEQUENCE) for sequence objects that multiple users can access concurrently to generate unique integers in the 8-byte integer range GRANT and REVOKE statements support access privileges on sequence objects and the CREATE SYNONYM and DROP SYNONYM statements can be used to reference synonyms for sequence objects in the local database The operators CURRVAL and NEXTVAL can read or increment the value of an existing synonym with behavior the same as Oracle

Indexes

Composite indexes

A composite index can have up to 16 key parts that are columns or up to 341 key parts that are values returned by a UDR This limit is language-dependent and applies to UDRs written in SPL or Javatrade functional indexes based on C language UDRs can have up to 102 key parts A composite index can have any of the following items as an index key

One or more columns

IBM Software Group IBM Information Management

Version 16 31

One or move values that is returned by a user-defined function (referred to as a functional index)

A combination of columns and user-defined functions

Maximum key size

The total widths of all indexed columns in a single CREATE INDEX statement have a limitation based upon the page size of the dbspace in which the index resides This limitation does not apply to functional indexes An enhancement introduced with Informix Dynamic Server Version 1110 is configurable page sizes for dbspaces Prior to this release the page size of dbspaces were restricted to that of the operating system and could not be changed thus Informix was limited to 390 byte indexes With page sizes configurable from 2K through 16K wider indexes are supported Refer to the table below 16K page sizes raises the limit on index width to over 3000 bytes Lifting the 390 byte limit also permits LVARCHAR columns larger than 387 bytes to be included in an index definition

Page Size Maximum Key Size

2 kilobytes 387 bytes

4 kilobytes 796 bytes

8 kilobytes 1615 bytes

12 kilobytes 2435 bytes

16 kilobytes 3245 bytes

In addition to aiding the porting process wider indexes have satisfied requirements for Unicode data as well as provide performance gains by reducing B-Tree index traversal costs since indexing can be built with more items on an index page and produce fewer levels

Index fragmentation

Just as Oracle and Informix support table fragmentation or partitioning in Oracle both support index fragmentation as well See the Table fragmentation section above for more information regarding Informix table fragmentation and Oracle table partitioning Oracle indexes that are partitioned in the same manner as the table they are indexing are referred to as local indexes Informix refers to these as attached indexes Oracle indexes that span partitions are known as global indexes Informix refers to these as detached indexes Informix detached indexes may also refer to indexes that do not follow the same fragmentation scheme as the table they are indexing Starting with Informix version 1110 indexes can be fragmented similarly to tables on a partition level

General index information

The Informix CLUSTER option should be used when appropriate This option orders the data within the table in the order the index requires It is important to note that the CLUSTER index is not maintained over time The primary factor determining the frequency of CLUSTER index rebuilds is the amount of DML performed against the table Frequent INSERTS UPDATES and DELETES make it necessary to closely monitor CLUSTER indexes There is only one clustered index per table since a tablersquos data can only be stored in one order Oraclersquos INITRANS and PCTFREE functionality is similar to the Informix index FILLFACTOR option of the CREATE INDEX statement or the FILLFACTOR configuration parameter in the ONCONFIG file In either case the functionality is handled by Informixrsquos engine once it is set and can be removed from the application FILLFACTOR specifies the degree of index-page

IBM Software Group IBM Information Management

Version 16 32

compactness A low value provides room for growth in the index A high value compacts the index If an index is fully compacted (100 percent) any new inserts result in splitting nodes The setting on the CREATE INDEX statement overrides the ONCONFIG file value The FILLFACTOR default value for both the CREATE INDEX statement as well as the ONCONFIG is 90 Informix has no support for bitmap indexes

Views Oraclersquos CREATE VIEW statement contains three options FORCE NO FORCE and WITH READ ONLY FORCE creates the view regardless of whether the views base tables exist or the owner of the schema containing the view has privileges on them NO FORCE creates the view only if the base tables exist and the owner of the schema containing the view has privileges on them WITH READ ONLY specifies that no deletes inserts or updates can be performed through the view These options must be removed from the Informix CREATE VIEW statements Because a view is not really a table it cannot be indexed and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE The columns of a view cannot be renamed with RENAME COLUMN To change anything about the definition of a view you must drop the view and re-create it Because it must be merged with the userrsquos query the SELECT statement on which a view is based cannot contain any of the following clauses

INTO TEMP The userrsquos query might contain INTO TEMP if the view also contains it the data would not know where to go

UNION The userrsquos query might contain UNION No meaning has been defined for nested

UNION clauses

ORDER BY The userrsquos query might contain ORDER BY If the view also contains it the choice of columns or sort directions could be in conflict

Stored procedures and triggers The ways stored procedures and triggers are created differ between Oracle and Informix Oracle allows a REPLACE clause in the CREATE statement to handle situations when the object already exists Informix does not support the REPLACE option Instead a DROP PROCEDURE or DROP TRIGGER statement must precede the CREATE PROCEDURE or CREATE TRIGGER statement respectively to handle the situation when the object already exists It should be noted a DROP statement will generate an error when the object does not exist If it is run interactively within the DBACCESS user interface the DROP statement error will terminate processing If it is run using script execution using DBACCESS at the command line processing will continue To run DBACCESS from the command line type

dbaccess db_name

To run the file containing the create statements from the command line type dbaccess db_name sql_file_name

Informix introduced an IF EXISTS clause to most of the CREATE and DROP statements at 117 but the logic is different from Oraclersquos OR REPLACE clause For example these statements

IBM Software Group IBM Information Management

Version 16 33

DROP PROCEDURE IF EXISTS hellip

CREATE PROCEDURE hellip

are logically the same as this Oracle statement

CREATE OR REPLACE PROCEDURE hellip

So it is possible to achieve the same result but not necessarily the same number of statements

Oracle extensions The Oracle CLUSTER option in CREATE statements should be removed These are not to be confused with Informix CLUSTER index statements (See Indexes section above) An Oracle cluster is a database schema object that contains one or more tables that all have one or more columns in common Rows of one or more tables that share the same value in these common columns are physically stored together within the database Removing this Oracle feature will not affect the application Other non-Informix DDL statements like CREATE DATAFILE CREATE CONTROLFILE CREATE ROLLBACK SEGMENT CREATE SNAPSHOT CREATE DATABASE and CREATE DATABASE LINK must be removed or changed (in the case of the CREATE DATABASE statement) The Oracle CREATE PROFILE statement must be removed An Oracle profile is a set of limits on database resources Profiles can be used to limit the database resources available to a user for a single SQL statement or a single session

IBM Software Group IBM Information Management

Version 16 34

C H A P T E R 4 Data Manipulation Language

SQL

Labels using keywords

Oracle displays labels in SQL statements that are Informix reserved words such as UNITS YEAR MONTH DAY HOUR and so on must be converted by using the Informix AS clause between the column name and the display label Otherwise syntactic ambiguities will cause errors

Inequality operations

In addition to the Informix supported ldquonot equal tordquo symbols ldquoltgtrdquo and ldquo=rdquo Oracle supports the symbol ldquo^=rdquo All occurrences of ^= must be replaced with one of the Informix supported symbols

Selects

Queries are executed based on how the optimizer determines the best path to the data Oracle and Informix developed their own query optimizers with their proprietary methods and rules A query that looks exactly the same in both environments may run differently in each following a different path and executing faster or slower Therefore every query in the ported application should be tested for performance regardless of whether a query had to be converted Furthermore Oracle supports optimizer hints within a SELECT statement Prior to IDS 73 and Informix Dynamic Server 92 Informix did not allow optimizer hints See the Optimizer Directives subsection below for more information on porting Oraclersquos optimizer hints to Informixrsquos optimizer directives

Optimizer directives

Informix offers optimizer directives similar to Oraclersquos optimizer hints This feature provides the query developer the flexibility to direct the optimizer to follow specific paths rather than choosing a plan through its analysis A query is processed in two steps First it is optimized and compiled to product a query plan Secondly it is executed to produce a result Optimizer directives are a method for influencing the choice of the optimizer in the creation of the plan

IBM Software Group IBM Information Management

Version 16 35

Optimizer directives address the following key issues

Reduced time for correcting performance problems Rewriting queries can be very time consuming and this allows you to have a quick way to alter a plan

Competitive pressure Users accustomed to this function were looking for it in Informix

Product development tuning This allows product development to alter plans dynamically rather than through code changes to evaluate the effect of different optimization techniques

The syntax and behavior of Informixrsquos implementation is compatible with Oraclersquos optimizer hints which eases the porting of applications from Oracle to Informix Directives are written as a comment whose first character is a lsquo+rsquo (plus sign) An example is

select + ORDERED AVOID_FULL(e) empname deptno

from employee e department d

where edept_no = ddept_no

This above example specifies that the tables should be joined in the order specified in the query and that the employee table (e) should NOT be accessed with a full table scan The Informix implementation differentiates itself significantly from Oraclersquos in one way Informix supports the notion of negative directives whereas Oracle only supports direct hints A directive that tells the optimizer what to avoid rather than what to choose is unique to Informix The query result can be realized by writing a directive to avoid certain actions known to cause performance issues but allow any new indexes or table attributes to be explored by the optimizer as they are added over the life of the table and query This allows a DBA to continue to add indexes to tables and not have to rewrite directives Additionally Informix supports full recognition of directives with SET EXPLAIN output Informix will highlight semantic and syntactic errors which Oracle does not Optimizer directives support control in the following areas of the optimization process

Access methods Index versus scans

Join Methods Forcing hash joins nested loop joins

Join Order Specify which order the tables are joined

Goal Specify first rows or all rows (response time versus throughput) See the Informix Guide to SQL Syntax or Reference for more information

External optimizer directives

External optimizer directives give the DBA the ability to specify query directives and save them in the database These directives are applied automatically to subsequent instances of the same query The SAVE EXTERNAL DIRECTIVES statement associates one or more optimizer directives with a query and stores a record of this association in the sysdirectives system catalog table for subsequent use with queries that match the specified query string The query string must be an exact match that includes case and white space positioning This statement establishes an association between the list of optimizer directives and the text of a query but it does not execute the specified query Only the DBA or user informix can execute SAVE EXTERNAL DIRECTIVES This associates AVOID_INDEX and FULL directives with the specified query

SAVE EXTERNAL DIRECTIVES

+ AVOID_INDEX (table1 index1) + FULL(table1)

ACTIVE FOR

SELECT col1 col2 FROM table1 table2

IBM Software Group IBM Information Management

Version 16 36

WHERE table1col1 = table2col1

These directives are applied automatically to subsequent instances of the same query You must include one of the ACTIVE INACTIVE or TEST ONLY keyword options to enable disable or restrict the scope of external directives When external directives are enabled and the sysdirectives system catalog table is not empty the database server compares every query with the query text of every ACTIVE external directive and for queries executed by the DBA or user informix with every TEST ONLY external directive External directives are ignored if the EXT_DIRECTIVES parameter is set to 0 in the ONCONFIG file In addition the client system can disable this feature for its current session by setting the IFX_EXTDIRECTIVES environment variable to 0 If an external directive has been applied to a query output from the SET EXPLAIN statement indicates ldquoEXTERNAL DIRECTIVES IN EFFECTrdquo for that query Any inline directive is ignored by the optimizer when the external directives are applied to a query that matches the SELECT statement Like inline optimizer directives that are embedded within a query external directives can improve performance in some queries for which the default behavior of the query optimizer is not satisfactory Unlike inline directives external directives can be applied without revising or recompiling existing applications

Inserts

Informix does not support Oraclersquos INSERT with SELECT statement utilizing an UNION clause (although a view with an UNION clause can be referenced resulting in an UNION operation) Additionally Informix does not support an INSERT statement with a VALUE clause with SELECT statements The SELECT statement within a VALUE clause can be rewritten by omitting the VALUE clause and performing an INSERT INTO table_name SELECT hellip FROM other_table_name

Temporary tables

Informix and Oracle implemented the concept of temporary tables differently Oracle implements temporary tables as a work area during batch data loads Informix implements temporary tables just like regular database tables These temporary tables can be created manipulated and dropped only within a session such as stored procedures and ESQL programs Once the session ends any remaining temporary tables are automatically dropped Temporary tables can give an application extra functionality however their use should be limited if reducing database extensions to increase database independence within an application is a priority

Outer joins

Both Oracle (starting with Oracle 9i) and Informix support ANSI standard syntax for outer join specification The syntax for left and right outer join using the plus sign (+) in the WHERE clause is only supported for backward compatibility however it is still in existence The use of ANSI outer join syntax is recommended The Oracle outer join syntax + (placed after the column which has values not matching the corresponding column in the joined table) can be replaced with the Informix equivalent OUTER The OUTER keyword is placed within the SELECT statement before the name of the subservient table Unlike Oracle in Informix multiple outer joins per SELECT statement are allowed grouped with parentheses

Sorts

In Oracle sorts NULL values are considered the highest value and are therefore ordered last in ascending sorts Informix sorts with NULLS as the lowest value ordering them first in ascending sorts First it must be determined whether this sorting difference will affect the outcome enough to warrant a work around In most cases it will not If it does then a stored procedure can be

IBM Software Group IBM Information Management

Version 16 37

written to evaluate whether a column is NULL and if so replace it with a high value so that it will sort last Once the application receives the results it must replace the high values with NULL if the column is going to be displayed or manipulated

Exceptions

Error handling using hard coded Oracle SQL codes must be replaced with the corresponding Informix SQL codes

Correlation names

Informix does not support correlation names with aliases on the main table of an UPDATE or DELETE statement Such cases must be converted For example

Oracle UPDATE customer C

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE Ccreate_date lt= Zeffective_date)

Informix UPDATE customer

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE customercreate_date lt= Zeffective_date)

-and-

Oracle DELETE customer C

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND Cstate = Tstate )

Informix DELETE customer

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND customerstate = Tstate )

Note that Informix allows correlation names with aliases on tables other than the updated or deleted table

Aliases

Unlike Oracle in Informix if an alias is used in the FROM clause of a SELECT statement it must also be used in the SELECT list and WHERE clauses The original table name should be replaced with the alias wherever aliases and original names are used together within a SELECT statement in an Oracle application

Hierarchical queries

Informix does not allow query results to be organized hierarchically in a B-tree fashion Oracle does allow it by using the clauses START WITHhellip and CONNECT BY PRIOR in the SQL

IBM Software Group IBM Information Management

Version 16 38

statement In Oracle if a table contains hierarchical data a bill of materials for example rows can be selected in a hierarchical order using the following clauses START WITH

The START WITH clause identifies the row(s) to be used as the root(s) of a hierarchical query This clause specifies a condition that the root(s) must satisfy If this clause is omitted Oracle uses all rows in the table as root rows A START WITH condition can contain a subquery

CONNECT BY

The CONNECT BY clause specifies the relationship between parent and child rows in a hierarchical query This clause contains a condition that defines this relationship The part of the condition containing the PRIOR operator must have one of the following forms

PRIOR expression comparison_operator expression -or- expression comparison_operator PRIOR expression

To find the children of a parent row Oracle first evaluates the PRIOR expression to identify the parent row(s) and the other expression for each row in the table Rows for which the other expression is true are the children of the parent The CONNECT BY clause can contain other conditions to further filter the rows selected by the query

WHERE

The WHERE clause can restrict the rows returned by the query without affecting other rows of the hierarchy

Oracle uses the information from each of the clauses mentioned above to form the hierarchy using the following steps

1 Oracle selects the root row(s) of the hierarchy These are the rows that satisfy the condition of the START WITH clause

2 Oracle selects the child rows of each root row Each child row must satisfy the condition of the CONNECT BY clause with respect to one of the root rows

3 Oracle selects successive generations of child rows Oracle first selects the children of the rows returned in step 2 and then the children of those children and so on Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row

4 If the query contains a WHERE clause Oracle removes all rows from the hierarchy that do not satisfy the condition of the WHERE clause Oracle evaluates the WHERE condition for each row individually after the row has been fetched rather than only fetching rows that satisfy the WHERE condition

5 Oracle returns the rows in the order of an in-order or left-root-right binary tree traversal

IBM Software Group IBM Information Management

Version 16 39

For example the following SQL statement returns the data in the adjacent table in hierarchical order The root row is defined to be the employee whose job is lsquoPRESIDENTrsquo The child rows of a parent row are defined to be those rows whose manager number is the employee number of the parent row

SELECT ename empno mgr job FROM emp START WITH job = lsquoPRESIDENTrsquo CONNECT BY PRIOR empno = mgr

To duplicate this hierarchical functionality in Informix stored procedures or functions can be written requiring intensive use of cursors and program arrays Informix offers the choice of creating and using a User Defined Routine or ldquoUDRrdquo See User Defined Routines section below Use of Informix global arrays will help considerably To maximize read processing at the expense of insert processing another method is to break the table into two tables one containing the data and the other containing the relationship (foreign keys) between each parent and child A parent row would have an entry in the relationship table for each of its children grandchildren great grandchildren and so on The opposite is true where a child row would have an entry in the relationship table for its parent grandparent great grandparent and so on

Truncate

Informix supports the TRUNCATE statement for deleting all active data rows from a table and associated indexes When using Informixrsquos TRUNCATE you also have the option of releasing the storage space that was occupied by the rows and index extents or keeping the space allocated to be used as the table is repopulated with new data

TRUNCATE [TABLE] table [ [ DROP | REUSE ] STORAGE ]

You may use the commandrsquos simplest usage

TRUNCATE my_table

In the example above the TRUNCATE statement drops all the data for the table and keeps only the initial extents There is a minor difference from Oracle syntax as Informix does not require the keyword TABLE Another example

TRUNCATE my_table REUSE STORAGE

ENAME EMPNO MGR JOB

KING 7839 PRESIDENT

JONES 7566 7839 MANAGER

SCOTT 7788 7566 ANALYST

ADAMS 7876 7788 CLERK

FORD 7902 7566 ANALYST

SMITH 7369 7902 CLERK

BLAKE 7698 7839 MANAGER

ALLEN 7499 7698 SALESMAN

WARD 7521 7698 SALESMAN

MARTIN 7654 7698 SALESMAN

TURNER 7844 7698 SALESMAN

JAMES 7900 7698 CLERK

CLARK 7782 7839 MANAGER

MILLER 7934 7782 CLERK

IBM Software Group IBM Information Management

Version 16 40

This example drops all the data for the table but retains all the space allocated The permissions needed for TRUNCATE TABLE depend on the existence of DELETE triggers on the table For tables with DELETE triggers ALTER permission on the table is required and RESOURCE or DBA privileges because the DELETE triggers will be bypassed For tables without DELETE triggers you need DELETE permission on the table and CONNECT privilege to the database While Oracle does not provide rollback Informix does permit TRUNCATE TABLE to execute within a transaction When you rollback a TRUNCATE statement no rows are removed from the table and the storage extents that hold the data rows and index pages continue to be allocated to the table In a database that supports transaction logging only the COMMIT WORK or ROLLBACK WORK statement is valid after the TRUNCATE statement within a transaction Any other statement will generate an error The TRUNCATE statement does not reset the serial value of SERIAL or SERIAL8 columns To reset the counter of a serial column you must do so explicitly by using the MODIFY clause of the ALTER TABLE statement either before or after you execute the TRUNCATE statement After the TRUNCATE statement successfully executes Informix automatically updates the statistics and distributions for the table and for its indexes in the system catalog to show no rows in the table nor in its dbspace partitions It is not necessary to run the UPDATE STATISTICS statement immediately after you commit the TRUNCATE statement

Host variables Host variable formats should not change during the porting process Instead data types should be converted in a manner to preserve the column and host variablersquos formats However there are times when the database schema changes in a way where the host variable format must change Any column converted to a different format in Informix than that of Oracle requires that its corresponding host variable format be changed to be consistent Alternatively if an Oracle format such as date and numeric variables is not directly supported in Informix then the conversion may require some format processing before or after the SQL statement For example the Oracle function TO_CHAR is used to format both date and numerical values A similar function or at least two functions one to handle date data types and another to handle numeric data types can be declared and used in the Informix application Informix provides two built-in functions TO_DATE which converts a character string to a DATETIME variable and TO_CHAR which converts a DATETIME variable to a character string When converting variables an optional formatting string is allowed which determines how the string is displayed (full day names partial day names full months month number and so on) There is also a function ifx_to_gl_datetime() which takes an Oracle date format and returns the corresponding Informix date format This function is supplied in genlib and is for use in ESQL programs to ease migration efforts from Oracle The syntax is as follows

TO_CHAR (source_date fmt) Returns a character string containing the date specified in source_date in the format specified by fmt if one is provided If fmt is missing the function will use the default date format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

TO_DATE (source_string fmt) Evaluates source_string as a date according to the

format fmt If fmt is missing the function will use the

IBM Software Group IBM Information Management

Version 16 41

default format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

These functions are mainly useful for simplifying migration from Oracle to Informix but are also useful for performing advanced searches on DATETIME data types and for better output presentation

Date and time functions Informix version now has built-in support for most of Oraclersquos date functions so it will not be necessary to modify or replace Oraclersquos SYSDATE or ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat)

SYSDATE

IDS 1110 will support the SYSDATE operator which returns a single value representing the current date and time from the operating system clock SYSDATE is identical to the Informixrsquos CURRENT operator except that the default precision of SYSDATE is YEAR TO FRACTION(5) while the default precision of CURRENT is YEAR TO FRACTION(3) On Windows platforms that do not support a seconds scale greater than FRACTION(3) SYSDATE is effectively a synonym for the CURRENT operator In addition to SYSDATE Informix version 1110 has support for Oraclersquos date functions ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat) Depending on the whether or not the Oracle date_format argument is supported by Informix TO_CHAR(date char_format) and TO_DATE(character_string date_format) may have to be converted to Informix date processing Date processing may be required because the Oracle application may format the date in many different ways unsupported by Informix The formats used in the Oracle functions TO_CHAR TO_NUMBER and TO_DATE are illustrated below These formats should be replaced with Informix formats wherever possible format processing functions or stored procedures written to duplicate the Oracle functionality Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

Number formats

Element Example Description 9 9999 Return value with the specified number of digits with a leading

space if positive Return value with the specified number of digits with a leading minus if negative Leading zeros are blank except for a zero value which returns a zero for the integer part of the fixed-point number

0 09999990 Return leading zeros Return trailing zeros $ $9999 Return value with a leading dollar sign B B9999 Return blanks for the integer part of a fixed-point number

when the integer part is zero (suppress leading zeros regardless of whether zeros are used in the format model ie B00999 )

MI 9999MI Return negative value with a trailing minus sign ldquo-ldquo Return positive value with a trailing blank

S S9999999 Return negative value with a leading minus sign ldquo-ldquo Return

IBM Software Group IBM Information Management

Version 16 42

Element Example Description S positive value with a leading plus sign ldquo+rdquo Return negative

value with a trailing minus sign ldquo-ldquo Return positive value with a trailing plus sign ldquo+rdquo

PR 9999PR Return negative value in ltangle bracketsgt Return positive value with a leading and trailing blank

D 99D99 Return a decimal point ldquordquo In the specified position G 9G999 Return a group separator in the specified position C C999 Return the ISO currency symbol in the specified position L L999 Return the local currency symbol in the specified position 9999 Return a comma in the specified position 9999 Return a decimal point ldquordquo In the specified position V 999V99 Return a value multiplied by 10

n (and if necessary round it

up) where n is the number of ldquo9rdquos after the ldquoVrdquo EEEE 99EEEE Return a value in scientific notation RNrn RN Return a value as Roman numerals in uppercase Return a

value as Roman numerals in lowercase Value can be an integer between 1 and 3999

FM FM909 Return a value with no leading or trailing blanks

Date formats

Element Meaning -rdquotextrdquo Punctuation and quoted text is reproduced in the result AD or AD AD indicator with or without periods AM or AM Meridian indicator with or without periods BC or BC BC indicator with or without periods CC or SCC Century ldquoSrdquo prefixes BC dates with ldquo-ldquo D Day of week (1-7) DAY Name of day padded with blanks to length of 9 characters DD Day of month (1-31) DDD Day of year (1-366) DY Abbreviated name of day IW Week of year (1-52 or 1-53) based on the ISO standard IYY or IY or I Last 3 2 or 1 digit(s) of ISO year IYYY 4-digit year based on the ISO standard HH or HH12 Hour of day (1-12) HH24 Hour of day (0-23) J Julian day the number of days since January 1 4712 BC Number

specified with lsquoJrsquo must be integers MI Minute (0-59) MM Month (01-12 JAN = 01) MONTH Name of month padded with blanks to length of 9 characters MON Abbreviated name of month RM Roman numeral month (I-XII JAN = I) Q Quarter of year (1 2 3 4 JAN-MAR = 1) RR Last 2 digits of year see below for years in other centuries WW Week of year (1-53) where week 1 starts on the first day of the year

and continues to the seventh day of the year W Week of month (1-5) where week 1 starts on the first day of the

month and ends on the seventh PM or PM Meridian indicator with and without periods SS Second (0-59) SSSSS Seconds past midnight (0-86399) YYYY Year with comma in the ldquordquo position YEAR or SYEAR Year spelled out ldquoSrdquo prefixes BC dates with ldquo-ldquo YYYY or SYYYY 4-digit year ldquoSrdquo prefixes BC dates with ldquo-ldquo

IBM Software Group IBM Information Management

Version 16 43

YYY or YY or Y Last 3 2 or 1 digit(s) of year

The RR date format element

The RR date format element is similar to the YY date format element but it provides additional flexibility for storing date values in other centuries The RR date format element allows storing the century even though only two digits are entered for the year The table below illustrates how the year is stored based on only two digits

If the year is entered as

0 ndash 49 50 - 99 If the last two digits of the

0 - 49 The return date is in the current century

The return date is in the century before the current one

current year are

50 - 99 The return date is in the century after the current one

The return date is in the current century

User-defined routines User-defined data types user defined behaviors and user defined access methods add rich functionality to Informix A user-defined routine (UDR) can be developed in C Java or Informix SPL language to vastly extend the capabilities of the database Porting applications to Informix gives the option to create UDRs for aggregate and mathematical functions or to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or you can rename an Informix function to the corresponding Oracle function name

Compatible SQL Functions Informix Dynamic Server version 1110 has added support for a number of built-in SQL functions to ease a migration effort These new functions which perform common operations and data manipulation provide compatibility with Oracle routines thus simplifying the migration of applications that have been developed for an Oracle database

Date and time functions ROUND TRUNC ADD_MONTHS LAST_DAY NEXT_DAY MONTHS_BETWEEN SYSDATE

Conversion functions ASCII TO_CHAR TO_NUMBER

String manipulation LTRIM RTRIM

Number manipulation ROUND TRUNC CEIL FLOOR POWER

Bit manipulation BITAND BITOR BITXOR BITNOT BITANDNOT

Others NULLIF FORMAT_UNITS These functions are documented with examples in the IBM Informix Guide to SQL Syntax

Aggregate functions Like Oracle the result returned by an Informix aggregate function is NULL if all of the column values are NULL with the exception of COUNT which returns 0 (zero) Like Oracle Informix aggregate functions cannot be used in a WHERE clause unless it is on a corresponding column originating from a parent query and the WHERE clause is within a sub-query that is within a HAVING clause or the aggregate function is contained within a sub-query Unlike Oracle in Informix the argument of an aggregate function cannot be another aggregate function Informix supports the SELECT COUNT (column_name) hellip statement where the number of rows containing non-null values in the specified column is returned

IBM Software Group IBM Information Management

Version 16 44

The Oracle aggregate functions STDDEV and VARIANCE are supported however the Informix standard deviation routine is named STDEV thus all references to Oraclersquos STDDEV must be changed to match Informixrsquos STDEV Informix does not support Oraclersquos greatest lower boundary (GLB ) or least upper boundary (LUB) Therefore UDRs must be written to provide equivalent functionality Informix allows users to define their own aggregate functions known as user-defined aggregates (UDA) This extension of existing aggregates can be used for new data types as well as the definition of new aggregates In Informix TEXT and BYTE columns cannot be used in aggregate functions such as COUNT AVG MAX MIN and SUM

Mathematical functions Informix does not support all of Oraclersquos mathematical functions such as SIGN COSH SINH and TANH Therefore functions or UDRs must be written in the Informix application to provide equivalent functionality In Informix the rounding factor within the ROUND function must be a value from -32 to 32 This limitation has seldom been encountered as a migration issue

String functions

LENGTH

Oraclersquos LENGTH function will return different values than Informix for strings stored in CHAR data types The numeric return value representing the string length returned by Oracle will include all trailing spaces Whereas Informixrsquos LENGTH function will ignore trailing blanks regardless of data type For example for the two CHAR strings ldquoBOBrdquo and ldquoBOB ldquo Oraclersquos LENGTH function will return different values for each string 3 and 5 respectively Whereas Informixrsquos LENGTH function will ignore trailing blanks and return the value 3 for both When the input string is NULL both database functions will return a NULL

LTRIM and RTRIM

The SQL Compatibility features of Informx has support for LTRIM and RTRIM and will return identical values to that of Oracle No modifications will be necessary to SQL statements utilizing these functions

Oracle Extensions

Informix does not support all of Oraclersquos string functions such as CHR INSTR SOUNDEX and TRANSLATE Therefore corresponding user-defined routines or UDRs (ie functions or stored procedures) must be written in the Informix application to provide equivalent functionality Please note that the VERITY and EXCALIBUR Datablades included with Informix will work with Oraclersquos string function SOUNDEX

Other Oracle Functions Informix does not support the following Oracle functions Therefore corresponding functions must be written in the Informix application to provide equivalent functionality Alternatives to some of the more common Oracle functions follow this list

CHARTOROWID CONVERT DUMP GREATEST GREATEST_LB

IBM Software Group IBM Information Management

Version 16 45

HEXTORAW LEAST LEAST_UB RAWTOHEX ROWIDTOCHAR TO_LABEL TO_MULTI_BYTE TO_SINGLE_BYTE UID USERENV(OSDBA LABEL LANGUAGE TERMINAL SESSIONID ENTRYID) VSIZE

Macros Oracle contains macros sometimes referred to as language constructs which can determine the status of an object Informix does not support Oraclersquos macros These macros must be removed from the code and the associated logic should be implemented with equivalent Informix logic where applicable

ISOPEN and NOT FOUND

The macro cursor_nameISOPEN returns a Boolean value to indicate whether the cursor is open and cursor_nameNOTFOUND indicates whether there are any more rows yet to be fetched from the cursor cursor_name These macros used in condition statements are followed by some logic to handle the true andor false conditions In the case of ISOPEN this macro and its associated logic can just be omitted since the FOREACH loop processing does not explicitly open a cursor and therefore the condition cannot be checked In the case of NOTFOUND this macro should be omitted and its associated logic converted to Informix logic within an Informix FOREACH loop

ROWTYPE

The Oracle macro prefixROWTYPE is used in the declarative section as a data type to declare variables similar to the structure construct of C or RECORD of INFORMIX The prefix can be either a table name or another structure name Structure names ultimately refer back to a table name This macro may be replaced with the Informix statement LIKE table_name The construct LIKE table_name cannot be used in SPL Instead the construct DEFINE column1 LIKE table_namecolumn1 DEFINE column2 LIKE table_namecolumn2 and so on should be used to declare variables corresponding to all the columns of the table Then operations on the whole or part of the structure should be replaced with operations on single SPL variables

TYPE

The Oracle macro prefixTYPE is used in the declarative section as a data type to declare single variables The prefix is either a table_namecolumn_name or a structure_namevariable_name A structure_namevariable_name ultimately refers back to a table_namecolumn_name This macro can be replaced with the Informix statement LIKE table_namecolumn_name

Pseudo-columns Pseudo-columns are columns that exist in tables but are not displayed from a SELECT FROM table_name query Informix pseudo-columns are generally reserved for the enginersquos use Eliminating the use of such columns increases an applicationrsquos portability and eliminates the need for future modifications if the engine is ever modified to process the column differently or not at all

IBM Software Group IBM Information Management

Version 16 46

LEVEL

In Oracle for each row returned by a hierarchical query the pseudo-column LEVEL returns 1 for a root node 2 for a child of a root 3 for a child whose parent is at level 2 and so on A root node is the highest node within an inverted tree and therefore has no parent A child node is any non-root node A parent node is any node that has children A leaf node is any node without children To define a hierarchical relationship in a query you must use the START WITH and CONNECT BY clauses Informix does not support the LEVEL clause See the Hierarchical Queries subsection in the SQL section in the ldquoData Manipulation Languagerdquo chapter for more information on how to process these queries

ROWID

Oraclersquos ROWID pseudo-column returns the rows address for each row in the database ROWID values contain the following information necessary to locate a row

Which data block in the data file

Which row in the data block (first row is 0)

Which data file (first file is 1)

Usually a ROWID value uniquely identifies a row in the database However rows in different tables that are stored together in the same cluster can have the same ROWID Values of the ROWID pseudo-column have the data type ROWID ROWID values have several important uses

They are the fastest way to access a single row

They can show you how a tables rows are stored

They are unique identifiers for rows in a table

A ROWID does not change during the lifetime of its row However you should not use ROWID as a tables primary key If a row is deleted and re-inserted its ROWID may change even when using the export and import utilities If a row is deleted Oracle may re-assign its ROWID to a new row inserted later Although you can use the ROWID pseudo-column in the SELECT and WHERE clauses of a query these pseudo-column values are not actually stored in the database The value of a ROWID pseudo-column cannot be inserted updated or deleted For example the following Oracle statement selects the address of all rows that contain data for employees in department 20

SELECT ROWID ename FROM emp WHERE deptno = 20

The equivalent pseudo-column in Informix is also known as ROWID and although the behavior is similar the data type is different from Oraclersquos See the ROWID subsection in the Data Types section in the chapter ldquoData definition languagerdquo for more information

ROWNUM

In Oracle for each row returned by a query the ROWNUM pseudo-column returns a number indicating the order in which Oracle selected the row from a table or set of joined rows The first row selected has a ROWNUM of 1 the second has 2 and so on ROWNUM can be used to limit the number of rows returned by a query as in this example to read 9 rows

SELECT

FROM emp

WHERE ROWNUM lt 10

ROWID ENAME 0000000F00000002 SMITH 0000000F00030002 JONES 0000000F00070002 SCOTT 0000000F000A0002 ADAMS 0000000F000C0002 FORD

IBM Software Group IBM Information Management

Version 16 47

You can also use ROWNUM to assign unique values to each row of a table as in this example

UPDATE tabx

SET col1 = ROWNUM

Oracle assigns a ROWNUM value to each row as it is retrieved before the rows are sorted by an ORDER BY clause Therefore the final order of the rows is in ORDER BY order not in ROWNUM order An ORDER BY clause does not affect the ROWNUM values except in the case where the ORDER BY clause causes Oracle to use an index In that case the ROWNUM values are set in the order the rows are retrieved using the index and hence in ORDER BY order This order is different than if the rows were retrieved without the index So in this case the ORDER BY can affect the ROWNUM values Conditions which test for ROWNUM values greater than zero are always false For example this query returns no rows

SELECT FROM employee WHERE ROWNUM gt 1

The first row fetched is assigned a ROWNUM of 1 thus making the condition false The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 making the condition false All rows subsequently fail to satisfy the condition so no rows are returned Although there is no ROWNUM equivalent in Informix there are solutions Beginning with IDS 73 and in Informix Dynamic Server 2000 Informix provides a feature which allows the user to limit the results of a query to the first N rows This was implemented for TPC-D compliance and to support ldquorankrdquo queries Rank queries can be assembled by using FIRST N with the ORDER BY clause Informix will return the top N rows according to some ordering criteria Therefore the following Oracle SELECT utilizing ROWNUM

SELECT FROM emp WHERE ROWNUM lt 10

can be ported to Informix as follows

SELECT FIRST 9 FROM emp

Informix does not support SELECT FIRST N in complex cases as the following

Sub-queries (SELECT within a SELECT)

View definitions (Cannot be used by a SELECT statement which references a view)

UNION queries The behavior of SELECT FIRST N depends on the presence of an ORDER BY clause If no order by clause is specified the first N rows returned may be in any order Examples are as follows

find 10 highest paid employees

SELECT FIRST 10 name salary

FROM emp

ORDER BY salary

find 10 highest salary values

SELECT FIRST 10 DISTINCT salary

FROM emp

ORDER BY salary

IBM Software Group IBM Information Management

Version 16 48

Informix supports column names of ldquofirstrdquo Thus without a positive integer following the word ldquofirstrdquo the token is parsed as a column name rather than a keyword The value of N may be between 1 and (2

31-1)

When ROWNUM is used in a WHERE clause the same results can be obtained through the use of the FIRST N and SKIP clauses but if ROWNUM is used in the select list the solution is a little more complicated Simply stated you can construct a query where the ROWNUM column in any row is the count of the rows that came before This involves creating a correlated subquery where the subquery contains a self-join This can be done for any table or set of tables which has a unique key defined on it Here is an example using the customer table of the stores7 database

select

counterrownum

basecustomer_num

basefname

baselname

from

-- There can be more than one table here and the result

-- set should thought of as a table (just not a base table)

-- The result table has to be joined to itself in the

-- subquery so if there are multiple tables in this FROM

-- clause the expansion can get messy You have to have a

-- set of columns that uniquely identify each row in the

-- result table and join across them ROWID would

-- likely work if the table is not fragmented but if it is

-- there is no guarantee the final results would be accurate

-- because ROWID is not guaranteed to be unique across

-- fragments

customer base

(select

count() as rownum

acustomer_num -- any unique key possibly multiple

-- columns

from

customer a

customer b

where

-- This is where the rownum is determined the relationship

-- here has to match the outer order-by where the rows

-- are sorted and has to create a unique sort order

--

-- Any columns to be ordered by go here

-- Also the unique key has to be used to keep rows

-- that do not have a unique sort order from being merged

(alname gt blname) -- example sorting by last name

or

(alname = blname and afname gt bfname)

-- sorting by fname where lname is equal

or

(alname = blname and afname = bfname

and acustomer_num gt= bcustomer_num)

-- sorting by unique key where all the

-- other sort columns are equal

-- The expansion above is logically the same as

-- alname || afname || to_char(acustomer_num) gt=

-- blname || bfname || to_char(bcustomer_num)

-- but it allows the server to utilize any indexes that

-- may exist

group by

-- unique key columns go here

IBM Software Group IBM Information Management

Version 16 49

acustomer_num

) counter

where

-- key columns in the base tables go here

basecustomer_num = countercustomer_num

-- if you want to limit on rownum it goes here

-- and rownum lt= 10

order by

counterrownum

If using ROWNUM as an assignment as in

UPDATE tabx

SET col1 = ROWNUM

The following Informix-ESQLC pseudo-code example would have to be used

int counter = 0

EXEC SQL declare c1 cursor for

SELECT col1 col2

INTO col1 col2

FROM table 1

WHERE col1 = XX

EXEC SQL open c1

while (SQLCODE == 0)

EXEC SQL fetch c1

counter++ Increment counter for each row

fetched

if (counter gt= 5)

break

logic

End if

End while

Update using cursors There are slight differences between the ways Informix and Oracle process cursors Unlike Oracle in Informix the WHERE CURRENT OF clause cannot be used to update tables in a SELECT statement joining multiple tables since the WHERE CURRENT OF clause requires a FOR UPDATE cursor and Informix does not support the FOR UPDATE clause in SELECT statements that join multiple tables Therefore in the multi-table join statements the Oracle options FOR UPDATE and WHERE CURRENT OF should be removed and the update of the rows should be done using a separate UPDATE statement in the same cursor loop

IBM Software Group IBM Information Management

Version 16 50

In Informix a commit or rollback statement closes all cursors open in a given transaction boundary See the Transaction Processing section in CHAPTER 5 Application Architecture for more information In situations where the intention is to commit or rollback without closing the cursor in other words where the commit or rollback is executed within a cursor fetch loop the cursor can be declared as a HOLD cursor This requires that a BEGIN WORK is issued before the cursor loop starts A HOLD cursor is not closed when a commit or rollback statement is issued In Informix the FOR UPDATE clause cannot be used when declaring a HOLD cursor Thus where an Oracle application updates a table from which it fetches data in the fetch loop or issues a commit work in the fetch loop it must be converted to Informix The cursor can be declared with HOLD and then an UPDATE statement can be issued without the WHERE CURRENT OF clause In order to uniquely identify the row to be updated in the table in other words in order to simulate the WHERE CURRENT OF clause the ROWID or unique primary key columns of the table(s) to be updated must also be fetched and the WHERE CURRENT OF clause can be replaced with WHERE ROWID = fetched rowid or WHERE unique primary key column(s) = fetched unique primary key column(s) A BEGIN WORK must follow immediately after a COMMIT WORK or ROLLBACK WORK in the fetch loops to simulate Oracle implied transaction boundaries These transaction control statements work for either Informix logged databases or Informix ANSI mode databases however ANSI mode database processing with these statements will set certain warning flags after executing the BEGIN WORK statement and continue processing without failure See the ANSI vs Non-ANSI subsection in the Databases section in the chapter ldquoData Manipulation Languagerdquo for more information

System tables References to Oracle system tables should be replaced with corresponding references to Informix system tables The information schema views provided by Informix can be used These views are created after the database is installed They are populated by data in the system catalog tables and are used for easier porting

Stored procedures Informix procedures and functions are considered to be user-defined routines (UDR) A UDR can be written in Informixrsquos Stored Procedure Language (SPL) or an external language such as C or Java A procedure is a routine written that does not return a value A function is a routine written that returns a single value a value with a complex data type or multiple values Informix SPL is an extension to Informix SQL and provides procedural flow control such as looping and branching A SPL routine is a generic term that includes both SPL procedures and SPL

functions You use SQL and SPL statements to write an SPL routine SPL statements can be used only inside the CREATE PROCEDURE CREATE PROCEDURE FROM CREATE FUNCTION and CREATE FUNCTION FROM statements SPL routines are parsed optimized and stored in the system catalog tables in executable format Like Oracle Informix stored procedures support input output and inputoutput parameters and can be used in SQL statements wherever expressions are allowed

Size limit

Informix stored procedures have a size limit of approximately 64K Oracle stored procedures greater than 64K in size can be broken into smaller Informix stored procedures communicating with each other as though they were one by passing and returning the necessary values

Parameter limit

IBM Software Group IBM Information Management

Version 16 51

Informix has a limit of 341 parameters for each stored procedure This limit also applies to UDRs written in the Java language UDRs written in the C language can have no more than 102 parameters You can define any number of SPL routine parameters but the total length of all parameters passed to an SPL routine must be less than 64 kilobytes No more than nine arguments to a UDR written in the Java language can be DECIMAL data types of SQL that the UDR declares as BigDecimal data types of the Java language Any C language UDR that returns an opaque data type must specify opaque_type in the var binary declaration of the C host variable

Packages

An Oracle package is a collection of functions procedures and variables that can be enabled and accessed as a unit There is no direct equivalent within Informix but there are ways of achieving similar capabilities Within Oracle a procedure within a package can be accessed through grammar such as package_nameprocedure_name If you create an owner or schema name within the Informix system the same as the package name then it will be easier to migrate calls to that procedure because the grammar is effectively the same although the meaning changes somewhat Using this practice a call to a migrated procedure would be ownerprocedure_name where the owner name is the same as the package name Translating package names as owner names is a way to maintain the scoping of the objects within the package Maintaining the aspect of being able to enable use of or upgrade the collection of package objects can be done by creating a datablade that contains all the objects that used to be part of the package Datablade routines can be procedures or functions written in Stored Procedure Language (SPL) C and Java In addition routines can be written in C++ on Windows platforms

Routines

Oraclersquos stored functions and stored procedures are similar in concept to Informixrsquos stored procedures Oraclersquos user defined database level functions such as stored functions stored procedures all need to be converted to Informix stored procedures using the Informix SPL C or Java Routines written in SPL have the advantage of being maintained and backed up with database backups Routines written in C are fast but are not automatically backed up when the database is and need to be compiled specifically for the operating system on which it will run Routines written in Java also not backed up by the DBMS itself but they are platform independent However probably as a result of having to convert between system memory where the objects have C structures and Java virtual machine memory where the objects have Java structures the performance of Java routines can be slow compared with the C equivalent All procedures written in an Oracle package body must be rewritten as separate Informix procedures When rewriting package bodies into separate procedures Oraclersquos variable declarations can be replaced at the package level (global) with Informixrsquos global variables The Informix global variables must be defined in the first stored procedure of the logical group

Exceptions

The method of handling exceptions is different between Informix and Oracle Oracle has many predefined and user defined exception labels such as CURSOR_ALREADY_OPEN NO_DATA_FOUND ZERO_DIVIDE and so on The labels can be used in the logic to identify errors Only one exception check is allowed per BEGIN and END block using the EXCEPTION construct and it is normally placed just before the END statement Informix also supports predefined and user defined exceptions however they are represented numerically not with labels In Informix all the exceptions checked in the stored procedure control blocks delimited with BEGIN and END statements must be declared explicitly at the top of each

IBM Software Group IBM Information Management

Version 16 52

control block with the Informix EXCEPTION construct Therefore Oracle procedure code must be restructured to manipulate these exceptions In Oracle an exception can be raised globally and acted upon globally In Informix the scope of an exception mechanism is always restricted to the block in which it is located This leads to the addition of multiple Informix exception handling mechanisms for each Oracle exception raised as well as a redesign of the overall stored procedure to a more blocked format

Error handling

In Oracle errors are processed as part of a function call return value In Informix errors are retrieved as a separate function call that has multiple structures that have to be created in order to retrieve error and status The SQLCA structure is not fully available in Informix stored procedures It is not possible to check the SQLCODE variable in the stored procedure body Instead the function DBINFO can be used to extract the value of two members of the SQLCA structure sqlcasqlerrd1 and sqlcasqlerrd2 This function should be used inside the FOREACH construct while the cursor is open Once the cursor is closed the DBINFO function cannot return proper values The sqlcasqlerrd1 option returns different values depending on the type of SQL statement For INSERT statements if the table contains a serial column then the sqlcasqlerrd1 option will return the serial value of the last row inserted into the table For SELECT DELETE and UPDATE statements the sqlcasqlerrd1 option will return the number of rows processed by the query In these cases upon each pass through the FOREACH loop sqlcasqlerrd1 is the same value the number of rows the FOREACH loop will process The sqlcasqlerrd1 value can still be interrogated during each pass through the FOREACH loop The sqlcasqlerrd2 option returns the number of rows processed by a SELECT INSERT UPDATE DELETE or EXECUTE PROCEDURE statement It should not be interrogated until after the cursor has finished processing In other words within the FOREACH loop the sqlcasqlerrd2 value can be moved to a variable which is then interrogated outside of the FOREACH loop

Cursors

Unlike Informix in Oracle cursors can be global to a package In Informix Oraclersquos global cursors can be replaced with temporary tables A temporary table can be created and populated in place of where the cursor is opened The temporary table can then be processed the same way the cursor is processed Finally the temporary table should be dropped in place of where the cursor is closed Cursors are explicitly declared opened and fetched in Oracle stored procedures In Informix cursors do not need to be explicitly declared opened and fetched in stored procedures Instead Oracle stored procedure cursors can be replaced with Informixrsquos FOREACH construct The Oracle cursor name should be used in the FOREACH statement for example FOREACH cursor_name SELECT hellip END FOREACH In order to update a cursor row in Oracle the cursor must be declared with the FOR UPDATE clause In Informix if the SELECT statement in the FOREACH construct is not a multi-table join then each fetched row can be updated using the UPDATE lttable_namegt WHERE CURRENT OF ltcursor_namegt statement See the Update Using Cursors section in ldquoData Manipulation Languagerdquo for more information Informix does not support the SELECT FOR UPDATE statement in a stored procedure Therefore the SELECT FOR UPDATE clause cannot be used in the FOREACH construct

IBM Software Group IBM Information Management

Version 16 53

Variable declaration and assignment

Oracle allows implicit variable definitions within a FOR loop The variables are defined using an assignment operator and a column name For example

out_customer_name = customername

The variable out_customer_name is defined as the same type as the column name in the customer table Informix requires that all variables be defined at the beginning of each stored procedure control block For example

DEFINE out_customer_name LIKE customername

DEFINE counter INTEGER

Therefore Oraclersquos implicit variable declaration must be replaced with Informixrsquos explicit variable declaration before the control block Additionally assignment operations will need to be ported Oracle uses a colon and an equal sign (=) for assignment while Informix utilizes the LET keyword in combination with an equal sign (=) (ie LET var = 1) Therefore assignment statements must be modified with the LET keyword and an equal sign

Boolean

Oraclersquos BOOLEAN variable type can be replaced with Informixrsquos BOOLEAN data type

Binary data types

Binary data types are very different between Oracle and Informix In Oracle the binary type is defined as a type RAW and is explicitly defined with a maximum length as part of the declaration In Informix the binary type is defined as REFERENCES BYTE which deals only with pointers to BLOBs It implicitly defines a maximum length as part of the function call in which the pointer to the BLOB and maximum length (as used in the function call) was passed as values As a result the binary type cannot be assigned a binary value in a stored procedure nor can it be inserted into a table via the SQL INSERT statement in a stored procedure These operations that initialize a binary type must be performed outside of stored procedures

Dynamic SQL

Unlike Oracle Informix does not support dynamic SQL within the Stored Procedure Language In other words a statement such as SELECT variable_name FROM variable_name WHERE variable_name is not supported This kind of processing can be achieved in Informix within an embedded SQL program This requires that either the Oracle stored procedure be converted to an embedded SQL program or just the Dynamic SQL portion be placed in an embedded SQL program and then called from within the stored procedure The latter option will have performance implications since calling an embedded SQL program from a stored procedure requires an operating system call Another option is to use the Informix EXEC Bladelet The EXEC Bladelet consists of user-defined functions that take a SQL query as an argument execute it and return a result (the format of which varies depending on the function and the kind of query) The EXEC Bladelet functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries Further details can be found in Chapter 7 Using Bladelets

Compiler

Unlike Oracle the Informix compiler was developed with the concept that developers can create stored procedures independently of the database Therefore Informixrsquos stored procedure

IBM Software Group IBM Information Management

Version 16 54

compiler has a limited set of errors that it checks compared to Oraclersquos For example the Informix stored procedure compiler does not validate database object names such as table column and view names Therefore database object naming errors will occur at runtime not compile time Additionally the error messages generated from the compiler are not very specific Identifying a problem in a stored procedure may require breaking it apart and recompiling the pieces until the problem is found This may impact the time necessary to unit test the stored procedures

Triggers Oracle supports the use of multiple trigger events for example insert update and delete within the same trigger Informix only supports one trigger event per trigger In Informix the Oracle trigger body in this example must be copied into three different triggers each with only one event Informix triggers have some constraints Oraclersquos do not In Informix if a trigger is fired due to inserting a row into a table a trigger can only act on any rows or columns within that table using the EXECUTE PROCEDURE hellip INTO syntax Similarly if a trigger is fired due to updating a row then the trigger can only act on the column that caused the trigger to fire using the EXECUTE PROCEDURE hellip INTO syntax Like Oracle if a trigger is fired due to deleting a row there are no restrictions Prior to IDS 73 when a trigger was fired on an INSERTUPDATE action no modification could be done to the columns (in the row) which just fired the trigger The reentrant UPDATEINSERT triggers feature introduced with IDS 1110 enables users to update the triggering columns by using the EXECUTE PROCEDURE INTO syntax Additionally the feature enforce that this action will not cause any additional triggers to be fired (same or different trigger) causing a cascading of triggers and potentially an infinite loop The following example demonstrates how the reentrant UPDATEINSERT trigger feature is used

create table foo

(

x int default NULL

y int default NULL

z int default NULL

)

create procedure reentrant()

returning int

return 56

end procedure

create trigger reentrant_trigger insert on foo for each row

(

execute procedure reentrant() into z

)

insert into foo values

(

1

2

3

)

The following SELECT will result in the following returned data

select from foo

x y z

1 2 56

IBM Software Group IBM Information Management

Version 16 55

Oracle allows SQL statements logical statements and stored procedure calls within a trigger body Informix allows only SQL statements and stored procedure calls within a trigger body Oracle triggers containing logical statements must be converted to Informix by moving their contents into a stored procedure The stored procedure should then be executed from the trigger

Constraints Constraints in both Oracle and Informix can be enabled and disabled within an application transaction however there are behavioral differences In Oracle the application is always executing within a transaction In Informix transaction boundaries are explicitly declared and care should be taken to ensure that this functionality is performed within the boundaries of a transaction See the Transaction Processing section in CHAPTER 5 Application Architecture for more information The constraint syntax available in Informix is

SET CONSTRAINTSINDEXESTRIGGERS FOR table_name

ENABLED|DISABLED

SET CONSTRAINTS comma_separated_constraint_names

ENABLED|DISABLED

SET INDEXES comma_separated_index_names ENABLED|DISABLED

SET TRIGGERS comma_triggers_constraint_names ENABLED|DISABLED

SET CONSTRAINTS ALLconstraint_name IMMEDIATE|DEFERRED

The first four statements must be executed with DBA privileges if placed in the application Therefore care should be taken when using them Note that the last statement contains a DEFERRED clause This is the statement used if the users of the application do not have DBA privileges When the constraint is set with the DEFERRED clause the specified constraints are not checked until the transaction is committed If a constraint violation occurs while the transaction is being committed the transaction is rolled back

DUAL table Oraclersquos DUAL table is a system table with only one row containing one column named DUMMY This table is used to complete the syntax of an SQL statement that does not involve an existing table such as

A SELECT statement which assigns some constant value (which can only be derived in an SQL statement) to a host variable

SELECT TO_CHAR(SYSDATE) INTO date_var FROM DUAL

A SELECT statement which assigns a value of another variable to a variable

SELECT source_var INTO dest_var FROM DUAL

A SELECT statement which unions application host variable values with another SELECT statement to return a result containing a row of application variable values

SELECT col1 col2 col3 FROM table_name

UNION

SELECT host_var1 host_var2 host_var3 FROM DUAL

Converting Oraclersquos DUAL table functionality to Informix depends on the way it is used Converting statements that just assign constants is as simple as replacing the DUAL statement with an Informix assignment statement The solutions below apply to Informix versions prior to 11 At 11 and above the concept of a DUAL table as well as sysdate is supported

IBM Software Group IBM Information Management

Version 16 56

SELECT sysdate FROM sysmastersysdual

If you want a dual table in your local database then create the following synonym The sysmastersysdual table is much faster than a physical table in your database because it is an in- memory pseudo table

CREATE SYNONYM dual FOR sysmastersysdual

If you are restricted to using a version of Informix prior to 11 then the following solutions can be used A dummy table can be created to mimic the behavior of simple SELECT INTO statements used to assign values to variables

CREATE TABLE dual (dummy VARCHAR(1))

INSERT INTO dual VALUES(lsquoXrsquo)

An alternate solution to widespread use of the DUAL table could be creating a permanent view that is generally accessible

CREATE VIEW dual (d) as SELECT X

FROM systables WHERE tabid = 1

The exact definition could be used or modified as needed but this would solve the problem of having DUAL be permanent usable by anyone and not modifiable

IBM Software Group IBM Information Management

Version 16 57

C H A P T E R 5 Embedded SQL

Oraclersquos embedded SQL products are ProC and ProCOBOL Informixrsquos corresponding embedded SQL products are ESQLC and ESQLCOBOL

Host variables

Declaration override

The Oracle EXEC SQL VAR declarative statement (host variable equivalency of Oracle external data types by overriding the default assignment) can be converted to an Informix explicit declaration statement For example

Oracle char char_var[20]

EXEC SQL VAR char_var IS STRING(11)

Informix

char char_var[11]

Note that the size and type used in the EXEC SQL VAR section is the final information required to declare the host variable in Informix

Arrays

Oracle arrays are not subscripted in SQL statements since it is not required to process the host arrays in a loop in the SQL statement In Informix subscripting is mandatory In Oracle if an array is defined of size 200 then an SQL statement would be

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A

VAR-B

VAR-C

END-EXEC

-or- EXEC SQL SELECT COL1 COL2 COL3

INTO VAR-A

VAR-B

VAR-C

FROM TABLE1

WHERE COL2 gt 100

END-EXEC

where VAR-A VAR-B and VAR-C are each an array of say 200

IBM Software Group IBM Information Management

Version 16 58

In Informix the first example would be converted to

PERFORM VARYING LOOP-CTR FROM 1 BY 1 UNTIL

LOOP-CTR IS GREATER THAN 200

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A(LOOP-CTR)

VAR-B(LOOP-CTR)

VAR-C(LOOP-CTR)

END-EXEC

IF SQLCODE = 100

GO TO EXIT-PERFORM

END-IF

END-PERFORM

EXIT-PERFORM

For the second Oracle example given above a cursor must be declared in Informix opened and fetched for 200 rows or less (less because there may be less than 200 qualifying rows) into the host array and then should be closed If the number of qualifying rows is more than 200 then the extra rows must be ignored to duplicate the Oracle functionality But for the first example each fetch in Oracle will return the next 200 or less number of rows Therefore each Oracle fetch needs to be replaced by another call to the Informix fetch loop Oracle also uses this method for inserts deletes and updates These array techniques are mainly used in batch SQL processing

Formatting

In Informix when a DECIMAL MONEY DATE or DATETIME value is selected into a host variable of the same data type the value must be formatted using the available Informix formatting routines before they can be printed or displayed For example

hellip

dec_t dec_host_var

char formatted_dec[40]

EXEC SQL SELECT DEC_COLUMN INTO dec_host_var FROM TABLE_NAME

rfmtdec(ampdec_host_var ldquoampampampampampampampampampamprdquo formatted_dec)

printf(ldquoThe Decimal Value is snrdquo formatted_dec)

hellip

IBM Software Group IBM Information Management

Version 16 59

Informix supplies many formatting functions and formatting strings The names of these functions are different in Informix ESQLC and ESQLCOBOL but the functionality is the same Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

SQL structures

SQLCA

Oraclersquos SQLCA structure is different from that of Informix However the components of both structures are logically the same Oraclersquos SQLCA components can be replaced with the corresponding Informix components Oraclersquos SQLCA structure

SQLCAID string containing ldquoSQLCArdquo SQLCABC length of SQLCA data structure SQLCODE Oracle error message code SQLERRM sub-record for error message

SQLERRML length of error message SQLERRMC text of error message SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) reserved for future use SQLERRD(1) reserved for future use SQLERRD(2) number of rows processed SQLERRD(3) reserved for future use SQLERRD(4) parse error offset SQLERRD(5) reserved for future use

SQLWARN array of eight warning flags SQLWARN(0) another warning flag set SQLWARN(1) character string truncated SQLWARN(2) no longer in use SQLWARN(3) SELECT list not equal to INTO list SQLWARN(4) DELETE or UPDATE without WHERE clause SQLWARN(5) reserved for future use SQLWARN(6) no longer in use SQLWARN(7) no longer in use

SQLTEXT reserved for future use

IBM Software Group IBM Information Management

Version 16 60

Informixrsquos SQLCA structure

SQLCODE Informix error code SQLERRM error message parameter SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) estimated number of rows returned SQLERRD(1) serial value of INSERT or ISAM error code SQLERRD(2) number of rows processed SQLERRD(3) estimated cost SQLERRD(4) parse error offset SQLERRD(5) ROWID after INSERT

SQLWARN structure of eight warning flags SQLWARN0 another warning flag set SQLWARN1 character string truncated or no privileges revoked SQLWARN2 NULL value returned or ANSI database SQLWARN3 SELECT list not equal to INTO list or turbo back-end SQLWARN4 DELETE or UPDATE without WHERE clause SQLWARN5 if non-ANSI statement SQLWARN6 if server is in data replication secondary mode SQLWARN7 reserved

In order to get Oracle error messages an application normally uses the SQLCA element SQLERRMC The Informix equivalent is SQLERRM On the HPUX and Solaris platforms the Informix function rgetmsg should be used instead of the element SQLERRM At the time of this writing using SQLERRM would cause an error on the HPUX and Solaris platforms

SQLDA

The implementation of Oraclersquos SQLDA structure is very different from that of Informix Significant changes are necessary to convert Oraclersquos functionality to Informix Oraclersquos sqlald function can be replaced with Informixrsquos ALLOCATE DESCRIPTOR statement Since Oraclersquos and Informixrsquos SQLDA structures are so different Oraclersquos SQLDA logic must be rewritten with the more powerful Informix SQLDA logic or alternatively the Informix system-descriptor area logic Oraclersquos SQLDA Structure

N maximum number of SELECT list items or placeholders V pointer to array of address of SELECT list items or bind variables L pointer to array of lengths of SELECT list items or bind variables T pointer to array of data types of SELECT list items or bind variables I pointer to array of addresses of indicator variable values F actual number of SELECT list items or placeholders S pointer to array of addresses of SELECT list items or placeholder names M pointer to array of max lengths of SELECT list items or placeholder names C pointer to array of current lengths of SELECT list items or placeholder names X pointer to array of addresses of indicator variable names Y pointer to array of maximum lengths of indicator variable names Z pointer to array of current lengths of indicator variable names

IBM Software Group IBM Information Management

Version 16 61

Informixrsquos SQLDA Structure SQLD count of the following SQLVAR members SQLVAR pointer to array of structures

SQLDATA pointer to actual data SQLTYPE data type of placeholder or SELECT item SQLLEN length of the placeholder or SELECT item SQLIND pointer to the indicator SQLNAME pointer to placeholder or SELECT item name SQLFORMAT reserved SQLIDATA indicator data pointer SQLITYPE indicator variable type SQLILEN length of indicator variable

If an Oracle application uses the simple dynamic SQL method using macros only not the SQLDA structure directly the value indicatorsplaceholders can be replaced with a lsquorsquo in Informix For example Oracle sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES (v1 v2)rdquo) Informix sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES ( )rdquo)

ORACA

Oraclersquos ORACA structure is not supported by Informix This structure is used to handle Oracle specific communication and more runtime information than SQLCA Oracle statements containing references to this structure should be removed from the application

Pre-compiler options The Oracle options beginning with the EXEC ORACLE OPTION statement can be removed from the application The options set after this statement do not affect the application logic They may affect some application performance only

Embedded PLSQL Oracle allows procedure language (PLSQL) blocks inside ProC and ProCOBOL code delimited by the EXEC SQL EXECUTE and END-EXEC statements In Informix these blocks must be replaced with the equivalent ESQLC or ESQLCOBOL code

Oracle Call Interface Oracle call interface (OCI) is the base layer for a variety of other application programming interfaces such as JDBC-OCI Oracle Precompilers and Oracle ODBC It is also used directly by customers who are willing to develop their code using a lower level proprietary API From a high level it can be thought of as if IBM Informix had standardized and published the function calls in the ESQLC library Although some customers have reverse engineered these calls and developed applications using them this is generally discouraged because there is no guarantee that the library of calls will not change There is no direct equivalent to this Oracle API in Informix Migrating applications written using Oracle Call Interface (OCI) will require rewriting the code from scratch OCI is native to the C language and so it should be less effort to migrate the application to an Informix API that is also native to C This could be ESQLC or CLI The following information explains differences between Oracle OCI and Informix ODBC

IBM Software Group IBM Information Management

Version 16 62

The following table is an approximate mapping of the differences between the Informix CLI and Oracle OCI function calls in which there is not a direct one-to-one mapping

Oracle Informix Buffer Areas HAD LDA CDA HENV HDBC HSTMT

Connect and allocate resources

OLOG OOPEN SQLConnect SQLAllocEnv SQLAllocConnect SQLAllocStmt

Update delete insert select OPARSE OBNDRV OEXEC SQLPrepare SQLBindParameter SQLExecute

Select ODEFIN OFETCH SQLBindCol SQLFetch

Commit Rollback OCOM OROL SQLTransact

Disconnect OLOGOF OCLOSE SQLDisconnect SQLFreeStmt SQLFreeConnect SQLFreeEnv

Database library calls

One of the first main differences between Informix CLI and Oracle OCI calls is the overall data structures and mechanisms used to process database library calls Oracle uses direct connections to the database server Informix uses an ODBC connection to the database server As a result the Informix calls will be implemented as ODBC SQL calls utilizing three tiers of increasing SQL levels of complexity

Global area processing

Another main difference between Informix CLI and Oracle OCI is Informixrsquos use of pointers to three global areas versus Oraclersquos use of pointers to three different but similar global areas Hence the Oracle OCI calls that utilize HAD (Handle Data Area) LDA (Logon Data Area) and CDA (Cursor Data Area) pointers must be translated over to Informix CLI calls that utilize HENV (Environment Area) HDBC (Database Connection Area) and HSTMT (Statement Area) pointers respectively in conjunction with an ODBC interface

Fetch cycle

Another difference between Informix CLI and Oracle OCI calls is that the overall fetch cycle is different for each and must be modified accordingly In Oracle the fetch cycle for selecting multiple rows utilizing a cursor area involves parsing binding defining fetching and then executing into a cursor data area These must be translated to a cycle that involves preparing binding executing binding and then fetching via the ldquoFor Eachrdquo cycle

RAW binary data type processing

RAW binary data types in Oracle will need to be translated to a pointer-to-BLOB REFERENCES BYTE type in Informix See the Binary Data Types subsection of the Stored Procedures section in CHAPTER 3

Parameter bindings

In Oracle multiple output bindings of parameters are declared as type ldquoOUTPUTrdquo in the ODEFIN() calls In Informix convert the calls to Informix SQLBindCol() calls and bind the output parameters as columns Differences also exist between Informix CLI and Oracle OCI in the use of inputoutput bindings In Oracle these bindings are declared as type ldquoINPUTOUTPUTrdquo in the ODEFIN() calls In Informix a ldquoround robinrdquo approach is used using three variables in the following manner A=B B=C C=A A variable (A) is declared before the SQL bindings as an input variable The function is called

IBM Software Group IBM Information Management

Version 16 63

using a second input variable (B) that is set to the first input variable (A) The function returns a third variable (C) that is bound as an output column Finally the first variable (A) is now set to the returned third variable (C) that made the first variable (A) appear as an ldquoinputoutputrdquo variable to the rest of the program

Embedded SQL for C

VARCHAR

Oraclersquos ProC VARCHAR data type is expanded after pre-compiling into a structure with two elements one is unsigned short len and the other is unsigned char arr[size] The name of the expanded structure is the same name as the VARCHAR variable and size is replaced with the size of the VARCHAR variable In Informix the VARCHAR data type is just a synonym for the C languagersquos char data type Therefore statements that use variable_namelen can be removed from the application and all occurrences of variable_namearr can be replaced with variable_name For example

Oracle VARCHAR vName[40]

strcpy(vNamearr ldquoCompany Namerdquo)

vNamelen = strlen(vNamearr)

Informix VARCHAR vName[40]

strcpy(vName ldquoCompany Namerdquo)

Host variables

The Oracle statement EXEC SQL TYPE is synonymous with the C languagersquos typedef declarative instruction It can be easily replaced with the Informix declarative instruction typedef

Embedded SQL for COBOL

VARCHAR

Oraclersquos ProCOBOL character host variable declaration statementrsquos VARYING clause is expanded after pre-compiling into a group with two elements one is variable-name-LEN PIC S9(4) COMP and the other is variable-name-ARR PIC X(size) The group name is the same as the host variable name and size is replaced with the size of the VARYING variable Informix does not support this concept Therefore statements that use variable-name-LEN must be removed from the application and all occurrences of variable-name-ARR must be replaced with variable-name Also the VARYING clause must be removed from the declarative statement For example

Oracle

05 vName PIC X(40) VARYING

hellip

MOVE ldquoCompany Namerdquo TO vName-ARR

MOVE 12 TO vName-LEN

Informix

05 vName PIC X(40)

hellip

MOVE ldquoCompany Namerdquo TO vName

IBM Software Group IBM Information Management

Version 16 64

Level 88

COBOLrsquos level 88 functionality is not supported within an Informix ESQLCOBOL host variable declaration section in versions prior to 72 Level 88 functionality is supported in Informix ESQLCOBOL 72

SQLDA

In Informix ESQLCOBOL the SQLDA structure is not available The Informix macros such as ALLOCATE DESCRIPTOR DESCRIBE GET DESCRIPTOR and SET DESCRIPTOR must be used to retrieve and manipulate the SQLDA data

REDEFINES

Oracle supports the use of the REDEFINES clause at the elementary level in the host variable declaration section In other words the redefined item cannot be a group item but the redefining item may be a group item Informix does not support the use of the REDEFINES clause in the host variable declaration section in versions prior to 72 The REDEFINES clause is supported in Informix ESQLCOBOL 72

Tips

If the Informix pre-compiler finds an SQL statement within an IF [ELSE IF hellip ] END-IF or EVALUATE END-EVALUATE or PERFORM END-PERFORM block then the pre-compiler adds a period after the generated COBOL statements regardless of whether there is a period at the end of the SQL statement This is a violation of COBOL rules for such blocks and the code may cause syntax errors during compilation or may behave unexpectedly To avoid these problems each SQL statement group should be moved to a new paragraph and these paragraphs should be performed from the block from which they were moved

ODBC Although the Open Database Connectivity (ODBC) API is designed to make it possible to write and compile an application once and use it with any ODBC driver on the same platform there are frequently differences between the underlying DBMSs that can expose problems to the applications For instance there can be differences between how unspecified parts of a date-time value are filled Most of these kinds of differences that get exposed through ODBC have their origins in the differences between the DBMSs themselves There are also cases where there are gaps in the ODBC standard for example there is a standard ODBC call that allows the application to ask the driver if it can support scrollable cursors and there is another call to ask if it can support updateable cursors There is no call to ask if it can support both at the same time With Informix you can have a scrollable cursor and you can have an updateable cursor but you can not have one cursor that is both scrollable and updateable A more complete description of ODBC application migration issues is beyond the scope of this article

IBM Software Group IBM Information Management

Version 16 65

C H A P T E R 6 Application Architecture

Transaction processing Transaction boundaries are defined differently in Oracle and Informix Oraclersquos transactions begin implicitly in one of two ways either by issuing a CONNECT statement or issuing a COMMIT or ROLLBACK statement A CONNECT statement marks the beginning of a transaction and a COMMIT or ROLLBACK statement commits or rolls back the previous transaction respectively and then implicitly begins a new transaction CONNECT statements are usually issued once at the beginning of a program however they may be nested or issued more than once serially to connect to the same or a different database When using more than one CONNECT statement within a program each CONNECT statement must be named This marks the beginning of named transactions Every SQL statement within a named transaction must also be named with the same transaction name as the CONNECT statement at where the SQL is to be executed SQL is named using the EXEC SQL statementrsquos AT clause Informixrsquos transaction boundaries are explicitly marked with the reserved words BEGIN WORK and COMMIT WORK or ROLLBACK WORK Note that once a transaction has begun for a given connection it stays open until a COMMIT or ROLLBACK is executed In other words if an ESQL program begins a transaction and then calls a stored procedure the stored procedure executes within the same transaction If the stored procedure issues a COMMIT then the whole transaction is committed and the calling ESQL program should not issue a COMMIT or ROLLBACK Informix transactions can be written to behave the same way as Oraclersquos To simulate Oraclersquos CONNECT statement behavior an Informix CONNECT should also be issued followed by a BEGIN WORK statement If more than one CONNECT statement is used in a program Informix also requires that the CONNECT and SQL statements be named To simulate Oraclersquos COMMIT and ROLLBACK statement behavior an Informix COMMIT WORK or ROLLBACK WORK statement should be issued followed by a BEGIN WORK statement Nested transactions can be simulated in Informix with the CONNECT statement and naming the transactions Then the Informix SET CONNECTION connection_name statement can be used to switch between transactions Committing or rolling back each named transaction does not commit or roll back other active transactions The Oracle statement EXEC SQL COMMITROLLBACK RELEASE should be replaced with the Informix statements EXEC SQL COMMITROLLBACK [WORK] followed by EXEC SQL DISCONNECT CURRENT In the following examples ws-dbenviron is the database name ws-connect-nm is the user name and ws-identity-nm is the password set in the program enp and connection-name are the connection names For Informix the user name and password information should correspond to the entries in the etcpasswd file on the UNIX system See the User Authentication section later in this chapter for more information The default server name is automatically obtained from the environment variable INFORMIXSERVER The following examples illustrate how Oracle and Informix implement the CONNECT functionality

IBM Software Group IBM Information Management

Version 16 66

Simple Connect

Oracle

CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm

Informix

CONNECT ws-dbenviron USER ws-connect-nm USING ws-identity-nm

Named Connect with Literal

Oracle

DECLARE enp DATABASE hellip CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm AT enp USING ws-dbenviron hellip AT enp SELECT col1 col2 INTO var1 var2

FROM table_name

Informix

CONNECT TO ws-dbenviron AS ldquoenprdquo USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION ldquoenprdquo hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Named Connect with Variable

Oracle

CONNECT ws-connect-nm

IDENTIFIED BY ws-identity-nm AT connection-name USING ws-dbenviron hellip AT connection-name SELECT col1 col2 INTO var1 var2 FROM table_name

Informix

CONNECT TO ws-dbenviron AS connection-name USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION connection-name hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Autonomous Transaction

An autonomous transaction is an independent transaction that is initiated by another transaction (the parent transaction) An autonomous transaction can modify data and commit or rollback independent of the state of the parent transaction The autonomous transaction must commit or roll back before the autonomous transaction is ended and the parent transaction continues

IBM Software Group IBM Information Management

Version 16 67

An autonomous transactions has been available since the release of Oracle 8i An autonomous transaction is defined in the declaration of a PLSQL block This can be an anonymous block function procedure object method or triggerThis is done by adding the statement PRAGMA AUTONOMOUS_TRANSACTION anywhere in the declaration block There isnt much involved in defining a PLSQL block as an autonomous transaction You simply include the following statement in your declaration section PRAGMA AUTONOMOUS_TRANSACTION Sample code

PROCEDURE test_autonomous

IS

PRAGMA AUTONOMOUS_TRANSACTION

BEGIN

insert

commit

END test_autonomous

Autonomous transactions can be used for logging in the database independent of the rollbackcommit of the parent transaction

Savepoints

Oracle allows savepoints within its PLSQL For example a PLSQL block can be structured so that SAVEPOINT A is issued upon entry and SAVEPOINT B is issued after some processing Then after some more processing a COMMIT or ROLLBACK can be issued against all the logic since the last COMMIT point which is before the PLSQL block or up to any of the savepoints by naming the COMMIT or ROLLBACK with the savepoint name In other words a savepoint can be issued at the beginning of a stored procedure and then only the stored procedure logic can be committed without committing the changes pending before the stored procedure was executed Those changes can be committed or rolled back once processing is returned from the stored procedure Informix does not support savepoint processing within a stored procedure

Concurrency Database concurrency can be managed through the combination of two configurable settings one specifies the lock granularity on database objects while the other influences how the application behaves in regards to the presence and placement of locks using a transaction isolation level

Row Level Locking

Oracle and Informix implement locking differently on database objects Oracle defaults to row level locking whereas Informix defaults to page level In most cases row level locking is preferred to improve concurrency Informix supports row level locking however it must be either explicitly requested specified by an environment variable or permanently changed in the instancersquos configuration Having three methods for establishing the lock level there is an order of precedence

1 To be explicitly requested the CREATE TABLE statement must include the specification of the LOCK MODE attribute

CREATE TABLE emp (

name CHAR(40)

salary MONEY

ssn LVARCHAR(64)

) LOCK MODE ROW

IBM Software Group IBM Information Management

Version 16 68

2 The environment variable IFX_DEF_TABLE_LOCKMODE will establish the default for CREATE TABLE statements issued without the LOCK MODE attribute and will override the Instancersquos configuration setting The variable setting on the client will override the server environment setting

set IFX_DEF_TABLE_LOCKMODE=ROW -or- export IFX_DEF_TABLE_LOCKMODE=ROW

3 Informix allows the instancersquos lock level default to be changed using a configuration parameter Row level locking can be as the default by adding the parameter DEF_TABLE_LOCKMODE to the instancersquos ONCONFIG file This parameter may not be found in the existing file and if not present can be added using an editor and establish a new default setting of ROW

DEF_TABLE_LOCKMODE ROW

None of the steps will apply a change to existing tables only establish the lock level for the CREATE TABLE statement

Transaction Isolation Level

Oracle databases incorporate a feature known as ldquoread consistencyrdquo which allows a query return a result based on the state of the data when the query started regardless of other processes updating or deleting the same data while the query is running Informix facilitates this type of behavior differently by providing control of the applicationrsquos placement of locks as well as how it reacts to those placed by other processes through the use of the transactionrsquos isolation level If Oraclersquos technique of ldquoreaders not blocking writersrdquo is a requirement then in many circumstance Informixrsquos DIRTY READ isolation level can be used The readers will not block the writers with dirty read processing however the query result may contain updates performed while the query was running which may be uncommitted If the emulation of Oraclersquos ldquoread consistencyrdquo is desired the LAST COMMITTED option of Informixrsquos COMMITTED READ isolation level can reduce the risk of locking conflicts when two or more sessions attempt to access the same row in a table whose locking granularity is row-level When an application attempts to read a row on which another session holds an exclusive lock these keywords instruct the database server to return the most recently committed version of the row rather than wait for the lock to be released This isolation level attribute could be preferable to executing queries using DIRTY READ since it will return only the most recently committed versions of the data The LAST COMMITTED option can be enabled in the following ways

1 Setting the USELASTCOMMITTED parameter in the Instancersquos configuration (ONCONFIG) will apply this feature as the default isolation level to all database transactions The parameterlsquos values will designate the scope of applying the LAST COMMITED option to either ALL NONE or only COMMITED READ and DIRTY READ isolation levels

USELASTCOMMITTED [ALL | NONE | COMMITTED READ | DIRTY READ]

2 The SET ENVIRONMENT statement can override the USELASTCOMMITTED configuration parameter setting for the duration of the current session The same semantics apply as the parameter within the ONCONFIG file with the setting value enclosed in quotes (lsquo)

SET ENVIRONMENT USELASTCOMMITTED lsquoALLrsquo

IBM Software Group IBM Information Management

Version 16 69

3 The SET ISOLATION statement can be used to override the instance configuration and session environment setting The SET ISOLATION statement is an Informix extension to the ANSI SQL-92 standard and provides the same functionality as the ISOANSI-compliant SET TRANSACTION statement There is no support for the LAST COMMITTED option with the SET TRANSACTION statement SET TRANSACTION complies with ANSI SQL-92 and only ANSI supported isolation levels are supported

SET ISOLATION TO COMMITTED READ LAST COMMITTED

4 PREPARE statements in ODBCJDBC applications

This feature is primarily documented in the Guide to SQL Syntax Guide to SQL Reference Administrators Reference and Administrators Guide

IBM Software Group IBM Information Management

Version 16 70

C H A P T E R 7 Security

User authentication In Oracle security information is stored in the database Up until recently Informix has used only the operating system security subsystem to check security For security purposes Oracle connects to the server and passes the user ID and password information to the database for verification

Operating system security

Informix does not store user ID and password information in the database Instead they are validated against the operating systemrsquos security mechanism on the server for example the etcpasswd file in UNIX Therefore either every database user must have an entry in the serverrsquos password file or the application must handle a level of security where user IDs are converted into a group id based on database permissions and only those group IDs are entered into the password file Note that if the second alternative is chosen then auditing capabilities based on user ID are lost Also if the application performs security functions then those functions are not applicable to third party applications such as report writers application development tools and so on when they access the database The home directory of all the users should point to the same physical directory where the application executable resides The Informix method of using the operating system for security checking allows external programs to be called from within stored procedures This capability is not allowed in Oracle In Oracle the OPS$User_name is sometimes used to connect to the database where OPS$User_name is a valid Oracle user and User_name is a valid operating system level user In this case the connection is made to the database using just the lsquorsquo character without the user id and password Informixrsquos technique of using the etcpasswd file for security works fine for this type of connection

Non-operating system security

In previous releases each user who needed to access the database server also needed an operating system account on the host computer Now you can configure Informix so that users who are authenticated by an external authentication service (such as Kerberos or Microsoft Active Directory) can connect to Informix The new USERMAPPING configuration parameter specifies whether or not such users can access the database server and whether any of those users can have administrative privileges When Informix is configured to allow user mapping you can still control which externally authenticated users are allowed to connect to Informix and their privileges Please refer to the IBM Informix documentation on connection security for more information

IBM Software Group IBM Information Management

Version 16 71

Informix supports for the pluggable authentication module (PAM) framework which lets an administrator customize authentication for individual applications and permits column-level encryption

Role based authority Role based authority can help you manage your database permissions As of version 1110 you can create a role and assign that as a default role for individual users (or to PUBLIC) A role is a work-task classification such as ldquopayrollrdquo or ldquomanagerrdquo Each defined role has privileges on the database object granted to the role You use the CREATE ROLE statement to define a role and GRANT DEFAULT ROLE to establish the userrsquos initial setting when connecting to the database A userrsquos role can be changed after connecting by using the SET ROLE statement

Column-level encryption You can use column-level encryption to improve the confidentiality of your data IDS Version 1110 has new built-in SQL scalar functions provide methods for data in columns to be stored in an encrypted format Use the ENCRYPT_AES or the ENCRYPT_TDES function to define encrypted data Use the DECRYPT_BINARY() and DECRYPT_CHAR() functions to query encrypted data When using the routines the encryption of data is under application control and the DBMS is not aware that data is encrypted Informixrsquos support of column level encryption is analogous to Oraclersquos DBMS Obfuscation Tool Kit Built-in ENCRYPT functions provide methods for encrypting and decrypting the following character data types or smart large object data types

CHAR

NCHAR

VARCHAR

NVARCHAR

LVARCHAR

BLOB

CLOB

Passwords and hints

Passwords are necessary when using the encryption functions Only users who can provide a secret password can view copy or modify encrypted data The password must be a minimum of 6 bytes and can be a maximum of 128 bytes When you set an encryption password you have the option of specifying a password hint Hints can be up to 32 bytes of text If you specify a hint you can store the hint with the encrypted password or in another location Passwords (and hints) to be used by default can be set for a session using the SET ENCRYPTION PASSWORD statement

SET ENCRYPTION PASSWORD lsquopasswordrsquo [ WITH HINT lsquohint stringrsquo ]

Hence the password and hint parameters can be optional when calling the encryption function Explicit values override the session default values The password or hint can be a single word or several words The hint should be a word or phrase that helps you to remember the password but does not include the password You can subsequently execute the built-in GETHINT function (with an encrypted value as its argument) to return the plain text of hint Calling the GETHINT function with an argument of encrypted data will return the hint (if any) from the encrypted data or an empty string (NULL) is no hint was provided There is no privilege needed anybody can get any hint at any time When you set a password Informix transfers the password and any hint to 128-bit key that is used to encrypt the password and hint Passwords and hints are not stored as plain text any table of the system catalog The key is a time-based random value per instance The database server

IBM Software Group IBM Information Management

Version 16 72

initializes the key when the server starts the key is destroyed when the database server shuts down

Encrypting a column

Column data can be encrypted through the use of two functions ENCRYPT_TDES and ENCRYPT_AES corresponding to the two data encryption standards Triple Data Encryption Standard (Triple-DES) and Advanced Encryption Standard (AES) which describes the cipher algorithm used to protect data from unauthorized viewing AES encryption (also known as Rijndael) uses a 128-bit key size and Triple-DES encryption uses two 56-bit keys for 112-bits overall Both functions are variant functions and will return a different result every time it is used The following example demonstrates how to use the encryption functions with a column that contains a social security number

CREATE TABLE emp (name CHAR (40) salary MONEY ssn LVARCHAR(64))

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890one two

three 123))

-or-

CREATE TABLE emp (name CHAR(40) salary MONEY ssn LVARCHAR(64))

SET ENCRYPTION PASSWORD one two three 123

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890))

Querying an encrypted column

Encrypted data can be translated using Informixrsquos DECRYPT_CHAR and DECRYPT_BINARY scalar functions Encrypted data contains information about the encryption method and all the other data needed to decrypt it except the password The encrypted data value is passed as the first argument and a password as the second unless the SET ENCRYPTION statement has specified for this session with the same session password by which the first argument was encrypted If the data is not encrypted the function call will return an error The DECRYPT_CHAR function is used to invoke a decryption routine on character data types (ie CHAR LVARCHAR NCHAR NVARCHAR and VARCHAR) while the DECRYPT_BINARY function accepts an encrypted large object of type BLOB or CLOB If the first argument to DECRYPT_CHAR or DECRYPT_BINARY is not an encrypted value or if the second argument (or the default password specified by SET ENCRYPTION) is not the password that was used when the first argument was encrypted Informix will issue an error and the call fails If the call to the decryption function is successful it returns the plain text version of the encrypted data argument The following example demonstrates how to use the decrypt function to query encrypted data

SELECT name salary DECRYPT_CHAR(ssn lsquoone two three 123rsquo)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

-or-

SET ENCRYPTION PASSWORD lsquoone two three 123rsquo

SELECT name salary DECRYPT_CHAR(ssn)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

The first argument to DECRYPT_BINARY is expected to be an encrypted value of a large object data type however if it is called with a character data type Informix invokes the DECRYPT_CHAR function and attempts to decrypt the specified value

IBM Software Group IBM Information Management

Version 16 73

Do not use either decryption function to create a functional index on an encrypted column This would store the decrypted values as plain text data in the database defeating the purpose of encryption

Performance impact of encryption

The performance impact of encryption is significant Encryption by its nature will slow down most SQL statements If some care and discretion are used the amount of extra overhead should be minimal Also encrypted data will have a significant impact on your database design In general you want to encrypt a few very sensitive data elements in a schema like social security numbers credit card numbers patient names and so on The effect on performance depends on direction encrypting is slower than decrypting It does not depend measurably on which algorithm is used AES performs at the same speed as Triple-DES It does depend on data size the relative overhead is less when there is more data to encrypt

Storage considerations

An encrypted value uses more storage space than the corresponding plain text value Data encrypted using AES can be bigger than Triple-DES but not by a significant amount This occurs because all of the information needed to decrypt the value except the encryption key is stored with the value Therefore before you set the encryption password and encrypt the data you must be sure the encrypted data can fit in the column A chart of the expected sizes can be found in the IBM Informix Administrator Guide

Compliance regulations

Informixrsquos encryption routines comply with the United Statesrsquo regulations of Health Insurance Portability and Accountability Act (HIPAA) Sarbanes-Oxley Gramm-Leach-Bliley and California Personal Information Privacy (SB 1386) as well as the international requirements of Basel II Also they comply with the latest cryptographic standards (OpenSSL 097c)

IBM Software Group IBM Information Management

Version 16 74

C H A P T E R 8 Environment

Scripts Oracle make files used to build the application should be modified to invoke the appropriate Informix ESQLCOBOL ESQLC MF COBOL and other application language commands The shell scripts shell startup scripts and command files should be modified for Informix compliant statements

SQL script substitution variables

In Oracle a substitution variable is a user variable name preceded by one or two ampersands (amp) When Oracle (SQLPlus) encounters a substitution variable in a command Oracle executes the command as though it contained the value of the substitution variable rather than the variable itself In Oracle the substitution variables can be used anywhere in SQL and SQLPlus commands except as the first word entered at the command prompt When SQLPlus encounters an undefined substitution variable in a command SQLPlus prompts the user for the value SQLPlus reads the responses from the keyboard even if terminal input or output has been redirected to a file If a terminal is not available (if for example the command file is run in batch mode) SQLPlus uses the redirected file Informixrsquos dbaccess does not provide this functionality however a work-around for the redirected file type of substitution is a follows (no user prompting) Create the following shell script (named subvalsksh in this case)

binkshif [[ $ -ne 2 ]]

then

echo nUsage $0 ltdfilegt ltcfilegtn

echo Desc This script accepts two files - dfile the decode

file

echo and cfile the change file It modifies the

change file

echo using the values listed in the decode file

echo The decode file should contain two columns - old

value

echo and new value

echo Ex

echo changethis tothis

echo

echo In this case every occurance of changethis

would be

echo replaced with tothisn

exit 1

fi

IBM Software Group IBM Information Management

Version 16 75

-----------------------

Declare variables

-----------------------

dfile=$1

cfile=$2

awk print s$1$2 $dfile gt $dfile_sed

sed -f $dfile_sed $cfile

The preceding script is used by creating a ldquodecoderdquo file (named decodefile in this case) which holds two columns in the form which may contain multiple rows

oldval newval

Executing the following command

subvalsksh decodefile chgfile

will replace every occurrence of oldval with newval in the file chgfile The shell script (subvalsksh) writes to standard output therefore the output should be redirected The redirected file will then be able to run with dbaccess

Utilities To improve performance the Informix EXPLAIN utility should be used by executing the SET EXPLAIN ON command to see how an SQL statement accesses the database From that point forward the access path for every SQL statement is written in the SQEXPLAINOUT file in the current working directory or the home directory of the process that initiated the request on the host machine The Informix SET EXPLAIN OFF should be executed to turn off this feature when finished The overall system performance should be monitored using the Informix ONSTAT utility

System catalog The following items discuss how Informix implements the system catalog differently than Oracle Each item refers to the Informix implementation only Object names are stored in lower case The system catalog tables are owned by lsquoinformixrsquo To query the systables table use SELECT from lsquoinformixrsquosystables Each table in systables is assigned a tabid by the system It is used as the primary key and therefore the foreign key for the other catalog tables The identifier information is stored in sysindexes Columns part1 - part16 each contain a column component of a composite index They are integers positive for ascending order negative for descending order In syscolumns collength and coltype have special meanings depending on the data type of the column See the Informix Guide to SQL Reference Version for details

IBM Software Group IBM Information Management

Version 16 76

C H A P T E R 9 Using Bladelets

What is a Bladelet

A Bladelet is a small informal Informix Datablade module Its meant to be useful out of the box and is offered complete with source code at no cost -- and no support or warranty In the context of this document the term Datablade refers to an extension to the standard IBM Informix database engine These generally take the form of new data types (for example timeseries or video) andor new routines that execute inside the server The new routines might operate on new data types or on existing ones A Datablade module is usually a formal product available for sale In addition a Datablade is

Developed either by IBM Informix or by a third-party developer

Rigorously tested

Packaged and sold for profit

May or may not be formally certified by IBM Informix as having been developed according to approved Datablade coding practices

In contrast a Bladelet is

Not rigorously tested

Not sold for profit

Not certified by IBM Informix A Bladelet is an extension to the database engine that is narrow in scope and thought to be generally useful being offered at no cost complete with source Just remember before you use any of this code in mission-critical applications its up to you to thoroughly test it and fix any problems you find Please review the disclaimer which applies to any sample code you find on this site httpwwwibmcomdeveloperworksdb2zonesinformixlibrarysamplesdb_downloadshtml Note The bladelets at this link have not been updated for some time (at the time of this writing) some of the capabilities especially simple function call that increase compatibility may have been introduced into the Informix server itself since they were written

Useful Bladelets

Bladelet Description

Exec Defines two user-defined functions that provide dynamic SQL functionality within a SPL procedure

Flat File Access Method A complete access method that lets you build virtual tables based on operating system files

IUtil Implements a collection of other database vendor functions for Informix

IBM Software Group IBM Information Management

Version 16 77

JPEG Image Bladelet Provides a user-defined type for JPEG images that allows you to manipulate images and to extract and search on image properties

Multirepresentational lvarchar Opaque Type

Creates the idn_mrLvarchar opaque type which stores character data up to 2 gigabytes

Node Datablade Module Creates the node opaque type which is intended to solve one of the hardest problems in relational databases transitive closure

Regexp Creates routines that let you manipulate character and clob data using regular expressions

Shapes DataBlade Module Creates several opaque types for managing spatial data including R-tree index support

Smart Blob Information DataBlade Module

Includes a variety of useful routines for working with smart blobs

SqlLib C SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

SqlLib Java SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

Versioning Table Access Method

Permits users to create and manage versioned tables

We will look closer at two bladelets which could assist with migration the Exec datablade and SQLLib

Informix Exec bladelet for Dynamic SQL Often it is desirable to execute a SQL query that is generated at run-time within the RDBMS For example a developer may not know the name of the temporary table they wish to run the query against or they might want to append predicates to a query In external programs this can be accomplished using the ESQLC SQLCA and DESCRIPTOR facilities Unfortunately the INFORMIX Stored Procedure Language (SPL) does not support Dynamic SQL Queries must be hard-coded into the SPL logic The objective of the Exec bladelet is to remedy this situation Exec consists of user-defined functions that take an SQL query as an argument execute it and return the result (the format of which varies depending on which function is called and the kind of query) The Exec functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries For more details and download refer to

httpwwwibmcomdeveloperworksdb2zonesinformixlibrarydemoids_exechtml

There are three User Defined Routines (UDRs) in the Exec bladelet Two of them are external C functions that use the Server API (SAPI) These must be compiled into shared libraries on the target machine and you need to declare them to the server using CREATE FUNCTION statements The third UDR is a routine written in Informix Stored Procedure Language (SPL) that uses the first two UDRs to return a collection of items The Exec bladelet module consists of the following

1 EXEC The EXEC() function takes an LVARCHAR that it treats as a SQL query executes the query and returns a single LVARCHAR result string Depending on what kind of SQL statement is submitted Exec() returns a different result format

IBM Software Group IBM Information Management

Version 16 78

2 EXEC_FOR_ROWS The EXEC_FOR_ROWS() UDR is an iterator function which means it can return more than one result row Of course it only does so when it is asked to execute a SELECT Otherwise it behaves exactly as the EXEC() UDR Being an iterator function limits the ways in which such a UDR can be used It cannot be used in another SQL query The only place it can be used effectively is inside a SPL routine

3 EXEC_FOR_MSET EXEC_FOR_MSET() is a SPL routine that uses the EXEC_FOR_ROWS() routine introduced above Instead of returning a set of rows as an iterator or a single row as the EXEC() UDF does this UDR collects the results of the SQL query together into a single object a multi-set

Refer to Appendix E Sample Code for examples on using the EXEC bladelet functions

SqlLib DataBlade module (SqlLibC11 SqlLibJ11) The SqlLib DataBlade module implements SQL routines that the Informix does not support natively but that are supported by some other database vendors Source code is freely available for download and includes two implementations one in C (SqlLibC) and the other in Java (SqlLibJ)

The following routines are included

ascii - takes a single character as input and returns the ASCII value in decimal that corresponds to that character

ceil - takes a single numeric value as input and returns the smallest integer that is either equal to or greater than the input value

chr - takes an integer value and returns the character that is represented by the ASCII value (in decimal) of that integer

instr - searches for a value in a string and returns the position where it was found It

returns 0 if the search value was not found instrb - provides the exact same functionality as instr() but for single-byte character sets

sign - takes a numeric argument and returns an integer that indicates if the input value is

positive (1) negative (-1) or zero (0) to_decimal - converts the input character argument into a decimal type

to_float - converts the input character argument into a float type

to_integer - converts the input character argument into an integer type For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

IBM Software Group IBM Information Management

Version 16 79

A P P E N D I X A Planning guide

The checklist below will help an analyst determine which Oracle features which need to be converted to Informix and give some guidance on the effort involved Each porting task is listed They are followed by a quantity field used to determine how prevalent the item the difficulty or amount of effort involved 1 (low) to 5 (high) is used to estimate the amount of time needed to perform the task when the associated item exists in the application a moderate number of times What is moderate depends on the size of the application If there are an unusually large number of occurrences of an item then the effort should be increased Conversely if there are a small number of occurrences of an item then the effort should be decreased Each of these items is discussed in detail within this document Each heading corresponds to a section heading within the document

Tasks Quantity Effort

DDL

Identifiers Delimit identifiers named with Informix reserved words 2 Databases Determine database names and create databases 3 Replace Oracle tablespace names with Informix dbspace names 1 ANSI vs Non-ANSI considerations 3 Tables Convert create table statements 2 Convert DDL syntax 3 Reduce primary key length to 390 bytes 5 Data Types Convert Oraclersquos NUMBER data type 3 Convert VARCHAR columns 2 Convert Oraclersquos DATE data type 5 Convert raw data types 2 Convert Rowids 2 Indexes Convert Indexes 2 Views Remove CREATE VIEW statement options 1 Stored Procedures and Triggers Convert CREATE and REPLACE Stored Procedure and Trigger syntax 1 Oracle Extensions Remove non-supported Oracle extensions from DDL 1

Tasks Quantity Effort

DML

SQL Add the Informix AS clause to display labels 1 Replace non-supported DML syntax ^= hellip = ELSE IF 2 Convert Optimizer DirectiveHints 2 Convert InsertSelectUnion and InsertValueSelect statements 3

IBM Software Group IBM Information Management

Version 16 80

Convert Delete statement syntax 1 Convert temporary table processing 2 Convert Join statements + MINUS INTERSECT different data types 2 Convert sorts 4 Convert hard coded SQL error messages 3 Remove correlation names on the main table of Update and Delete statements

2

Replace original table names in SELECT statements using aliases 1 Convert hierarchical implementation (CONNECT BY PRIOR) 5 Host Variables Convert host variable format or add conversion processing 5 Functions Convert date and time functions 5 Convert aggregate functions 3 Convert mathematical functions 5 Convert string function syntax 1 Convert other unsupported Oracle functions 5 Macros Convert ISOPEN NOT FOUND ROWTYPE and TYPE macros 3 Pseudo-Columns Convert Level processing 3 Convert Rownum processing 2 Update Using Cursors Convert WHERE CURRENT OF processing for multiple table joins 5 Convert FOR UPDATE with a HOLD cursor processing 2 Convert concurrency processing from Oraclersquos implicit to Informixrsquos explicit

4

System Tables Convert system table references 1

Tasks Quantity Effort

Stored procedures Break stored procedures greater than 64K in size into smaller ones 2 Convert Oraclersquos stored procedure packages 3 Convert exception processing 5 Convert error handling (SQLCA) 2 Convert Oraclersquos global cursor processing 5 Convert Oraclersquos explicit cursor processing 2 Convert flow control processing 5 Convert Oraclersquos implicit variable declaration and assignment 3 Convert Oraclersquos BOOLEAN variable type 1 Convert binary data type processing Convert Oraclersquos dynamic SQL processing 5 Triggers Convert multi-functional triggers 3 Convert Insert and Update triggers which are not supported in Informix 5 Place logical statements in a stored procedure 5 Constraints Convert constraint enabling and disabling processing 5 DUAL table Convert Dual table processing 4

Embedded SQL

Host variables

IBM Software Group IBM Information Management

Version 16 81

Convert declaration overrides 1 Convert array processing 5 Convert Oraclersquos formatting functions 4 SQL structures Convert SQLDA processing 5 Convert ORACA processing 1 Pre-compiler options Convert Oracle pre-compiler options 1 Embedded PLSQL Convert Oraclersquos Embedded PLSQL 5 ODBC Convert Oraclersquos OCI 5 Convert database library calls Convert global area processing Convert fetch cycle Convert RAW data type processing Convert parameter bindings Embedded SQL for C Convert VARCHAR processing 2 Embedded SQL for COBOL Convert VARCHAR processing 2 Convert 88 Level processing in COBOL 2 Convert Redefine processing in COBOL 4

Tasks Quantity Effort

Application architecture

Transaction processing Convert application to Informix transaction processing 5 Convert multiple connect processing 5 Convert savepoints Concurrency Address Informix locking processing na 2 User authentication Address Informix security processing na 4

Environment

Convert make files 2 Convert shell scripts shell startup scripts and command files 2 Convert script substitution variables

IBM Software Group IBM Information Management

Version 16 82

A P P E N D I X B Syntax comparison

See the Informix Guide to SQL Syntax for more information on each item

Oracle Informix Boolean AND AND AND NOT NOT NOT OR OR OR Greater Than or Equal To gt= gt= Less Than or Equal TO lt= lt= Not Equal ltgt = or ^= ltgt or = Identifiers letters numbersrdquo_rdquordquo$rdquordquordquo letters numbers and ldquo_rdquo Data types Character CHAR CHAR Long Character VARCHAR (2000) if lt= 2000

LONG VARCHAR if gt 2000 CHAR or TEXT

Number (2 bytes) NUMBER SMALLINT Number (4 bytes) NUMBER INTEGER Number (gt 4 bytes) NUMBER DECIMAL Image LONG RAW CLOB BLOB BYTE TEXT CLOB BLOB DML Comments -- hellip -- hellip Assignment var1 = expression LET var1 = expression Condition ELSE IF ELSE or ELIF

IF Aggregate functions Average AVG(expression) AVG(ALL

expression) AVG(DISTINCT expression)

AVG(expression) AVG(ALL expression) AVG(DISTINCT column_name) AVG(UNIQUE column_name)

Count COUNT() COUNT (expression) COUNT(ALL expression) COUNT (DISTINCT expression)

COUNT() COUNT(DISTINCT column_name) COUNT (UNIQUE column_name)

Maximum MAX(expression) MAX(ALL expression) MAX(DISTINCT expression)

MAX(expression) MAX(ALL expression) MAX(DISTINCT column_name) MAX(UNIQUE column_name)

Minimum MIN(expression) MIN(ALL expression) MIN(DISTINCT expression)

MIN(expression) MIN(ALL expression) MIN(DISTINCT column_name) MIN(UNIQUE column_name)

Sum SUM(expression) SUM(ALL expression) SUM(DISTINCT expression)

SUM(expression) SUM(ALL expression) SUM(DISTINCT column_name) SUM(UNIQUE column_name)

Algebraic functions Round ROUND(expressionrounding

factor) ROUND(expressionrounding factor)

Statistical functions Standard Deviation STDEV(expression) STDDEV(expression) Variance VARIANCE(expression) VARIANCE(expression) Range RANGE(expression)

IBM Software Group IBM Information Management

Version 16 83

String functions

Trim LTRIM(expression) RTRIM(expression)

LTRIM(expression) RTRIM(expression)

Length LENGTH(string) LENGTH(string) Like LIKE(string) LIKE(string) Like (single character) _ _ Like (wildcard) String Delimiter lsquo or ldquo lsquo or ldquo Escape Character set within LIKE clause using

ESCAPE ldquordquo to make ldquordquo the escape character

or set within LIKE clause using ESCAPE ldquordquo to make ldquordquo the escape character

Stored procedures Create CREATE OR REPLACE

PROCEDURE procedure_name (var1 IN CHAR(1) var2 OUT DATE var3 IN OUT NUMBER)

DROP PROCEDURE procedure_name CREATE PROCEDURE procedure_name (var1 CHAR(1) var3 INTEGER) RETURNING DATE INTEGER

Arguments EXECUTE PROCEDURE procedure_name (var1 IN var2 OUT var3 IN OUT)

EXECUTE PROCEDURE procedure_name (var1 var3) RETURNING var2 var3

IBM Software Group IBM Information Management

Version 16 84

A P P E N D I X C Database concepts

The table below illustrates the relationship between each database vendorrsquos database objects

Oracle Informix

Database name attached to a group of files Specific database name

Data file Chunk

Tablespace (logical partition) or Segments (Index Segment Table Segment and so on)

Dbspace

Extent Extent

Rollback Segment Physical Log

Redo Log Logical Log

System tablespace Root dbspace

Temporary tablespace Temporary dbspaces dbspacetemp environment variable or dbspacetemp onconfig parameter

Pointer Blobspace Sbspace

Table partitioning table fragmentation

Database link Not supported

Snapshot Not supported

oerr utility finderr utility

sqldba and svrmgrl - monitor utilities onstat and oncheck utilities

SQLPlus utility dbaccess utility

ProC ESQLC

ProCOBOL ESQLCOBOL

SQLNET INet

OCI Like the ESQL function library after pre-compiling if they were publically documented

Read Consistency COMMITTED READ LAST COMMITTED

IBM Software Group IBM Information Management

Version 16 85

A P P E N D I X D Sample code

User defined functions User Defined Routines (UDR) can be developed to extend the capabilities of the database and provides the option to create UDRs to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or rename an Informix function to the corresponding Oracle function name

CONCAT

CREATE PROCEDURE concat (str1 VARCHAR(255) str2 VARCHAR(255)) RETURNING VARCHAR(255) RETURN str1 || str2

END PROCEDURE

INSTR

CREATE PROCEDURE instr( str VARCHAR(255) mask VARCHAR(255) strt SMALLINT DEFAULT 1 occur SMALLINT DEFAULT 1 ) RETURNING INT DEFINE slen SMALLINT DEFINE mlen SMALLINT DEFINE tempstr VARCHAR(255) DEFINE tempmask VARCHAR(255)

DEFINE nomatch SMALLINT DEFINE count SMALLINT DEFINE pos SMALLINT DEFINE retpos SMALLINT DEFINE i SMALLINT DEFINE j SMALLINT DEFINE srchstrt SMALLINT LET slen = LENGTH(str) LET mlen = LENGTH(mask) LET count = 0 LET nomatch = 0 LET pos = 1 LET retpos = 1 LET tempstr = LET tempmask = LET srchstrt = strt

IF (strt lt 0) THEN - reverse the str FOR i = 1 TO slen LET tempstr = str[11] || tempstr LET str = str[2255] END FOR -- reverse the mask FOR i = 1 TO mlen LET tempmask = mask[11] || tempmask LET mask = mask[2255] END FOR

IBM Software Group IBM Information Management

Version 16 86

LET srchstrt = strt -1 LET str = tempstr LET mask = tempmask END IF FOR j = 1 TO slen LET tempstr = str LET tempmask = mask FOR i = 1 TO mlen IF (tempmask[11] = tempstr[11]) THEN LET nomatch = 1 EXIT FOR END IF LET tempmask = tempmask[2255] LET tempstr = tempstr[2255]

END FOR IF (nomatch = 0) THEN IF (pos gt= srchstrt) THEN LET count = count + 1 END IF IF (count = occur) THEN IF (strt lt 0) THEN RETURN slen - pos + 1 ELSE RETURN pos END IF END IF END IF LET str = str[2255] LET nomatch = 0

LET pos = pos + 1 END FOR RETURN 0 END PROCEDURE

YYYYMMDD

CREATE PROCEDURE yyyymmdd (str VARCHAR(10)) RETURNING varchar(8)

DEFINE retstr VARCHAR(8)

IF str IS NULL THEN

RETURN NULL

ELSE

LET retstr = str[710] || str[12] || str[45]

RETURN retstr

END IF

END PROCEDURE

Using EXEC bladelet functions

IBM Software Group IBM Information Management

Version 16 87

Using EXEC

Note the ROW data type variable can be referenced using table and column syntax CREATE PROCEDURE example1() RETURNING INTEGER

DEFINE sql_stmt LVARCHAR(255)

DEFINE rcnt ROW(val INTEGER)

LET sql_stmt = select count() from items where manu_code = lsquoANZrsquo

EXECUTE FUNCTION EXEC(sql_stmt) INTO rcnt

RETURN rcntval

END PROCEDURE

Using EXEC_FOR_ROWS

CREATE PROCEDURE example2() RETURNING INTEGER CHAR(1)

DEFINE rs_rowdata ROW(customer_num INTEGER call_code CHAR(1))

DEFINE sql_stmt LVARCHAR(255)

LET sql_stmt = select customer_num call_code from cust_calls where

customer_num = 106

FOREACH

EXECUTE FUNCTION EXEC_FOR_ROWS(sql_stmt) INTO rs_rowdata

RETURN rs_rowdatacustomer_num rs_rowdatacall_code WITH RESUME

END FOREACH

END PROCEDURE

Using EXEC_FOR_MSET

Note the DEFINE statement for the variable rs_data Collection data types used in a SPL routine cannot be defined using the LIKE attribute in the DEFINE statement CREATE PROCEDURE example3() RETURNING INTEGER VARCHAR(8)

DEFINE v_customer_num LIKE accountscustomer_num

DEFINE v_account_cd LIKE accountsaccount_cd

DEFINE rs_data MULTISET(ROW(

r_customer_num INTEGER

r_account_cd VARCHAR(8)) NOT NULL)

DEFINE sql_stmt LVARCHAR

LET sql_stmt = select customer_num order_num from orders where

company_id = 51155

EXECUTE FUNCTION EXEC_FOR_MSET(sql_stmt) INTO rs_data

FOREACH

SELECT r_customer_num r_account_cd INTO v_customer_num

v_account_cd FROM TABLE(rs_data)

RETURN v_customer_num v_account_cd WITH RESUME

END FOREACH

END PROCEDURE

IBM Software Group IBM Information Management

Version 16 88

Date arithmetic Informix has extensive capabilities for manipulating dates and times You can add or subtract DATE and DATETIME variables from each other You can add or subtract an INTERVAL to a DATE or DATETIME

UNITS Keyword

When working with INTERVAL values sometimes it is necessary to specify the precision with which you are dealing For example suppose you have the following field defined To add 10 days to the lead time you could use a SQL statement like this

SELECT lead_time + INTERVAL(10) DAY to DAY FROM orders

-or- SELECT lead_time + 10 UNITS DAY FROM orders

Using EXTEND function

The EXTEND function allows operations between data types of different precisions SELECT

EXTEND(myvar YEAR to MINUTE) ndash INTERVAL(5) MINUTE to MINUTE

FROM member

Calculate Week Of The Year

SELECT ROUND((TODAY - DATE(0101||YEAR(TODAY))) 7 + 5) FROM DUAL

Number of days difference SELECT DATE(0106||YEAR(TODAY)) - DATE(01062005) FROM DUAL

Number of weeks difference

SELECT ROUND((DATE(0106||YEAR(TODAY)) - DATE(01062005))

7 + 5) FROM DUAL

String representation of date and time

Day and date

SELECT TO_CHAR(TODAY A B d Y) FROM dual

-returns month day and 4 digit year-

Tuesday January 03 2006

Abbreviation of day of week

SELECT SUBSTR(TO_CHAR(TODAY A B d Y R)13) FROM dual

-or-

SELECT TO_CHAR(TODAY a) FROM dual

-returns MON TUE WED THU FRI SAT SUN-

Returning the number of rows affected

IBM Software Group IBM Information Management

Version 16 89

Within SPL routines you can use the DBINFO function to find out the number of rows that have been processed in SELECT INSERT UPDATE DELETE EXECUTE PROCEDURE and EXECUTE FUNCTION statements

CREATE FUNCTION del_rows(pnumb INT) RETURNING INT

DEFINE nrows INT

DELETE FROM sec_tab WHERE part_num = pnumb

LET nrows = DBINFO(sqlcasqlerrd2)

RETURN nrows

END FUNCTION

To ensure valid results use this option after SELECT and EXECUTE PROCEDURE or EXECUTE FUNCTION statements have completed executing If you use the sqlcasqlerrd2 option within cursors make sure that all rows are fetched before the cursors are closed

Using an Informix collection data type

A collection data type as a VARRAY

In the following examples the collection data types of MULTISET and SET are used in a function to hold a collection of values You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value Informix SPL allows you to declare a cursor for a collection variable using the FOREACH statement called a collection cursor

Also demonstrated is how to utilize a variable declared with the keyword COLLECTION A variable declared as type SET MULTISET or LIST is a typed collection variable It can hold a collection of its specified data type only However a COLLECTION is an un-typed (or generic) collection variable that can hold a collection of any data type

This function will build a MULTISET list of values

CREATE FUNCTION func1() RETURNING MULTISET(INTEGER NOT NULL)

DEFINE v_array_of_ints MULTISET(INTEGER NOT NULL)

INSERT INTO TABLE (v_array_of_ints) VALUES(1)

INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(5)

INSERT INTO TABLE (v_array_of_ints) VALUES(4)

RETURN v_array_of_ints

END FUNCTION

This function will receive the COLLECTION list of values from func1

CREATE FUNCTION func2() RETURNING INTEGER

--

-- DEFINE lmset MULTISET(INTEGER NOT NULL)

--

DEFINE lmset COLLECTION

DEFINE v_int INTEGER

--

-- call func1 to populate local multiset variable

--

LET lmset = func1()

--

-- tally a count the number of elements

--

FOREACH

SELECT COUNT() INTO v_int FROM TABLE(lmset)

IBM Software Group IBM Information Management

Version 16 90

RETURN v_int WITH RESUME

END FOREACH

--

-- return the values

--

FOREACH

SELECT INTO v_int FROM TABLE(lmset)

RETURN v_int WITH RESUME

END FOREACH

END FUNCTION

NOTE In the example func2 a duplicate declaration for the ldquolmsetrdquo variable as a MULTISET data type has been commented out by declaring the variable as a COLLECTION it can accept any of the 3 types (MULTISET SET and LIST)

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

4 (row count) 1 2 5 4

By using a SET data type inserts will not permit duplicates

CREATE FUNCTION func1() RETURNING SET(INTEGER NOT NULL) DEFINE v_array_of_ints SET(INTEGER NOT NULL) INSERT INTO TABLE (v_array_of_ints) VALUES(1) INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(2) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) RETURN v_array_of_ints END FUNCTION

NOTE Because func2 is expecting a un-typed COLLECTION variable func1 does not have to be dropped and recreated It can receive a value from any Collection Data Type (MULITSET SET and LIST)

The functionrsquos return values would change to (with duplicates suppressed)

EXECUTE FUNCTION func2()

(expression)

3 (row count) 1 2 5

Using a LIST data type support for assigning values based on ordinal position

IBM Software Group IBM Information Management

Version 16 91

CREATE FUNCTION func1() RETURNING LIST(INTEGER NOT NULL)

DEFINE v_array_of_ints LIST(INTEGER NOT NULL) -- -- first insert no ordinal position can be established By default the -- database server inserts LIST elements at the end of the list -- INSERT AT 5 INTO TABLE (v_array_of_ints) VALUES(5) INSERT AT 1 INTO TABLE (v_array_of_ints) VALUES(1) INSERT AT 2 INTO TABLE (v_array_of_ints) VALUES(2) -- -- Only 3 LIST elements exist position 4 has not been instantiated -- this element will insert at the end of the list -- INSERT AT 4 INTO TABLE (v_array_of_ints) VALUES(4) INSERT AT 3 INTO TABLE (v_array_of_ints) VALUES(3) RETURN v_array_of_ints END FUNCTION

NOTE The elements of a LIST have ordinal positions with a first second and third element in a LIST To support the ordinal position of a LIST the INSERT statement provides the AT clause This clause allows you to specify the position at which you want to insert a list-element value Note the behavior of the ordinal positioning above preceded by a commented explanation

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

5 (row count) 1 2 3 5 4

Using MULTISET and ROW to replace PLSQL TABLE and RECORD types

Creating variables using Informix Collection data types SET MULTISET and LIST in combination with ROW data types can be useful when migrating applications which use Oracle REF CURSORS as arguments to functions as well as Oracle collection data types TABLE and RECORD

Typical Oracle Package specification

CREATE OR REPLACE PACKAGE MyPackage

IS

TYPE recOrders IS RECORD (

order_num ordersorder_numTYPE

order_date ordersorder_dateTYPE

customer_num orderscustomer_numTYPE

po_num orderspo_numTYPE

)

TYPE tabOrders IS TABLE OF recOrders

INDEX BY BINARY_INTEGER

TYPE ref_curtype IS REF CURSOR

Both tabOrders or ref_curtype can be converted to the following Informix SPL definition

DEFINE tabOrders MULTISET(ROW(

IBM Software Group IBM Information Management

Version 16 92

order_num INTEGER

order_date DATETIME YEAR TO FRACTION(3)

customer_num INTEGER

po_num CHAR(10)) NOT NULL)

DEFINE ref_curtype MULTISET(ROW(

define columns based on query result set

) NOT NULL)

IBM Software Group IBM Information Management

Version 16 93

A P P E N D I X E Counting system objects

Using the system catalog

System catalog

Below is a list of SQL statements that will extract most if not all of the counts of system objects owned by user lsquoXXXrsquo

select count(table_name) from all_tables

where owner=rsquoxxxrsquo

select count() from dba_indexes

where owner=rsquoxxxrsquo

select count(synonym_name) from dba_synonyms

where owner=rsquoxxxrsquo

select count() from dba_views

where owner=rsquoxxxrsquo

select count() from dba_tab_columns

where length(column_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

and owner=rsquoxxxrsquo

select count distinct() from dba_tab_columns

and owner=rsquoxxxrsquo

select count() from dba_tables

where length(table_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_synonyms

where length(synonym_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_views

where length(view_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_indexes

where length(index_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and owner=rsquoxxxrsquo

IBM Software Group IBM Information Management

Version 16 94

select data_type count(data_type) from dba_tab_columns

where owner=rsquoxxxrsquo

group by data_type

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and length(data_type)gt254

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquonumberrsquo

and data_scale=0

and owner=rsquoxxxrsquo

Using SQL code

Built-in function references

The following instructions can be used to find references to built-in functions On the UNIX machine or the NT box where your code resides please create the following file as tmpfunctionlist

convert(

hextoint(

inttohex(

getdate(

datename(

datepart(

datediff(

dateadd(

months_between(

char(

char_length(

charindex(

compute(

difference(

length(

lower(

patindex(

replicate(

reverse(

right(

soundex(

space(

str(

stuff(

substring(

upper(

abs(

atn2(

log(

ceiling(

IBM Software Group IBM Information Management

Version 16 95

cot(

degrees(

floor(

radians(

rand(

sign(

to_char(

to_date(

to_number(

exception(

pi(

raise_application_error(

raiserror(

SQLCODE

rollback

savepoint

declare

decode(

nvl(

print(

rowid

waitfor

recompile

bcp

isopen(

notfound(

rowtype(

type(

Then please run the following program with the proper subdirectories

binksh

rm ndashf somehomeoutfile

cd somesourcedatabase

export sourcebase=rdquosomepathrdquo

for functor in `cat tmpfunction_list`

do

echo before find $functor

find $sourcebasedatabase -exec grep -i $functor gtgt

somehome$functoroutfile

find $sourcebaseintfc -exec grep -i $functor gtgt

somehome$functoroutfile

echo after find $functor

done

Object types and counts

This script attempts to count the objects of each type by grepping for CREATE statements containing the object type and counts procedure definitions that are inside package bodies which are not proceeded by a CREATE keyword It is not a sophisticated parser so the results may not be perfect

binbash if [ $1 = ] then

IBM Software Group IBM Information Management

Version 16 96

echo Usage objCountssh ltFilePatterngt return 1 fi declare -a objectTypes=(CLUSTER CONTEXT CONTROLFILE DATABASE DATABASE +LINK DIMENSION DIRECTORY DISKGROUP FUNCTION INDEX INDEXTYPE JAVA LIBRARY MATERIALIZED +VIEW MATERIALIZED +VIEW +LOG OPERATOR OUTLINE PACKAGE PACKAGE +BODY PFILE PROCEDURE PROFILE RESTORE +POINT ROLE ROLLBACK +SEGMENT SCHEMA SEQUENCE SPFILE SYNONYM TABLE TABLESPACE TRIGGER TYPE TYPE +BODY USER VIEW) echo for type in $objectTypes[] do if [ $type = PROCEDURE ] then echo $type object count `cat $1 | grep -icE ^ (|CREATE +|OR REPLACE +)b$typeb` else echo $type object count `cat $1 | grep -icE ^ (CREATE +|OR +REPLACE +)b$typeb` fi done

IBM Software Group IBM Information Management

Version 16 97

A P P E N D I X F Data type mapping

Oracle built-in data types (including ANSI types) can be converted to similar data types in the Informix database according to the mapping described here This table provides default mappings based on most common usage patterns in some cases another mapping may work better

In the following table n is used to indicate length p is used to indicate precision and s is used to indicate scale

Oracle data type Informixreg Server data type

BFILE LONG RAW BLOB

BLOB

BINARY_DOUBLE DOUBLE PRECISION

BINARY_FLOAT DOUBLE PRECISION

BINARY_INTEGER

PLS_INTEGER

NATURAL

NATURALN

POSITIVE

POSITIVEN

32-bit integers only used in PLSQL NATURAL and POSITIVE are unsigned integers

INTEGER

BOOLEAN (PLSQL only) BOOLEAN

CHAR(n) or CHARACTER(n) CHAR(n)

DATE DATETIME YEAR TO SECOND

DOUBLE PRECISION DOUBLE PRECISION

IBM Software Group IBM Information Management

Version 16 98

FLOAT

See note on FLOAT below

FLOAT

INTEGER INT

A 38-digit NUMBER sub-type May want to flag with a warning on possible overflow

INTEGER

INTERVAL DAY(p) TO SECOND(s)

Note Oracle fractional seconds have 9 digits

INTERVAL DAY(p) TO FRACTION(min(5 s))

INTERVAL YEAR(p) TO MONTH

INTERVAL YEAR(p) TO MONTH

LONG CLOB

CLOB

LONG VARCHAR (xxx)

Oracle recommends not using this type

LVARCHAR

NCHAR(n) NATIONAL CHAR(n) or NATIONAL CHARACTER(n)

NCHAR(n)

See National Language Types below

NCLOB CLOB

NUMBER

NUMBER(0)

NUMBER(p) NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s lt 10

NUMBER(3-2) 12300

INTEGER

IBM Software Group IBM Information Management

Version 16 99

NUMBER(p) NUMBER (p0)

Where precision (p) is greater than or equal to 10 and lt= 18

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and 10 lt= p-s lt 19

NUMBER(9-2) 12345678900

BIGINT

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is greater than or equal to s (that is s gt 0 and p gt= s)

NUMERIC (min(p32) min(s32))

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is less than s (that is s gt 0 and p lt s)

NUMBER(35) 000123

NUMERIC (min(s32)min(s32))

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s gt 18 and p-s lt= 32

NUMERIC (min(p-s32)0)

NUMBER(p s)

Where scale (s) is greater than 32 or pInformix-s is greater than 32

NUMERIC (32)

Scale cannot be greater than precision

NUMERIC(3232) would guarantee that digits to the left of the decimal would be lost Using a floating point decimal provides the simplest best way to capture as many digits in a value as possible

IBM Software Group IBM Information Management

Version 16 100

DEC

DECIMAL

NUMERIC

DEC(p)

DECIMAL(p)

NUMERIC(p)

DEC(p s)

DECIMAL(p s) NUMERIC(p s)

There is no difference within Oracle between these types and each other and these types and NUMBER The Oracle system catalogs contain the NUMBER type id for all declarations of these types and the integer types as well Declarations of these types can be mapped using the same rules as those for NUMBER

NVARCHAR2(n) NCHAR VARYING(n) NATIONAL CHAR VARYING(n) NATIONAL CHARACTER VARYING(n)

LVARCHAR(min(n 32767))

RAW(n) BLOB

REAL DOUBLE PRECISION

Record ROWTYPE

Using a CREATE ROWTYPE statement

ROWID INTEGER

SMALLINT SMALLINT

TIMESTAMP(p)

If p is not specified precision defaults to 6

DATETIME YEAR TO FRACTION(min(5 p))

UROWID(n) INTEGER

IBM Software Group IBM Information Management

Version 16 101

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is less than or equal to 255 (that is n lt= 255)

VARCHAR(n)

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is greater than 255 (that is n gt 255)

LVARCHAR(n)

XMLType CLOB

Notes on specific types are below

DOUBLE

The range of values for the DOUBLE PRECISION data type is the same as the range of the C double data type on your computer

VARCHAR

While Oracle VARCHAR data types have a limit of 4000 bytes an Informix Server VARCHAR data types has a limit of 255 bytes An Informix Server LVARCHAR has a limit of 32739 Bytes

NUMBER

Oracle abstracts its numeric types from the hardware and operating system through the use of its NUMBER type Most numeric types like INTEGER are actually NUMBERs internally When porting to a database server like Informix which retains more of a relationship between the operating system types and the database types it is essentially a one-to-many mapping and heuristics have to be used to determine the best-fit target type No single set of type mapping rules will fit all use scenarios The converter has default rules which fit the more common user patterns When considering a number represented as mantissa and exponent

mantissa x 10exponent

precision is the number of digits in the mantissa and scale is the negative exponent how many places to the right of the decimal point the least significant digit is located Oracle NUMBERs have a maximum precision of 38 and the maximum precision available in Informix native types is 32 The first step in a type mapping is to truncate the target type precision to min(precision 32) The scale of a type can be considered its anchor point with respect to the decimal point The most

IBM Software Group IBM Information Management

Version 16 102

significant digit of a numeric type is located precision digits to the left of the decimal point and precision-scale digits to the right of the decimal point The start and end locations of the digits are used to determine the closest fitting Informix type The order of preference is INTEGER BIGINT NUMERIC(p s) and lastly NUMERIC(p) NUMERIC(p) in a non-ANSI mode database is a decimal type with a floating point type In an ANSI mode database the scale is implicitly 0 All Oracle integer declaration types such as INT INTEGER SMALLINT become NUMBER(38) type in the Oracle metadata In Oracle when precision is given but scale is not scale becomes 0 implicitly which makes the type in the set of integral types One exception to the general mapping rules is the NUMBER type specified without precision or scale Strictly speaking this has a floating point scale with 38 digits of precision but most commonly it is used where an integer is more appropriate Even if the user does specify INTEGER in a type definition when it comes out of the Oracle catalogs the type is NUMBER This is one case in particular where one type mapping will not fit well with all usage scenarios

National language types

Oracle Nchar types are allocated by number of characters where Informix is allocated by the number of bytes For Oracle the storage size of the characters varies with the encoding used and is always subject to the standard 32767 limit on maximum bytes but during declarations n always means the number of characters Oracle PLSQL supports explicit and implicit data type conversions These explicit and implicit data types are converted to syntax by using Informix Dynamic Servers explicit and implicit data type conversion mechanism

ROWID

Oracle databases support a pseudo-column named ROWID such that every row in every table is assigned an auto-generated ID Oracle also allows you to define a column of type ROWID which can be used as a foreign key to a ROWID pseudo-column Oracle ROWID columns contain data that if converted to a string are 18 characters long for example lsquoAAAQ+jAAEAAAAAeAANrsquo It is probably not advisable to migrate this data to an Informix database and instead use the Informix type which is an integer If there is a dependency on the values themselves and therefore need migrate the data then an integer type would not hold the values

TYPE

In PLSQL you can refer to the type of an existing variable field or column by using the TYPE attribute The converter replaces this reference directly by the type it refers to

ROWTYPE

In PLSQL you can refer to the record type that represents a row of a table a cursor or a cursor variable PLSQL scripts containing the ROWTYPE attribute are handled in the same way as a record type that has been previously declared

FLOAT

Oracle FLOAT type is a floating point number capable of storing up to 38 decimal digits or 126 binary digits It has a floating point scale that can exist outside the boundaries of what an Informix DECIMAL can represent A C language double or Informix float type is capable of only 16 digits so there is the chance that some data will be lost Using an Informix FLOAT type makes it so that less significant digits are lost in preference to more significant digits

IBM Software Group IBM Information Management

Version 16 103

References to subtypes declared in packages and PLSQL blocks are converted to the Informix Server equivalent base types Variables of type RECORD are not translated by the DDL Converter at the time of this writing They will be handled by the stored procedure converter

XMLType

Informix does not have a built-in type for representing XML The nearest approximation is to store it in a CLOB Another character type like LVARCHAR can be used if it can be determined that the actual data will fit in it

Page 9: Oracle to IBM Informix Server Porting Guide

IBM Software Group IBM Information Management

Version 16 9

are discussed in the DDL and DML sections This allows separate discussions on the issues facing the same item in each area For example the issues surrounding creating a stored procedure are discussed in the DDL section and the issues surrounding the stored procedure language are discussed in the DML section Among the other references the ldquoPlanning Guiderdquo appendix contains a quick reference of most of the differences between Oracle and Informix along with the degree of difficulty to port each difference This reference is intended for use in the planning process to illustrate the scope and the effort required to perform the porting project Some of the stored procedure logic used to convert Oracle functions is included in the appendix rdquoSample coderdquo

Conventions The conventions used in this document include

Courier Text Distinguishes a logic example

from regular text

Example Illustrates a point In most cases an Oracle example will be followed by an Informix example

Italicized Text Signifies a substitution in other words substitutes for the italicized word the actual object the word is describing for example table_name column_name and so on

UPPER CASE TEXT Signifies database vendor reserved words or statements such as INTEGER CREATE TABLE and so on

Bold example text highlights the item that is being explained

IBM Software Group IBM Information Management

Version 16 10

IBM Software Group IBM Information Management

Version 16 11

C H A P T E R 2 Defining the Problem Space

It is important to define the set of objects to be migrated and it is better if effort is put into this prior to beginning the actual migration This is true if you are the responsible for both the database in general and its migration from one supporting DBMS to another but it is particularly true that there be a clear agreement on the scope of what is to be migrated if the migration is to be performed by a party other than the one with long term responsibility for the database Defining the scope will involve extracting a representation of the objects to be migrated out of the Oracle system catalogs and representing them in some format that can be manipulated into constructs that can be used in Informix

Extracting the objects to be migrated It is possible to represent the objects in more than one language Using the SQL language is the most common method and it will be the only one discussed at length in this document (in its current revision) However it is also possible to express database objects in XML SQL has the advantage that the standard common grammars are widely understood in the context of defining tables indexes etc XML would have an advantage of not requiring parsing that is sensitive to the minor differences in ways of expressing essentially the same object

Working With Oracle Dump Files

There exist 3rd

-party tools for reading system catalogs but it is doubtful that any can read the Oracle catalogs more reliably than Oraclersquos own tools There are two incompatible export and import tool sets used by Oracle The older tools are imp and exp and the newer ones are impdp and expdp where dp stands for Data Pump Oracle has encouraged the use of the newer tools instead of the older ones since the newer ones were introduced at version 10 Nonetheless there are many Oracle users still using imp and exp In the discussions below only the metadata will be extracted into a dump file That is because any data in the dump file will be in a proprietary format and very likely some of the data will have to go through a type conversion process before being loaded into an Informix system Oracle exported data generally cannot be used to load a database in Informix Export and Import

If someone has given you a dump file created with the older export tool there exist tools such as The DDL Wizard by Net 2000 Limited which can be used to extract viable DDL The contents of the dump file contain the SQL for re-creating the database but they are not in a readily usable format The older export and import tools are also more sensitive to the layout of the tablespaces than impdb The ability to extract DDL from the dump file in a usable form segmented by whatever grouping you choose is limited compared to what can be achieved through the Data Pump versions

IBM Software Group IBM Information Management

Version 16 12

It may be tempting to feed the dump file into the IBM Migration Toolkit (MTK) or other tool that works on SQL flat files This will not work MTK works on flat text SQL files and the dump file is binary If you open it up you can see what may be a large number of SQL statements but there are also binary codes within the same file That binary data will prevent MTK from being able to process it Getting SQL statements

If you want to get the SQL statements out of the dump file as they would be executed on the server there is an option available from the import tool itself show=y

imp myIDmyPWD as sysdba file=myFiledmp

full=yes show=y gt dmp_showtxt

This will produce a file which contains the statements but they are wrapped in quotes The contents will look something like

ALTER SESSION SET CURRENT_SCHEMA= SYSTEM CREATE UNDO TABLESPACE TBSPC1 BLOCKSIZE 8192 DATAFILE DORACLEORADA TASCHEMA1CHUNKDBF SIZE 387973120 AUTOEXTEND ON NEXT 5242880 MAXS IZE 32767M EXTENT MANAGEMENT LOCAL

which makes them strings instead of SQL statements Fixing this is a two-step process

-- removes quotes from the start of lines

sed s^ g dmp_showtxt gt step1txt

-- removes quotes from the end of lines

sed s$g step1txt gt dmp_step2sql

The statements are still not correctly formatted because they have been truncated to a fixed length and line-endings inserted However at this point it is possible to get a count of how many of each object type there is using the script in the appendix ldquoGetting an initial count of database objectsrdquo

Data Pump Export and Import

These newer tools provide better performance and more capabilities than their predecessors Please refer to documentation on Oracle for a complete description searches for ldquoData Pump Importrdquo and ldquoData Pump Exportrdquo should return relevant results quickly Below is enough information to get started on defining and extracting the objects to be migrated Metadata can be filtered through the use of the export mode clause and INCLUDE and EXCLUDE parameters However any dependent object of an included or excluded object is likewise included or excluded For example if you include an index then the table associated with the index will also be included and if you exclude a table then any associated indexes will also be excluded The SQL that will generate all the objects in the dump file can be created by the impdp command with the SQLFILE parameter If the output file is very large you might want to break it into smaller pieces There are a couple of ways to do this and the one that is best for you somewhat depends

IBM Software Group IBM Information Management

Version 16 13

on how you intend to proceed with the conversion Data definition language (DDL) SQL for all the objects can be put into one file or the INCLUDE or EXCLUDE parameters can be added to direct Data Pump to filter on the types of objects If you put all the objects into one file then you can break that into smaller files by object type fairly easily because the objects are sorted by type in the SQL file So it is just a matter of cutting the file into smaller pieces This method may be preferred because it allows for you to do things like create all tables load the data and then create the indexes and triggers If the data set is large creating the indexes after loading the data can yield substantial performance improvements However this is less useful if you want to convert sets of objects according to dependencies in which case the filtering option is likely to be more useful Just to illustrate a difference between these two methods in one customer case the metadata dump file was about 18MB and putting all objects in one SQL file resulted in a file that was about 15MB The table definitions occupied a little under 300KB of the 15MB The output file generated by filtering on objects of type TABLE was just over 1MB The addition content was mostly GRANT INDEX and TRIGGER creation statements There were no differences in the CREATE TABLE statements themselves Examples

Prerequisite The Data Pump tools require the use of an Oracle DIRECTORY object This is basically a mapping between a name that exists within the DBMS and a system path It can be a tripping point but it provides an abstraction layer that for instance allows the same commands to work across systems with different disk layouts or different operating systems Creating a DIRECTORY on a Windows system from SQLPlus

SQLgtconnect as sysdba

SQLgtCREATE OR REPLACE DIRECTORY dumpDir AS ctemp

Note Make sure this directory is not read-only There also could be problems if the directory is a network drive on Windows these can be related to there being different users between the Oracle executable and the current user and those users having different permissions on the network drive

SQLgtGRANT read write ON DIRECTORY dumpDir TO userID

Creating a dump file of the entire database

expdp userNameuserPwd as sysdba FULL=Y dumpfile=DB_fulldmp

LOGFILE=LG_expdplog CONTENT=METADATA_ONLY DIRECTORY=dumpDir

Creating a dump file of just one schema

expdp userNameuserPwd as sysdba SCHEMAS=hr DIRECTORY=dumpDir

DUMPFILE=hr dmp LOGFILE=hr log CONTENT=METADATA_ONLY

Creating a dump of just the tables and their dependents

expdp userNameuserPwd as sysdba SCHEMAS=hr INCLUDE=TABLE

DIRECTORY=dumpDir DUMPFILE=hrdmp LOGFILE=hrlog

CONTENT=METADATA_ONLY

Creating a dump of just one table

expdp userNameuserPwd as sysdba SCHEMAS=hr

INCLUDE=TABLELIKE COUNTRIES DIRECTORY=dumpDir

DUMPFILE=hrdmp LOGFILE=hrlog CONTENT=METADATA_ONLY

IBM Software Group IBM Information Management

Version 16 14

Creatinge an SQL file from a dump file

impdp userNameuserPwd as sysdba DIRECTORY=dumpDir

DUMPFILE=hrdmp SQLFILE=dumpDirhrsql

The INCLUDE and EXCLUDE options are also valid when used with impdb so it may be easier to get a complete dump of everything to be migrated then use these options to create subsets of objects it smaller SQL files than it would be to create separate dump files It is easier to divide objects than to merge them together if they are not divided initially as wanted There is a caveat when using this impdp to generate an SQL file the object names will all be delimited identifiers Example

CREATE TABLE HRCOUNTRIES Because of differences between how Informix handles these and how Oracle handles these case-sensitivity issues could occur See the chapter on ldquoDelimited Identifiersrdquo and in particular the description of default shift problems If it can be determined that there are no name collisions if regular identifiers are used removing the quotation marks as part of the conversion might avoid many problems In other words if there are no objects whose names only differ in case like foo and FOO then changing every occurrence of ldquoFOOrdquo to FOO in the DDL could eliminate case-sensitivity issues in the application DML It depends on if the application code uses the delimited form of the name predominantly or not

IBM Software Group IBM Information Management

Version 16 15

C H A P T E R 3 Data Definition Language

Identifiers An identifier specifies the simple name of a database object such as a table name column name index name view name stored procedure name and so on The maximum length of an Oracle identifier is 30 characters and can contain letters numbers ldquo_rdquo ldquo$rdquo and ldquordquo although Oracle highly recommends that ldquo$rdquo and ldquordquo should not be used In contrast Informix identifiers have a maximum length of 128 characters and may contain letters numbers ldquo_rdquo and ldquo$rdquo (as long as ldquo$rdquo is not the first character) See the Delimited Identifiers section below for information This means that all Oracle identifiers containing a ldquordquo anywhere in the identifier or a ldquo$rdquo as the first character must be replaced or modified to remove those characters from the identifier

Delimited identifiers

Delimited identifiers are also known as quoted identifiers and sometimes as escaped identifiers They have been part of the SQL standard since SQL92 but existed in various database management systems (DBMS) prior to that time In a nutshell they are a way to preserve case sensitivity in object names as well as to allow objects to have names outside of the conventions of SQL regular identifiers Prior to the behavior of identifiers in general being standardized different DBMS vendors implemented different means of achieving case-insensitivity for object names some converted all regular identifiers to uppercase and some converted regular identifiers to lowercase By SQL99 the concept of case normal form was standardized to mean simply stated that if there exists an uppercase equivalent of any character in a name then the uppercase version is stored in the system catalogs and used for comparison purposes See the SQL99 standard chapter 5 section 2 and in particular items 21 and 22 for a formal description of case normal form and how it applies to identifier comparisons Delimited identifiers can be used to specify names for database objects that are otherwise identical to SQL reserved keywords such as TABLE WHERE DECLARE and so on The only database object for which delimited identifiers cannot be used is a database name Database administrators and application programmers do not always communicate to each other with 100 efficiency and there is no guarantee that within either of these pools every member codes by the standard practice of the other members After describing how delimited identifiers work in Informix there will be a description of how any inconsistency of usage and the differences between Oracle and Informix can introduce some migration hurdles DELIMIDENT Environment Variable

To use delimited identifiers with Informix you must set the DELIMIDENT environment variable While DELIMIDENT is set strings enclosed in quotation marks ( ldquo ) are treated as identifiers of database objects and strings enclosed in apostrophes ( rsquo ) are treated as literal strings If the

IBM Software Group IBM Information Management

Version 16 16

DELIMIDENT environment variable is not set strings enclosed in quotation marks are also treated as literal strings When you set the DELIMIDENT environment variable you cannot use quotation marks ( rdquo ) to delimit literal strings If DELIMIDENT is set the database server interprets all strings enclosed in quotation marks as SQL identifiers not string literals Commonly within Informix systems DELIMIDENT is set or not on the client side according to the design of the application However if you are converting a database and all applications accessing it from a system where every occurrence of quotation marks (ldquoobjectNamerdquo) indicates an identifier and not a string literal you may want to consider setting it in the server environment in order to avoid any inconsistency between clients where it is set and where it might not be Using Quotes in Strings The apostrophe ( rsquo ) has no special significance in string literals delimited by quotation marks Conversely double quote ( Prime ) has no special significance in strings delimited by apostrophes For example these strings are valid Nancyrsquos puppy jumped the fence

rsquoBilly told his kitten No rsquo A string delimited by quotation marks can include a double quote character by preceding it with another double quote as the following string shows Enter y to

select this row When the DELIMIDENT environment variable is set quotation marks can only delimit identifiers not strings Use of Uppercase Characters You can specify the name of a database object with uppercase characters but the Informix server shifts these to lowercase characters unless the DELIMIDENT environment variable is set and the name of the database object is enclosed in quotation marks In this case the database server treats the name of the database object as a delimited identifier and preserves the uppercase characters in the name Delimited Identifiers By default the character set of a valid SQL identifier is restricted to letters digits underscore and dollar-sign symbols If you set the DELIMIDENT environment variable however SQL identifiers can also include additional characters from the codeset implied by the setting of the DB_LOCALE environment variable See the Identifier section of the Informix Guide to SQL Syntax for more information Storage Object Names In Informix delimited identifiers can be used to specify non-alphanumeric characters in the names of database objects However delimited identifiers can not be used to specify non-alpha characters in the names of storage objects such as dbspaces and blobspaces To use delimited identifiers DELIMIDENT must be set both at compile and run times For example to set DELIMIDENT environment variable with sh or ksh issue the following at the command line prompt

export DELIMIDENT=

Note You do not need to assign a value to the environment variable and counter-intuitively setting DELIMIDENT=n has the same effect as DELIMIDENT=y Also in a Windows environment

set DELIMIDENT=

effectively undefines the variable Default shift problems

Any direct access of system catalog information involving names will cause problems when migrating from a system like Oracle where system catalog names are stored in uppercase to a system like Informix where the catalog names are stored in lowercase For example

CREATE TABLE foo (c1 int)

IBM Software Group IBM Information Management

Version 16 17

Within Oracle the following will return information about the table

select from sysall_objects where object_name = FOO

and the following will not

select from sysall_objects where object_name = foo

Conversely in Informix

select from systables where tabname = foo

will be successful and the same with FOO will not be A similar if not more common problem can occur when the table has been created without the name being delimited but is sometimes delimited when accessed by the application Per the standard foo == FOO == ldquoFOOrdquo but in Informix foo == FOO == ldquofoordquo In Oracle the following SELECT statement will be successful

SELECT FROM ldquoFOOrdquo

but within Informix this will result in an error ldquo206 The specified table (FOO) is not in the databaserdquo Likewise if the name is delimited in its definition such as

CREATE TABLE SCHEMA1TABLE1

this creates a table that can be referenced in Oracle without the name being delimited The statements

SELECT FROM schema1table1

and SELECT FROM SCHEMA1TABLE1

will be successful in the Oracle system but will fail in the Informix one In theory whether on object name is delimited or not should be the same in the database and at every occurrence within the application but this is not always the case It may be beneficial to examine whether delimited identifiers or regular identifiers are most commonly used in application code and use whichever is most common as a naming convention when translating the DDL

Explicit versus implicit schemaowner names

Another complication to keep in mind is that when the log mode is ANSI implicit and explicit owner names are treated differently between the Oracle and Informix servers In Oracle there is no difference in the case handling of an implicit owner name and an explicit one For example if connected to Oracle as scott the following CREATE TABLE statements

create table foo1(c1 int) create table scottfoo2(c1 int) create table SCOTTfoo3(c1 int)

all result in tables owned by SCOTT The following select statements in various forms that may be in application code will all run without error

select from foo1 select from scottfoo1

IBM Software Group IBM Information Management

Version 16 18

select from SCOTTfoo1 select from foo2 select from scottfoo2 select from SCOTTfoo2 select from foo3 select from scottfoo3 select from SCOTTfoo3

These statements will also run without error within a non-ANSI mode Informix database but not all of them will run successfully within an ANSI mode database This is because Informix does not uniformly fold the case of owner names and handles implicit names differently from explicit names so there will always be some combination of DDL and DML usage patterns that work within an Oracle system that do not work in an Informix one You can set ANSIOWNER before starting your Informix server but that will merely change which combinations do not work You may want to examine usage patterns within the applications and choose a naming convention when translating the DDL that matches the most common naming convention used in the applications Note This behavior of Informix forces a tradeoff between using an ANSI mode database which most closely matches the transaction behavior of Oracle and a non-ANSI mode database which has the least mismatch in identifier case sensitivity

Reserved words or keywords

Oracle and Informix both allow identifiers to be reserved words as long as they are delimited However Oracle and Informix reserved words differ In addition both systems have keywords like FROM that are not always reserved in the sense that using them as an identifier will always generate a syntax error There should be few problems with reserved words or keywords if identifiers that are delimited in the original database remain delimited in the destination database The appendix Keywords of SQL for IBM Informix in the Guide to SQL Syntax contains more information about Informix keywords Also one word non-delimited identifiers should be verified against the Informix reserved words list to ensure that they do not need to be delimited or renamed Although almost any word can be used as an identifier in Informix syntactic ambiguities can result from using reserved words as identifiers in SQL statements Delimited identifiers provide a way to use a reserved word as an identifier without causing syntactic ambiguities However doing this changes a case-insensitive name into a case-sensitive one and that means that every reference to the object has to be checked for issues related to case-sensitivity Essentially this is not much less work than changing the name of the object because in essence it is changing the name of the object Examples

The following example shows how to create an Informix table with a case sensitive table name

CREATE TABLE My_Customers (hellip)

The following example shows how to create a table whose name includes a space character If the table name were not in quotation marks () a space character or any other non-alpha character except an underscore ( _ ) or dollar sign ($) (see special conditions above) could be used in the name

CREATE TABLE My Customers (hellip)

IBM Software Group IBM Information Management

Version 16 19

The following example shows how to create a table that uses a keyword as the table name

CREATE TABLE TABLE (hellip)

To include a double-quote () within a delimited identifier the double-quote () must be preceded with another double-quote () as shown in the following example

CREATE TABLE MyGoodData (hellip)

Summary

The main points to keep in mind when deciding about any questions on how identifiers should be translated are

Oracle always has delimited identifiers enabled and Informix does not

Oracle folds regular identifiers to uppercase and Informix folds to lowercase

Informix has behavioral differences between an ANSI mode database and a non-ANSI mode one

It is beneficial to consider the most common usage patterns within the existing application code prior to deciding default identifier translation patterns

Databases

Databases database names and instances

Oracle and Informix implement databases and instances differently Oracle considers a database to be a set of data files control file(s) and log files while an instance is a set of background processes and memory structures accessing database data Oracle instances are also known as servers Each Oracle instance or server runs against one database but through the use of Oracle Parallel Server a database may have multiple instances accessing it An Oracle database is named at initialization and the name has a limit of 8 ASCII characters Informix databases are defined as ldquoa collection of information contained in tables that are useful to a particular organization or used for a specific purposerdquo Informix database names may be up to 128 characters in length An Informix instance is a set of processes memory and disk allocations that manage data and will contain at least two and in most cases many databases Informix instances are also referred to as servers Informix databases may share disk allocations (dbspaces) with other databases within an Informix instance Oracle databases cannot share disk allocations (tablespaces) Informix databases should be created in a dbspace other than the root dbspace The root dbspace holds data for the system configuration information for the engine and so on If user-defined objects are created in this dbspace then the dbspace may become unmanageably large and during backup the system information may also get backed up unnecessarily The CREATE DATABASE statements of Informix and Oracle have differences which may require modification to routines responsible for database creation Informix will accept the same minimal syntax required by Oracle (eg CREATE DATABASE myDB) however issuing the command will implicitly accept the creation of a database without transaction logging enabled and establish the default location for all database objects as the instancersquos default storage location The instancersquos default storage location or ldquorootrdquo dbspace should not contain user-defined objects The root dbspace holds data for the system and some configuration information for the engine If user-

IBM Software Group IBM Information Management

Version 16 20

defined objects are created in this dbspace it may become unmanageable and result in the system contending with user objects for the available space

ANSI vs non-ANSI

Informix supports both ANSI and non-ANSI databases Informix non-ANSI databases are most common but there are some advantages of ANSI databases when porting from Oracle

Oraclersquos transaction behavior is more or less like that of an ANSI database Applications ported on Oracle are always in a transaction In Oracle and ANSI databases transactions begin implicitly with the first of a series of SQL statements and will end immediately after a commit or rollback statement Therefore unlike a non-ANSI database a COMMIT WORK statement does not need to be preceded with a BEGIN WORK statement

In ANSI databases database object references must be prefixed by the ownerrsquos name unless the owner is the one referencing the object If Oracle applications reference database objects with a both parts of the object name prefixing the object name with schema using an ANSI database may ease modifications necessary when porting to Informix

The ldquolsquogrant to PUBLICrdquorsquo concept provide by Informix database security does not apply to ANSI databases Every database object is private and privileges must be explicitly granted to each user

If an Informix ESQLC or 4GL application was developed to run on a non-ANSI Informix database (including BEGIN WORK statements) the application could run on an ANSI Informix database in one of two ways

By placing the BEGIN WORK statement in a pre-processor directive such as IFDEF object_name and omitting the proper preprocessor compile options such as -D object_name

By compiling the application normally and ignoring the resulting warning messages

Additionally the LOG MODE ANSI clause must be added to the CREATE DATABASE statements ANSI mode databases cannot have buffered logging Applications written to use an open API like ODBC or JDBC are compiled without awareness of the database and these APIs are written with the intent to abstract specific database behavior For instance in one of these the application developer would call a function to begin or end a transaction rather than execute a BEGIN and COMMIT or ROLLBACK The API would execute these statements internally or not as necessary for the database connection See the Transaction Processing section in Application Architecture for more information on how an application running on a non-ANSI Informix database can simulate Oracle transaction behavior

Tablespaces and dbspaces Oracle tablespace names need to be replaced with Informix dbspace names Unlike the Oracle tablespace the Informix dbspace cannot be created using DDL (SQL) scripts It must be created using the Informix onspaces utility before any DDL (SQL) scripts are executed Therefore Oraclersquos CREATE TABLESPACE statements should be removed from the DDL (SQL) scripts The user interface for accomplishing these tasks is onmonitor The command line utility is onspaces Therefore the onspaces commands can be placed in shell or batch scripts After successfully executing the onspaces commands the DDL (SQL) scripts may be called through the same shell or batch scripts For example

IBM Software Group IBM Information Management

Version 16 21

onspaces hellip onspaces hellip hellip dbaccess database_name DDL_script_file_name dbaccess database_name DDL_script_file_name hellip

Tables

Attributes and general syntax

When creating tables the Oracle CREATE TABLE statement must be converted to Informix taking advantage of the Informix options IN EXTENT NEXT and LOCK MODE

IN specifies the dbspace in which the table will reside

EXTENT specifies the amount of space that will initially be allocated to the table (16K default on most platforms)

NEXT specifies the amount of space that will be allocated when additional space is needed (16K default on most platforms

Lock mode

LOCK MODE specifies whether to use row or page locks for the table In Oracle the default is row level locking in Informix the default setting is page level locking However it can be changed by using one of the following methods (resolved in the following order of precedence)

1 LOCK MODE specified using an attribute of the CREATE TABLE or ALTER TABLE command syntax

2 IFX_DEF_TABLE_LOCKMODE environment variable setting 3 DEF_TABLE_LOCKMODE parameter setting in the ONCONFIG file

NOTE If the DEF_TABLE_LOCKMODE parameter cannot be found in the ONCONFIG file it can be added to make the specification for every database within the instance The Informix instance must be restarted for this parameter to take effect The new ldquodefaultrdquo LOCK MODE will apply to all tables created after the parameter has been changed To change the LOCK MODE of existing objects use the ALTER TABLE statement

Storage

The Oracle STORAGE INITIAL and STORAGE NEXT clauses must be changed to the Informix EXTENT SIZE and NEXT SIZE clauses respectively In Oracle the STORAGE clause options MINEXTENTS MAXEXTENTS and PCTINCREASE should be removed For example Oracle

CREATE TABLE dept(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13)

)

STORAGE (INITIAL 100K NEXT 50K MINEXTENTS 1 MAXEXTENTS 50

PCTINCREASE 5)

Informix CREATE TABLE dept (

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

IBM Software Group IBM Information Management

Version 16 22

EXTENT SIZE 200 NEXT SIZE 50

When an Oracle CREATE TABLE statement does not include a STORAGE clause the table will be created using the tablespace STORAGE clause by default If an Oracle tablespace is created specifying a STORAGE INITIAL of 100KB and a STORAGE NEXT of 50KB then all tables created within that tablespace will have a default value of STORAGE INITIAL 100KB and STORAGE NEXT 50KB Oracle tables cannot be created with smaller STORAGE clause values than the tablespace default they are created in Informix dbspaces do not have storage clauses attached to them As stated earlier the default Informix EXTENT and NEXT sizes are 16KB on most platforms The minimum EXTENT and NEXT sizes are 4 times the page size

Constraints

The Oracle constraint syntax must be changed to the Informix syntax for primary keys foreign keys unique and so on For example

Oracle CONSTRAINT PK_NUMBER PRIMARY KEY(CUST_NUM)

CONSTRAINT CK_EMP_CODE CHECK (EMP_CODE gt 100)

Informix PRIMARY KEY(CUST_NUM) CONSTRAINT PK_NUMBER

CHECK (EMP_CODE gt 100) CONSTRAINT CK_EMP_CODE

An Oracle check constraint statement may contain functions that are not available in Informix In this circumstance it may be necessary to code the combination of a trigger and a stored procedure to emulate the same functionality A trigger based on an insert or update event can execute a stored procedure which tests the constraint condition and if necessary raise an exception to reject the row data which violates the constraint The Oracle PARALLEL clause which specifies parallel execution of an operation must be removed from any SQL statements (such as CREATE TABLE and ALTER TABLE) In Informix there are ways to accomplish this parallel execution depending on the context in which these SQL statements are called (shell script file batch file and so on)

ALTER TABLE

Informix offers a rich set of ALTER TABLE features adding and dropping columns (rename by using the RENAME statement) changing column data types altering the next size and changing the lock mode Informix will choose one of three algorithms when executing an ALTER TABLE statement depending upon the operation to be performed For certain conditions the database server uses either a ldquoslowrdquo ldquoin-place or ldquofastrdquo alter algorithm to modify the table Informix provides ldquoin-placerdquo alter table support for adding or dropping a column anywhere in the table changing the column length and changing the column data type without an exclusive lock on the table An ldquoin-placerdquo alter will modify the tablersquos definition without changing the existing rows or unloading and reloading the data After the ALTER TABLE operation the database server inserts rows using the latest definition Informix will not change the row structure until a data row is touched by a user operation Once a query accesses a row that is not yet converted there can be a slight degradation in the performance because the database server reformats each row in memory before it is returned Informix uses the ldquoslowrdquo alter algorithm when the ALTER TABLE statement makes column changes that it cannot perform in place This type of alter would be

Adding or drop a column created with the ROWIDS keyword

Dropping a column of the TEXT or BYTE data type

IBM Software Group IBM Information Management

Version 16 23

Converting an INT or a SMALLINT column to SERIAL or SERIAL8

Modifying the data type of a column so that some possible values of the old data type cannot be converted to the new data type

For example if you modify a column of data type INTEGER to CHAR(n) the database server uses the slow ALTER algorithm if the value of n is less than 11 An INTEGER requires 10 characters plus one for the minus sign for the lowest possible negative values

Modifying the data type of a fragmentation column in a way that value conversion might cause rows to move to another fragment

Adding dropping or modifying any column when the table contains user-defined data types or smart large objects

When the database server uses the slow alter algorithm to process an ALTER TABLE statement the table can be unavailable to other users for a long period of time because the database server will lock the table exclusively for the duration of the operation make a copy of the table to convert the table to the new definition and convert the data rows This type of ALTER TABLE processing can encounter the scenario of a statement being a long transaction and abort it if the Long Transaction High Water Mark (LTXHWM) threshold is exceeded Informix will use the ldquofastrdquo alter algorithm when the ALTER TABLE statement changes attributes of the table but does not affect the data The database server uses the fast alter algorithm when you use the ALTER TABLE statement to make the following changes

bull Change the next-extent size

bull Add or drop a constraint

bull Change the lock mode of the table

bull Change the unique index attribute without modifying the column type

With the ldquofastrdquo alter algorithm the database server holds a lock on the table for a very brief period In some cases the database server will lock the system catalog tables but only long enough to change the attribute In either case the table is unavailable for queries for only a short time

Data Partitioning

Informix Table Fragmentation is the counterpart to Oraclersquos Table Partitioning and allows the user to control where data is physically placed at the table level Table Fragmentation or Data Partitioning is typically done to large tables but Informix and Oracle implement fragmentation and partitioning for different reasons and with different results Informix recommends using table fragmentation to improve single-user response time concurrency data availability backup restore characteristics and data-load performance While Oracle does state that table partitioning may improve the performance of queries and that the Oracle optimizer takes partitioning into account the primary goal of partitioning in Oracle is improving database maintenance Partitioning strategies in Oracle include range partitioning as well as hash and composite partitioning Composite partitioning combines range and hash partitions through the use of sub-partitions Tables incorporating Oracle LOBrsquos (large objects) cannot be partitioned Informix fragmentation strategies include expression-based and round robin Basic expression-based fragmentation can replace Oracle range partitioning Unlike Oracle LOBs Informixrsquos Smart Large Objects can be fragmented Examples of creating tables with Oracle range partitioning and Informix fragmentation by expression are shown below Oracle range partitioning

CREATE TABLE dept

IBM Software Group IBM Information Management

Version 16 24

(

deptno NUMBER(2)

dname VARCHAR2(14)

loc VARCHAR2(13) )

partition by range (deptno)

(partition PART1 values less than (11)

tablespace PART1_TS

partition PART2 values less than (21)

tablespace PART2_TS

partition PART3 values less than (31)

tablespace PART3_TS

partition PART4 values less than (MAXVALUE)

tablespace PART4_TS)

Informix expression based fragmentation CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

deptno lt 11 IN dbspace1

deptno gt= 11 AND deptno lt 21 IN dbspace2

deptno gt= 21 AND deptno lt 31 IN dbspace3

REMAINDER IN dbspace4

Oracle uses MAXVALUE for values not found in the specified range while Informix uses the REMAINDER keyword for values that fall outside the specified expression or expressions Prior to IDS version 1000 each table fragment had to go into a separate dbspace Now tables can be fragmented within a single dbspace You can create partitions within a dbspace that can each support a table fragment It is better to have one chunk per disk drive and now it is not necessary to create a dbspace just to facilitate fragmentation This feature can simplify the management of dbspaces The benefits gained through this new development include

It reduces the total number of dbspaces needed for a fragmented table

Storing multiple table fragments in a single dbspace improves query performance over storing each fragmented expression in a different dbspace

For example Informix partition fragmention in a single dbspace

CREATE TABLE dept(

deptno SMALLINT

dname VARCHAR(14)

loc VARCHAR(13)

)

FRAGMENT BY EXPRESSION

PARTITION part1 (deptno lt 11) IN dbspace1

PARTITION part2 (deptno lt 21) IN dbspace1

PARTITION part3 (deptno lt 31) IN dbspace1

PARTITION part4 REMAINDER IN dbspace1

Partitions of an Informix fragmented table can be manipulated using the ALTER FRAGMENT statement which supports attaching detaching adding modifying and dropping as well as initializing the distribution strategy

IBM Software Group IBM Information Management

Version 16 25

For example the following SQL removes a partition fragment and places the contents into a new table

ALTER FRAGMENT ON TABLE dept DETACH PARTITION part3 dept_part3

Making use of ALTER FRAGMENT to detach fragments can be an effective way of deleting large quantities of rows from a table quickly and easily After the above statement completes the table will no longer contain rows with a deptno greater than 21 and less than 31 Refer to the Informix Guide to SQL Syntax for a complete description on how to use the ALTER FRAGMENT statement to change the distribution strategy or the storage location of an existing table or index

Data types

Numeric

Oraclersquos NUMBER data type needs to be replaced with one of the following Informix equivalent data types depending on the size of the column The Informix numeric data types are listed below

SMALLINT (-32767 to 32767)

INTEGER (-2147483647 to 2147483647)

BIGINT (-9223372036854775807 to 9223372036854775807)

INT8 (-9223372036854775807 to 9223372036854775807)

The BIGINT type is more efficient in terms of space and speed there are few reasons to use INT8 now that BIGINT is available

DECIMAL (floating point up to 32 significant digits -10-130

to 10124

)

In an ANSI database there is an implied scale of 0 when no scale is given so this is not strictly speaking a floating point type within an ANSI database

NUMERIC (floating point up to 32 significant digits -10-130

to 10124

)

FLOAT (double precision like double data type of C)

SMALLFLOAT (single precision like float data type of C)

REAL (same as SMALLFLOAT)

DOUBLE (same as FLOAT)

LONG (same as long data type of C)

Oraclersquos NUMBER data type is used to store zero positive and negative fixed size and floating point numbers with magnitudes between 10 x 10

-130 and 999 x 10

125 (38 9s followed by 88 0s)

with 38 digits of precision A fixed-point number is specified by NUMBER(p s) where p is the precision or the total number of digits and s is the scale or the number of digits to the right of the decimal point For example a column defined as NUMBER(104) would contain numbers in the format 9999999999 In Oracle the scale can range from -84 to 127 If the scale is 0 or not mentioned then the data type can be converted into Informixrsquos SMALLINT INTEGER or BIGINT depending on the precision or FLOAT SMALLFLOAT DOUBLE or REAL depending on usage in the application When the scale is positive the data type should be converted to Informixrsquos DECIMAL or NUMERIC A floating-point data type in Oracle is declared using the type NUMBER without mentioning scale and precision In Informix this can be replaced with FLOAT SMALLFLOAT REAL DOUBLE PRECISION or DECIMAL(p) in an non-ANSI database

IBM Software Group IBM Information Management

Version 16 26

Oracle allows a negative scale If the scale is negative the actual data is rounded to the specified number of places to the left of the decimal point For example a specification of NUMBER (10 -2) means to round to the hundred If the general form for any number is

mantissa X 10exponent

then precision is the number of digits in the mantissa and scale is the negative exponent Example

select cast( 987654321 AS NUMBER(10-2) ) from dual

returns

987654300

Informix does not support a negative scale If precision - scale is less than the maximum precision of an integer type then that is the most efficient type to use Failing that and if the database is non-ANSI a floating point DECIMAL can be used If that is not sufficient then it may be necessary to define a user type and associated functions Oracle also allows the scale to be greater than the precision Precision is just the number of digits that will be preserved A NUMBER(3 5) might have the value 000123 If the Oracle scale is less than the Informix maximum precision then the Oracle scale can be used for both the Informix precision and scale A NUMERIC(55) column could also store the value 000123 You may need to take into consideration not only the minimum and maximum values but the default size for data types For example when the size of the NUMBER data type is absent Oracle will default to NUMBER(38) while Informix defaults to NUMERIC(16) Oracle and Informix support the ANSI DECIMAL data type Therefore in the case of an ANSI data type the Oracle data type can be converted to the same Informix data type There are differences between conversions based on theory versus those based on practice For instance it is very common to see an undecorated NUMBER declaration where the customer database and applications are using integer data When converting NUMBER declarations it may be necessary to consider how the data is being used in order to determine the best type mapping

CHAR VARCHAR and LVARCHAR

In Oracle the default for a CHAR column is one character and the maximum allowed is 255 characters In Informix the maximum length of CHAR and LVARCHAR columns is 32767 Therefore Oraclersquos CHAR columns can always be converted to an Informix CHAR column The CHAR data type columns can only contain printable characters tabs and spaces The CHAR columns store leading and trailing spaces In Oracle a zero-length string can be inserted into a CHAR column but the column is padded with one blank character when it is used in comparisons Also in Informix a zero-length string can be inserted into a CHAR column however the column is padded with enough spaces to fill the column In the case of inserting NULL into an Informix CHAR column no padding occurs Oraclersquos VARCHAR and VARCHAR2 are currently synonymous and have a maximum data length of 4000 bytes while the maximum length for the Informix VARCHAR data type is 255 Informixrsquos CHAR and LVARCHAR data types have a maximum length of 32767 and 32739 respectively measured in bytes These should be used to replace Oraclersquos VARCHAR VARCHAR2 LONG and LONG VARCHAR if the data length is between 256 and the maximum If the data length exceeds the maximum use Informixrsquos TEXT BYTE BLOB or CLOB data types See the Raw Data section below for more information on TEXT BYTE BLOB and CLOB data types

IBM Software Group IBM Information Management

Version 16 27

Empty Oracle VARCHAR2 strings are considered NULL Empty Informix VARCHAR and LVARCHAR strings are not considered NULL rather they contain at least one space Oracle

compares VARCHAR2 values using non-padded comparison semantics Therefore ldquoBOBrdquo ldquoBOB ldquo Informix ignores trailing blanks Therefore ldquoBOBrdquo = ldquoBOB ldquo or ldquordquo = ldquo rdquo Hence checks for NULL within the application must be replaced with checks for an empty string (such as ldquordquo or ldquo rdquo) whenever an empty string is inserted into the column If NULL is truly inserted into the column checking for NULL is appropriate (for example SELECT FROM hellip WHERE hellip IS NULL) In Oracle LONG columns store variable length character strings containing up to 2 gigabytes or 2

31-1 bytes Informix LONG columns store numeric data Oraclersquos LONG columns have many of

the characteristics of VARCHAR2 columns They can be used in a SELECT list in the SET clause of an UPDATE statement and in an INSERT statement but they cannot be used in a WHERE clause a GROUP BY clause or an ORDER BY clause and they cannot be indexed Oraclersquos LONG columns should be converted to an Informix Smart Large Object or ldquoSLOBrdquo (BLOB CLOB) column

Date and Time

Oraclersquos DATE data type contains date and time components from year down to second It can be to be replaced most directly with Informixrsquos DATETIME YEAR TO SECOND Some analysis may be necessary to determine whether the time is really necessary In other words does the application reference the date and time portions of the values If the application only references the date portion then replace Oraclersquos DATE with Informixrsquos DATE and change the host variable to X(10) or char(10) accordingly The Informix DATE default display format is MM-DD-YYYY although the DATE data type stores the calendar date The Informix DATE data type requires 4 bytes which is stored internally as an integer value equal to the number of days since December 31 1899 The default display format can be changed with the environment variable DBDATE If the application uses different date formats then using DBDATE is not a solution Sometimes it might be necessary to write small subroutines to emulate Oraclersquos DATE representations See the Informix Guide to SQL Reference manual for details on DBDATE and also DBCENTURY If the application only references the time portion of the values replace Oraclersquos DATE with Informixrsquos DATETIME using the EXTEND function to specify precision In addition Informix provides the data type INTERVAL for use while performing DATE and DATETIME calculations In Oracle the DATE data type is used to store date and time information Although date and time information can be represented in both CHAR and NUMBER data types the DATE data type has special associated properties For each DATE value the following information is stored

century

year

month

day

hour

minute

second

Also regarding the Oracle DATE data type if a date value without a time component is specified the default time is 120000am If a DATE value without a date is specified the default date is the first day of the current month

Interval

Within Informix there are two classes of interval types YEAR-MONTH and DAY-FRACTION There are different numbers if days in different months so the MONTH-DAY boundary cannot be crossed without creating ill-defined results Within each of these classes Informix allows you to declare columns or variables as any subset of the start and end fields Oracle has one INTERVAL

IBM Software Group IBM Information Management

Version 16 28

type for each of the two classes YEAR(p) TO MONTH and DAY(p) TO SECOND(s) The Oracle scale on the SECOND field is logically equivalent to the Informix scale on the FRACTION field

Raw data and Large Objects

Oraclersquos support of large blocks of raw unstructured data (such as graphic images video clips and sound waveforms) in binary or character format is provided by the large object (LOB) data types BLOB CLOB NCLOB and BFILE Traditional Oracle data types MLSLABEL (used with Trusted Oracle) RAW and LONG RAW are also used for data that is not to be interpreted by the engine and converted when moving data between different systems Informix supports two types of large objects (LOBs Simple Large Objects and Smart Large Objects Simple LOBs consist of the TEXT and BYTE data types and can be 2

31 bytes or 2

Gigabytes in size Smart LOBs include both Character Large Object (CLOB) and Binary Large Object (BLOB) data types and may be up to 42

40 bytes or 4 Terabytes in size Simple LOBs can

be stored either in-line with table data or in blobspaces while Smart LOBrsquos are stored in sbspaces Oraclersquos CLOB BLOB MLSLABEL RAW and LONG RAW data types should be replaced with Informixrsquos BYTE TEXT CLOB or BLOB depending on the columnrsquos size and usage Informixrsquos Smart BLOB data types CLOB and BLOB should be used under the following conditions and considerations

The large object needs to be referenced by multiple sources

The object size exceeds 2 GB

Fragmentation is required

Byte level locking is available making it possible to lock only a portion of the object

Logging can be specified at the object level

Updates are done in place or moved as needed

Be aware of the following restrictions for Simple Large Objects

Data can only be inserted into a BYTE or TEXT column with the dbload or onload utilities the DBACCESS load statement BYTE or TEXT host variables respectively in ESQLC or declaring a file in ESQLCOBOL

BYTE and TEXT columns cannot be inserted or updated with a literal neither quoted text string nor number

BYTE or TEXT columns cannot be used in string operations with aggregate functions with the GROUP BY ORDER BY IN LIKE or MATCHES clauses

ROWID

The implementation of ROWID differs between Oracle and Informix Oraclersquos ROWID is both a pseudo-column and a data type See the ROWID subsection in the Pseudo-Columns section in CHAPTER 3 Data Manipulation Language for more information Informix implements ROWID as a pseudo-column only Oracle stores the ROWID column and ROWID data type column values in hexadecimal format Informix stores the ROWID column values in INTEGER format The Oracle and Informix engines maintain the values of the ROWID pseudo-column Oraclersquos engine does not maintain the values of other columns of type ROWID In Informix the term rowid refers to an integer that defines the physical location of a row Informix assigns rows in a non-fragmented table a unique rowid which allows applications access to a particular row in a table Rows in fragmented tables in contrast are not assigned a rowid To access data by rowid in a fragmented table a rowid column must be explicitly created as is described in the Informix Guide to SQL Reference manual Creating a Rowid Column If applications attempt to reference a rowid in a fragmented table that does not contain a rowid that was explicitly created Informix displays an appropriate error message and execution of the application is halted

IBM Software Group IBM Information Management

Version 16 29

When used as a data type for a column Oracle does not guarantee that the values are valid ROWIDs For example if the ROWID is used as a data type on a column such as a column in a child table named parent_rowid containing the ROWID of the parent then the values are maintained by the application outside of the engine The application must read the ROWID of the parent and insert it into the parentrsquos corresponding child table rows This is usually done so the two tables can be joined on the parentrsquos ROWID and the childrsquos parent_rowid column This functionality can be duplicated in Informix by using primary and foreign keys Informix recommends that primary keys are used as a method of access in applications rather than rowids because primary keys are defined in the ANSI specification of SQL using them to access data makes applications more portable Refer to the Informix Guide to SQL Reference and the Informix Guide to SQL Syntax for a complete description on how to define and use primary keys to access data

User-defined types

Both Oracle and Informix allow the user to create and define data types Oracle refers to these as abstract data types while Informix refers to these as user-defined types In Oracle all user-defined types are referred to as abstract data types while Informix may refer to user-defined types as COLLECTION types ROW types DISTINCT types and OPAQUE types Currently the Informix ROW type is closest in form and function to the Oracle abstract data type An example of syntax for creating both an Oracle abstract data type and an Informix ROW type is shown below

Oracle abstract data type

CREATE TYPE name_type AS OBJECT

(first_name VARCHAR2(25)

middle_initial CHAR(1)

last_name VARCHAR2(30))

Informix row type

CREATE ROW TYPE name_type

(first_name VARCHAR(25)

middle_initial CHAR(1)

last_name VARCHAR(30))

Both Oracle and Informix support the use of user-defined types for table definition or column definition within a table Building on the example above the following create table example show a table definition and column definition within a table based on user-defined types Oracle table creation

CREATE TABLE name OF name_type

Informix table creation

CREATE TABLE name OF type name_type

Oracle column definition

CREATE TABLE employee

(empno NUMBER(9)

name name_type)

Informix column definition

CREATE TABLE employee

IBM Software Group IBM Information Management

Version 16 30

(empno INTEGER

name name_type)

For more information on User Defined Types see the Informix Guide to SQL Syntax

Complex data types

Informix offers users the ability to create data types from existing built-in types OPAQUE types DISTINCT types and other complex types Complex data types may either be a ROW type or a COLLECTION type Oracle treats complex data types as abstract data types For more information on Oracle abstract data types see the User Defined Types section above For more information on Complex Data Types see the Informix Guide to SQL Syntax For recommended type mappings and additional information see the appendix ldquoData type mappingsrdquo

Sequence objects

Oracle sequences

An Oracle sequence is a database object from which multiple users or transactions may generate unique integers For example sequences can be used to automatically generate primary key values When a sequence object is queried the sequence number is incremented and passed to the query independent of the transaction committing or rolling back If two applications increment the same sequence the sequence numbers each application acquires may not be sequential since sequence numbers are being generated by the other application One user or transaction can never acquire the sequence number generated by another user or transaction Once a user or transaction generates a sequence value that value will never be generated and passed to another user or transaction

Informix sequences

Informix rsquos implementation of sequence objects is identical to that of Oracle Issues regarding syntax compatibility should be negligible with the exception of some keywords which have no effect on the behavior of the sequence Informix supports DML statements (CREATE SEQUENCE ALTER SEQUENCE RENAME SEQUENCE DROP SEQUENCE) for sequence objects that multiple users can access concurrently to generate unique integers in the 8-byte integer range GRANT and REVOKE statements support access privileges on sequence objects and the CREATE SYNONYM and DROP SYNONYM statements can be used to reference synonyms for sequence objects in the local database The operators CURRVAL and NEXTVAL can read or increment the value of an existing synonym with behavior the same as Oracle

Indexes

Composite indexes

A composite index can have up to 16 key parts that are columns or up to 341 key parts that are values returned by a UDR This limit is language-dependent and applies to UDRs written in SPL or Javatrade functional indexes based on C language UDRs can have up to 102 key parts A composite index can have any of the following items as an index key

One or more columns

IBM Software Group IBM Information Management

Version 16 31

One or move values that is returned by a user-defined function (referred to as a functional index)

A combination of columns and user-defined functions

Maximum key size

The total widths of all indexed columns in a single CREATE INDEX statement have a limitation based upon the page size of the dbspace in which the index resides This limitation does not apply to functional indexes An enhancement introduced with Informix Dynamic Server Version 1110 is configurable page sizes for dbspaces Prior to this release the page size of dbspaces were restricted to that of the operating system and could not be changed thus Informix was limited to 390 byte indexes With page sizes configurable from 2K through 16K wider indexes are supported Refer to the table below 16K page sizes raises the limit on index width to over 3000 bytes Lifting the 390 byte limit also permits LVARCHAR columns larger than 387 bytes to be included in an index definition

Page Size Maximum Key Size

2 kilobytes 387 bytes

4 kilobytes 796 bytes

8 kilobytes 1615 bytes

12 kilobytes 2435 bytes

16 kilobytes 3245 bytes

In addition to aiding the porting process wider indexes have satisfied requirements for Unicode data as well as provide performance gains by reducing B-Tree index traversal costs since indexing can be built with more items on an index page and produce fewer levels

Index fragmentation

Just as Oracle and Informix support table fragmentation or partitioning in Oracle both support index fragmentation as well See the Table fragmentation section above for more information regarding Informix table fragmentation and Oracle table partitioning Oracle indexes that are partitioned in the same manner as the table they are indexing are referred to as local indexes Informix refers to these as attached indexes Oracle indexes that span partitions are known as global indexes Informix refers to these as detached indexes Informix detached indexes may also refer to indexes that do not follow the same fragmentation scheme as the table they are indexing Starting with Informix version 1110 indexes can be fragmented similarly to tables on a partition level

General index information

The Informix CLUSTER option should be used when appropriate This option orders the data within the table in the order the index requires It is important to note that the CLUSTER index is not maintained over time The primary factor determining the frequency of CLUSTER index rebuilds is the amount of DML performed against the table Frequent INSERTS UPDATES and DELETES make it necessary to closely monitor CLUSTER indexes There is only one clustered index per table since a tablersquos data can only be stored in one order Oraclersquos INITRANS and PCTFREE functionality is similar to the Informix index FILLFACTOR option of the CREATE INDEX statement or the FILLFACTOR configuration parameter in the ONCONFIG file In either case the functionality is handled by Informixrsquos engine once it is set and can be removed from the application FILLFACTOR specifies the degree of index-page

IBM Software Group IBM Information Management

Version 16 32

compactness A low value provides room for growth in the index A high value compacts the index If an index is fully compacted (100 percent) any new inserts result in splitting nodes The setting on the CREATE INDEX statement overrides the ONCONFIG file value The FILLFACTOR default value for both the CREATE INDEX statement as well as the ONCONFIG is 90 Informix has no support for bitmap indexes

Views Oraclersquos CREATE VIEW statement contains three options FORCE NO FORCE and WITH READ ONLY FORCE creates the view regardless of whether the views base tables exist or the owner of the schema containing the view has privileges on them NO FORCE creates the view only if the base tables exist and the owner of the schema containing the view has privileges on them WITH READ ONLY specifies that no deletes inserts or updates can be performed through the view These options must be removed from the Informix CREATE VIEW statements Because a view is not really a table it cannot be indexed and it cannot be the object of such statements as ALTER TABLE and RENAME TABLE The columns of a view cannot be renamed with RENAME COLUMN To change anything about the definition of a view you must drop the view and re-create it Because it must be merged with the userrsquos query the SELECT statement on which a view is based cannot contain any of the following clauses

INTO TEMP The userrsquos query might contain INTO TEMP if the view also contains it the data would not know where to go

UNION The userrsquos query might contain UNION No meaning has been defined for nested

UNION clauses

ORDER BY The userrsquos query might contain ORDER BY If the view also contains it the choice of columns or sort directions could be in conflict

Stored procedures and triggers The ways stored procedures and triggers are created differ between Oracle and Informix Oracle allows a REPLACE clause in the CREATE statement to handle situations when the object already exists Informix does not support the REPLACE option Instead a DROP PROCEDURE or DROP TRIGGER statement must precede the CREATE PROCEDURE or CREATE TRIGGER statement respectively to handle the situation when the object already exists It should be noted a DROP statement will generate an error when the object does not exist If it is run interactively within the DBACCESS user interface the DROP statement error will terminate processing If it is run using script execution using DBACCESS at the command line processing will continue To run DBACCESS from the command line type

dbaccess db_name

To run the file containing the create statements from the command line type dbaccess db_name sql_file_name

Informix introduced an IF EXISTS clause to most of the CREATE and DROP statements at 117 but the logic is different from Oraclersquos OR REPLACE clause For example these statements

IBM Software Group IBM Information Management

Version 16 33

DROP PROCEDURE IF EXISTS hellip

CREATE PROCEDURE hellip

are logically the same as this Oracle statement

CREATE OR REPLACE PROCEDURE hellip

So it is possible to achieve the same result but not necessarily the same number of statements

Oracle extensions The Oracle CLUSTER option in CREATE statements should be removed These are not to be confused with Informix CLUSTER index statements (See Indexes section above) An Oracle cluster is a database schema object that contains one or more tables that all have one or more columns in common Rows of one or more tables that share the same value in these common columns are physically stored together within the database Removing this Oracle feature will not affect the application Other non-Informix DDL statements like CREATE DATAFILE CREATE CONTROLFILE CREATE ROLLBACK SEGMENT CREATE SNAPSHOT CREATE DATABASE and CREATE DATABASE LINK must be removed or changed (in the case of the CREATE DATABASE statement) The Oracle CREATE PROFILE statement must be removed An Oracle profile is a set of limits on database resources Profiles can be used to limit the database resources available to a user for a single SQL statement or a single session

IBM Software Group IBM Information Management

Version 16 34

C H A P T E R 4 Data Manipulation Language

SQL

Labels using keywords

Oracle displays labels in SQL statements that are Informix reserved words such as UNITS YEAR MONTH DAY HOUR and so on must be converted by using the Informix AS clause between the column name and the display label Otherwise syntactic ambiguities will cause errors

Inequality operations

In addition to the Informix supported ldquonot equal tordquo symbols ldquoltgtrdquo and ldquo=rdquo Oracle supports the symbol ldquo^=rdquo All occurrences of ^= must be replaced with one of the Informix supported symbols

Selects

Queries are executed based on how the optimizer determines the best path to the data Oracle and Informix developed their own query optimizers with their proprietary methods and rules A query that looks exactly the same in both environments may run differently in each following a different path and executing faster or slower Therefore every query in the ported application should be tested for performance regardless of whether a query had to be converted Furthermore Oracle supports optimizer hints within a SELECT statement Prior to IDS 73 and Informix Dynamic Server 92 Informix did not allow optimizer hints See the Optimizer Directives subsection below for more information on porting Oraclersquos optimizer hints to Informixrsquos optimizer directives

Optimizer directives

Informix offers optimizer directives similar to Oraclersquos optimizer hints This feature provides the query developer the flexibility to direct the optimizer to follow specific paths rather than choosing a plan through its analysis A query is processed in two steps First it is optimized and compiled to product a query plan Secondly it is executed to produce a result Optimizer directives are a method for influencing the choice of the optimizer in the creation of the plan

IBM Software Group IBM Information Management

Version 16 35

Optimizer directives address the following key issues

Reduced time for correcting performance problems Rewriting queries can be very time consuming and this allows you to have a quick way to alter a plan

Competitive pressure Users accustomed to this function were looking for it in Informix

Product development tuning This allows product development to alter plans dynamically rather than through code changes to evaluate the effect of different optimization techniques

The syntax and behavior of Informixrsquos implementation is compatible with Oraclersquos optimizer hints which eases the porting of applications from Oracle to Informix Directives are written as a comment whose first character is a lsquo+rsquo (plus sign) An example is

select + ORDERED AVOID_FULL(e) empname deptno

from employee e department d

where edept_no = ddept_no

This above example specifies that the tables should be joined in the order specified in the query and that the employee table (e) should NOT be accessed with a full table scan The Informix implementation differentiates itself significantly from Oraclersquos in one way Informix supports the notion of negative directives whereas Oracle only supports direct hints A directive that tells the optimizer what to avoid rather than what to choose is unique to Informix The query result can be realized by writing a directive to avoid certain actions known to cause performance issues but allow any new indexes or table attributes to be explored by the optimizer as they are added over the life of the table and query This allows a DBA to continue to add indexes to tables and not have to rewrite directives Additionally Informix supports full recognition of directives with SET EXPLAIN output Informix will highlight semantic and syntactic errors which Oracle does not Optimizer directives support control in the following areas of the optimization process

Access methods Index versus scans

Join Methods Forcing hash joins nested loop joins

Join Order Specify which order the tables are joined

Goal Specify first rows or all rows (response time versus throughput) See the Informix Guide to SQL Syntax or Reference for more information

External optimizer directives

External optimizer directives give the DBA the ability to specify query directives and save them in the database These directives are applied automatically to subsequent instances of the same query The SAVE EXTERNAL DIRECTIVES statement associates one or more optimizer directives with a query and stores a record of this association in the sysdirectives system catalog table for subsequent use with queries that match the specified query string The query string must be an exact match that includes case and white space positioning This statement establishes an association between the list of optimizer directives and the text of a query but it does not execute the specified query Only the DBA or user informix can execute SAVE EXTERNAL DIRECTIVES This associates AVOID_INDEX and FULL directives with the specified query

SAVE EXTERNAL DIRECTIVES

+ AVOID_INDEX (table1 index1) + FULL(table1)

ACTIVE FOR

SELECT col1 col2 FROM table1 table2

IBM Software Group IBM Information Management

Version 16 36

WHERE table1col1 = table2col1

These directives are applied automatically to subsequent instances of the same query You must include one of the ACTIVE INACTIVE or TEST ONLY keyword options to enable disable or restrict the scope of external directives When external directives are enabled and the sysdirectives system catalog table is not empty the database server compares every query with the query text of every ACTIVE external directive and for queries executed by the DBA or user informix with every TEST ONLY external directive External directives are ignored if the EXT_DIRECTIVES parameter is set to 0 in the ONCONFIG file In addition the client system can disable this feature for its current session by setting the IFX_EXTDIRECTIVES environment variable to 0 If an external directive has been applied to a query output from the SET EXPLAIN statement indicates ldquoEXTERNAL DIRECTIVES IN EFFECTrdquo for that query Any inline directive is ignored by the optimizer when the external directives are applied to a query that matches the SELECT statement Like inline optimizer directives that are embedded within a query external directives can improve performance in some queries for which the default behavior of the query optimizer is not satisfactory Unlike inline directives external directives can be applied without revising or recompiling existing applications

Inserts

Informix does not support Oraclersquos INSERT with SELECT statement utilizing an UNION clause (although a view with an UNION clause can be referenced resulting in an UNION operation) Additionally Informix does not support an INSERT statement with a VALUE clause with SELECT statements The SELECT statement within a VALUE clause can be rewritten by omitting the VALUE clause and performing an INSERT INTO table_name SELECT hellip FROM other_table_name

Temporary tables

Informix and Oracle implemented the concept of temporary tables differently Oracle implements temporary tables as a work area during batch data loads Informix implements temporary tables just like regular database tables These temporary tables can be created manipulated and dropped only within a session such as stored procedures and ESQL programs Once the session ends any remaining temporary tables are automatically dropped Temporary tables can give an application extra functionality however their use should be limited if reducing database extensions to increase database independence within an application is a priority

Outer joins

Both Oracle (starting with Oracle 9i) and Informix support ANSI standard syntax for outer join specification The syntax for left and right outer join using the plus sign (+) in the WHERE clause is only supported for backward compatibility however it is still in existence The use of ANSI outer join syntax is recommended The Oracle outer join syntax + (placed after the column which has values not matching the corresponding column in the joined table) can be replaced with the Informix equivalent OUTER The OUTER keyword is placed within the SELECT statement before the name of the subservient table Unlike Oracle in Informix multiple outer joins per SELECT statement are allowed grouped with parentheses

Sorts

In Oracle sorts NULL values are considered the highest value and are therefore ordered last in ascending sorts Informix sorts with NULLS as the lowest value ordering them first in ascending sorts First it must be determined whether this sorting difference will affect the outcome enough to warrant a work around In most cases it will not If it does then a stored procedure can be

IBM Software Group IBM Information Management

Version 16 37

written to evaluate whether a column is NULL and if so replace it with a high value so that it will sort last Once the application receives the results it must replace the high values with NULL if the column is going to be displayed or manipulated

Exceptions

Error handling using hard coded Oracle SQL codes must be replaced with the corresponding Informix SQL codes

Correlation names

Informix does not support correlation names with aliases on the main table of an UPDATE or DELETE statement Such cases must be converted For example

Oracle UPDATE customer C

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE Ccreate_date lt= Zeffective_date)

Informix UPDATE customer

SET zip_code = lsquo92612rsquo

WHERE zip_code IN

(SELECT zip_code FROM zip_table Z

WHERE customercreate_date lt= Zeffective_date)

-and-

Oracle DELETE customer C

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND Cstate = Tstate )

Informix DELETE customer

WHERE order_date lt=

(SELECT control_value FROM control_table T

WHERE Tcontrol_field = lsquoarchive_datersquo

AND customerstate = Tstate )

Note that Informix allows correlation names with aliases on tables other than the updated or deleted table

Aliases

Unlike Oracle in Informix if an alias is used in the FROM clause of a SELECT statement it must also be used in the SELECT list and WHERE clauses The original table name should be replaced with the alias wherever aliases and original names are used together within a SELECT statement in an Oracle application

Hierarchical queries

Informix does not allow query results to be organized hierarchically in a B-tree fashion Oracle does allow it by using the clauses START WITHhellip and CONNECT BY PRIOR in the SQL

IBM Software Group IBM Information Management

Version 16 38

statement In Oracle if a table contains hierarchical data a bill of materials for example rows can be selected in a hierarchical order using the following clauses START WITH

The START WITH clause identifies the row(s) to be used as the root(s) of a hierarchical query This clause specifies a condition that the root(s) must satisfy If this clause is omitted Oracle uses all rows in the table as root rows A START WITH condition can contain a subquery

CONNECT BY

The CONNECT BY clause specifies the relationship between parent and child rows in a hierarchical query This clause contains a condition that defines this relationship The part of the condition containing the PRIOR operator must have one of the following forms

PRIOR expression comparison_operator expression -or- expression comparison_operator PRIOR expression

To find the children of a parent row Oracle first evaluates the PRIOR expression to identify the parent row(s) and the other expression for each row in the table Rows for which the other expression is true are the children of the parent The CONNECT BY clause can contain other conditions to further filter the rows selected by the query

WHERE

The WHERE clause can restrict the rows returned by the query without affecting other rows of the hierarchy

Oracle uses the information from each of the clauses mentioned above to form the hierarchy using the following steps

1 Oracle selects the root row(s) of the hierarchy These are the rows that satisfy the condition of the START WITH clause

2 Oracle selects the child rows of each root row Each child row must satisfy the condition of the CONNECT BY clause with respect to one of the root rows

3 Oracle selects successive generations of child rows Oracle first selects the children of the rows returned in step 2 and then the children of those children and so on Oracle always selects children by evaluating the CONNECT BY condition with respect to a current parent row

4 If the query contains a WHERE clause Oracle removes all rows from the hierarchy that do not satisfy the condition of the WHERE clause Oracle evaluates the WHERE condition for each row individually after the row has been fetched rather than only fetching rows that satisfy the WHERE condition

5 Oracle returns the rows in the order of an in-order or left-root-right binary tree traversal

IBM Software Group IBM Information Management

Version 16 39

For example the following SQL statement returns the data in the adjacent table in hierarchical order The root row is defined to be the employee whose job is lsquoPRESIDENTrsquo The child rows of a parent row are defined to be those rows whose manager number is the employee number of the parent row

SELECT ename empno mgr job FROM emp START WITH job = lsquoPRESIDENTrsquo CONNECT BY PRIOR empno = mgr

To duplicate this hierarchical functionality in Informix stored procedures or functions can be written requiring intensive use of cursors and program arrays Informix offers the choice of creating and using a User Defined Routine or ldquoUDRrdquo See User Defined Routines section below Use of Informix global arrays will help considerably To maximize read processing at the expense of insert processing another method is to break the table into two tables one containing the data and the other containing the relationship (foreign keys) between each parent and child A parent row would have an entry in the relationship table for each of its children grandchildren great grandchildren and so on The opposite is true where a child row would have an entry in the relationship table for its parent grandparent great grandparent and so on

Truncate

Informix supports the TRUNCATE statement for deleting all active data rows from a table and associated indexes When using Informixrsquos TRUNCATE you also have the option of releasing the storage space that was occupied by the rows and index extents or keeping the space allocated to be used as the table is repopulated with new data

TRUNCATE [TABLE] table [ [ DROP | REUSE ] STORAGE ]

You may use the commandrsquos simplest usage

TRUNCATE my_table

In the example above the TRUNCATE statement drops all the data for the table and keeps only the initial extents There is a minor difference from Oracle syntax as Informix does not require the keyword TABLE Another example

TRUNCATE my_table REUSE STORAGE

ENAME EMPNO MGR JOB

KING 7839 PRESIDENT

JONES 7566 7839 MANAGER

SCOTT 7788 7566 ANALYST

ADAMS 7876 7788 CLERK

FORD 7902 7566 ANALYST

SMITH 7369 7902 CLERK

BLAKE 7698 7839 MANAGER

ALLEN 7499 7698 SALESMAN

WARD 7521 7698 SALESMAN

MARTIN 7654 7698 SALESMAN

TURNER 7844 7698 SALESMAN

JAMES 7900 7698 CLERK

CLARK 7782 7839 MANAGER

MILLER 7934 7782 CLERK

IBM Software Group IBM Information Management

Version 16 40

This example drops all the data for the table but retains all the space allocated The permissions needed for TRUNCATE TABLE depend on the existence of DELETE triggers on the table For tables with DELETE triggers ALTER permission on the table is required and RESOURCE or DBA privileges because the DELETE triggers will be bypassed For tables without DELETE triggers you need DELETE permission on the table and CONNECT privilege to the database While Oracle does not provide rollback Informix does permit TRUNCATE TABLE to execute within a transaction When you rollback a TRUNCATE statement no rows are removed from the table and the storage extents that hold the data rows and index pages continue to be allocated to the table In a database that supports transaction logging only the COMMIT WORK or ROLLBACK WORK statement is valid after the TRUNCATE statement within a transaction Any other statement will generate an error The TRUNCATE statement does not reset the serial value of SERIAL or SERIAL8 columns To reset the counter of a serial column you must do so explicitly by using the MODIFY clause of the ALTER TABLE statement either before or after you execute the TRUNCATE statement After the TRUNCATE statement successfully executes Informix automatically updates the statistics and distributions for the table and for its indexes in the system catalog to show no rows in the table nor in its dbspace partitions It is not necessary to run the UPDATE STATISTICS statement immediately after you commit the TRUNCATE statement

Host variables Host variable formats should not change during the porting process Instead data types should be converted in a manner to preserve the column and host variablersquos formats However there are times when the database schema changes in a way where the host variable format must change Any column converted to a different format in Informix than that of Oracle requires that its corresponding host variable format be changed to be consistent Alternatively if an Oracle format such as date and numeric variables is not directly supported in Informix then the conversion may require some format processing before or after the SQL statement For example the Oracle function TO_CHAR is used to format both date and numerical values A similar function or at least two functions one to handle date data types and another to handle numeric data types can be declared and used in the Informix application Informix provides two built-in functions TO_DATE which converts a character string to a DATETIME variable and TO_CHAR which converts a DATETIME variable to a character string When converting variables an optional formatting string is allowed which determines how the string is displayed (full day names partial day names full months month number and so on) There is also a function ifx_to_gl_datetime() which takes an Oracle date format and returns the corresponding Informix date format This function is supplied in genlib and is for use in ESQL programs to ease migration efforts from Oracle The syntax is as follows

TO_CHAR (source_date fmt) Returns a character string containing the date specified in source_date in the format specified by fmt if one is provided If fmt is missing the function will use the default date format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

TO_DATE (source_string fmt) Evaluates source_string as a date according to the

format fmt If fmt is missing the function will use the

IBM Software Group IBM Information Management

Version 16 41

default format (as specified by the client environment variables) Note fmt must be an Informix format and does not necessarily include all possible Oracle date formats

These functions are mainly useful for simplifying migration from Oracle to Informix but are also useful for performing advanced searches on DATETIME data types and for better output presentation

Date and time functions Informix version now has built-in support for most of Oraclersquos date functions so it will not be necessary to modify or replace Oraclersquos SYSDATE or ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat)

SYSDATE

IDS 1110 will support the SYSDATE operator which returns a single value representing the current date and time from the operating system clock SYSDATE is identical to the Informixrsquos CURRENT operator except that the default precision of SYSDATE is YEAR TO FRACTION(5) while the default precision of CURRENT is YEAR TO FRACTION(3) On Windows platforms that do not support a seconds scale greater than FRACTION(3) SYSDATE is effectively a synonym for the CURRENT operator In addition to SYSDATE Informix version 1110 has support for Oraclersquos date functions ADD_MONTHS(datemonths) LAST_DAY(date) MONTHS_BETWEEN(date1 date2) NEXT_DAY(datechar) ROUND(dateformat) SYSDATE and TRUNC(dateformat) Depending on the whether or not the Oracle date_format argument is supported by Informix TO_CHAR(date char_format) and TO_DATE(character_string date_format) may have to be converted to Informix date processing Date processing may be required because the Oracle application may format the date in many different ways unsupported by Informix The formats used in the Oracle functions TO_CHAR TO_NUMBER and TO_DATE are illustrated below These formats should be replaced with Informix formats wherever possible format processing functions or stored procedures written to duplicate the Oracle functionality Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

Number formats

Element Example Description 9 9999 Return value with the specified number of digits with a leading

space if positive Return value with the specified number of digits with a leading minus if negative Leading zeros are blank except for a zero value which returns a zero for the integer part of the fixed-point number

0 09999990 Return leading zeros Return trailing zeros $ $9999 Return value with a leading dollar sign B B9999 Return blanks for the integer part of a fixed-point number

when the integer part is zero (suppress leading zeros regardless of whether zeros are used in the format model ie B00999 )

MI 9999MI Return negative value with a trailing minus sign ldquo-ldquo Return positive value with a trailing blank

S S9999999 Return negative value with a leading minus sign ldquo-ldquo Return

IBM Software Group IBM Information Management

Version 16 42

Element Example Description S positive value with a leading plus sign ldquo+rdquo Return negative

value with a trailing minus sign ldquo-ldquo Return positive value with a trailing plus sign ldquo+rdquo

PR 9999PR Return negative value in ltangle bracketsgt Return positive value with a leading and trailing blank

D 99D99 Return a decimal point ldquordquo In the specified position G 9G999 Return a group separator in the specified position C C999 Return the ISO currency symbol in the specified position L L999 Return the local currency symbol in the specified position 9999 Return a comma in the specified position 9999 Return a decimal point ldquordquo In the specified position V 999V99 Return a value multiplied by 10

n (and if necessary round it

up) where n is the number of ldquo9rdquos after the ldquoVrdquo EEEE 99EEEE Return a value in scientific notation RNrn RN Return a value as Roman numerals in uppercase Return a

value as Roman numerals in lowercase Value can be an integer between 1 and 3999

FM FM909 Return a value with no leading or trailing blanks

Date formats

Element Meaning -rdquotextrdquo Punctuation and quoted text is reproduced in the result AD or AD AD indicator with or without periods AM or AM Meridian indicator with or without periods BC or BC BC indicator with or without periods CC or SCC Century ldquoSrdquo prefixes BC dates with ldquo-ldquo D Day of week (1-7) DAY Name of day padded with blanks to length of 9 characters DD Day of month (1-31) DDD Day of year (1-366) DY Abbreviated name of day IW Week of year (1-52 or 1-53) based on the ISO standard IYY or IY or I Last 3 2 or 1 digit(s) of ISO year IYYY 4-digit year based on the ISO standard HH or HH12 Hour of day (1-12) HH24 Hour of day (0-23) J Julian day the number of days since January 1 4712 BC Number

specified with lsquoJrsquo must be integers MI Minute (0-59) MM Month (01-12 JAN = 01) MONTH Name of month padded with blanks to length of 9 characters MON Abbreviated name of month RM Roman numeral month (I-XII JAN = I) Q Quarter of year (1 2 3 4 JAN-MAR = 1) RR Last 2 digits of year see below for years in other centuries WW Week of year (1-53) where week 1 starts on the first day of the year

and continues to the seventh day of the year W Week of month (1-5) where week 1 starts on the first day of the

month and ends on the seventh PM or PM Meridian indicator with and without periods SS Second (0-59) SSSSS Seconds past midnight (0-86399) YYYY Year with comma in the ldquordquo position YEAR or SYEAR Year spelled out ldquoSrdquo prefixes BC dates with ldquo-ldquo YYYY or SYYYY 4-digit year ldquoSrdquo prefixes BC dates with ldquo-ldquo

IBM Software Group IBM Information Management

Version 16 43

YYY or YY or Y Last 3 2 or 1 digit(s) of year

The RR date format element

The RR date format element is similar to the YY date format element but it provides additional flexibility for storing date values in other centuries The RR date format element allows storing the century even though only two digits are entered for the year The table below illustrates how the year is stored based on only two digits

If the year is entered as

0 ndash 49 50 - 99 If the last two digits of the

0 - 49 The return date is in the current century

The return date is in the century before the current one

current year are

50 - 99 The return date is in the century after the current one

The return date is in the current century

User-defined routines User-defined data types user defined behaviors and user defined access methods add rich functionality to Informix A user-defined routine (UDR) can be developed in C Java or Informix SPL language to vastly extend the capabilities of the database Porting applications to Informix gives the option to create UDRs for aggregate and mathematical functions or to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or you can rename an Informix function to the corresponding Oracle function name

Compatible SQL Functions Informix Dynamic Server version 1110 has added support for a number of built-in SQL functions to ease a migration effort These new functions which perform common operations and data manipulation provide compatibility with Oracle routines thus simplifying the migration of applications that have been developed for an Oracle database

Date and time functions ROUND TRUNC ADD_MONTHS LAST_DAY NEXT_DAY MONTHS_BETWEEN SYSDATE

Conversion functions ASCII TO_CHAR TO_NUMBER

String manipulation LTRIM RTRIM

Number manipulation ROUND TRUNC CEIL FLOOR POWER

Bit manipulation BITAND BITOR BITXOR BITNOT BITANDNOT

Others NULLIF FORMAT_UNITS These functions are documented with examples in the IBM Informix Guide to SQL Syntax

Aggregate functions Like Oracle the result returned by an Informix aggregate function is NULL if all of the column values are NULL with the exception of COUNT which returns 0 (zero) Like Oracle Informix aggregate functions cannot be used in a WHERE clause unless it is on a corresponding column originating from a parent query and the WHERE clause is within a sub-query that is within a HAVING clause or the aggregate function is contained within a sub-query Unlike Oracle in Informix the argument of an aggregate function cannot be another aggregate function Informix supports the SELECT COUNT (column_name) hellip statement where the number of rows containing non-null values in the specified column is returned

IBM Software Group IBM Information Management

Version 16 44

The Oracle aggregate functions STDDEV and VARIANCE are supported however the Informix standard deviation routine is named STDEV thus all references to Oraclersquos STDDEV must be changed to match Informixrsquos STDEV Informix does not support Oraclersquos greatest lower boundary (GLB ) or least upper boundary (LUB) Therefore UDRs must be written to provide equivalent functionality Informix allows users to define their own aggregate functions known as user-defined aggregates (UDA) This extension of existing aggregates can be used for new data types as well as the definition of new aggregates In Informix TEXT and BYTE columns cannot be used in aggregate functions such as COUNT AVG MAX MIN and SUM

Mathematical functions Informix does not support all of Oraclersquos mathematical functions such as SIGN COSH SINH and TANH Therefore functions or UDRs must be written in the Informix application to provide equivalent functionality In Informix the rounding factor within the ROUND function must be a value from -32 to 32 This limitation has seldom been encountered as a migration issue

String functions

LENGTH

Oraclersquos LENGTH function will return different values than Informix for strings stored in CHAR data types The numeric return value representing the string length returned by Oracle will include all trailing spaces Whereas Informixrsquos LENGTH function will ignore trailing blanks regardless of data type For example for the two CHAR strings ldquoBOBrdquo and ldquoBOB ldquo Oraclersquos LENGTH function will return different values for each string 3 and 5 respectively Whereas Informixrsquos LENGTH function will ignore trailing blanks and return the value 3 for both When the input string is NULL both database functions will return a NULL

LTRIM and RTRIM

The SQL Compatibility features of Informx has support for LTRIM and RTRIM and will return identical values to that of Oracle No modifications will be necessary to SQL statements utilizing these functions

Oracle Extensions

Informix does not support all of Oraclersquos string functions such as CHR INSTR SOUNDEX and TRANSLATE Therefore corresponding user-defined routines or UDRs (ie functions or stored procedures) must be written in the Informix application to provide equivalent functionality Please note that the VERITY and EXCALIBUR Datablades included with Informix will work with Oraclersquos string function SOUNDEX

Other Oracle Functions Informix does not support the following Oracle functions Therefore corresponding functions must be written in the Informix application to provide equivalent functionality Alternatives to some of the more common Oracle functions follow this list

CHARTOROWID CONVERT DUMP GREATEST GREATEST_LB

IBM Software Group IBM Information Management

Version 16 45

HEXTORAW LEAST LEAST_UB RAWTOHEX ROWIDTOCHAR TO_LABEL TO_MULTI_BYTE TO_SINGLE_BYTE UID USERENV(OSDBA LABEL LANGUAGE TERMINAL SESSIONID ENTRYID) VSIZE

Macros Oracle contains macros sometimes referred to as language constructs which can determine the status of an object Informix does not support Oraclersquos macros These macros must be removed from the code and the associated logic should be implemented with equivalent Informix logic where applicable

ISOPEN and NOT FOUND

The macro cursor_nameISOPEN returns a Boolean value to indicate whether the cursor is open and cursor_nameNOTFOUND indicates whether there are any more rows yet to be fetched from the cursor cursor_name These macros used in condition statements are followed by some logic to handle the true andor false conditions In the case of ISOPEN this macro and its associated logic can just be omitted since the FOREACH loop processing does not explicitly open a cursor and therefore the condition cannot be checked In the case of NOTFOUND this macro should be omitted and its associated logic converted to Informix logic within an Informix FOREACH loop

ROWTYPE

The Oracle macro prefixROWTYPE is used in the declarative section as a data type to declare variables similar to the structure construct of C or RECORD of INFORMIX The prefix can be either a table name or another structure name Structure names ultimately refer back to a table name This macro may be replaced with the Informix statement LIKE table_name The construct LIKE table_name cannot be used in SPL Instead the construct DEFINE column1 LIKE table_namecolumn1 DEFINE column2 LIKE table_namecolumn2 and so on should be used to declare variables corresponding to all the columns of the table Then operations on the whole or part of the structure should be replaced with operations on single SPL variables

TYPE

The Oracle macro prefixTYPE is used in the declarative section as a data type to declare single variables The prefix is either a table_namecolumn_name or a structure_namevariable_name A structure_namevariable_name ultimately refers back to a table_namecolumn_name This macro can be replaced with the Informix statement LIKE table_namecolumn_name

Pseudo-columns Pseudo-columns are columns that exist in tables but are not displayed from a SELECT FROM table_name query Informix pseudo-columns are generally reserved for the enginersquos use Eliminating the use of such columns increases an applicationrsquos portability and eliminates the need for future modifications if the engine is ever modified to process the column differently or not at all

IBM Software Group IBM Information Management

Version 16 46

LEVEL

In Oracle for each row returned by a hierarchical query the pseudo-column LEVEL returns 1 for a root node 2 for a child of a root 3 for a child whose parent is at level 2 and so on A root node is the highest node within an inverted tree and therefore has no parent A child node is any non-root node A parent node is any node that has children A leaf node is any node without children To define a hierarchical relationship in a query you must use the START WITH and CONNECT BY clauses Informix does not support the LEVEL clause See the Hierarchical Queries subsection in the SQL section in the ldquoData Manipulation Languagerdquo chapter for more information on how to process these queries

ROWID

Oraclersquos ROWID pseudo-column returns the rows address for each row in the database ROWID values contain the following information necessary to locate a row

Which data block in the data file

Which row in the data block (first row is 0)

Which data file (first file is 1)

Usually a ROWID value uniquely identifies a row in the database However rows in different tables that are stored together in the same cluster can have the same ROWID Values of the ROWID pseudo-column have the data type ROWID ROWID values have several important uses

They are the fastest way to access a single row

They can show you how a tables rows are stored

They are unique identifiers for rows in a table

A ROWID does not change during the lifetime of its row However you should not use ROWID as a tables primary key If a row is deleted and re-inserted its ROWID may change even when using the export and import utilities If a row is deleted Oracle may re-assign its ROWID to a new row inserted later Although you can use the ROWID pseudo-column in the SELECT and WHERE clauses of a query these pseudo-column values are not actually stored in the database The value of a ROWID pseudo-column cannot be inserted updated or deleted For example the following Oracle statement selects the address of all rows that contain data for employees in department 20

SELECT ROWID ename FROM emp WHERE deptno = 20

The equivalent pseudo-column in Informix is also known as ROWID and although the behavior is similar the data type is different from Oraclersquos See the ROWID subsection in the Data Types section in the chapter ldquoData definition languagerdquo for more information

ROWNUM

In Oracle for each row returned by a query the ROWNUM pseudo-column returns a number indicating the order in which Oracle selected the row from a table or set of joined rows The first row selected has a ROWNUM of 1 the second has 2 and so on ROWNUM can be used to limit the number of rows returned by a query as in this example to read 9 rows

SELECT

FROM emp

WHERE ROWNUM lt 10

ROWID ENAME 0000000F00000002 SMITH 0000000F00030002 JONES 0000000F00070002 SCOTT 0000000F000A0002 ADAMS 0000000F000C0002 FORD

IBM Software Group IBM Information Management

Version 16 47

You can also use ROWNUM to assign unique values to each row of a table as in this example

UPDATE tabx

SET col1 = ROWNUM

Oracle assigns a ROWNUM value to each row as it is retrieved before the rows are sorted by an ORDER BY clause Therefore the final order of the rows is in ORDER BY order not in ROWNUM order An ORDER BY clause does not affect the ROWNUM values except in the case where the ORDER BY clause causes Oracle to use an index In that case the ROWNUM values are set in the order the rows are retrieved using the index and hence in ORDER BY order This order is different than if the rows were retrieved without the index So in this case the ORDER BY can affect the ROWNUM values Conditions which test for ROWNUM values greater than zero are always false For example this query returns no rows

SELECT FROM employee WHERE ROWNUM gt 1

The first row fetched is assigned a ROWNUM of 1 thus making the condition false The second row to be fetched is now the first row and is also assigned a ROWNUM of 1 making the condition false All rows subsequently fail to satisfy the condition so no rows are returned Although there is no ROWNUM equivalent in Informix there are solutions Beginning with IDS 73 and in Informix Dynamic Server 2000 Informix provides a feature which allows the user to limit the results of a query to the first N rows This was implemented for TPC-D compliance and to support ldquorankrdquo queries Rank queries can be assembled by using FIRST N with the ORDER BY clause Informix will return the top N rows according to some ordering criteria Therefore the following Oracle SELECT utilizing ROWNUM

SELECT FROM emp WHERE ROWNUM lt 10

can be ported to Informix as follows

SELECT FIRST 9 FROM emp

Informix does not support SELECT FIRST N in complex cases as the following

Sub-queries (SELECT within a SELECT)

View definitions (Cannot be used by a SELECT statement which references a view)

UNION queries The behavior of SELECT FIRST N depends on the presence of an ORDER BY clause If no order by clause is specified the first N rows returned may be in any order Examples are as follows

find 10 highest paid employees

SELECT FIRST 10 name salary

FROM emp

ORDER BY salary

find 10 highest salary values

SELECT FIRST 10 DISTINCT salary

FROM emp

ORDER BY salary

IBM Software Group IBM Information Management

Version 16 48

Informix supports column names of ldquofirstrdquo Thus without a positive integer following the word ldquofirstrdquo the token is parsed as a column name rather than a keyword The value of N may be between 1 and (2

31-1)

When ROWNUM is used in a WHERE clause the same results can be obtained through the use of the FIRST N and SKIP clauses but if ROWNUM is used in the select list the solution is a little more complicated Simply stated you can construct a query where the ROWNUM column in any row is the count of the rows that came before This involves creating a correlated subquery where the subquery contains a self-join This can be done for any table or set of tables which has a unique key defined on it Here is an example using the customer table of the stores7 database

select

counterrownum

basecustomer_num

basefname

baselname

from

-- There can be more than one table here and the result

-- set should thought of as a table (just not a base table)

-- The result table has to be joined to itself in the

-- subquery so if there are multiple tables in this FROM

-- clause the expansion can get messy You have to have a

-- set of columns that uniquely identify each row in the

-- result table and join across them ROWID would

-- likely work if the table is not fragmented but if it is

-- there is no guarantee the final results would be accurate

-- because ROWID is not guaranteed to be unique across

-- fragments

customer base

(select

count() as rownum

acustomer_num -- any unique key possibly multiple

-- columns

from

customer a

customer b

where

-- This is where the rownum is determined the relationship

-- here has to match the outer order-by where the rows

-- are sorted and has to create a unique sort order

--

-- Any columns to be ordered by go here

-- Also the unique key has to be used to keep rows

-- that do not have a unique sort order from being merged

(alname gt blname) -- example sorting by last name

or

(alname = blname and afname gt bfname)

-- sorting by fname where lname is equal

or

(alname = blname and afname = bfname

and acustomer_num gt= bcustomer_num)

-- sorting by unique key where all the

-- other sort columns are equal

-- The expansion above is logically the same as

-- alname || afname || to_char(acustomer_num) gt=

-- blname || bfname || to_char(bcustomer_num)

-- but it allows the server to utilize any indexes that

-- may exist

group by

-- unique key columns go here

IBM Software Group IBM Information Management

Version 16 49

acustomer_num

) counter

where

-- key columns in the base tables go here

basecustomer_num = countercustomer_num

-- if you want to limit on rownum it goes here

-- and rownum lt= 10

order by

counterrownum

If using ROWNUM as an assignment as in

UPDATE tabx

SET col1 = ROWNUM

The following Informix-ESQLC pseudo-code example would have to be used

int counter = 0

EXEC SQL declare c1 cursor for

SELECT col1 col2

INTO col1 col2

FROM table 1

WHERE col1 = XX

EXEC SQL open c1

while (SQLCODE == 0)

EXEC SQL fetch c1

counter++ Increment counter for each row

fetched

if (counter gt= 5)

break

logic

End if

End while

Update using cursors There are slight differences between the ways Informix and Oracle process cursors Unlike Oracle in Informix the WHERE CURRENT OF clause cannot be used to update tables in a SELECT statement joining multiple tables since the WHERE CURRENT OF clause requires a FOR UPDATE cursor and Informix does not support the FOR UPDATE clause in SELECT statements that join multiple tables Therefore in the multi-table join statements the Oracle options FOR UPDATE and WHERE CURRENT OF should be removed and the update of the rows should be done using a separate UPDATE statement in the same cursor loop

IBM Software Group IBM Information Management

Version 16 50

In Informix a commit or rollback statement closes all cursors open in a given transaction boundary See the Transaction Processing section in CHAPTER 5 Application Architecture for more information In situations where the intention is to commit or rollback without closing the cursor in other words where the commit or rollback is executed within a cursor fetch loop the cursor can be declared as a HOLD cursor This requires that a BEGIN WORK is issued before the cursor loop starts A HOLD cursor is not closed when a commit or rollback statement is issued In Informix the FOR UPDATE clause cannot be used when declaring a HOLD cursor Thus where an Oracle application updates a table from which it fetches data in the fetch loop or issues a commit work in the fetch loop it must be converted to Informix The cursor can be declared with HOLD and then an UPDATE statement can be issued without the WHERE CURRENT OF clause In order to uniquely identify the row to be updated in the table in other words in order to simulate the WHERE CURRENT OF clause the ROWID or unique primary key columns of the table(s) to be updated must also be fetched and the WHERE CURRENT OF clause can be replaced with WHERE ROWID = fetched rowid or WHERE unique primary key column(s) = fetched unique primary key column(s) A BEGIN WORK must follow immediately after a COMMIT WORK or ROLLBACK WORK in the fetch loops to simulate Oracle implied transaction boundaries These transaction control statements work for either Informix logged databases or Informix ANSI mode databases however ANSI mode database processing with these statements will set certain warning flags after executing the BEGIN WORK statement and continue processing without failure See the ANSI vs Non-ANSI subsection in the Databases section in the chapter ldquoData Manipulation Languagerdquo for more information

System tables References to Oracle system tables should be replaced with corresponding references to Informix system tables The information schema views provided by Informix can be used These views are created after the database is installed They are populated by data in the system catalog tables and are used for easier porting

Stored procedures Informix procedures and functions are considered to be user-defined routines (UDR) A UDR can be written in Informixrsquos Stored Procedure Language (SPL) or an external language such as C or Java A procedure is a routine written that does not return a value A function is a routine written that returns a single value a value with a complex data type or multiple values Informix SPL is an extension to Informix SQL and provides procedural flow control such as looping and branching A SPL routine is a generic term that includes both SPL procedures and SPL

functions You use SQL and SPL statements to write an SPL routine SPL statements can be used only inside the CREATE PROCEDURE CREATE PROCEDURE FROM CREATE FUNCTION and CREATE FUNCTION FROM statements SPL routines are parsed optimized and stored in the system catalog tables in executable format Like Oracle Informix stored procedures support input output and inputoutput parameters and can be used in SQL statements wherever expressions are allowed

Size limit

Informix stored procedures have a size limit of approximately 64K Oracle stored procedures greater than 64K in size can be broken into smaller Informix stored procedures communicating with each other as though they were one by passing and returning the necessary values

Parameter limit

IBM Software Group IBM Information Management

Version 16 51

Informix has a limit of 341 parameters for each stored procedure This limit also applies to UDRs written in the Java language UDRs written in the C language can have no more than 102 parameters You can define any number of SPL routine parameters but the total length of all parameters passed to an SPL routine must be less than 64 kilobytes No more than nine arguments to a UDR written in the Java language can be DECIMAL data types of SQL that the UDR declares as BigDecimal data types of the Java language Any C language UDR that returns an opaque data type must specify opaque_type in the var binary declaration of the C host variable

Packages

An Oracle package is a collection of functions procedures and variables that can be enabled and accessed as a unit There is no direct equivalent within Informix but there are ways of achieving similar capabilities Within Oracle a procedure within a package can be accessed through grammar such as package_nameprocedure_name If you create an owner or schema name within the Informix system the same as the package name then it will be easier to migrate calls to that procedure because the grammar is effectively the same although the meaning changes somewhat Using this practice a call to a migrated procedure would be ownerprocedure_name where the owner name is the same as the package name Translating package names as owner names is a way to maintain the scoping of the objects within the package Maintaining the aspect of being able to enable use of or upgrade the collection of package objects can be done by creating a datablade that contains all the objects that used to be part of the package Datablade routines can be procedures or functions written in Stored Procedure Language (SPL) C and Java In addition routines can be written in C++ on Windows platforms

Routines

Oraclersquos stored functions and stored procedures are similar in concept to Informixrsquos stored procedures Oraclersquos user defined database level functions such as stored functions stored procedures all need to be converted to Informix stored procedures using the Informix SPL C or Java Routines written in SPL have the advantage of being maintained and backed up with database backups Routines written in C are fast but are not automatically backed up when the database is and need to be compiled specifically for the operating system on which it will run Routines written in Java also not backed up by the DBMS itself but they are platform independent However probably as a result of having to convert between system memory where the objects have C structures and Java virtual machine memory where the objects have Java structures the performance of Java routines can be slow compared with the C equivalent All procedures written in an Oracle package body must be rewritten as separate Informix procedures When rewriting package bodies into separate procedures Oraclersquos variable declarations can be replaced at the package level (global) with Informixrsquos global variables The Informix global variables must be defined in the first stored procedure of the logical group

Exceptions

The method of handling exceptions is different between Informix and Oracle Oracle has many predefined and user defined exception labels such as CURSOR_ALREADY_OPEN NO_DATA_FOUND ZERO_DIVIDE and so on The labels can be used in the logic to identify errors Only one exception check is allowed per BEGIN and END block using the EXCEPTION construct and it is normally placed just before the END statement Informix also supports predefined and user defined exceptions however they are represented numerically not with labels In Informix all the exceptions checked in the stored procedure control blocks delimited with BEGIN and END statements must be declared explicitly at the top of each

IBM Software Group IBM Information Management

Version 16 52

control block with the Informix EXCEPTION construct Therefore Oracle procedure code must be restructured to manipulate these exceptions In Oracle an exception can be raised globally and acted upon globally In Informix the scope of an exception mechanism is always restricted to the block in which it is located This leads to the addition of multiple Informix exception handling mechanisms for each Oracle exception raised as well as a redesign of the overall stored procedure to a more blocked format

Error handling

In Oracle errors are processed as part of a function call return value In Informix errors are retrieved as a separate function call that has multiple structures that have to be created in order to retrieve error and status The SQLCA structure is not fully available in Informix stored procedures It is not possible to check the SQLCODE variable in the stored procedure body Instead the function DBINFO can be used to extract the value of two members of the SQLCA structure sqlcasqlerrd1 and sqlcasqlerrd2 This function should be used inside the FOREACH construct while the cursor is open Once the cursor is closed the DBINFO function cannot return proper values The sqlcasqlerrd1 option returns different values depending on the type of SQL statement For INSERT statements if the table contains a serial column then the sqlcasqlerrd1 option will return the serial value of the last row inserted into the table For SELECT DELETE and UPDATE statements the sqlcasqlerrd1 option will return the number of rows processed by the query In these cases upon each pass through the FOREACH loop sqlcasqlerrd1 is the same value the number of rows the FOREACH loop will process The sqlcasqlerrd1 value can still be interrogated during each pass through the FOREACH loop The sqlcasqlerrd2 option returns the number of rows processed by a SELECT INSERT UPDATE DELETE or EXECUTE PROCEDURE statement It should not be interrogated until after the cursor has finished processing In other words within the FOREACH loop the sqlcasqlerrd2 value can be moved to a variable which is then interrogated outside of the FOREACH loop

Cursors

Unlike Informix in Oracle cursors can be global to a package In Informix Oraclersquos global cursors can be replaced with temporary tables A temporary table can be created and populated in place of where the cursor is opened The temporary table can then be processed the same way the cursor is processed Finally the temporary table should be dropped in place of where the cursor is closed Cursors are explicitly declared opened and fetched in Oracle stored procedures In Informix cursors do not need to be explicitly declared opened and fetched in stored procedures Instead Oracle stored procedure cursors can be replaced with Informixrsquos FOREACH construct The Oracle cursor name should be used in the FOREACH statement for example FOREACH cursor_name SELECT hellip END FOREACH In order to update a cursor row in Oracle the cursor must be declared with the FOR UPDATE clause In Informix if the SELECT statement in the FOREACH construct is not a multi-table join then each fetched row can be updated using the UPDATE lttable_namegt WHERE CURRENT OF ltcursor_namegt statement See the Update Using Cursors section in ldquoData Manipulation Languagerdquo for more information Informix does not support the SELECT FOR UPDATE statement in a stored procedure Therefore the SELECT FOR UPDATE clause cannot be used in the FOREACH construct

IBM Software Group IBM Information Management

Version 16 53

Variable declaration and assignment

Oracle allows implicit variable definitions within a FOR loop The variables are defined using an assignment operator and a column name For example

out_customer_name = customername

The variable out_customer_name is defined as the same type as the column name in the customer table Informix requires that all variables be defined at the beginning of each stored procedure control block For example

DEFINE out_customer_name LIKE customername

DEFINE counter INTEGER

Therefore Oraclersquos implicit variable declaration must be replaced with Informixrsquos explicit variable declaration before the control block Additionally assignment operations will need to be ported Oracle uses a colon and an equal sign (=) for assignment while Informix utilizes the LET keyword in combination with an equal sign (=) (ie LET var = 1) Therefore assignment statements must be modified with the LET keyword and an equal sign

Boolean

Oraclersquos BOOLEAN variable type can be replaced with Informixrsquos BOOLEAN data type

Binary data types

Binary data types are very different between Oracle and Informix In Oracle the binary type is defined as a type RAW and is explicitly defined with a maximum length as part of the declaration In Informix the binary type is defined as REFERENCES BYTE which deals only with pointers to BLOBs It implicitly defines a maximum length as part of the function call in which the pointer to the BLOB and maximum length (as used in the function call) was passed as values As a result the binary type cannot be assigned a binary value in a stored procedure nor can it be inserted into a table via the SQL INSERT statement in a stored procedure These operations that initialize a binary type must be performed outside of stored procedures

Dynamic SQL

Unlike Oracle Informix does not support dynamic SQL within the Stored Procedure Language In other words a statement such as SELECT variable_name FROM variable_name WHERE variable_name is not supported This kind of processing can be achieved in Informix within an embedded SQL program This requires that either the Oracle stored procedure be converted to an embedded SQL program or just the Dynamic SQL portion be placed in an embedded SQL program and then called from within the stored procedure The latter option will have performance implications since calling an embedded SQL program from a stored procedure requires an operating system call Another option is to use the Informix EXEC Bladelet The EXEC Bladelet consists of user-defined functions that take a SQL query as an argument execute it and return a result (the format of which varies depending on the function and the kind of query) The EXEC Bladelet functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries Further details can be found in Chapter 7 Using Bladelets

Compiler

Unlike Oracle the Informix compiler was developed with the concept that developers can create stored procedures independently of the database Therefore Informixrsquos stored procedure

IBM Software Group IBM Information Management

Version 16 54

compiler has a limited set of errors that it checks compared to Oraclersquos For example the Informix stored procedure compiler does not validate database object names such as table column and view names Therefore database object naming errors will occur at runtime not compile time Additionally the error messages generated from the compiler are not very specific Identifying a problem in a stored procedure may require breaking it apart and recompiling the pieces until the problem is found This may impact the time necessary to unit test the stored procedures

Triggers Oracle supports the use of multiple trigger events for example insert update and delete within the same trigger Informix only supports one trigger event per trigger In Informix the Oracle trigger body in this example must be copied into three different triggers each with only one event Informix triggers have some constraints Oraclersquos do not In Informix if a trigger is fired due to inserting a row into a table a trigger can only act on any rows or columns within that table using the EXECUTE PROCEDURE hellip INTO syntax Similarly if a trigger is fired due to updating a row then the trigger can only act on the column that caused the trigger to fire using the EXECUTE PROCEDURE hellip INTO syntax Like Oracle if a trigger is fired due to deleting a row there are no restrictions Prior to IDS 73 when a trigger was fired on an INSERTUPDATE action no modification could be done to the columns (in the row) which just fired the trigger The reentrant UPDATEINSERT triggers feature introduced with IDS 1110 enables users to update the triggering columns by using the EXECUTE PROCEDURE INTO syntax Additionally the feature enforce that this action will not cause any additional triggers to be fired (same or different trigger) causing a cascading of triggers and potentially an infinite loop The following example demonstrates how the reentrant UPDATEINSERT trigger feature is used

create table foo

(

x int default NULL

y int default NULL

z int default NULL

)

create procedure reentrant()

returning int

return 56

end procedure

create trigger reentrant_trigger insert on foo for each row

(

execute procedure reentrant() into z

)

insert into foo values

(

1

2

3

)

The following SELECT will result in the following returned data

select from foo

x y z

1 2 56

IBM Software Group IBM Information Management

Version 16 55

Oracle allows SQL statements logical statements and stored procedure calls within a trigger body Informix allows only SQL statements and stored procedure calls within a trigger body Oracle triggers containing logical statements must be converted to Informix by moving their contents into a stored procedure The stored procedure should then be executed from the trigger

Constraints Constraints in both Oracle and Informix can be enabled and disabled within an application transaction however there are behavioral differences In Oracle the application is always executing within a transaction In Informix transaction boundaries are explicitly declared and care should be taken to ensure that this functionality is performed within the boundaries of a transaction See the Transaction Processing section in CHAPTER 5 Application Architecture for more information The constraint syntax available in Informix is

SET CONSTRAINTSINDEXESTRIGGERS FOR table_name

ENABLED|DISABLED

SET CONSTRAINTS comma_separated_constraint_names

ENABLED|DISABLED

SET INDEXES comma_separated_index_names ENABLED|DISABLED

SET TRIGGERS comma_triggers_constraint_names ENABLED|DISABLED

SET CONSTRAINTS ALLconstraint_name IMMEDIATE|DEFERRED

The first four statements must be executed with DBA privileges if placed in the application Therefore care should be taken when using them Note that the last statement contains a DEFERRED clause This is the statement used if the users of the application do not have DBA privileges When the constraint is set with the DEFERRED clause the specified constraints are not checked until the transaction is committed If a constraint violation occurs while the transaction is being committed the transaction is rolled back

DUAL table Oraclersquos DUAL table is a system table with only one row containing one column named DUMMY This table is used to complete the syntax of an SQL statement that does not involve an existing table such as

A SELECT statement which assigns some constant value (which can only be derived in an SQL statement) to a host variable

SELECT TO_CHAR(SYSDATE) INTO date_var FROM DUAL

A SELECT statement which assigns a value of another variable to a variable

SELECT source_var INTO dest_var FROM DUAL

A SELECT statement which unions application host variable values with another SELECT statement to return a result containing a row of application variable values

SELECT col1 col2 col3 FROM table_name

UNION

SELECT host_var1 host_var2 host_var3 FROM DUAL

Converting Oraclersquos DUAL table functionality to Informix depends on the way it is used Converting statements that just assign constants is as simple as replacing the DUAL statement with an Informix assignment statement The solutions below apply to Informix versions prior to 11 At 11 and above the concept of a DUAL table as well as sysdate is supported

IBM Software Group IBM Information Management

Version 16 56

SELECT sysdate FROM sysmastersysdual

If you want a dual table in your local database then create the following synonym The sysmastersysdual table is much faster than a physical table in your database because it is an in- memory pseudo table

CREATE SYNONYM dual FOR sysmastersysdual

If you are restricted to using a version of Informix prior to 11 then the following solutions can be used A dummy table can be created to mimic the behavior of simple SELECT INTO statements used to assign values to variables

CREATE TABLE dual (dummy VARCHAR(1))

INSERT INTO dual VALUES(lsquoXrsquo)

An alternate solution to widespread use of the DUAL table could be creating a permanent view that is generally accessible

CREATE VIEW dual (d) as SELECT X

FROM systables WHERE tabid = 1

The exact definition could be used or modified as needed but this would solve the problem of having DUAL be permanent usable by anyone and not modifiable

IBM Software Group IBM Information Management

Version 16 57

C H A P T E R 5 Embedded SQL

Oraclersquos embedded SQL products are ProC and ProCOBOL Informixrsquos corresponding embedded SQL products are ESQLC and ESQLCOBOL

Host variables

Declaration override

The Oracle EXEC SQL VAR declarative statement (host variable equivalency of Oracle external data types by overriding the default assignment) can be converted to an Informix explicit declaration statement For example

Oracle char char_var[20]

EXEC SQL VAR char_var IS STRING(11)

Informix

char char_var[11]

Note that the size and type used in the EXEC SQL VAR section is the final information required to declare the host variable in Informix

Arrays

Oracle arrays are not subscripted in SQL statements since it is not required to process the host arrays in a loop in the SQL statement In Informix subscripting is mandatory In Oracle if an array is defined of size 200 then an SQL statement would be

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A

VAR-B

VAR-C

END-EXEC

-or- EXEC SQL SELECT COL1 COL2 COL3

INTO VAR-A

VAR-B

VAR-C

FROM TABLE1

WHERE COL2 gt 100

END-EXEC

where VAR-A VAR-B and VAR-C are each an array of say 200

IBM Software Group IBM Information Management

Version 16 58

In Informix the first example would be converted to

PERFORM VARYING LOOP-CTR FROM 1 BY 1 UNTIL

LOOP-CTR IS GREATER THAN 200

EXEC SQL FETCH CURSOR-NAME INTO

VAR-A(LOOP-CTR)

VAR-B(LOOP-CTR)

VAR-C(LOOP-CTR)

END-EXEC

IF SQLCODE = 100

GO TO EXIT-PERFORM

END-IF

END-PERFORM

EXIT-PERFORM

For the second Oracle example given above a cursor must be declared in Informix opened and fetched for 200 rows or less (less because there may be less than 200 qualifying rows) into the host array and then should be closed If the number of qualifying rows is more than 200 then the extra rows must be ignored to duplicate the Oracle functionality But for the first example each fetch in Oracle will return the next 200 or less number of rows Therefore each Oracle fetch needs to be replaced by another call to the Informix fetch loop Oracle also uses this method for inserts deletes and updates These array techniques are mainly used in batch SQL processing

Formatting

In Informix when a DECIMAL MONEY DATE or DATETIME value is selected into a host variable of the same data type the value must be formatted using the available Informix formatting routines before they can be printed or displayed For example

hellip

dec_t dec_host_var

char formatted_dec[40]

EXEC SQL SELECT DEC_COLUMN INTO dec_host_var FROM TABLE_NAME

rfmtdec(ampdec_host_var ldquoampampampampampampampampampamprdquo formatted_dec)

printf(ldquoThe Decimal Value is snrdquo formatted_dec)

hellip

IBM Software Group IBM Information Management

Version 16 59

Informix supplies many formatting functions and formatting strings The names of these functions are different in Informix ESQLC and ESQLCOBOL but the functionality is the same Refer to the appropriate Informix API Programmerrsquos Manual (Informix-ESQLC Programmerrsquos Manual or Informix-ESQLCOBOL Programmerrsquos Manual) for more information

SQL structures

SQLCA

Oraclersquos SQLCA structure is different from that of Informix However the components of both structures are logically the same Oraclersquos SQLCA components can be replaced with the corresponding Informix components Oraclersquos SQLCA structure

SQLCAID string containing ldquoSQLCArdquo SQLCABC length of SQLCA data structure SQLCODE Oracle error message code SQLERRM sub-record for error message

SQLERRML length of error message SQLERRMC text of error message SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) reserved for future use SQLERRD(1) reserved for future use SQLERRD(2) number of rows processed SQLERRD(3) reserved for future use SQLERRD(4) parse error offset SQLERRD(5) reserved for future use

SQLWARN array of eight warning flags SQLWARN(0) another warning flag set SQLWARN(1) character string truncated SQLWARN(2) no longer in use SQLWARN(3) SELECT list not equal to INTO list SQLWARN(4) DELETE or UPDATE without WHERE clause SQLWARN(5) reserved for future use SQLWARN(6) no longer in use SQLWARN(7) no longer in use

SQLTEXT reserved for future use

IBM Software Group IBM Information Management

Version 16 60

Informixrsquos SQLCA structure

SQLCODE Informix error code SQLERRM error message parameter SQLERRP reserved for future use SQLERRD array of six-integer status codes

SQLERRD(0) estimated number of rows returned SQLERRD(1) serial value of INSERT or ISAM error code SQLERRD(2) number of rows processed SQLERRD(3) estimated cost SQLERRD(4) parse error offset SQLERRD(5) ROWID after INSERT

SQLWARN structure of eight warning flags SQLWARN0 another warning flag set SQLWARN1 character string truncated or no privileges revoked SQLWARN2 NULL value returned or ANSI database SQLWARN3 SELECT list not equal to INTO list or turbo back-end SQLWARN4 DELETE or UPDATE without WHERE clause SQLWARN5 if non-ANSI statement SQLWARN6 if server is in data replication secondary mode SQLWARN7 reserved

In order to get Oracle error messages an application normally uses the SQLCA element SQLERRMC The Informix equivalent is SQLERRM On the HPUX and Solaris platforms the Informix function rgetmsg should be used instead of the element SQLERRM At the time of this writing using SQLERRM would cause an error on the HPUX and Solaris platforms

SQLDA

The implementation of Oraclersquos SQLDA structure is very different from that of Informix Significant changes are necessary to convert Oraclersquos functionality to Informix Oraclersquos sqlald function can be replaced with Informixrsquos ALLOCATE DESCRIPTOR statement Since Oraclersquos and Informixrsquos SQLDA structures are so different Oraclersquos SQLDA logic must be rewritten with the more powerful Informix SQLDA logic or alternatively the Informix system-descriptor area logic Oraclersquos SQLDA Structure

N maximum number of SELECT list items or placeholders V pointer to array of address of SELECT list items or bind variables L pointer to array of lengths of SELECT list items or bind variables T pointer to array of data types of SELECT list items or bind variables I pointer to array of addresses of indicator variable values F actual number of SELECT list items or placeholders S pointer to array of addresses of SELECT list items or placeholder names M pointer to array of max lengths of SELECT list items or placeholder names C pointer to array of current lengths of SELECT list items or placeholder names X pointer to array of addresses of indicator variable names Y pointer to array of maximum lengths of indicator variable names Z pointer to array of current lengths of indicator variable names

IBM Software Group IBM Information Management

Version 16 61

Informixrsquos SQLDA Structure SQLD count of the following SQLVAR members SQLVAR pointer to array of structures

SQLDATA pointer to actual data SQLTYPE data type of placeholder or SELECT item SQLLEN length of the placeholder or SELECT item SQLIND pointer to the indicator SQLNAME pointer to placeholder or SELECT item name SQLFORMAT reserved SQLIDATA indicator data pointer SQLITYPE indicator variable type SQLILEN length of indicator variable

If an Oracle application uses the simple dynamic SQL method using macros only not the SQLDA structure directly the value indicatorsplaceholders can be replaced with a lsquorsquo in Informix For example Oracle sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES (v1 v2)rdquo) Informix sprintf(sqlstring ldquoINSERT INTO TABLE1 VALUES ( )rdquo)

ORACA

Oraclersquos ORACA structure is not supported by Informix This structure is used to handle Oracle specific communication and more runtime information than SQLCA Oracle statements containing references to this structure should be removed from the application

Pre-compiler options The Oracle options beginning with the EXEC ORACLE OPTION statement can be removed from the application The options set after this statement do not affect the application logic They may affect some application performance only

Embedded PLSQL Oracle allows procedure language (PLSQL) blocks inside ProC and ProCOBOL code delimited by the EXEC SQL EXECUTE and END-EXEC statements In Informix these blocks must be replaced with the equivalent ESQLC or ESQLCOBOL code

Oracle Call Interface Oracle call interface (OCI) is the base layer for a variety of other application programming interfaces such as JDBC-OCI Oracle Precompilers and Oracle ODBC It is also used directly by customers who are willing to develop their code using a lower level proprietary API From a high level it can be thought of as if IBM Informix had standardized and published the function calls in the ESQLC library Although some customers have reverse engineered these calls and developed applications using them this is generally discouraged because there is no guarantee that the library of calls will not change There is no direct equivalent to this Oracle API in Informix Migrating applications written using Oracle Call Interface (OCI) will require rewriting the code from scratch OCI is native to the C language and so it should be less effort to migrate the application to an Informix API that is also native to C This could be ESQLC or CLI The following information explains differences between Oracle OCI and Informix ODBC

IBM Software Group IBM Information Management

Version 16 62

The following table is an approximate mapping of the differences between the Informix CLI and Oracle OCI function calls in which there is not a direct one-to-one mapping

Oracle Informix Buffer Areas HAD LDA CDA HENV HDBC HSTMT

Connect and allocate resources

OLOG OOPEN SQLConnect SQLAllocEnv SQLAllocConnect SQLAllocStmt

Update delete insert select OPARSE OBNDRV OEXEC SQLPrepare SQLBindParameter SQLExecute

Select ODEFIN OFETCH SQLBindCol SQLFetch

Commit Rollback OCOM OROL SQLTransact

Disconnect OLOGOF OCLOSE SQLDisconnect SQLFreeStmt SQLFreeConnect SQLFreeEnv

Database library calls

One of the first main differences between Informix CLI and Oracle OCI calls is the overall data structures and mechanisms used to process database library calls Oracle uses direct connections to the database server Informix uses an ODBC connection to the database server As a result the Informix calls will be implemented as ODBC SQL calls utilizing three tiers of increasing SQL levels of complexity

Global area processing

Another main difference between Informix CLI and Oracle OCI is Informixrsquos use of pointers to three global areas versus Oraclersquos use of pointers to three different but similar global areas Hence the Oracle OCI calls that utilize HAD (Handle Data Area) LDA (Logon Data Area) and CDA (Cursor Data Area) pointers must be translated over to Informix CLI calls that utilize HENV (Environment Area) HDBC (Database Connection Area) and HSTMT (Statement Area) pointers respectively in conjunction with an ODBC interface

Fetch cycle

Another difference between Informix CLI and Oracle OCI calls is that the overall fetch cycle is different for each and must be modified accordingly In Oracle the fetch cycle for selecting multiple rows utilizing a cursor area involves parsing binding defining fetching and then executing into a cursor data area These must be translated to a cycle that involves preparing binding executing binding and then fetching via the ldquoFor Eachrdquo cycle

RAW binary data type processing

RAW binary data types in Oracle will need to be translated to a pointer-to-BLOB REFERENCES BYTE type in Informix See the Binary Data Types subsection of the Stored Procedures section in CHAPTER 3

Parameter bindings

In Oracle multiple output bindings of parameters are declared as type ldquoOUTPUTrdquo in the ODEFIN() calls In Informix convert the calls to Informix SQLBindCol() calls and bind the output parameters as columns Differences also exist between Informix CLI and Oracle OCI in the use of inputoutput bindings In Oracle these bindings are declared as type ldquoINPUTOUTPUTrdquo in the ODEFIN() calls In Informix a ldquoround robinrdquo approach is used using three variables in the following manner A=B B=C C=A A variable (A) is declared before the SQL bindings as an input variable The function is called

IBM Software Group IBM Information Management

Version 16 63

using a second input variable (B) that is set to the first input variable (A) The function returns a third variable (C) that is bound as an output column Finally the first variable (A) is now set to the returned third variable (C) that made the first variable (A) appear as an ldquoinputoutputrdquo variable to the rest of the program

Embedded SQL for C

VARCHAR

Oraclersquos ProC VARCHAR data type is expanded after pre-compiling into a structure with two elements one is unsigned short len and the other is unsigned char arr[size] The name of the expanded structure is the same name as the VARCHAR variable and size is replaced with the size of the VARCHAR variable In Informix the VARCHAR data type is just a synonym for the C languagersquos char data type Therefore statements that use variable_namelen can be removed from the application and all occurrences of variable_namearr can be replaced with variable_name For example

Oracle VARCHAR vName[40]

strcpy(vNamearr ldquoCompany Namerdquo)

vNamelen = strlen(vNamearr)

Informix VARCHAR vName[40]

strcpy(vName ldquoCompany Namerdquo)

Host variables

The Oracle statement EXEC SQL TYPE is synonymous with the C languagersquos typedef declarative instruction It can be easily replaced with the Informix declarative instruction typedef

Embedded SQL for COBOL

VARCHAR

Oraclersquos ProCOBOL character host variable declaration statementrsquos VARYING clause is expanded after pre-compiling into a group with two elements one is variable-name-LEN PIC S9(4) COMP and the other is variable-name-ARR PIC X(size) The group name is the same as the host variable name and size is replaced with the size of the VARYING variable Informix does not support this concept Therefore statements that use variable-name-LEN must be removed from the application and all occurrences of variable-name-ARR must be replaced with variable-name Also the VARYING clause must be removed from the declarative statement For example

Oracle

05 vName PIC X(40) VARYING

hellip

MOVE ldquoCompany Namerdquo TO vName-ARR

MOVE 12 TO vName-LEN

Informix

05 vName PIC X(40)

hellip

MOVE ldquoCompany Namerdquo TO vName

IBM Software Group IBM Information Management

Version 16 64

Level 88

COBOLrsquos level 88 functionality is not supported within an Informix ESQLCOBOL host variable declaration section in versions prior to 72 Level 88 functionality is supported in Informix ESQLCOBOL 72

SQLDA

In Informix ESQLCOBOL the SQLDA structure is not available The Informix macros such as ALLOCATE DESCRIPTOR DESCRIBE GET DESCRIPTOR and SET DESCRIPTOR must be used to retrieve and manipulate the SQLDA data

REDEFINES

Oracle supports the use of the REDEFINES clause at the elementary level in the host variable declaration section In other words the redefined item cannot be a group item but the redefining item may be a group item Informix does not support the use of the REDEFINES clause in the host variable declaration section in versions prior to 72 The REDEFINES clause is supported in Informix ESQLCOBOL 72

Tips

If the Informix pre-compiler finds an SQL statement within an IF [ELSE IF hellip ] END-IF or EVALUATE END-EVALUATE or PERFORM END-PERFORM block then the pre-compiler adds a period after the generated COBOL statements regardless of whether there is a period at the end of the SQL statement This is a violation of COBOL rules for such blocks and the code may cause syntax errors during compilation or may behave unexpectedly To avoid these problems each SQL statement group should be moved to a new paragraph and these paragraphs should be performed from the block from which they were moved

ODBC Although the Open Database Connectivity (ODBC) API is designed to make it possible to write and compile an application once and use it with any ODBC driver on the same platform there are frequently differences between the underlying DBMSs that can expose problems to the applications For instance there can be differences between how unspecified parts of a date-time value are filled Most of these kinds of differences that get exposed through ODBC have their origins in the differences between the DBMSs themselves There are also cases where there are gaps in the ODBC standard for example there is a standard ODBC call that allows the application to ask the driver if it can support scrollable cursors and there is another call to ask if it can support updateable cursors There is no call to ask if it can support both at the same time With Informix you can have a scrollable cursor and you can have an updateable cursor but you can not have one cursor that is both scrollable and updateable A more complete description of ODBC application migration issues is beyond the scope of this article

IBM Software Group IBM Information Management

Version 16 65

C H A P T E R 6 Application Architecture

Transaction processing Transaction boundaries are defined differently in Oracle and Informix Oraclersquos transactions begin implicitly in one of two ways either by issuing a CONNECT statement or issuing a COMMIT or ROLLBACK statement A CONNECT statement marks the beginning of a transaction and a COMMIT or ROLLBACK statement commits or rolls back the previous transaction respectively and then implicitly begins a new transaction CONNECT statements are usually issued once at the beginning of a program however they may be nested or issued more than once serially to connect to the same or a different database When using more than one CONNECT statement within a program each CONNECT statement must be named This marks the beginning of named transactions Every SQL statement within a named transaction must also be named with the same transaction name as the CONNECT statement at where the SQL is to be executed SQL is named using the EXEC SQL statementrsquos AT clause Informixrsquos transaction boundaries are explicitly marked with the reserved words BEGIN WORK and COMMIT WORK or ROLLBACK WORK Note that once a transaction has begun for a given connection it stays open until a COMMIT or ROLLBACK is executed In other words if an ESQL program begins a transaction and then calls a stored procedure the stored procedure executes within the same transaction If the stored procedure issues a COMMIT then the whole transaction is committed and the calling ESQL program should not issue a COMMIT or ROLLBACK Informix transactions can be written to behave the same way as Oraclersquos To simulate Oraclersquos CONNECT statement behavior an Informix CONNECT should also be issued followed by a BEGIN WORK statement If more than one CONNECT statement is used in a program Informix also requires that the CONNECT and SQL statements be named To simulate Oraclersquos COMMIT and ROLLBACK statement behavior an Informix COMMIT WORK or ROLLBACK WORK statement should be issued followed by a BEGIN WORK statement Nested transactions can be simulated in Informix with the CONNECT statement and naming the transactions Then the Informix SET CONNECTION connection_name statement can be used to switch between transactions Committing or rolling back each named transaction does not commit or roll back other active transactions The Oracle statement EXEC SQL COMMITROLLBACK RELEASE should be replaced with the Informix statements EXEC SQL COMMITROLLBACK [WORK] followed by EXEC SQL DISCONNECT CURRENT In the following examples ws-dbenviron is the database name ws-connect-nm is the user name and ws-identity-nm is the password set in the program enp and connection-name are the connection names For Informix the user name and password information should correspond to the entries in the etcpasswd file on the UNIX system See the User Authentication section later in this chapter for more information The default server name is automatically obtained from the environment variable INFORMIXSERVER The following examples illustrate how Oracle and Informix implement the CONNECT functionality

IBM Software Group IBM Information Management

Version 16 66

Simple Connect

Oracle

CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm

Informix

CONNECT ws-dbenviron USER ws-connect-nm USING ws-identity-nm

Named Connect with Literal

Oracle

DECLARE enp DATABASE hellip CONNECT ws-connect-nm IDENTIFIED BY ws-identity-nm AT enp USING ws-dbenviron hellip AT enp SELECT col1 col2 INTO var1 var2

FROM table_name

Informix

CONNECT TO ws-dbenviron AS ldquoenprdquo USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION ldquoenprdquo hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Named Connect with Variable

Oracle

CONNECT ws-connect-nm

IDENTIFIED BY ws-identity-nm AT connection-name USING ws-dbenviron hellip AT connection-name SELECT col1 col2 INTO var1 var2 FROM table_name

Informix

CONNECT TO ws-dbenviron AS connection-name USER ws-connect-nm USING ws-identity-nm WITH CONCURRENT TRANSACTION hellip SET CONNECTION connection-name hellip SELECT col1 col2 INTO var1 var2 FROM table_name

Autonomous Transaction

An autonomous transaction is an independent transaction that is initiated by another transaction (the parent transaction) An autonomous transaction can modify data and commit or rollback independent of the state of the parent transaction The autonomous transaction must commit or roll back before the autonomous transaction is ended and the parent transaction continues

IBM Software Group IBM Information Management

Version 16 67

An autonomous transactions has been available since the release of Oracle 8i An autonomous transaction is defined in the declaration of a PLSQL block This can be an anonymous block function procedure object method or triggerThis is done by adding the statement PRAGMA AUTONOMOUS_TRANSACTION anywhere in the declaration block There isnt much involved in defining a PLSQL block as an autonomous transaction You simply include the following statement in your declaration section PRAGMA AUTONOMOUS_TRANSACTION Sample code

PROCEDURE test_autonomous

IS

PRAGMA AUTONOMOUS_TRANSACTION

BEGIN

insert

commit

END test_autonomous

Autonomous transactions can be used for logging in the database independent of the rollbackcommit of the parent transaction

Savepoints

Oracle allows savepoints within its PLSQL For example a PLSQL block can be structured so that SAVEPOINT A is issued upon entry and SAVEPOINT B is issued after some processing Then after some more processing a COMMIT or ROLLBACK can be issued against all the logic since the last COMMIT point which is before the PLSQL block or up to any of the savepoints by naming the COMMIT or ROLLBACK with the savepoint name In other words a savepoint can be issued at the beginning of a stored procedure and then only the stored procedure logic can be committed without committing the changes pending before the stored procedure was executed Those changes can be committed or rolled back once processing is returned from the stored procedure Informix does not support savepoint processing within a stored procedure

Concurrency Database concurrency can be managed through the combination of two configurable settings one specifies the lock granularity on database objects while the other influences how the application behaves in regards to the presence and placement of locks using a transaction isolation level

Row Level Locking

Oracle and Informix implement locking differently on database objects Oracle defaults to row level locking whereas Informix defaults to page level In most cases row level locking is preferred to improve concurrency Informix supports row level locking however it must be either explicitly requested specified by an environment variable or permanently changed in the instancersquos configuration Having three methods for establishing the lock level there is an order of precedence

1 To be explicitly requested the CREATE TABLE statement must include the specification of the LOCK MODE attribute

CREATE TABLE emp (

name CHAR(40)

salary MONEY

ssn LVARCHAR(64)

) LOCK MODE ROW

IBM Software Group IBM Information Management

Version 16 68

2 The environment variable IFX_DEF_TABLE_LOCKMODE will establish the default for CREATE TABLE statements issued without the LOCK MODE attribute and will override the Instancersquos configuration setting The variable setting on the client will override the server environment setting

set IFX_DEF_TABLE_LOCKMODE=ROW -or- export IFX_DEF_TABLE_LOCKMODE=ROW

3 Informix allows the instancersquos lock level default to be changed using a configuration parameter Row level locking can be as the default by adding the parameter DEF_TABLE_LOCKMODE to the instancersquos ONCONFIG file This parameter may not be found in the existing file and if not present can be added using an editor and establish a new default setting of ROW

DEF_TABLE_LOCKMODE ROW

None of the steps will apply a change to existing tables only establish the lock level for the CREATE TABLE statement

Transaction Isolation Level

Oracle databases incorporate a feature known as ldquoread consistencyrdquo which allows a query return a result based on the state of the data when the query started regardless of other processes updating or deleting the same data while the query is running Informix facilitates this type of behavior differently by providing control of the applicationrsquos placement of locks as well as how it reacts to those placed by other processes through the use of the transactionrsquos isolation level If Oraclersquos technique of ldquoreaders not blocking writersrdquo is a requirement then in many circumstance Informixrsquos DIRTY READ isolation level can be used The readers will not block the writers with dirty read processing however the query result may contain updates performed while the query was running which may be uncommitted If the emulation of Oraclersquos ldquoread consistencyrdquo is desired the LAST COMMITTED option of Informixrsquos COMMITTED READ isolation level can reduce the risk of locking conflicts when two or more sessions attempt to access the same row in a table whose locking granularity is row-level When an application attempts to read a row on which another session holds an exclusive lock these keywords instruct the database server to return the most recently committed version of the row rather than wait for the lock to be released This isolation level attribute could be preferable to executing queries using DIRTY READ since it will return only the most recently committed versions of the data The LAST COMMITTED option can be enabled in the following ways

1 Setting the USELASTCOMMITTED parameter in the Instancersquos configuration (ONCONFIG) will apply this feature as the default isolation level to all database transactions The parameterlsquos values will designate the scope of applying the LAST COMMITED option to either ALL NONE or only COMMITED READ and DIRTY READ isolation levels

USELASTCOMMITTED [ALL | NONE | COMMITTED READ | DIRTY READ]

2 The SET ENVIRONMENT statement can override the USELASTCOMMITTED configuration parameter setting for the duration of the current session The same semantics apply as the parameter within the ONCONFIG file with the setting value enclosed in quotes (lsquo)

SET ENVIRONMENT USELASTCOMMITTED lsquoALLrsquo

IBM Software Group IBM Information Management

Version 16 69

3 The SET ISOLATION statement can be used to override the instance configuration and session environment setting The SET ISOLATION statement is an Informix extension to the ANSI SQL-92 standard and provides the same functionality as the ISOANSI-compliant SET TRANSACTION statement There is no support for the LAST COMMITTED option with the SET TRANSACTION statement SET TRANSACTION complies with ANSI SQL-92 and only ANSI supported isolation levels are supported

SET ISOLATION TO COMMITTED READ LAST COMMITTED

4 PREPARE statements in ODBCJDBC applications

This feature is primarily documented in the Guide to SQL Syntax Guide to SQL Reference Administrators Reference and Administrators Guide

IBM Software Group IBM Information Management

Version 16 70

C H A P T E R 7 Security

User authentication In Oracle security information is stored in the database Up until recently Informix has used only the operating system security subsystem to check security For security purposes Oracle connects to the server and passes the user ID and password information to the database for verification

Operating system security

Informix does not store user ID and password information in the database Instead they are validated against the operating systemrsquos security mechanism on the server for example the etcpasswd file in UNIX Therefore either every database user must have an entry in the serverrsquos password file or the application must handle a level of security where user IDs are converted into a group id based on database permissions and only those group IDs are entered into the password file Note that if the second alternative is chosen then auditing capabilities based on user ID are lost Also if the application performs security functions then those functions are not applicable to third party applications such as report writers application development tools and so on when they access the database The home directory of all the users should point to the same physical directory where the application executable resides The Informix method of using the operating system for security checking allows external programs to be called from within stored procedures This capability is not allowed in Oracle In Oracle the OPS$User_name is sometimes used to connect to the database where OPS$User_name is a valid Oracle user and User_name is a valid operating system level user In this case the connection is made to the database using just the lsquorsquo character without the user id and password Informixrsquos technique of using the etcpasswd file for security works fine for this type of connection

Non-operating system security

In previous releases each user who needed to access the database server also needed an operating system account on the host computer Now you can configure Informix so that users who are authenticated by an external authentication service (such as Kerberos or Microsoft Active Directory) can connect to Informix The new USERMAPPING configuration parameter specifies whether or not such users can access the database server and whether any of those users can have administrative privileges When Informix is configured to allow user mapping you can still control which externally authenticated users are allowed to connect to Informix and their privileges Please refer to the IBM Informix documentation on connection security for more information

IBM Software Group IBM Information Management

Version 16 71

Informix supports for the pluggable authentication module (PAM) framework which lets an administrator customize authentication for individual applications and permits column-level encryption

Role based authority Role based authority can help you manage your database permissions As of version 1110 you can create a role and assign that as a default role for individual users (or to PUBLIC) A role is a work-task classification such as ldquopayrollrdquo or ldquomanagerrdquo Each defined role has privileges on the database object granted to the role You use the CREATE ROLE statement to define a role and GRANT DEFAULT ROLE to establish the userrsquos initial setting when connecting to the database A userrsquos role can be changed after connecting by using the SET ROLE statement

Column-level encryption You can use column-level encryption to improve the confidentiality of your data IDS Version 1110 has new built-in SQL scalar functions provide methods for data in columns to be stored in an encrypted format Use the ENCRYPT_AES or the ENCRYPT_TDES function to define encrypted data Use the DECRYPT_BINARY() and DECRYPT_CHAR() functions to query encrypted data When using the routines the encryption of data is under application control and the DBMS is not aware that data is encrypted Informixrsquos support of column level encryption is analogous to Oraclersquos DBMS Obfuscation Tool Kit Built-in ENCRYPT functions provide methods for encrypting and decrypting the following character data types or smart large object data types

CHAR

NCHAR

VARCHAR

NVARCHAR

LVARCHAR

BLOB

CLOB

Passwords and hints

Passwords are necessary when using the encryption functions Only users who can provide a secret password can view copy or modify encrypted data The password must be a minimum of 6 bytes and can be a maximum of 128 bytes When you set an encryption password you have the option of specifying a password hint Hints can be up to 32 bytes of text If you specify a hint you can store the hint with the encrypted password or in another location Passwords (and hints) to be used by default can be set for a session using the SET ENCRYPTION PASSWORD statement

SET ENCRYPTION PASSWORD lsquopasswordrsquo [ WITH HINT lsquohint stringrsquo ]

Hence the password and hint parameters can be optional when calling the encryption function Explicit values override the session default values The password or hint can be a single word or several words The hint should be a word or phrase that helps you to remember the password but does not include the password You can subsequently execute the built-in GETHINT function (with an encrypted value as its argument) to return the plain text of hint Calling the GETHINT function with an argument of encrypted data will return the hint (if any) from the encrypted data or an empty string (NULL) is no hint was provided There is no privilege needed anybody can get any hint at any time When you set a password Informix transfers the password and any hint to 128-bit key that is used to encrypt the password and hint Passwords and hints are not stored as plain text any table of the system catalog The key is a time-based random value per instance The database server

IBM Software Group IBM Information Management

Version 16 72

initializes the key when the server starts the key is destroyed when the database server shuts down

Encrypting a column

Column data can be encrypted through the use of two functions ENCRYPT_TDES and ENCRYPT_AES corresponding to the two data encryption standards Triple Data Encryption Standard (Triple-DES) and Advanced Encryption Standard (AES) which describes the cipher algorithm used to protect data from unauthorized viewing AES encryption (also known as Rijndael) uses a 128-bit key size and Triple-DES encryption uses two 56-bit keys for 112-bits overall Both functions are variant functions and will return a different result every time it is used The following example demonstrates how to use the encryption functions with a column that contains a social security number

CREATE TABLE emp (name CHAR (40) salary MONEY ssn LVARCHAR(64))

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890one two

three 123))

-or-

CREATE TABLE emp (name CHAR(40) salary MONEY ssn LVARCHAR(64))

SET ENCRYPTION PASSWORD one two three 123

INSERT INTO emp

VALUES (Alice 50000 ENCRYPT_AES(123-456-7890))

Querying an encrypted column

Encrypted data can be translated using Informixrsquos DECRYPT_CHAR and DECRYPT_BINARY scalar functions Encrypted data contains information about the encryption method and all the other data needed to decrypt it except the password The encrypted data value is passed as the first argument and a password as the second unless the SET ENCRYPTION statement has specified for this session with the same session password by which the first argument was encrypted If the data is not encrypted the function call will return an error The DECRYPT_CHAR function is used to invoke a decryption routine on character data types (ie CHAR LVARCHAR NCHAR NVARCHAR and VARCHAR) while the DECRYPT_BINARY function accepts an encrypted large object of type BLOB or CLOB If the first argument to DECRYPT_CHAR or DECRYPT_BINARY is not an encrypted value or if the second argument (or the default password specified by SET ENCRYPTION) is not the password that was used when the first argument was encrypted Informix will issue an error and the call fails If the call to the decryption function is successful it returns the plain text version of the encrypted data argument The following example demonstrates how to use the decrypt function to query encrypted data

SELECT name salary DECRYPT_CHAR(ssn lsquoone two three 123rsquo)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

-or-

SET ENCRYPTION PASSWORD lsquoone two three 123rsquo

SELECT name salary DECRYPT_CHAR(ssn)

FROM emp

WHERE DECRYPT_CHAR(ssn) = lsquo123-456-7890rsquo

The first argument to DECRYPT_BINARY is expected to be an encrypted value of a large object data type however if it is called with a character data type Informix invokes the DECRYPT_CHAR function and attempts to decrypt the specified value

IBM Software Group IBM Information Management

Version 16 73

Do not use either decryption function to create a functional index on an encrypted column This would store the decrypted values as plain text data in the database defeating the purpose of encryption

Performance impact of encryption

The performance impact of encryption is significant Encryption by its nature will slow down most SQL statements If some care and discretion are used the amount of extra overhead should be minimal Also encrypted data will have a significant impact on your database design In general you want to encrypt a few very sensitive data elements in a schema like social security numbers credit card numbers patient names and so on The effect on performance depends on direction encrypting is slower than decrypting It does not depend measurably on which algorithm is used AES performs at the same speed as Triple-DES It does depend on data size the relative overhead is less when there is more data to encrypt

Storage considerations

An encrypted value uses more storage space than the corresponding plain text value Data encrypted using AES can be bigger than Triple-DES but not by a significant amount This occurs because all of the information needed to decrypt the value except the encryption key is stored with the value Therefore before you set the encryption password and encrypt the data you must be sure the encrypted data can fit in the column A chart of the expected sizes can be found in the IBM Informix Administrator Guide

Compliance regulations

Informixrsquos encryption routines comply with the United Statesrsquo regulations of Health Insurance Portability and Accountability Act (HIPAA) Sarbanes-Oxley Gramm-Leach-Bliley and California Personal Information Privacy (SB 1386) as well as the international requirements of Basel II Also they comply with the latest cryptographic standards (OpenSSL 097c)

IBM Software Group IBM Information Management

Version 16 74

C H A P T E R 8 Environment

Scripts Oracle make files used to build the application should be modified to invoke the appropriate Informix ESQLCOBOL ESQLC MF COBOL and other application language commands The shell scripts shell startup scripts and command files should be modified for Informix compliant statements

SQL script substitution variables

In Oracle a substitution variable is a user variable name preceded by one or two ampersands (amp) When Oracle (SQLPlus) encounters a substitution variable in a command Oracle executes the command as though it contained the value of the substitution variable rather than the variable itself In Oracle the substitution variables can be used anywhere in SQL and SQLPlus commands except as the first word entered at the command prompt When SQLPlus encounters an undefined substitution variable in a command SQLPlus prompts the user for the value SQLPlus reads the responses from the keyboard even if terminal input or output has been redirected to a file If a terminal is not available (if for example the command file is run in batch mode) SQLPlus uses the redirected file Informixrsquos dbaccess does not provide this functionality however a work-around for the redirected file type of substitution is a follows (no user prompting) Create the following shell script (named subvalsksh in this case)

binkshif [[ $ -ne 2 ]]

then

echo nUsage $0 ltdfilegt ltcfilegtn

echo Desc This script accepts two files - dfile the decode

file

echo and cfile the change file It modifies the

change file

echo using the values listed in the decode file

echo The decode file should contain two columns - old

value

echo and new value

echo Ex

echo changethis tothis

echo

echo In this case every occurance of changethis

would be

echo replaced with tothisn

exit 1

fi

IBM Software Group IBM Information Management

Version 16 75

-----------------------

Declare variables

-----------------------

dfile=$1

cfile=$2

awk print s$1$2 $dfile gt $dfile_sed

sed -f $dfile_sed $cfile

The preceding script is used by creating a ldquodecoderdquo file (named decodefile in this case) which holds two columns in the form which may contain multiple rows

oldval newval

Executing the following command

subvalsksh decodefile chgfile

will replace every occurrence of oldval with newval in the file chgfile The shell script (subvalsksh) writes to standard output therefore the output should be redirected The redirected file will then be able to run with dbaccess

Utilities To improve performance the Informix EXPLAIN utility should be used by executing the SET EXPLAIN ON command to see how an SQL statement accesses the database From that point forward the access path for every SQL statement is written in the SQEXPLAINOUT file in the current working directory or the home directory of the process that initiated the request on the host machine The Informix SET EXPLAIN OFF should be executed to turn off this feature when finished The overall system performance should be monitored using the Informix ONSTAT utility

System catalog The following items discuss how Informix implements the system catalog differently than Oracle Each item refers to the Informix implementation only Object names are stored in lower case The system catalog tables are owned by lsquoinformixrsquo To query the systables table use SELECT from lsquoinformixrsquosystables Each table in systables is assigned a tabid by the system It is used as the primary key and therefore the foreign key for the other catalog tables The identifier information is stored in sysindexes Columns part1 - part16 each contain a column component of a composite index They are integers positive for ascending order negative for descending order In syscolumns collength and coltype have special meanings depending on the data type of the column See the Informix Guide to SQL Reference Version for details

IBM Software Group IBM Information Management

Version 16 76

C H A P T E R 9 Using Bladelets

What is a Bladelet

A Bladelet is a small informal Informix Datablade module Its meant to be useful out of the box and is offered complete with source code at no cost -- and no support or warranty In the context of this document the term Datablade refers to an extension to the standard IBM Informix database engine These generally take the form of new data types (for example timeseries or video) andor new routines that execute inside the server The new routines might operate on new data types or on existing ones A Datablade module is usually a formal product available for sale In addition a Datablade is

Developed either by IBM Informix or by a third-party developer

Rigorously tested

Packaged and sold for profit

May or may not be formally certified by IBM Informix as having been developed according to approved Datablade coding practices

In contrast a Bladelet is

Not rigorously tested

Not sold for profit

Not certified by IBM Informix A Bladelet is an extension to the database engine that is narrow in scope and thought to be generally useful being offered at no cost complete with source Just remember before you use any of this code in mission-critical applications its up to you to thoroughly test it and fix any problems you find Please review the disclaimer which applies to any sample code you find on this site httpwwwibmcomdeveloperworksdb2zonesinformixlibrarysamplesdb_downloadshtml Note The bladelets at this link have not been updated for some time (at the time of this writing) some of the capabilities especially simple function call that increase compatibility may have been introduced into the Informix server itself since they were written

Useful Bladelets

Bladelet Description

Exec Defines two user-defined functions that provide dynamic SQL functionality within a SPL procedure

Flat File Access Method A complete access method that lets you build virtual tables based on operating system files

IUtil Implements a collection of other database vendor functions for Informix

IBM Software Group IBM Information Management

Version 16 77

JPEG Image Bladelet Provides a user-defined type for JPEG images that allows you to manipulate images and to extract and search on image properties

Multirepresentational lvarchar Opaque Type

Creates the idn_mrLvarchar opaque type which stores character data up to 2 gigabytes

Node Datablade Module Creates the node opaque type which is intended to solve one of the hardest problems in relational databases transitive closure

Regexp Creates routines that let you manipulate character and clob data using regular expressions

Shapes DataBlade Module Creates several opaque types for managing spatial data including R-tree index support

Smart Blob Information DataBlade Module

Includes a variety of useful routines for working with smart blobs

SqlLib C SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

SqlLib Java SqlLib is a Bladelet that adds several other database compatibility functions to Informix There are two functionally identical implementations SqlLib for Java and SqlLib for C

Versioning Table Access Method

Permits users to create and manage versioned tables

We will look closer at two bladelets which could assist with migration the Exec datablade and SQLLib

Informix Exec bladelet for Dynamic SQL Often it is desirable to execute a SQL query that is generated at run-time within the RDBMS For example a developer may not know the name of the temporary table they wish to run the query against or they might want to append predicates to a query In external programs this can be accomplished using the ESQLC SQLCA and DESCRIPTOR facilities Unfortunately the INFORMIX Stored Procedure Language (SPL) does not support Dynamic SQL Queries must be hard-coded into the SPL logic The objective of the Exec bladelet is to remedy this situation Exec consists of user-defined functions that take an SQL query as an argument execute it and return the result (the format of which varies depending on which function is called and the kind of query) The Exec functions can handle most Data Definition Language (DDL) statements and all Data Manipulation Language (DML) queries For more details and download refer to

httpwwwibmcomdeveloperworksdb2zonesinformixlibrarydemoids_exechtml

There are three User Defined Routines (UDRs) in the Exec bladelet Two of them are external C functions that use the Server API (SAPI) These must be compiled into shared libraries on the target machine and you need to declare them to the server using CREATE FUNCTION statements The third UDR is a routine written in Informix Stored Procedure Language (SPL) that uses the first two UDRs to return a collection of items The Exec bladelet module consists of the following

1 EXEC The EXEC() function takes an LVARCHAR that it treats as a SQL query executes the query and returns a single LVARCHAR result string Depending on what kind of SQL statement is submitted Exec() returns a different result format

IBM Software Group IBM Information Management

Version 16 78

2 EXEC_FOR_ROWS The EXEC_FOR_ROWS() UDR is an iterator function which means it can return more than one result row Of course it only does so when it is asked to execute a SELECT Otherwise it behaves exactly as the EXEC() UDR Being an iterator function limits the ways in which such a UDR can be used It cannot be used in another SQL query The only place it can be used effectively is inside a SPL routine

3 EXEC_FOR_MSET EXEC_FOR_MSET() is a SPL routine that uses the EXEC_FOR_ROWS() routine introduced above Instead of returning a set of rows as an iterator or a single row as the EXEC() UDF does this UDR collects the results of the SQL query together into a single object a multi-set

Refer to Appendix E Sample Code for examples on using the EXEC bladelet functions

SqlLib DataBlade module (SqlLibC11 SqlLibJ11) The SqlLib DataBlade module implements SQL routines that the Informix does not support natively but that are supported by some other database vendors Source code is freely available for download and includes two implementations one in C (SqlLibC) and the other in Java (SqlLibJ)

The following routines are included

ascii - takes a single character as input and returns the ASCII value in decimal that corresponds to that character

ceil - takes a single numeric value as input and returns the smallest integer that is either equal to or greater than the input value

chr - takes an integer value and returns the character that is represented by the ASCII value (in decimal) of that integer

instr - searches for a value in a string and returns the position where it was found It

returns 0 if the search value was not found instrb - provides the exact same functionality as instr() but for single-byte character sets

sign - takes a numeric argument and returns an integer that indicates if the input value is

positive (1) negative (-1) or zero (0) to_decimal - converts the input character argument into a decimal type

to_float - converts the input character argument into a float type

to_integer - converts the input character argument into an integer type For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

For more details and download refer to httpwwwibmcomdeveloperworksdb2zonesinformixlibrarytecharticledb_sqllibhtml

IBM Software Group IBM Information Management

Version 16 79

A P P E N D I X A Planning guide

The checklist below will help an analyst determine which Oracle features which need to be converted to Informix and give some guidance on the effort involved Each porting task is listed They are followed by a quantity field used to determine how prevalent the item the difficulty or amount of effort involved 1 (low) to 5 (high) is used to estimate the amount of time needed to perform the task when the associated item exists in the application a moderate number of times What is moderate depends on the size of the application If there are an unusually large number of occurrences of an item then the effort should be increased Conversely if there are a small number of occurrences of an item then the effort should be decreased Each of these items is discussed in detail within this document Each heading corresponds to a section heading within the document

Tasks Quantity Effort

DDL

Identifiers Delimit identifiers named with Informix reserved words 2 Databases Determine database names and create databases 3 Replace Oracle tablespace names with Informix dbspace names 1 ANSI vs Non-ANSI considerations 3 Tables Convert create table statements 2 Convert DDL syntax 3 Reduce primary key length to 390 bytes 5 Data Types Convert Oraclersquos NUMBER data type 3 Convert VARCHAR columns 2 Convert Oraclersquos DATE data type 5 Convert raw data types 2 Convert Rowids 2 Indexes Convert Indexes 2 Views Remove CREATE VIEW statement options 1 Stored Procedures and Triggers Convert CREATE and REPLACE Stored Procedure and Trigger syntax 1 Oracle Extensions Remove non-supported Oracle extensions from DDL 1

Tasks Quantity Effort

DML

SQL Add the Informix AS clause to display labels 1 Replace non-supported DML syntax ^= hellip = ELSE IF 2 Convert Optimizer DirectiveHints 2 Convert InsertSelectUnion and InsertValueSelect statements 3

IBM Software Group IBM Information Management

Version 16 80

Convert Delete statement syntax 1 Convert temporary table processing 2 Convert Join statements + MINUS INTERSECT different data types 2 Convert sorts 4 Convert hard coded SQL error messages 3 Remove correlation names on the main table of Update and Delete statements

2

Replace original table names in SELECT statements using aliases 1 Convert hierarchical implementation (CONNECT BY PRIOR) 5 Host Variables Convert host variable format or add conversion processing 5 Functions Convert date and time functions 5 Convert aggregate functions 3 Convert mathematical functions 5 Convert string function syntax 1 Convert other unsupported Oracle functions 5 Macros Convert ISOPEN NOT FOUND ROWTYPE and TYPE macros 3 Pseudo-Columns Convert Level processing 3 Convert Rownum processing 2 Update Using Cursors Convert WHERE CURRENT OF processing for multiple table joins 5 Convert FOR UPDATE with a HOLD cursor processing 2 Convert concurrency processing from Oraclersquos implicit to Informixrsquos explicit

4

System Tables Convert system table references 1

Tasks Quantity Effort

Stored procedures Break stored procedures greater than 64K in size into smaller ones 2 Convert Oraclersquos stored procedure packages 3 Convert exception processing 5 Convert error handling (SQLCA) 2 Convert Oraclersquos global cursor processing 5 Convert Oraclersquos explicit cursor processing 2 Convert flow control processing 5 Convert Oraclersquos implicit variable declaration and assignment 3 Convert Oraclersquos BOOLEAN variable type 1 Convert binary data type processing Convert Oraclersquos dynamic SQL processing 5 Triggers Convert multi-functional triggers 3 Convert Insert and Update triggers which are not supported in Informix 5 Place logical statements in a stored procedure 5 Constraints Convert constraint enabling and disabling processing 5 DUAL table Convert Dual table processing 4

Embedded SQL

Host variables

IBM Software Group IBM Information Management

Version 16 81

Convert declaration overrides 1 Convert array processing 5 Convert Oraclersquos formatting functions 4 SQL structures Convert SQLDA processing 5 Convert ORACA processing 1 Pre-compiler options Convert Oracle pre-compiler options 1 Embedded PLSQL Convert Oraclersquos Embedded PLSQL 5 ODBC Convert Oraclersquos OCI 5 Convert database library calls Convert global area processing Convert fetch cycle Convert RAW data type processing Convert parameter bindings Embedded SQL for C Convert VARCHAR processing 2 Embedded SQL for COBOL Convert VARCHAR processing 2 Convert 88 Level processing in COBOL 2 Convert Redefine processing in COBOL 4

Tasks Quantity Effort

Application architecture

Transaction processing Convert application to Informix transaction processing 5 Convert multiple connect processing 5 Convert savepoints Concurrency Address Informix locking processing na 2 User authentication Address Informix security processing na 4

Environment

Convert make files 2 Convert shell scripts shell startup scripts and command files 2 Convert script substitution variables

IBM Software Group IBM Information Management

Version 16 82

A P P E N D I X B Syntax comparison

See the Informix Guide to SQL Syntax for more information on each item

Oracle Informix Boolean AND AND AND NOT NOT NOT OR OR OR Greater Than or Equal To gt= gt= Less Than or Equal TO lt= lt= Not Equal ltgt = or ^= ltgt or = Identifiers letters numbersrdquo_rdquordquo$rdquordquordquo letters numbers and ldquo_rdquo Data types Character CHAR CHAR Long Character VARCHAR (2000) if lt= 2000

LONG VARCHAR if gt 2000 CHAR or TEXT

Number (2 bytes) NUMBER SMALLINT Number (4 bytes) NUMBER INTEGER Number (gt 4 bytes) NUMBER DECIMAL Image LONG RAW CLOB BLOB BYTE TEXT CLOB BLOB DML Comments -- hellip -- hellip Assignment var1 = expression LET var1 = expression Condition ELSE IF ELSE or ELIF

IF Aggregate functions Average AVG(expression) AVG(ALL

expression) AVG(DISTINCT expression)

AVG(expression) AVG(ALL expression) AVG(DISTINCT column_name) AVG(UNIQUE column_name)

Count COUNT() COUNT (expression) COUNT(ALL expression) COUNT (DISTINCT expression)

COUNT() COUNT(DISTINCT column_name) COUNT (UNIQUE column_name)

Maximum MAX(expression) MAX(ALL expression) MAX(DISTINCT expression)

MAX(expression) MAX(ALL expression) MAX(DISTINCT column_name) MAX(UNIQUE column_name)

Minimum MIN(expression) MIN(ALL expression) MIN(DISTINCT expression)

MIN(expression) MIN(ALL expression) MIN(DISTINCT column_name) MIN(UNIQUE column_name)

Sum SUM(expression) SUM(ALL expression) SUM(DISTINCT expression)

SUM(expression) SUM(ALL expression) SUM(DISTINCT column_name) SUM(UNIQUE column_name)

Algebraic functions Round ROUND(expressionrounding

factor) ROUND(expressionrounding factor)

Statistical functions Standard Deviation STDEV(expression) STDDEV(expression) Variance VARIANCE(expression) VARIANCE(expression) Range RANGE(expression)

IBM Software Group IBM Information Management

Version 16 83

String functions

Trim LTRIM(expression) RTRIM(expression)

LTRIM(expression) RTRIM(expression)

Length LENGTH(string) LENGTH(string) Like LIKE(string) LIKE(string) Like (single character) _ _ Like (wildcard) String Delimiter lsquo or ldquo lsquo or ldquo Escape Character set within LIKE clause using

ESCAPE ldquordquo to make ldquordquo the escape character

or set within LIKE clause using ESCAPE ldquordquo to make ldquordquo the escape character

Stored procedures Create CREATE OR REPLACE

PROCEDURE procedure_name (var1 IN CHAR(1) var2 OUT DATE var3 IN OUT NUMBER)

DROP PROCEDURE procedure_name CREATE PROCEDURE procedure_name (var1 CHAR(1) var3 INTEGER) RETURNING DATE INTEGER

Arguments EXECUTE PROCEDURE procedure_name (var1 IN var2 OUT var3 IN OUT)

EXECUTE PROCEDURE procedure_name (var1 var3) RETURNING var2 var3

IBM Software Group IBM Information Management

Version 16 84

A P P E N D I X C Database concepts

The table below illustrates the relationship between each database vendorrsquos database objects

Oracle Informix

Database name attached to a group of files Specific database name

Data file Chunk

Tablespace (logical partition) or Segments (Index Segment Table Segment and so on)

Dbspace

Extent Extent

Rollback Segment Physical Log

Redo Log Logical Log

System tablespace Root dbspace

Temporary tablespace Temporary dbspaces dbspacetemp environment variable or dbspacetemp onconfig parameter

Pointer Blobspace Sbspace

Table partitioning table fragmentation

Database link Not supported

Snapshot Not supported

oerr utility finderr utility

sqldba and svrmgrl - monitor utilities onstat and oncheck utilities

SQLPlus utility dbaccess utility

ProC ESQLC

ProCOBOL ESQLCOBOL

SQLNET INet

OCI Like the ESQL function library after pre-compiling if they were publically documented

Read Consistency COMMITTED READ LAST COMMITTED

IBM Software Group IBM Information Management

Version 16 85

A P P E N D I X D Sample code

User defined functions User Defined Routines (UDR) can be developed to extend the capabilities of the database and provides the option to create UDRs to emulate Oracle built-in functions and reduce the impact of replacing all references throughout the application Or rename an Informix function to the corresponding Oracle function name

CONCAT

CREATE PROCEDURE concat (str1 VARCHAR(255) str2 VARCHAR(255)) RETURNING VARCHAR(255) RETURN str1 || str2

END PROCEDURE

INSTR

CREATE PROCEDURE instr( str VARCHAR(255) mask VARCHAR(255) strt SMALLINT DEFAULT 1 occur SMALLINT DEFAULT 1 ) RETURNING INT DEFINE slen SMALLINT DEFINE mlen SMALLINT DEFINE tempstr VARCHAR(255) DEFINE tempmask VARCHAR(255)

DEFINE nomatch SMALLINT DEFINE count SMALLINT DEFINE pos SMALLINT DEFINE retpos SMALLINT DEFINE i SMALLINT DEFINE j SMALLINT DEFINE srchstrt SMALLINT LET slen = LENGTH(str) LET mlen = LENGTH(mask) LET count = 0 LET nomatch = 0 LET pos = 1 LET retpos = 1 LET tempstr = LET tempmask = LET srchstrt = strt

IF (strt lt 0) THEN - reverse the str FOR i = 1 TO slen LET tempstr = str[11] || tempstr LET str = str[2255] END FOR -- reverse the mask FOR i = 1 TO mlen LET tempmask = mask[11] || tempmask LET mask = mask[2255] END FOR

IBM Software Group IBM Information Management

Version 16 86

LET srchstrt = strt -1 LET str = tempstr LET mask = tempmask END IF FOR j = 1 TO slen LET tempstr = str LET tempmask = mask FOR i = 1 TO mlen IF (tempmask[11] = tempstr[11]) THEN LET nomatch = 1 EXIT FOR END IF LET tempmask = tempmask[2255] LET tempstr = tempstr[2255]

END FOR IF (nomatch = 0) THEN IF (pos gt= srchstrt) THEN LET count = count + 1 END IF IF (count = occur) THEN IF (strt lt 0) THEN RETURN slen - pos + 1 ELSE RETURN pos END IF END IF END IF LET str = str[2255] LET nomatch = 0

LET pos = pos + 1 END FOR RETURN 0 END PROCEDURE

YYYYMMDD

CREATE PROCEDURE yyyymmdd (str VARCHAR(10)) RETURNING varchar(8)

DEFINE retstr VARCHAR(8)

IF str IS NULL THEN

RETURN NULL

ELSE

LET retstr = str[710] || str[12] || str[45]

RETURN retstr

END IF

END PROCEDURE

Using EXEC bladelet functions

IBM Software Group IBM Information Management

Version 16 87

Using EXEC

Note the ROW data type variable can be referenced using table and column syntax CREATE PROCEDURE example1() RETURNING INTEGER

DEFINE sql_stmt LVARCHAR(255)

DEFINE rcnt ROW(val INTEGER)

LET sql_stmt = select count() from items where manu_code = lsquoANZrsquo

EXECUTE FUNCTION EXEC(sql_stmt) INTO rcnt

RETURN rcntval

END PROCEDURE

Using EXEC_FOR_ROWS

CREATE PROCEDURE example2() RETURNING INTEGER CHAR(1)

DEFINE rs_rowdata ROW(customer_num INTEGER call_code CHAR(1))

DEFINE sql_stmt LVARCHAR(255)

LET sql_stmt = select customer_num call_code from cust_calls where

customer_num = 106

FOREACH

EXECUTE FUNCTION EXEC_FOR_ROWS(sql_stmt) INTO rs_rowdata

RETURN rs_rowdatacustomer_num rs_rowdatacall_code WITH RESUME

END FOREACH

END PROCEDURE

Using EXEC_FOR_MSET

Note the DEFINE statement for the variable rs_data Collection data types used in a SPL routine cannot be defined using the LIKE attribute in the DEFINE statement CREATE PROCEDURE example3() RETURNING INTEGER VARCHAR(8)

DEFINE v_customer_num LIKE accountscustomer_num

DEFINE v_account_cd LIKE accountsaccount_cd

DEFINE rs_data MULTISET(ROW(

r_customer_num INTEGER

r_account_cd VARCHAR(8)) NOT NULL)

DEFINE sql_stmt LVARCHAR

LET sql_stmt = select customer_num order_num from orders where

company_id = 51155

EXECUTE FUNCTION EXEC_FOR_MSET(sql_stmt) INTO rs_data

FOREACH

SELECT r_customer_num r_account_cd INTO v_customer_num

v_account_cd FROM TABLE(rs_data)

RETURN v_customer_num v_account_cd WITH RESUME

END FOREACH

END PROCEDURE

IBM Software Group IBM Information Management

Version 16 88

Date arithmetic Informix has extensive capabilities for manipulating dates and times You can add or subtract DATE and DATETIME variables from each other You can add or subtract an INTERVAL to a DATE or DATETIME

UNITS Keyword

When working with INTERVAL values sometimes it is necessary to specify the precision with which you are dealing For example suppose you have the following field defined To add 10 days to the lead time you could use a SQL statement like this

SELECT lead_time + INTERVAL(10) DAY to DAY FROM orders

-or- SELECT lead_time + 10 UNITS DAY FROM orders

Using EXTEND function

The EXTEND function allows operations between data types of different precisions SELECT

EXTEND(myvar YEAR to MINUTE) ndash INTERVAL(5) MINUTE to MINUTE

FROM member

Calculate Week Of The Year

SELECT ROUND((TODAY - DATE(0101||YEAR(TODAY))) 7 + 5) FROM DUAL

Number of days difference SELECT DATE(0106||YEAR(TODAY)) - DATE(01062005) FROM DUAL

Number of weeks difference

SELECT ROUND((DATE(0106||YEAR(TODAY)) - DATE(01062005))

7 + 5) FROM DUAL

String representation of date and time

Day and date

SELECT TO_CHAR(TODAY A B d Y) FROM dual

-returns month day and 4 digit year-

Tuesday January 03 2006

Abbreviation of day of week

SELECT SUBSTR(TO_CHAR(TODAY A B d Y R)13) FROM dual

-or-

SELECT TO_CHAR(TODAY a) FROM dual

-returns MON TUE WED THU FRI SAT SUN-

Returning the number of rows affected

IBM Software Group IBM Information Management

Version 16 89

Within SPL routines you can use the DBINFO function to find out the number of rows that have been processed in SELECT INSERT UPDATE DELETE EXECUTE PROCEDURE and EXECUTE FUNCTION statements

CREATE FUNCTION del_rows(pnumb INT) RETURNING INT

DEFINE nrows INT

DELETE FROM sec_tab WHERE part_num = pnumb

LET nrows = DBINFO(sqlcasqlerrd2)

RETURN nrows

END FUNCTION

To ensure valid results use this option after SELECT and EXECUTE PROCEDURE or EXECUTE FUNCTION statements have completed executing If you use the sqlcasqlerrd2 option within cursors make sure that all rows are fetched before the cursors are closed

Using an Informix collection data type

A collection data type as a VARRAY

In the following examples the collection data types of MULTISET and SET are used in a function to hold a collection of values You cannot define a collection variable as global (with the GLOBAL keyword) or with a default value Informix SPL allows you to declare a cursor for a collection variable using the FOREACH statement called a collection cursor

Also demonstrated is how to utilize a variable declared with the keyword COLLECTION A variable declared as type SET MULTISET or LIST is a typed collection variable It can hold a collection of its specified data type only However a COLLECTION is an un-typed (or generic) collection variable that can hold a collection of any data type

This function will build a MULTISET list of values

CREATE FUNCTION func1() RETURNING MULTISET(INTEGER NOT NULL)

DEFINE v_array_of_ints MULTISET(INTEGER NOT NULL)

INSERT INTO TABLE (v_array_of_ints) VALUES(1)

INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(5)

INSERT INTO TABLE (v_array_of_ints) VALUES(4)

RETURN v_array_of_ints

END FUNCTION

This function will receive the COLLECTION list of values from func1

CREATE FUNCTION func2() RETURNING INTEGER

--

-- DEFINE lmset MULTISET(INTEGER NOT NULL)

--

DEFINE lmset COLLECTION

DEFINE v_int INTEGER

--

-- call func1 to populate local multiset variable

--

LET lmset = func1()

--

-- tally a count the number of elements

--

FOREACH

SELECT COUNT() INTO v_int FROM TABLE(lmset)

IBM Software Group IBM Information Management

Version 16 90

RETURN v_int WITH RESUME

END FOREACH

--

-- return the values

--

FOREACH

SELECT INTO v_int FROM TABLE(lmset)

RETURN v_int WITH RESUME

END FOREACH

END FUNCTION

NOTE In the example func2 a duplicate declaration for the ldquolmsetrdquo variable as a MULTISET data type has been commented out by declaring the variable as a COLLECTION it can accept any of the 3 types (MULTISET SET and LIST)

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

4 (row count) 1 2 5 4

By using a SET data type inserts will not permit duplicates

CREATE FUNCTION func1() RETURNING SET(INTEGER NOT NULL) DEFINE v_array_of_ints SET(INTEGER NOT NULL) INSERT INTO TABLE (v_array_of_ints) VALUES(1) INSERT INTO TABLE (v_array_of_ints) VALUES(2)

INSERT INTO TABLE (v_array_of_ints) VALUES(2) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) INSERT INTO TABLE (v_array_of_ints) VALUES(5) RETURN v_array_of_ints END FUNCTION

NOTE Because func2 is expecting a un-typed COLLECTION variable func1 does not have to be dropped and recreated It can receive a value from any Collection Data Type (MULITSET SET and LIST)

The functionrsquos return values would change to (with duplicates suppressed)

EXECUTE FUNCTION func2()

(expression)

3 (row count) 1 2 5

Using a LIST data type support for assigning values based on ordinal position

IBM Software Group IBM Information Management

Version 16 91

CREATE FUNCTION func1() RETURNING LIST(INTEGER NOT NULL)

DEFINE v_array_of_ints LIST(INTEGER NOT NULL) -- -- first insert no ordinal position can be established By default the -- database server inserts LIST elements at the end of the list -- INSERT AT 5 INTO TABLE (v_array_of_ints) VALUES(5) INSERT AT 1 INTO TABLE (v_array_of_ints) VALUES(1) INSERT AT 2 INTO TABLE (v_array_of_ints) VALUES(2) -- -- Only 3 LIST elements exist position 4 has not been instantiated -- this element will insert at the end of the list -- INSERT AT 4 INTO TABLE (v_array_of_ints) VALUES(4) INSERT AT 3 INTO TABLE (v_array_of_ints) VALUES(3) RETURN v_array_of_ints END FUNCTION

NOTE The elements of a LIST have ordinal positions with a first second and third element in a LIST To support the ordinal position of a LIST the INSERT statement provides the AT clause This clause allows you to specify the position at which you want to insert a list-element value Note the behavior of the ordinal positioning above preceded by a commented explanation

When executing the function the resulting expression will be

EXECUTE FUNCTION func2()

(expression)

5 (row count) 1 2 3 5 4

Using MULTISET and ROW to replace PLSQL TABLE and RECORD types

Creating variables using Informix Collection data types SET MULTISET and LIST in combination with ROW data types can be useful when migrating applications which use Oracle REF CURSORS as arguments to functions as well as Oracle collection data types TABLE and RECORD

Typical Oracle Package specification

CREATE OR REPLACE PACKAGE MyPackage

IS

TYPE recOrders IS RECORD (

order_num ordersorder_numTYPE

order_date ordersorder_dateTYPE

customer_num orderscustomer_numTYPE

po_num orderspo_numTYPE

)

TYPE tabOrders IS TABLE OF recOrders

INDEX BY BINARY_INTEGER

TYPE ref_curtype IS REF CURSOR

Both tabOrders or ref_curtype can be converted to the following Informix SPL definition

DEFINE tabOrders MULTISET(ROW(

IBM Software Group IBM Information Management

Version 16 92

order_num INTEGER

order_date DATETIME YEAR TO FRACTION(3)

customer_num INTEGER

po_num CHAR(10)) NOT NULL)

DEFINE ref_curtype MULTISET(ROW(

define columns based on query result set

) NOT NULL)

IBM Software Group IBM Information Management

Version 16 93

A P P E N D I X E Counting system objects

Using the system catalog

System catalog

Below is a list of SQL statements that will extract most if not all of the counts of system objects owned by user lsquoXXXrsquo

select count(table_name) from all_tables

where owner=rsquoxxxrsquo

select count() from dba_indexes

where owner=rsquoxxxrsquo

select count(synonym_name) from dba_synonyms

where owner=rsquoxxxrsquo

select count() from dba_views

where owner=rsquoxxxrsquo

select count() from dba_tab_columns

where length(column_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

and owner=rsquoxxxrsquo

select count distinct() from dba_tab_columns

and owner=rsquoxxxrsquo

select count() from dba_tables

where length(table_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_synonyms

where length(synonym_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_views

where length(view_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_indexes

where length(index_name)gt18

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and owner=rsquoxxxrsquo

IBM Software Group IBM Information Management

Version 16 94

select data_type count(data_type) from dba_tab_columns

where owner=rsquoxxxrsquo

group by data_type

select count() from dba_tab_columns

where data_type=rsquovarchar2rsquo

and length(data_type)gt254

and owner=rsquoxxxrsquo

select count() from dba_tab_columns

where data_type=rsquonumberrsquo

and data_scale=0

and owner=rsquoxxxrsquo

Using SQL code

Built-in function references

The following instructions can be used to find references to built-in functions On the UNIX machine or the NT box where your code resides please create the following file as tmpfunctionlist

convert(

hextoint(

inttohex(

getdate(

datename(

datepart(

datediff(

dateadd(

months_between(

char(

char_length(

charindex(

compute(

difference(

length(

lower(

patindex(

replicate(

reverse(

right(

soundex(

space(

str(

stuff(

substring(

upper(

abs(

atn2(

log(

ceiling(

IBM Software Group IBM Information Management

Version 16 95

cot(

degrees(

floor(

radians(

rand(

sign(

to_char(

to_date(

to_number(

exception(

pi(

raise_application_error(

raiserror(

SQLCODE

rollback

savepoint

declare

decode(

nvl(

print(

rowid

waitfor

recompile

bcp

isopen(

notfound(

rowtype(

type(

Then please run the following program with the proper subdirectories

binksh

rm ndashf somehomeoutfile

cd somesourcedatabase

export sourcebase=rdquosomepathrdquo

for functor in `cat tmpfunction_list`

do

echo before find $functor

find $sourcebasedatabase -exec grep -i $functor gtgt

somehome$functoroutfile

find $sourcebaseintfc -exec grep -i $functor gtgt

somehome$functoroutfile

echo after find $functor

done

Object types and counts

This script attempts to count the objects of each type by grepping for CREATE statements containing the object type and counts procedure definitions that are inside package bodies which are not proceeded by a CREATE keyword It is not a sophisticated parser so the results may not be perfect

binbash if [ $1 = ] then

IBM Software Group IBM Information Management

Version 16 96

echo Usage objCountssh ltFilePatterngt return 1 fi declare -a objectTypes=(CLUSTER CONTEXT CONTROLFILE DATABASE DATABASE +LINK DIMENSION DIRECTORY DISKGROUP FUNCTION INDEX INDEXTYPE JAVA LIBRARY MATERIALIZED +VIEW MATERIALIZED +VIEW +LOG OPERATOR OUTLINE PACKAGE PACKAGE +BODY PFILE PROCEDURE PROFILE RESTORE +POINT ROLE ROLLBACK +SEGMENT SCHEMA SEQUENCE SPFILE SYNONYM TABLE TABLESPACE TRIGGER TYPE TYPE +BODY USER VIEW) echo for type in $objectTypes[] do if [ $type = PROCEDURE ] then echo $type object count `cat $1 | grep -icE ^ (|CREATE +|OR REPLACE +)b$typeb` else echo $type object count `cat $1 | grep -icE ^ (CREATE +|OR +REPLACE +)b$typeb` fi done

IBM Software Group IBM Information Management

Version 16 97

A P P E N D I X F Data type mapping

Oracle built-in data types (including ANSI types) can be converted to similar data types in the Informix database according to the mapping described here This table provides default mappings based on most common usage patterns in some cases another mapping may work better

In the following table n is used to indicate length p is used to indicate precision and s is used to indicate scale

Oracle data type Informixreg Server data type

BFILE LONG RAW BLOB

BLOB

BINARY_DOUBLE DOUBLE PRECISION

BINARY_FLOAT DOUBLE PRECISION

BINARY_INTEGER

PLS_INTEGER

NATURAL

NATURALN

POSITIVE

POSITIVEN

32-bit integers only used in PLSQL NATURAL and POSITIVE are unsigned integers

INTEGER

BOOLEAN (PLSQL only) BOOLEAN

CHAR(n) or CHARACTER(n) CHAR(n)

DATE DATETIME YEAR TO SECOND

DOUBLE PRECISION DOUBLE PRECISION

IBM Software Group IBM Information Management

Version 16 98

FLOAT

See note on FLOAT below

FLOAT

INTEGER INT

A 38-digit NUMBER sub-type May want to flag with a warning on possible overflow

INTEGER

INTERVAL DAY(p) TO SECOND(s)

Note Oracle fractional seconds have 9 digits

INTERVAL DAY(p) TO FRACTION(min(5 s))

INTERVAL YEAR(p) TO MONTH

INTERVAL YEAR(p) TO MONTH

LONG CLOB

CLOB

LONG VARCHAR (xxx)

Oracle recommends not using this type

LVARCHAR

NCHAR(n) NATIONAL CHAR(n) or NATIONAL CHARACTER(n)

NCHAR(n)

See National Language Types below

NCLOB CLOB

NUMBER

NUMBER(0)

NUMBER(p) NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s lt 10

NUMBER(3-2) 12300

INTEGER

IBM Software Group IBM Information Management

Version 16 99

NUMBER(p) NUMBER (p0)

Where precision (p) is greater than or equal to 10 and lt= 18

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and 10 lt= p-s lt 19

NUMBER(9-2) 12345678900

BIGINT

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is greater than or equal to s (that is s gt 0 and p gt= s)

NUMERIC (min(p32) min(s32))

NUMBER(p s)

Where scale (s) is greater than 0 and precision (p) is less than s (that is s gt 0 and p lt s)

NUMBER(35) 000123

NUMERIC (min(s32)min(s32))

NUMBER(p s)

Where scale (s) is less than 0 (that is s lt 0) and p-s gt 18 and p-s lt= 32

NUMERIC (min(p-s32)0)

NUMBER(p s)

Where scale (s) is greater than 32 or pInformix-s is greater than 32

NUMERIC (32)

Scale cannot be greater than precision

NUMERIC(3232) would guarantee that digits to the left of the decimal would be lost Using a floating point decimal provides the simplest best way to capture as many digits in a value as possible

IBM Software Group IBM Information Management

Version 16 100

DEC

DECIMAL

NUMERIC

DEC(p)

DECIMAL(p)

NUMERIC(p)

DEC(p s)

DECIMAL(p s) NUMERIC(p s)

There is no difference within Oracle between these types and each other and these types and NUMBER The Oracle system catalogs contain the NUMBER type id for all declarations of these types and the integer types as well Declarations of these types can be mapped using the same rules as those for NUMBER

NVARCHAR2(n) NCHAR VARYING(n) NATIONAL CHAR VARYING(n) NATIONAL CHARACTER VARYING(n)

LVARCHAR(min(n 32767))

RAW(n) BLOB

REAL DOUBLE PRECISION

Record ROWTYPE

Using a CREATE ROWTYPE statement

ROWID INTEGER

SMALLINT SMALLINT

TIMESTAMP(p)

If p is not specified precision defaults to 6

DATETIME YEAR TO FRACTION(min(5 p))

UROWID(n) INTEGER

IBM Software Group IBM Information Management

Version 16 101

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is less than or equal to 255 (that is n lt= 255)

VARCHAR(n)

VARCHAR2(n) VARCHAR(n) CHAR VARYING(n) CHARACTER VARYING(n)

2

Where number (n) is greater than 255 (that is n gt 255)

LVARCHAR(n)

XMLType CLOB

Notes on specific types are below

DOUBLE

The range of values for the DOUBLE PRECISION data type is the same as the range of the C double data type on your computer

VARCHAR

While Oracle VARCHAR data types have a limit of 4000 bytes an Informix Server VARCHAR data types has a limit of 255 bytes An Informix Server LVARCHAR has a limit of 32739 Bytes

NUMBER

Oracle abstracts its numeric types from the hardware and operating system through the use of its NUMBER type Most numeric types like INTEGER are actually NUMBERs internally When porting to a database server like Informix which retains more of a relationship between the operating system types and the database types it is essentially a one-to-many mapping and heuristics have to be used to determine the best-fit target type No single set of type mapping rules will fit all use scenarios The converter has default rules which fit the more common user patterns When considering a number represented as mantissa and exponent

mantissa x 10exponent

precision is the number of digits in the mantissa and scale is the negative exponent how many places to the right of the decimal point the least significant digit is located Oracle NUMBERs have a maximum precision of 38 and the maximum precision available in Informix native types is 32 The first step in a type mapping is to truncate the target type precision to min(precision 32) The scale of a type can be considered its anchor point with respect to the decimal point The most

IBM Software Group IBM Information Management

Version 16 102

significant digit of a numeric type is located precision digits to the left of the decimal point and precision-scale digits to the right of the decimal point The start and end locations of the digits are used to determine the closest fitting Informix type The order of preference is INTEGER BIGINT NUMERIC(p s) and lastly NUMERIC(p) NUMERIC(p) in a non-ANSI mode database is a decimal type with a floating point type In an ANSI mode database the scale is implicitly 0 All Oracle integer declaration types such as INT INTEGER SMALLINT become NUMBER(38) type in the Oracle metadata In Oracle when precision is given but scale is not scale becomes 0 implicitly which makes the type in the set of integral types One exception to the general mapping rules is the NUMBER type specified without precision or scale Strictly speaking this has a floating point scale with 38 digits of precision but most commonly it is used where an integer is more appropriate Even if the user does specify INTEGER in a type definition when it comes out of the Oracle catalogs the type is NUMBER This is one case in particular where one type mapping will not fit well with all usage scenarios

National language types

Oracle Nchar types are allocated by number of characters where Informix is allocated by the number of bytes For Oracle the storage size of the characters varies with the encoding used and is always subject to the standard 32767 limit on maximum bytes but during declarations n always means the number of characters Oracle PLSQL supports explicit and implicit data type conversions These explicit and implicit data types are converted to syntax by using Informix Dynamic Servers explicit and implicit data type conversion mechanism

ROWID

Oracle databases support a pseudo-column named ROWID such that every row in every table is assigned an auto-generated ID Oracle also allows you to define a column of type ROWID which can be used as a foreign key to a ROWID pseudo-column Oracle ROWID columns contain data that if converted to a string are 18 characters long for example lsquoAAAQ+jAAEAAAAAeAANrsquo It is probably not advisable to migrate this data to an Informix database and instead use the Informix type which is an integer If there is a dependency on the values themselves and therefore need migrate the data then an integer type would not hold the values

TYPE

In PLSQL you can refer to the type of an existing variable field or column by using the TYPE attribute The converter replaces this reference directly by the type it refers to

ROWTYPE

In PLSQL you can refer to the record type that represents a row of a table a cursor or a cursor variable PLSQL scripts containing the ROWTYPE attribute are handled in the same way as a record type that has been previously declared

FLOAT

Oracle FLOAT type is a floating point number capable of storing up to 38 decimal digits or 126 binary digits It has a floating point scale that can exist outside the boundaries of what an Informix DECIMAL can represent A C language double or Informix float type is capable of only 16 digits so there is the chance that some data will be lost Using an Informix FLOAT type makes it so that less significant digits are lost in preference to more significant digits

IBM Software Group IBM Information Management

Version 16 103

References to subtypes declared in packages and PLSQL blocks are converted to the Informix Server equivalent base types Variables of type RECORD are not translated by the DDL Converter at the time of this writing They will be handled by the stored procedure converter

XMLType

Informix does not have a built-in type for representing XML The nearest approximation is to store it in a CLOB Another character type like LVARCHAR can be used if it can be determined that the actual data will fit in it

Page 10: Oracle to IBM Informix Server Porting Guide
Page 11: Oracle to IBM Informix Server Porting Guide
Page 12: Oracle to IBM Informix Server Porting Guide
Page 13: Oracle to IBM Informix Server Porting Guide
Page 14: Oracle to IBM Informix Server Porting Guide
Page 15: Oracle to IBM Informix Server Porting Guide
Page 16: Oracle to IBM Informix Server Porting Guide
Page 17: Oracle to IBM Informix Server Porting Guide
Page 18: Oracle to IBM Informix Server Porting Guide
Page 19: Oracle to IBM Informix Server Porting Guide
Page 20: Oracle to IBM Informix Server Porting Guide
Page 21: Oracle to IBM Informix Server Porting Guide
Page 22: Oracle to IBM Informix Server Porting Guide
Page 23: Oracle to IBM Informix Server Porting Guide
Page 24: Oracle to IBM Informix Server Porting Guide
Page 25: Oracle to IBM Informix Server Porting Guide
Page 26: Oracle to IBM Informix Server Porting Guide
Page 27: Oracle to IBM Informix Server Porting Guide
Page 28: Oracle to IBM Informix Server Porting Guide
Page 29: Oracle to IBM Informix Server Porting Guide
Page 30: Oracle to IBM Informix Server Porting Guide
Page 31: Oracle to IBM Informix Server Porting Guide
Page 32: Oracle to IBM Informix Server Porting Guide
Page 33: Oracle to IBM Informix Server Porting Guide
Page 34: Oracle to IBM Informix Server Porting Guide
Page 35: Oracle to IBM Informix Server Porting Guide
Page 36: Oracle to IBM Informix Server Porting Guide
Page 37: Oracle to IBM Informix Server Porting Guide
Page 38: Oracle to IBM Informix Server Porting Guide
Page 39: Oracle to IBM Informix Server Porting Guide
Page 40: Oracle to IBM Informix Server Porting Guide
Page 41: Oracle to IBM Informix Server Porting Guide
Page 42: Oracle to IBM Informix Server Porting Guide
Page 43: Oracle to IBM Informix Server Porting Guide
Page 44: Oracle to IBM Informix Server Porting Guide
Page 45: Oracle to IBM Informix Server Porting Guide
Page 46: Oracle to IBM Informix Server Porting Guide
Page 47: Oracle to IBM Informix Server Porting Guide
Page 48: Oracle to IBM Informix Server Porting Guide
Page 49: Oracle to IBM Informix Server Porting Guide
Page 50: Oracle to IBM Informix Server Porting Guide
Page 51: Oracle to IBM Informix Server Porting Guide
Page 52: Oracle to IBM Informix Server Porting Guide
Page 53: Oracle to IBM Informix Server Porting Guide
Page 54: Oracle to IBM Informix Server Porting Guide
Page 55: Oracle to IBM Informix Server Porting Guide
Page 56: Oracle to IBM Informix Server Porting Guide
Page 57: Oracle to IBM Informix Server Porting Guide
Page 58: Oracle to IBM Informix Server Porting Guide
Page 59: Oracle to IBM Informix Server Porting Guide
Page 60: Oracle to IBM Informix Server Porting Guide
Page 61: Oracle to IBM Informix Server Porting Guide
Page 62: Oracle to IBM Informix Server Porting Guide
Page 63: Oracle to IBM Informix Server Porting Guide
Page 64: Oracle to IBM Informix Server Porting Guide
Page 65: Oracle to IBM Informix Server Porting Guide
Page 66: Oracle to IBM Informix Server Porting Guide
Page 67: Oracle to IBM Informix Server Porting Guide
Page 68: Oracle to IBM Informix Server Porting Guide
Page 69: Oracle to IBM Informix Server Porting Guide
Page 70: Oracle to IBM Informix Server Porting Guide
Page 71: Oracle to IBM Informix Server Porting Guide
Page 72: Oracle to IBM Informix Server Porting Guide
Page 73: Oracle to IBM Informix Server Porting Guide
Page 74: Oracle to IBM Informix Server Porting Guide
Page 75: Oracle to IBM Informix Server Porting Guide
Page 76: Oracle to IBM Informix Server Porting Guide
Page 77: Oracle to IBM Informix Server Porting Guide
Page 78: Oracle to IBM Informix Server Porting Guide
Page 79: Oracle to IBM Informix Server Porting Guide
Page 80: Oracle to IBM Informix Server Porting Guide
Page 81: Oracle to IBM Informix Server Porting Guide
Page 82: Oracle to IBM Informix Server Porting Guide
Page 83: Oracle to IBM Informix Server Porting Guide
Page 84: Oracle to IBM Informix Server Porting Guide
Page 85: Oracle to IBM Informix Server Porting Guide
Page 86: Oracle to IBM Informix Server Porting Guide
Page 87: Oracle to IBM Informix Server Porting Guide
Page 88: Oracle to IBM Informix Server Porting Guide
Page 89: Oracle to IBM Informix Server Porting Guide
Page 90: Oracle to IBM Informix Server Porting Guide
Page 91: Oracle to IBM Informix Server Porting Guide
Page 92: Oracle to IBM Informix Server Porting Guide
Page 93: Oracle to IBM Informix Server Porting Guide
Page 94: Oracle to IBM Informix Server Porting Guide
Page 95: Oracle to IBM Informix Server Porting Guide
Page 96: Oracle to IBM Informix Server Porting Guide
Page 97: Oracle to IBM Informix Server Porting Guide
Page 98: Oracle to IBM Informix Server Porting Guide
Page 99: Oracle to IBM Informix Server Porting Guide
Page 100: Oracle to IBM Informix Server Porting Guide
Page 101: Oracle to IBM Informix Server Porting Guide
Page 102: Oracle to IBM Informix Server Porting Guide
Page 103: Oracle to IBM Informix Server Porting Guide