Guide to Migrating from Informix to SQL Server 2008
SQL Server Technical Article
Writers: Arthur Alchangian (DB Best Technologies), Galina Shevchenko (DB Best
Technologies), Yuri Tumakov (DB Best Technologies), Yuri Rusakov (DB Best Technologies)
Technical Reviewer: Dmitry Balin (DB Best Technologies)
Published: August 2009
Applies to: SQL Server 2008 and SQL Server 2008 R2
Summary: This white paper explores challenges that arise when you migrate from an Informix
11 database to SQL Server 2008. It describes the implementation differences of database
objects and procedural code between the two platforms. Emulation of system functions is also
discussed.
Created by: DB Best Technologies LLC
P.O. Box 7461, Bellevue, WA 98008
Tel.: (408) 202-4567
E-mail: info@dbbest.com
Web: http://www.dbbest.com
Copyright
This is a preliminary document and may be changed substantially prior to final commercial
release of the software described herein.
The information contained in this document represents the current view of Microsoft Corporation
on the issues discussed as of the date of publication. Because Microsoft must respond to
changing market conditions, it should not be interpreted to be a commitment on the part of
Microsoft, and Microsoft cannot guarantee the accuracy of any information presented after the
date of publication.
This White Paper is for informational purposes only. MICROSOFT MAKES NO WARRANTIES,
EXPRESS, IMPLIED OR STATUTORY, AS TO THE INFORMATION IN THIS DOCUMENT.
Complying with all applicable copyright laws is the responsibility of the user. Without limiting the
rights under copyright, no part of this document may be reproduced, stored in or introduced into
a retrieval system, or transmitted in any form or by any means (electronic, mechanical,
photocopying, recording, or otherwise), or for any purpose, without the express written
permission of Microsoft Corporation.
Microsoft may have patents, patent applications, trademarks, copyrights, or other intellectual
property rights covering subject matter in this document. Except as expressly provided in any
written license agreement from Microsoft, the furnishing of this document does not give you any
license to these patents, trademarks, copyrights, or other intellectual property.
Unless otherwise noted, the example companies, organizations, products, domain names, email addresses, logos, people, places and events depicted herein are fictitious, and no
association with any real company, organization, product, domain name, email address, logo,
person, place or event is intended or should be inferred.
© 2009 Microsoft Corporation. All rights reserved.
Microsoft and SQL Server are registered trademarks of Microsoft Corporation in the United
States and other countries.
The names of actual companies and products mentioned herein may be the trademarks of their
respective owners.
Contents
Introduction ................................................................................................................................ 6
Migrating Informix Data Types ................................................................................................... 7
Type Mapping......................................................................................................................... 7
Data Type Migration Issues........................................................................................................ 9
Time Data Types .................................................................................................................... 9
Issue: DATETIME Field Qualifier ........................................................................................ 9
Issue: Serial Data Type Columns ........................................................................................ 9
Issue: INTERVAL Data Type and INTERVAL Field Qualifier ..............................................10
Complex Data Types .............................................................................................................11
Issue: Collection Data Types..............................................................................................11
Issue: ROW Data Types ....................................................................................................11
User-Defined Data Types ......................................................................................................12
Issue: DISTINCT Types .....................................................................................................12
Issue: OPAQUE Types ......................................................................................................12
Migration of Table Structure ......................................................................................................14
CREATE TABLE Statement ..................................................................................................14
Issue: RAW Keyword in the CREATE TABLE Statement ...................................................14
Issue: The OPERATIONAL Keyword in the CREATE TABLE Statement ...........................14
Issue: The STATIC Keyword in the CREATE TABLE Statement ........................................14
Issue: DISTINCT Keyword .................................................................................................14
Issue: Constraints Syntax ..................................................................................................15
Issue: Default Values for the Referenced Column ..............................................................17
Issue: CREATE TABLE Options ........................................................................................18
Issue: PUT clause ..............................................................................................................19
Issue: USING Access-Method Clause................................................................................19
Issue: LOCK MODE Options ..............................................................................................19
Issue: OF TYPE clause ......................................................................................................20
Issue: UNDER Clause in a Definition of a Typed Table ......................................................21
CREATE TEMP TABLE Statement ........................................................................................21
Issue: WITH NO LOG Option .............................................................................................21
Issue: Temporary Table Options ........................................................................................21
Data Manipulation Statements ..................................................................................................23
SELECT Statement ...............................................................................................................23
FIRST Clause ....................................................................................................................23
FIRST Clause in SELECT UNION .....................................................................................23
MIDDLE Clause (XPS only) ...............................................................................................24
SKIP Clause ......................................................................................................................24
Alias for a Nested Table Expression ..................................................................................25
Alias for a Computed Column in Nested Table Expression ................................................26
ORDER BY in a Subquery .................................................................................................26
Stored Procedures ....................................................................................................................28
SPL Statements ....................................................................................................................28
Issue: CALL Statement ......................................................................................................28
Issue: CASE Statement .....................................................................................................28
Issue: CONTINUE Statement.............................................................................................29
Issue: DEFINE Statement ..................................................................................................30
Issue: EXIT Statement .......................................................................................................31
Issue: FOR Statement........................................................................................................32
Issue: FOREACH Statement ..............................................................................................33
Issue: GOTO Statement.....................................................................................................36
Issue: IF Statement ............................................................................................................37
Issue: LET Statement ........................................................................................................38
Issue: LOOP Statement .....................................................................................................39
Issue: ON EXCEPTION Statement ....................................................................................41
Issue: RAISE EXCEPTION Statement ...............................................................................43
Issue: RETURN Statement ................................................................................................44
Issue: SYSTEM Statement ................................................................................................45
Issue: TRACE Statement ...................................................................................................45
Issue: WHILE Statement ....................................................................................................46
Migrating Informix Standard Functions ......................................................................................48
Equivalent Functions .............................................................................................................48
Emulated Functions ...............................................................................................................48
ADD_MONTHS (date/dtime_expr, integer) ........................................................................48
ATAN2(numeric-expression-1, numeric-expression-2) .......................................................48
CEIL (num_expression) .....................................................................................................49
CHAR_LENGTH ( string-expression ) ................................................................................49
CHARACTER_LENGTH ( string-expression ) ....................................................................50
CONCAT (expr_1, expr_2) .................................................................................................50
CURRENT .........................................................................................................................51
DECODE (expr, when_expr, then_expr, ..., else_expr) ......................................................51
LENGTH ( string-expression ) ............................................................................................52
LOGN (float_expression) ...................................................................................................53
LPAD (source_string, length, pad_string) ...........................................................................53
LTRIM (source_string, pad_string) .....................................................................................54
MDY (int month, int day, int year) .......................................................................................55
MOD (dividend, divisor)......................................................................................................55
NVL (expr1, expr2).............................................................................................................56
OCTET_LENGTH ( string-expression ) ..............................................................................56
POW (float_expression1, float_expression2) .....................................................................57
RANGE (numeric_column) .................................................................................................57
ROOT (float_expression1, float_expression2) ....................................................................57
ROUND (float_expression1, int_expression2) ....................................................................58
RPAD (source_string, length, pad_string) ..........................................................................58
RTRIM (source_string, pad_string) ....................................................................................59
SQLCODE .........................................................................................................................60
STDEV (numeric_column) .................................................................................................60
SUBSTR ( string-expression, start [, length ] ) ....................................................................61
SUBSTRING( string-expression FROM start [FOR length ] )..............................................61
TODAY ..............................................................................................................................62
TRIM ({BOTH|LEADING|TRAILING } pad_string FROM source_string) .............................62
TRUNC (float_expression1, int_expression2) ....................................................................63
VARIANCE (numeric_column) ...........................................................................................63
WEEKDAY (date/dtime_expr) ............................................................................................64
Conclusion ................................................................................................................................64
About DB Best Technologies .................................................................................................64
Introduction
This white paper covers issues related to migration of an Informix 11+ database to the
Microsoft® SQL Server® 2008 database software. We describe basic steps for this kind of
migration and what you must know about converting database objects.
Generally, the following steps are necessary:
1. Decide how you will map Informix databases to SQL Server 2008. You have two main
options:
o Map each Informix database to a separate SQL Server database. For example,
you could map the MyDB Informix database to MyDB SQL Server database.
o Map each Informix database to a single SQL Server database but a separate
schema. For example, you could map the MyDB Informix database to
InformixDatabases SQL Server database, schema MyDB.
2. Convert database objects: these are tables, table constraints, indexes, views,
procedures, functions, and triggers.
3. Map Informix data types to SQL Server data types.
4. Rewrite your views, procedures, and functions according to SQL Server syntax.
5. Change your applications as necessary so that they can connect and work with SQL
Server 2008.
After successful database conversion, migrate your data from the old Informix database to the
newly created SQL Server 2008 database. For this task you can use SQL Server Integration
Services (SSIS).
Migrating Informix Data Types
This section explains mappings and differences between Informix and SQL Server 2008 data
types and specific data type handling, and it provides solutions for problems related to data
types.
Type Mapping
Following are the recommended type mappings for converting built-in data types.
Informix type
SQL
Server 2008
equivalent
Conversion remarks
Alternative
mappings
BOOLEAN
bit
f maps to 0, t to 1
None
CHAR(N),
CHARACTER(N),
LVARCHAR(N, R)
char(n)
N is size of string in bytes.
Use VARCHAR(max) for size
greater than 8000
Use NCHAR(N) for multibyte
text strings and
NVARCHAR(max) for multibyte text strings with size
greater 4000
varchar(n),
nvarchar(n)
NCHAR(N)
nchar(n)
N is size of string in bytes. Use
NVARCHAR(max) for size
greater than 4000
nvarchar(n)
VARCHAR(N, R),
CHARACTER
VARYING(N, R)
varchar(n)
N is maximum size of string in
bytes.
Use NVARCHAR(M) for multibyte text strings
CHAR(N),
NCHAR(N)
NVARCHAR(N, R)
nvarchar(n)
N is maximum size of string in
bytes
nchar(n)
DECIMAL(P, S),
DEC(P, S),
NUMERIC(P, S),
MONEY(P, S)
decimal(p, s),
numeric(p, s)
P is precision, S is scale
None
INT, INTEGER
int, integer
None
tinyint,
smallint,
bigint
INT8, BIGINT
bigint
None
None
DECIMAL(P), DEC(P),
NUMERIC(P)
float(53), double
precision
P is precision
real, float(n)
FLOAT, DOUBLE
PRECISION (N)
float(53), double
precision
None
real, float(n)
SMALLFLOAT, REAL
real, float(24)
None
float(53),
double
precision
TEXT, CLOB
nvarchar(max)
None
None
BYTE, BLOB
varbinary(max)
None
None
DATE
date
None
None
DATETIME
datetime2(5)
None
None
Data Type Migration Issues
This section describes data type conversion issues. Each issue is caused by an Informix feature
that is not supported in SQL Server.
Time Data Types
Issue: DATETIME Field Qualifier
The Informix DATETIME Field Qualifier may be used to specify the largest and smallest unit of
time in a DATETIME column or value. Possible qualifiers are:







