Oracle to IBM Informix Server Porting Guide
Transcript of 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
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
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
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
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
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
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
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
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