YEAR
Specifies a year, in the range from A.D. 1 to 9999
MONTH
Specifies a month, in the range from 1 (January) to 12 (December)
DAY
Specifies a day, in the range from 1 to 28, 29, 30, or 31 (depending on
the specific month)
HOUR
Specifies an hour, in the range from 0 (midnight) to 23
MINUTE
Specifies a minute, in the range from 0 to 59
SECOND
Specifies a second, in the range from 0 to 59
FRACTION Specifies a fraction of a second, with up to five decimal places. The
default scale is three digits (thousandth of a second).
Example:
DATETIME (2003-9-30 12:30) YEAR TO MINUTE
Solution:
Use corresponding data type to store data, for example:



DATE for YAER TO DAY
TIME for HOUR TO FRACTION
INT for DAY TO DAY
Use DATEPART and DATEDIFF functions when converting these values to DATETIME2
format. In general, apply a user-defined type.
Issue: Serial Data Type Columns
The SERIAL, SERIAL8, and BIGSERIAL data types store a sequential integer, in the positive
range, that is automatically assigned by the database server when a new row is inserted. A
table can have no more than one SERIAL column, but it can have a SERIAL column and either
a SERIAL8 column or a BIGSERIAL column.
Example:
CREATE TABLE customer
(
cust_id serial,
. . .
)
Solution:
Use IDENTITY for columns that would be serial in Informix with corresponding data type (INT or
BIGINT). Use SET IDENTITY_INSERT <table> ON to insert custom values in such columns.
CREATE TABLE customer
(
cust_id INT NOT NULL IDENTITY(1, 1),
. . .
)
Issue: INTERVAL Data Type and INTERVAL Field Qualifier
The INTERVAL data type stores a value that represents a span of time. INTERVAL types are
divided into two classes: year-month intervals and day-time intervals. A year-month interval can
represent a span of years and months, and a day-time interval can represent a span of days,
hours, minutes, seconds, and fractions of a second:
INTERVAL largest_qualifier(n) TO smallest_qualifier
Qualifiers are:









YEAR-MONTH INTERVAL
YEAR
number of years
MONTH
number of months
DAY-TIME INTERVAL
DAY
number of days
HOUR
number of hours
MINUTE
number of minutes
SECOND
number of seconds
FRACTION decimal fraction of a second, with up to 5 digits. The default scale is 3
digits (thousandth of a second). To specify a nondefault scale, write FRACTION(n),
where 1 ≤ n ≤ 5.
Example:
INTERVAL (60 01:30) DAY TO MINUTE
Solution:
Use the corresponding integer data type to store values and DATEPART and DATEADD
functions to operate. In general case, use a user-defined type.
Complex Data Types
Issue: Collection Data Types
A collection data type is a complex type that is made up of one or more elements, all of the
same data type.
The SET data type is an unordered collection type that stores unique elements. The elements in
a SET have no ordinal position.
The MULTISET data type is a collection type that stores a nonordered set that can include
duplicate element values. The elements in a MULTISET have no ordinal position. The LIST data
type is a collection type that stores ordered, nonunique elements; that is, it allows duplicate
element values. The elements of a LIST have ordinal positions; that is, the list has a first
element, a second element, and so on.
Example:
LIST{"blue", "green", "yellow"}
INSERT INTO table1 VALUES (MULTISET{5, 9, 7, 5})
CREATE TABLE tab ( c CHAR(5), s SET(INTEGER NOT NULL) )
Solution:
Write a SQL Server user-defined type.
Issue: ROW Data Types
A named ROW type is declared by its name. That identifier must be unique within the schema.
No two named ROW types can be equal, even if they have identical structures, because they
have different names.
An unnamed ROW type is a ROW type that contains fields but has no user-defined name. An
unnamed ROW type is defined by its structure. Two unnamed ROW types are equal if they have
the same structure (meaning the ordered list of the data types of the fields). If two unnamed
ROW types have the same number of fields, and if the order of the data type of each field in one
ROW type matches the order of data types of the corresponding fields in the other ROW data
type, then the two unnamed ROW data types are equal.
Example:
name_t (lname CHAR(15), initial CHAR(1), fname CHAR(15))
ROW (dept char(15), rating char(1) name char(15))
Solution:
Write a SQL Server user-defined type.
User-Defined Data Types
Issue: DISTINCT Types
A distinct data type has the same internal structure as some other source data type in the
database. The source type can be a built-in or extended data type. What distinguishes a distinct
type from its source type are support functions that are defined on the distinct type.
Informix example:
CREATE DISTINCT TYPE birthday AS DATE;
Solution:
Use a SQL Server alias data type.
SQL Server example:
CREATE TYPE birthday FROM DATE
Issue: OPAQUE Types
An opaque data type is a user-defined data type that is fully encapsulated. That is, its internal
structure is unknown to the database server. User-defined types that are not DISTINCT types
whose source types are built-in types are opaque.
Example:
CREATE OPAQUE TYPE var_type (INTERNALLENGTH=VARIABLE, MAXLEN=4096);
Solution:
Write a SQL Server user-defined type.
Migration of Table Structure
This section discusses differences between the syntax of creating permanent and temporary
tables in Informix and SQL Server.
CREATE TABLE Statement
Issue: RAW Keyword in the CREATE TABLE Statement
In Informix, it is a nonlogging table that does not support referential constraints, primary key
constraints, or unique constraints, but that can be indexed and updated. This type of table is
used for quickly loading data. SQL Server table organization does not allow division of table
types.
Solution:
Ignore this keyword.
Issue: The OPERATIONAL Keyword in the CREATE TABLE Statement
In Informix, it is a logging table that uses light appends; it cannot be restored from archive. The
OPERATIONAL keyword is used on tables that are refreshed frequently, because light appends
allow the quick addition of many rows. SQL Server table organization does not have such
division of table types.
Solution:
Ignore this keyword.
Issue: The STATIC Keyword in the CREATE TABLE Statement
In Informix, it is a nonlogging table that can contain index and referential constraints but cannot
be updated. This type of table is used for read-only operations, because no logging or locking
overhead occurs. SQL Server table organization does not have such division of table types.
Solution:
Ignore this keyword.
Issue: DISTINCT Keyword
In Informix, the DISTINCT keyword requires that a column or set of columns accept only unique
data values. The keyword DISTINCT is a synonym for UNIQUE.
Informix example:
CREATE TABLE accounts
(acc_name
CHAR(12),
acc_num
INT DISTINCT CONSTRAINT acc_num);
Solution:
Replace the DISTINCT constraint with a UNIQUE constraint.
SQL Server example:
CREATE TABLE accounts
(acc_name
acc_num
CHAR(12),
INT CONSTRAINT acc_num UNIQUE );
Issue: Constraints Syntax
In Informix, the constraints syntax differs from SQL Server.
Informix examples:
Example 1:
CREATE TABLE accounts
(acc_name
acc_num
CHAR(12),
INTEGER UNIQUE CONSTRAINT acc_num);
Example 2:
CREATE TABLE accounts
(acc_name
acc_num
CHAR(12),
INTEGER PRIMARY KEY CONSTRAINT acc_num);
Example 3:
CREATE TABLE order_items
(
order_id INT,
line_item_id INT not null,
unit_price DECIMAL(6,2),
quantity INT,
UNIQUE (order_id,line_item_id) CONSTRAINT items_constr
);
Solution:
Convert the constraint to SQL Server syntax by moving the type of constraint to the end of the
constraint definition.
SQL Server examples:
Example 1:
CREATE TABLE accounts
(acc_name
acc_num
CHAR(12),
INT CONSTRAINT acc_num UNIQUE );
Example 2:
CREATE TABLE accounts
(acc_name
acc_num
CHAR(12),
INT CONSTRAINT acc_num PRIMARY KEY);
Example 3:
CREATE TABLE order_items
(
order_id INT,
line_item_id INT not null,
unit_price DECIMAL(6,2),
quantity INT,
CONSTRAINT items_constr UNIQUE (order_id,line_item_id)
);
Issue: Default Values for the Referenced Column
In Informix, if the referenced table is different from the referencing table, you do not need to
specify the referenced column; the default column is the primary key column (or columns) of the
referenced table.
Informix example:
CREATE TABLE accounts (
acc_num INTEGER PRIMARY KEY,
acc_type INTEGER,
acc_descr CHAR(20));
CREATE TABLE sub_accounts (
sub_acc INTEGER PRIMARY KEY,
ref_num INTEGER REFERENCES accounts,
sub_descr CHAR(20));
Solution:
Specify the referenced column(s) (which is a primary key column(s)) explicitly.
SQL Server example:
CREATE TABLE accounts (
acc_num INT PRIMARY KEY,
acc_type INT,
acc_descr CHAR(20));
CREATE TABLE sub_accounts (
sub_acc INT PRIMARY KEY,
ref_num INT REFERENCES accounts (acc_num),
sub_descr CHAR(20));
Issue: CREATE TABLE Options
In Informix, there are a number of options that can be defined in the CREATE TABLE
statement. These options are concerned with table storage strategies. The SQL Server
CREATE TABLE statement does not have such options, because the storage options are
defined mainly when the database is created.
Informix example:
CREATE TABLE family
(
id_num
INT UNIQUE,
name
CHAR(40),
nickname
CHAR(20),
mother
CHAR(40),
father
CHAR(40)
)
IN famdata;
Solution:
Because table storage principles in Informix and SQL Server are different, most of the Informix
options cannot be converted to SQL Server, except for IN<dbspace> and the PARTITION BY
clause. The Informix IN <dbspace> clause can be replaced with the ON <filegroup> clause in
SQL Server. But note that the filegroup should be created in the database in advance.
PARTITION BY is the same in Informix and SQL Server.
SQL Server example:
CREATE TABLE family
(
id_num
INT UNIQUE,
name
CHAR(40),
nickname
CHAR(20),
mother
CHAR(40),
father
CHAR(40)
)
ON famdata_filegroup;
Issue: PUT clause
In Informix, the PUT clause is used to specify the storage spaces and characteristics for each
column that will contain smart large objects. SQL Server does not have this functionality.
Solution:
In SQL Server, you only need to specify the corresponding data type (which can store large
amount of data). If you need emulate this Informix functionality, write CLR types instead and
design functions processing them by means of C#.
Issue: USING Access-Method Clause
In Informix, the USING Access Method clause can specify an access method. SQL Server does
not have this functionality.
Solution:
Ignore this keyword and use other methods available in SQL Server to manage access to
tables.
Issue: LOCK MODE Options
The LOCK MODE options are used to specify the locking granularity of the table. SQL Server
does not have this functionality.
Solution:
In SQL Server, the Database Engine manages granularity of locks automatically. If the number
of fine-grained locks is too large, it applies lock escalation. Lock escalation is the process of
converting many fine-grain locks into fewer coarse-grain locks.
Issue: OF TYPE clause
In Informix, the OF TYPE clause is used to create a typed table for an object-relational
database. SQL Server does not allow the creation of typed tables.
Informix example:
CREATE ROW TYPE student_t
(name
VARCHAR(30),
average
REAL,
birthdate
DATETIME YEAR TO DAY)
CREATE TABLE students OF TYPE student_t
Solution:
Create the table defining the columns from the ROW TYPE definition.
SQL Server example:
CREATE TABLE students(
name
VARCHAR(30),
average
REAL,
birthdate
DATE
)
Issue: UNDER Clause in a Definition of a Typed Table
When the UNDER clause is used, the ROW type must be derived from the ROW type of the
supertable. A type hierarchy must already exist in which the named ROW type of the new table
is a subtype of the named ROW type of the supertable. SQL Server does not allow the use of
table hierarchies.
Solution:
You can emulate this functionality by means of XML and CLR implementation.
CREATE TEMP TABLE Statement
Issue: WITH NO LOG Option
The WITH NO LOG option is used to reduce the overhead of transaction logging. SQL Server
syntax for creating temporary tables does not include a comparable option.
Informix example:
CREATE TEMP TABLE tab2 (fname CHAR(15), lname CHAR(15))
WITH NO LOG;
Solution:
Ignore this option.
SQL Server example:
CREATE TABLE #tab2 (fname CHAR(15), lname CHAR(15))
Issue: Temporary Table Options
Informix supports the following options for temporary table definition: WITH CRCOLS, storage
options, LOCK MODE options, USING access-method clause. SQL Server does not allow the
definition of options for temporary tables.
Solution:
Ignore these options.
Data Manipulation Statements
SELECT Statement
FIRST Clause
In Informix, the FIRST clause sets the maximum number of rows that can be retrieved.
Informix example:
select first 10 id, val
from tbl
order by id desc
Solution:
In SQL Server, emulate the FIRST clause by using the TOP clause of the SELECT statement.
SQL Server example:
SELECT TOP 10 id, val
FROM tbl
ORDER BY id desc
FIRST Clause in SELECT UNION
In Informix, the FIRST clause sets the maximum number of rows that can be retrieved after a
UNION operation is performed.
Informix example:
select first 4 id, val from tbl
union ALL
select id, val from tbl
order by id desc
Solution:
In SQL Server, emulate the FIRST clause by applying the TOP clause of the SELECT
statement to the result of the union operation.
SQL Server example:
SELECT TOP 4 id, val FROM
( SELECT
id, val FROM tbl
UNION ALL
SELECT id, val FROM tbl
) AS tmp
ORDER BY id desc
MIDDLE Clause (XPS only)
In Informix, the MIDDLE clause sets the maximum number of rows that can be retrieved from
the middle of the set of qualifying rows.
Informix example:
select middle 10 id, val
from tbl
order by id desc
Solution:
Replace the query with a common table expression and a ROW_NUMBER ( ) OVER
(order_by_clause ) construct that returns the sequential number of a row within a result set.
SKIP Clause
In Informix, the SKIP clause sets the number of rows to skip from top of the set of qualifying
rows.
Informix example:
select skip 2 id, val
from tbl
order by id desc
Solution:
In SQL Server, emulate the SKIP clause by using the following construction.
SQL Server example:
SELECT id, val FROM
(SELECT id, val, row_number() OVER ( PARTITION BY id, val ORDER BY
(SELECT 1)) AS Tmp$Num FROM tbl
EXCEPT
SELECT TOP 2 id, val, row_number() OVER ( PARTITION BY id, val ORDER
BY (SELECT 1)) AS Tmp$Num FROM tbl ORDER BY 1 desc
) AS tmp
ORDER BY 1 desc
Alias for a Nested Table Expression
In Informix, you do not need to specify an alias for a nested table expression. In SQL Server,
you must include an alias for a derived table (subquery).
Informix example:
select val
from (select id, val from tbl)
order by id;
Solution:
In SQL Server, add an alias for the nested table expression.
SQL Server example:
SELECT val
FROM (SELECT id, val FROM tbl) AS c
ORDER BY id;
Alias for a Computed Column in Nested Table Expression
In Informix, you do not need to specify an alias for a computed column in nested table
expression. In SQL Server, you must include an alias name for this column.
Informix example:
select *
from (select id, val, id||val from tbl)
order by id;
Solution:
In SQL Server, add an alias for a computed column in the nested table expression.
SQL Server example:
SELECT *
FROM (SELECT id, val, CAST(id AS varchar)+val somename FROM tbl) AS c
ORDER BY id;
ORDER BY in a Subquery
In Informix, the ORDER BY clause can be used in subqueries. The same ordering that is used
in an aliased query should be applied to the result table of the subselect. This functionality of
ORDER BY is not supported in SQL Server.
Informix example:
select *
from ( select id as a , val as b from tbl
order by b ) as sq
Solution:
In SQL Server, add the ORDER OF clause with a list of fields or aliases from the subquery sort
specification. Then either remove the ORDER BY clause from the subquery (see example 1), or
add the TOP clause to the subquery (see example 2).
SQL Server example 1:
SELECT *
FROM ( SELECT id AS a , val AS b FROM tbl ) AS sq
ORDER BY b
SQL Server example 2:
SELECT *
FROM ( SELECT TOP (100) PERCENT id AS a , val AS b
FROM tbl ORDER BY b ) AS sq
ORDER BY b
Stored Procedures
This section discusses differences between the Informix SPL procedural language and
SQL Server Transact-SQL. This includes the creation and calling of stored procedures as well
as working with local variables, cursors, and control-of-flow statements.
SPL Statements
Issue: CALL Statement
The CALL statement invokes a user-defined routine (UDR). The CALL statement is identical in
behavior to the EXECUTE PROCEDURE and EXECUTE FUNCTION statements, but it can
only be used from within an SPL routine.
Informix example:
CALL no_args (10,20);
CALL yes_args (5) RETURNING i, j, k;
Solution:
Use the EXECUTE statement for procedures. Functions can also be called directly.
SQL Server example:
EXEC no_args
EXEC yes_args
10,20
5, @I OUTPUT , @j OUTPUT,
@k OUTPUT
Issue: CASE Statement
The CASE statement is used to create a set of conditional branches within an SPL routine. The
CASE statement is a fast alternative to the IF statement.
Informix example:
CASE i
WHEN 1 THEN LET j = x;
WHEN 2 THEN LET k = x;
WHEN 3 THEN LET l = x;
WHEN 4 THEN LET m = x;
ELSE
LET n = x
END CASE;
Solution:
Use multiple IF…ELSE statements.
SQL Server example:
IF @i = 1 SET @j = @x
ELSE IF @i = 2 SET @k = @x
ELSE IF @i = 3 SET @l = @x
ELSE IF @i = 4 SET @m = @x
ELSE SET @n = @x
Issue: CONTINUE Statement
The CONTINUE statement starts the next iteration of the innermost FOR, LOOP, WHILE, or
FOREACH loop.
Informix example:
FOR i IN (3 TO 15 STEP 2)
INSERT INTO testtable1 values(i, null, null);
IF i = 11
CONTINUE FOR;
END IF;
INSERT INTO testtable2 values(i, null, null);
END FOR;
Solution:
Use the CONTINUE keyword.
SQL Server example:
DECLARE @i INT = 1
WHILE @i <= 15
BEGIN
SET @i += 2
INSERT testtable1 values(@i, null, null);
IF @i = 11 CONTINUE;
INSERT testtable2 values(@i, null, null);
END
Issue: DEFINE Statement
The DEFINE statement is used to declare local variables that an SPL routine uses, or to declare
global variables that can be shared by several SPL routines.
Informix example:
DEFINE GLOBAL gl_out CHAR(15);
-- global variable
DEFINE word INT DEFAULT 13;
DEFINE b_day DATE;
Solution:
For local variables, use the DECLARE statement. You can also emulate global variables by
storing and reading variable data from custom tables.
SQL Server example:
DECLARE @word INT = 15;
DECLARE @b_day DATE;
Issue: EXIT Statement
The EXIT statement transfers control of execution from an iterative statement, causing the
innermost loop of the enclosing statement type (FOR, FOREACH, LOOP, or WHILE) to
terminate. If no loop label or WHEN condition is specified, execution resumes at the first
statement that follows the current FOR, FOREACH, LOOP, or WHILE statement.
Informix example:
DEFINE i,s,j, INT;
FOR j = 1 TO 20
IF j > 10 THEN
CONTINUE FOR;
END IF
LET i,s = j,0;
WHILE i > 0
LET i = i -1;
IF i = 5 THEN
EXIT FOR;
END IF
END WHILE
END FOR
Solution:
Use the BREAK keyword in simple cases. For loop labels and nested cycles, use GOTO.
SQL Server example:
DECLARE @i INT, @s INT, @j INT = 0;
WHILE @j < 20
BEGIN
SET @j += 1
IF @j > 10 CONTINUE
SELECT @i = @j, @s = 0
WHILE @i > 0
BEGIN
SET @i -= 1;
IF @i = 5 GOTO for_exit; -- to exit outer loop GOTO is used
instead of BREAK
END
END
for_exit:
Issue: FOR Statement
The FOR statement is used to initiate a controlled (definite) loop with guaranteed termination.
The FOR statement uses expressions or range operators to specify a finite number of iterations
for a loop.
Informix example:
FOR index_var IN (12 TO 21 STEP 2)
-- statement block
END FOR;
Solution:
Use the WHILE keyword with provided logic to handle iterations—the cycle variable must be
declared and assigned before the cycle and changed manually during the cycle.
SQL Server example:
DECLARE @index_var INT = 10;
WHILE @index_var <= 21
BEGIN
SET @index_var += 2
-- statement block
END
Issue: FOREACH Statement
The FOREACH statement is used to select and manipulate more than one row or collection. A
FOREACH loop is the procedural equivalent of using a cursor.
Informix example:
CREATE PROCEDURE foreach_ex()
DEFINE i, j INT;
FOREACH SELECT c1 INTO i FROM tab ORDER BY 1
INSERT INTO tab2 VALUES (i);
END FOREACH
FOREACH cur1 FOR SELECT c2, c3 INTO i, j FROM tab
IF j > 100 THEN
DELETE FROM tab WHERE CURRENT OF cur1;
CONTINUE FOREACH;
END IF
UPDATE tab SET c2 = c2 + 10 WHERE CURRENT OF cur1;
END FOREACH
FOREACH EXECUTE PROCEDURE bar(10,20) INTO i
INSERT INTO tab2 VALUES (i);
END FOREACH
END PROCEDURE;
Solution:
Use a cursor with the WHILE cycle to get data. If you are executing a FOREACH routine, use a
temporary table or a table variable to hold data through the INSERT…EXEC statement from the
routine before you declare the cursor.
SQL Server example:
CREATE PROCEDURE foreach_ex
AS
DECLARE @i INT, @j INT;
DECLARE cur CURSOR FOR SELECT c1 INTO i FROM tab ORDER BY 1
OPEN cur
FETCH NEXT FROM cur INTO @i
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT tab2 VALUES (@i);
FETCH NEXT FROM cur INTO @i
END
CLOSE cur
DEALLOCATE cur
DECLARE cur1 CURSOR FOR SELECT c2, c3 FROM tab
OPEN cur1
FETCH NEXT FROM cur1 INTO @i, @j
WHILE @@FETCH_STATUS = 0
BEGIN
IF @j > 100
BEGIN
DELETE tab WHERE CURRENT OF cur1;
FETCH NEXT FROM cur INTO @i, @j
CONTINUE;
END
UPDATE tab SET c2 += 10 WHERE CURRENT OF cur1;
FETCH NEXT FROM cur INTO @i, @j
END
CLOSE cur1
DEALLOCATE cur1
DECLARE @Result TABLE (res INT)
INSERT @Result EXEC bar(10, 20)
DECLARE cur CURSOR FOR SELECT res FROM @Result ORDER BY 1
OPEN cur
FETCH NEXT FROM cur INTO @i
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT tab2 VALUES (@i);
FETCH NEXT FROM cur INTO @i
END
CLOSE cur
DEALLOCATE cur
Issue: GOTO Statement
The GOTO statement is used to transfer control of program execution to the statement that has
a specified statement label.
Informix example:
CREATE FUNCTION jump_back()
RETURNING INT;
DEFINE i,j INT;
...
<<back>>
LET j = j + i
FOR i IN (1 TO 52 STEP 5)
IF i < 11 THEN
LET j = j + 3
CONTINUE FOR;
END IF;
IF j > 100 THEN
GOTO back
END IF;
RETURN j;
END FOR;
END FUNCTION;
Solution:
Use the GOTO keyword and labels.
SQL Server example:
CREATE FUNCTION jump_back()
RETURNS INT
AS
BEGIN
DECLARE @i INT, @j INT;
...
back:
SET @j += @i
SET @i = -4
WHILE @i <= 52
BEGIN
SET @i += 5
IF @i < 11
BEGIN
SET @j += 3
CONTINUE
END
IF @j > 100 GOTO back
RETURN @j
END
END
Issue: IF Statement
The IF statement is used to create a logical branch within an SPL routine.
Informix example:
IF i = 1
THEN LET j = k
END IF
Solution:
Use IF…ELSE keywords.
SQL Server example:
IF @i = 1 SET @j = @k
Issue: LET Statement
The LET statement is used to assign values to variables or to call a user-defined SPL routine
and to assign the returned value or values to SPL variables.
Informix example:
LET a
= c + d;
LET a, b = c, d;
LET a, b, c = 1, test_func(1);
Solution:
Use the SET keyword for simple assignment; for multiple-variable and function assignment, use
SELECT.
SQL Server example:
SET @a = @c + @d
SELECT @a = @c, @b = @d
SELECT @a = 1, @b = f.b, @c = f.c FROM dbo.test_func(1) f
Issue: LOOP Statement
The LOOP statement is used to define a loop with an indeterminate number of iterations. The
LOOP statement is an iterative statement that resembles the FOR and WHILE statements. Like
FOR and WHILE, the LOOP statement can have an optional loop label. It can include the
CONTINUE statement to specify another iteration and the EXIT statement to terminate
execution of the loop.
Besides resembling FOR and WHILE in its functionality, the LOOP statement can use the
syntax of FOR or WHILE that precedes the statement block.
Informix example:
--simple loop
LOOP
LET i = i + 1;
EXIT WHEN i = 4;
END LOOP;
-- FOR loop
FOR i IN (1 TO 5) LOOP
EXIT WHEN i = 5;
END LOOP;
-- WHILE loop
WHILE (i < 6) LOOP
LET i = i + 1;
IF i = 5 THEN EXIT;
ELSE
CONTINUE;
END IF
END LOOP;
-- Labeled loop
<<voort>>
LOOP
LET x = x+1;
<<endo>>
WHILE ( i < 10 ) LOOP
LET x = x+1;
EXIT endo WHEN x = 7;
EXIT voort WHEN x > 9;
END LOOP endo;
LET x = x+1;
END LOOP voort;
Solution:
Use the WHILE statement. For loop labels and nested cycles, you can also use GOTO.
SQL Server example:
--simple loop
WHILE 1 = 1
BEGIN
SET @i += 1
IF @i = 4 BREAK
END
-- FOR loop
DECLARE @i INT = 0
WHILE @i <= 5
BEGIN
SET @i += 1
IF @i = 5 BREAK
END
-- WHILE loop
WHILE (@i < 6)
BEGIN
SET @i += 1;
IF @i = 5 BREAK
ELSE CONTINUE
END
-- Labeled loop
voort:
WHILE 1 = 1
BEGIN
SET @x += 1
endo:
WHILE @i < 10
BEGIN
SET @x += 1
IF @x = 7 GOTO endo
IF @x > 9 GOTO voort
END
SET @x += 1
END
Issue: ON EXCEPTION Statement
The ON EXCEPTION statement is used to specify actions to be taken for any error, or for a list
of one or more specified errors, during execution of a statement block. The ON EXCEPTION
statement, together with the RAISE EXCEPTION statement, provides an error-trapping and
error-recovery mechanism for SPL. ON EXCEPTION can specify the errors that you want to
trap as the SPL routine executes, and it specifies the action to take if the error occurs within the
statement block. ON EXCEPTION can specify an error number list in the IN clause, or it can
include no IN clause. If the IN clause is omitted, all errors are trapped.
Informix example:
CREATE PROCEDURE ex_test()
DEFINE error_num INT;
...
ON EXCEPTION SET error_num
-- action C
END EXCEPTION
ON EXCEPTION IN (-300)
-- action B
END EXCEPTION
ON EXCEPTION IN (-210, -211, -212) SET error_num
-- action A
END EXCEPTION
--test block
Solution:
Use the TRY…CATCH statement.
SQL Server example:
CREATE PROCEDURE ex_test
AS
DECLARE @error_num INT
BEGIN TRY
--test block
END TRY
BEGIN CATCH
DECLARE @error_number INT
SET @error_number = ERROR_NUMBER()
IF @error_number IN (50002, 50003, 50004)
BEGIN
SET @error_num = @error_number
-- action A
END
ELSE
IF @error_number= 50001
BEGIN
-- action B
END
ELSE
BEGIN
-- action C
END
END CATCH
Issue: RAISE EXCEPTION Statement
The RAISE EXCEPTION statement is used to simulate an error or to generate an error with a
custom message. The special error number -746 enables you to produce a customized
message.
Informix example:
RAISE EXCEPTION -208, 0;
RAISE EXCEPTION -746, 0, 'Some error';
Solution:
Use the RAISERROR() function. SQL Server error codes differ from Informix codes; if you want
to use an error code rather than build the message dynamically, you must provide the number
of an equivalent message in the sys.messages catalog view, or if the message does not exist
there, you can add a custom error code and message view using the sp_addmessage system
stored procedure.
SQL Server example:
RAISERROR (50000, 10, 1);
RAISERROR ('Some error', 16, 1);
Issue: RETURN Statement
The RETURN statement is used to specify what values (if any) the SPL function returns to the
calling context.
Informix example:
CREATE FUNCTION fn_return (stockno INT)
DEFINE des CHAR(15);
SELECT descript INTO des FROM stock
WHERE stocknum = stockno;
RETURN des;
END FUNCTION;
Solution:
Use the RETURN statement.
RETURNING CHAR (15);
SQL Server example:
CREATE FUNCTION fn_return (@stockno INT)
RETURNS CHAR(15)
AS
BEGIN
DECLARE @des CHAR(15)
SELECT @des = descript FROM stock
WHERE stocknum = @stockno
RETURN @des
END
Issue: SYSTEM Statement
The SYSTEM statement is used to issue an operating-system command from within an SPL
routine.
Solution:
Use the xp_cmdshell extended stored procedure. It is disabled by default and can be enabled
and disabled by using the Policy-Based Management or by executing the sp_configure system
procedure. The operating-system command must be converted manually depending on the
operating system.
Issue: TRACE Statement
The TRACE statement is used to control the generation of debugging output.
Informix example:
CREATE PROCEDURE tracing ()
DEFINE i INT;
BEGIN
ON EXCEPTION IN (1)
END EXCEPTION; -- do nothing
SET DEBUG FILE TO '/tmp/mytrace.trace';
TRACE OFF;
TRACE 'Forloop starts';
FOR i IN (1 TO 1000)
BEGIN
TRACE 'FOREACH starts';
FOREACH SELECT...INTO a FROM t
IF <some condition> THEN
RAISE EXCEPTION 1
-- emergency exit
END IF
END FOREACH
-- return some value
END
END FOR
-- do something
END;
END PROCEDURE
Solution:
Use SQL Server Profiler to see the trace of executing statements. In procedures, the PRINT
statement can be used, but the results of PRINT statements are only shown in the Messages
window in SQL Server Management Studio; they cannot be saved to a file.
Issue: WHILE Statement
The WHILE statement is used to establish a loop with variable end conditions.
Informix example:
DEFINE i INT;
LET i = 1;
WHILE i < 10
INSERT INTO tab_2 VALUES (i);
LET i = i + 1;
END WHILE;
Solution:
Use a WHILE statement.
SQL Server example:
DECLARE @i INT
SET @i = 1
WHILE @i < 10
BEGIN
INSERT tab_2 VALUES (@i)
SET @i+ = 1
END
Migrating Informix Standard Functions
This section describes how to map Informix standard functions to equivalent SQL Server
functions, and it provides solutions for emulating Informix functions.
Equivalent Functions
The following Informix system functions are usable as they stand, in SQL Server code:
ABS, ACOS, ASCII, ASIN, ATAN, AVG, CASE, COS, COUNT, DAY, EXP, FLOOR, LOG10,
LOWER, MAX, MIN, MONTH, NULLIF, POWER, REPLACE, SIN, SQRT, SUM, TAN, UPPER,
YEAR
Emulated Functions
The following Informix system functions can be emulated by using various SQL Server functions
or Transact-SQL constructions.
ADD_MONTHS (date/dtime_expr, integer)
The value returned is the sum of the DATE or DATETIME value of the first argument and an
INTERVAL UNITS MONTH value that is based on the number of months that the second
argument specifies.
Informix example:
add_months (current, 5)
Solution:
In SQL Server, use the DATEADD function with a datepart of month.
SQL Server example:
DATEADD (month, 5, GETDATE())
ATAN2(numeric-expression-1, numeric-expression-2)
Returns the arc-tangent, in radians, of the ratio of two numbers.
Informix example:
atan2 ( 0.52, 0.60 )
Solution:
In SQL Server, use the ATN2 function.
SQL SERVER EXAMPLE:
atn2 ( 0.52, 0.60 )
CEIL (num_expression)
Returns the smallest integer that is greater than or equal to its single argument.
Informix example:
ceil ( 32.3 )
ceil ( -32.3 )
Solution:
In SQL Server, use the CEILING function.
SQL Server example:
CEILING ( 32.3 )
CEILING ( -32.3 )
CHAR_LENGTH ( string-expression )
Returns the number of characters in a string.
Informix example:
char_length ('InForMix')
Solution:
In SQL Server, use the LEN function.
SQL Server example:
LEN ('InForMix')
CHARACTER_LENGTH ( string-expression )
Returns the number of characters in a string.
Informix example:
char_length ('InForMix')
Solution:
In SQL Server, use the LEN function.
SQL Server example:
LEN ('InForMix')
CONCAT (expr_1, expr_2)
Returns a character string that appends the string representation of the value returned by its
second argument to the string representation of the value returned by its first argument.
If one of its arguments returns a NULL value, the function returns the string representation of its
other argument.
Informix example:
concat ('Some', 'String')
concat (null, 'String')
Solution:
In SQL Server, use the ‘+’ operation to concatenate strings. Use the ISNULL function for both
arguments.
SQL Server example:
ISNULL('Some', '') + ISNULL('String', '' )
ISNULL (null, '') + ISNULL ('String', '')
CURRENT
Returns the current date and time.
Informix example:
current
Solution:
In SQL Server, use the GETDATE function.
SQL Server example:
GETDATE()
DECODE (expr, when_expr, then_expr, ..., else_expr)
Returns different results depending on the values found in a specified column.
Informix example:
argn( 2, '1', 'a', '2', 'b', '3', 'c', 'z' )
argn( 15, '1', 'a', '2', 'b', '3', 'c', 'z' )
Solution:
In SQL Server, use the CASE function.
SQL Server example:
CASE 2
WHEN 1 THEN 'a'
WHEN 2 THEN 'b'
WHEN 3 THEN 'c'
ELSE 'z'
END
CASE 15
WHEN 1 THEN 'a'
WHEN 2 THEN 'b'
WHEN 3 THEN 'c'
ELSE 'z'
END
LENGTH ( string-expression )
Returns the number of bytes in a string.
Informix example:
length( 'text' )
Solution:
In SQL Server, use the DATALENGTH function.
SQL Server example:
DATALENGTH('text')
LOGN (float_expression)
Returns the natural logarithm of a numeric argument.
Informix example:
logn ( 10 )
Solution:
In SQL Server, use the LOG function.
SQL Server example:
LOG ( 10 )
LPAD (source_string, length, pad_string)
Returns a copy of source_string that is left-padded to the total number of characters specified
by length.
Informix example:
lpad('text', 5, '<>')
Solution:
In SQL Server, use the following CASE construction:
CASE
WHEN @length>0 AND @length-LEN(@source_string)>0 THEN
REPLICATE (@pad_string, (@lengthLEN(@source_string))/LEN(@pad_string))+
substring(@pad_string, 1, (@lengthLEN(@source_string))%LEN(@pad_string))+@source_string
WHEN @length>=0 AND @length-LEN(@source_string)<=0 THEN
SUBSTRING(@source_string, 1, @length)
ELSE NULL END
If a negative value for the length argument returns NULL, or if the length argument is less than
the length of the source string, SUBSTRING is returned. Otherwise, the source string is leftpadded by the value specified in the pad_string argument as needed.
SQL Server example:
CASE
WHEN 5>0 AND 5-len('text')>0 THEN
REPLICATE ('<>', (5-len('text'))/len('<>'))+
SUBSTRING('<>', 1, (5-len('text'))%len('<>'))+'text'
WHEN 5>=0 and 5-len('text')<=0 THEN
SUBSTRING('text', 1, 5)
ELSE NULL END
LTRIM (source_string, pad_string)
The LTRIM function removes specified leading pad characters from a string.
Informix example:
ltrim('>><<text>><<', '<>')
Solution:
SQL Server also has a function named LTRIM, but it can trim only spaces. To emulate this
function in other cases, use the following construction:
SUBSTRING(@source_string,
PATINDEX('%[^'+@pad_string+']%',@source_string), LEN(@source_string))
SQL Server example:
SUBSTRING('>><<text>><<', patindex('%[^'+'<>'+']%','>><<text>><<'),
len('>><<text>><<'))
MDY (int month, int day, int year)
The MDY function takes as its arguments three integer expressions that represent the month,
day, and year, and it returns a type DATE value.
Informix example:
mdy ( 02, 27, 159 )
Solution:
In SQL Server, use multiple CAST, REPLICATE, and LEN functions.
SQL Server example:
CAST ( CAST (02 AS varchar(2)) + '/' + CAST (27 AS varchar(2))+ '/' +
REPLICATE('0', 4-len(CAST(159 AS varchar(4))))+ CAST(159 AS
varchar(4)) AS date)
MOD (dividend, divisor)
Returns the integer remainder of a division of the integer part of the first argument (the dividend)
by the integer part of the second argument (the divisor).
Informix example:
mod ( 24.2, 5 )
Solution:
In SQL Server, use the % operation and CAST function.
SQL Server example:
CAST( 24.2 AS numeric(38,0)) % CAST( 5 AS numeric(38,0))
NVL (expr1, expr2)
NVL evaluates expression1. If expression1 is not NULL, then NVL returns the value of
expression1. If expression1 is NULL, NVL returns the value of expression2.
Informix example:
nvl ( 24, 0 )
nvl ( null, 0 )
Solution:
In SQL Server, use the ISNULL function.
SQL Server example:
ISNULL ( 24, 0 )
ISNULL ( NULL, 0 )
OCTET_LENGTH ( string-expression )
Returns the number of bytes in a string.
Informix example:
octet_length ('text')
Solution:
In SQL Server, use the DATALENGTH function.
SQL Server example:
DATALENGTH ('text')
POW (float_expression1, float_expression2)
Raises its first numeric argument, the base, to the power of its second numeric argument, the
exponent.
Informix example:
pow ( 10, 2 )
Solution:
In SQL Server, use the POWER function.
SQL Server example:
POWER ( 10, 2 )
RANGE (numeric_column)
Return the difference between the maximum and the minimum values.
Informix example:
range ( expr )
Solution:
In SQL Server, use the MIN and MAX aggregate functions.
SQL Server example:
MAX ( expr ) - MIN ( expr )
ROOT (float_expression1, float_expression2)
Extracts a positive real root value, returned as a FLOAT data type, from its first numeric
expression argument.
Informix example:
root ( 100, 2 )
Solution:
In SQL Server, use the POWER function.
SQL Server example:
POWER ( 100, 1/2 )
ROUND (float_expression1, int_expression2)
Returns the rounded number to the specified precision value.
Informix example:
round ( 123.125, 2 )
Solution:
In SQL Server, use the ROUND function, but only for numeric and float data types.
Rounding of dates is not supported.
SQL Server example:
ROUND ( 123.125, 2 )
RPAD (source_string, length, pad_string)
Returns a copy of source_string that is right-padded to the total number of characters specified
by length.
Informix example:
rpad('text', 5, '<>')
Solution:
In SQL Server, use the following CASE construction:
CASE
WHEN @length>0 AND @length-LEN(@source_string)>0 THEN
@source_string + REPLICATE (@pad_string, (@lengthLEN(@source_string))/LEN(@pad_string))+
SUBSTRING(@pad_string, 1, (@lengthLEN(@source_string))%LEN(@pad_string))
WHEN @length>=0 AND @length-LEN(@source_string)<=0 THEN
SUBSTRING(@source_string, 1, @length)
ELSE NULL END
If a negative value for the length argument returns NULL, or if the length argument is less than
the length of the source string, SUBSTRING is returned. Otherwise, the source string is rightpadded by the value specified in the pad_string argument as needed.
SQL Server example:
CASE
WHEN 5>0 AND 5-LEN('text')>0 THEN
'text' + REPLICATE ('<>', (5-LEN('text'))/LEN('<>'))+
SUBSTRING('<>', 1, (5-LEN('text'))%LEN('<>'))
WHEN 5>=0 AND 5-len('text')<=0 THEN
SUBSTRING('text', 1, 5)
ELSE NULL END
RTRIM (source_string, pad_string)
The RTRIM function removes specified trailing pad characters from a string.
Informix example:
ltrim('>><<text>><<', '<>')
Solution:
SQL Server also has a function named RTRIM, but it can trim only spaces. To emulate this
function in other cases, use the following construction:
REVERSE(SUBSTRING(REVERSE(@source_string),
PATINDEX('%[^'+@pad_string+']%',REVERSE(@source_string)),
LEN(@source_string)))
SQL Server example:
REVERSE(SUBSTRING(REVERSE('>><<text>><<'),
PATINDEX('%[^'+'<>'+']%',REVERSE('>><<text>><<')),
LEN('>><<text>><<')))
SQLCODE
Returns the error code for the most recently executed SQL statement.
Informix example:
sqlcode
Solution:
In SQL Server, use the @@ERROR server variable.
SQL Server example:
@@ERROR
STDEV (numeric_column)
Return the standard deviation of a data set.
Informix example:
stdev ( expr )
Solution:
In SQL Server, use the STDEVP aggregate function.
SQL Server example:
STDEVP ( expr )
SUBSTR ( string-expression, start [, length ] )
Returns a substring of a string.
Informix example:
substring( 'Test Message', 1, 4 )
Solution:
SQL Server also has a function called SUBSTRING, but it does not allow negative start and
length. A user-defined function can be created to fully emulate Informix substring behavior.
SQL Server example:
SUBSTRING( 'Test Message', 1, 4 )
SUBSTRING( string-expression FROM start [FOR length ] )
Returns a substring of a string.
Informix example:
substring( 'Test Message' from 1 for 4 )
Solution:
SQL Server also has a function called SUBSTRING, but it does not allow negative start and
length. A user-defined function can be created to fully emulate Informix substring behavior.
SQL Server example:
SUBSTRING( 'Test Message', 1, 4 )
TODAY
Returns the current date.
Informix example:
today
Solution:
In SQL Server, use the GETDATE function.
SQL Server example:
CAST(GETDATE() AS DATE)
TRIM ({BOTH|LEADING|TRAILING } pad_string FROM source_string)
The TRIM function removes the pad characters specified by LEADING, TRAILING, or BOTH
from a string.
Informix example:
trim(both '<>' from '>><<text>><<')
Solution:
In SQL Server, for leading trim, see the emulation of LTRIM, and for trailing trim, see the
emulation of RTRIM. For both, apply the emulation of LTRIM and RTRIM, one after another.
TRUNC (float_expression1, int_expression2)
Returns the truncated to specified precision value.
Informix example:
round ( 123.125, 2 )
Solution:
In SQL Server, use the ROUND function with 1 in the third argument, but only for numeric and
float data types.
Rounding of dates is not supported.
SQL Server example:
ROUND ( 123.125, 2, 1 )
VARIANCE (numeric_column)
Return an estimate of the population variance, as the standard deviation squared.
Informix example:
variance ( expr )
Solution:
In SQL Server, use the VARP aggregate function.
SQL Server example:
VARP ( expr )
WEEKDAY (date/dtime_expr)
The WEEKDAY function takes a DATE or DATETIME argument and returns an integer in the
range from 0 to 6 that represents the day of the week. Zero (0) represents Sunday, one (1)
represents Monday, and so on.
Informix example:
weekday(current)
Solution:
In SQL Server, use the DATEPART function with a datepart of dw and the @@DATEFIRST
server variable.
SQL Server example:
(DATEPART(dw, GETDATE())-1+@@DATEFIRST)%7
Conclusion
This migration guide covers the differences between Informix 11 and SQL Server 2008
database platforms, and the steps necessary to convert an Informix database to SQL Server.
About DB Best Technologies
DB Best Technologies is a leading provider of database and application migration services and
custom software development. We have been focused on heterogeneous database
environments (SQL Server, Oracle, Sybase, DB2, MySQL) since starting at 2002 in Silicon
Valley. Today, with over 75 employees in the United States and Europe, we develop database
tools and provide services to customers worldwide.
DB Best developed migration tools to automate conversion between SQL dialects. In 2005
Microsoft acquired this technology, which later became a family of SQL Server Migration
Assistant (SSMA) products. We continue to develop new versions of SSMA, and support
Microsoft customers who are migrating to SQL Server.
We also provide migration services covering all major steps of a typical migration project:
complexity assessment, schema conversion, data migration, application conversion, testing,
integration, deployment, performance tuning, training, and support.
For more details, visit us at http://www.dbbest.com, e-mail us at info@dbbest.com, or call 1-408202-4567.
For more information:
http://www.microsoft.com/sqlserver/: SQL Server Web site
http://technet.microsoft.com/en-us/sqlserver/: SQL Server TechCenter
http://msdn.microsoft.com/en-us/sqlserver/: SQL Server DevCenter
Did this paper help you? Please give us your feedback. Tell us on a scale of 1 (poor) to 5
(excellent), how would you rate this paper and why have you given it this rating? For example:


Are you rating it high due to having good examples, excellent screen shots, clear writing,
or another reason?
Are you rating it low due to poor examples, fuzzy screen shots, or unclear writing?
This feedback will help us improve the quality of white papers we release.
Send feedback.