Oracle and SQL Server Data Interoperability Issues - Part 1

, 2008-06-06 (first published: )

Most of us work with and specialize in only one RDBMS system, such as MSSQL, Oracle, or IBM DB2. However, increasingly, we find outselves dealing with a heterougeous database environment and are asked to solve data interoperability probelms.

Although the major RDBMS vendors try to follow the relational data model principals, their implementation of them can be quite different. In addition, although most of the major RDBMS vendors also comply with SQL-92 standard, they all have their own proprietary extension to that standard. For example, both Oracle's PL/SQL and Microsoft's T-SQL added tons of extra extentions to ANSI SQL.

In a series of articles, I want to address data interoperability issues between SQL Server and Oracle. I will talk about data types used in these 2 different RDBMS. In particular, I will talk about Oracle's timestamp and SQL Server's datetime, because their incompatibility can cause a lot of problems in DTS, linked server, and distributed queries.

Overview of data type differences between Oracle and SQL Server

For the most part, Oracle and SQL Server has compatible data types, although they may have different names , width, precision, and/or scale. For example, Oracle's CHAR data type corresponds to SQL Server's CHAR data type but they have different width. In Oracle, CHAR can hold maximum 2000 bytes. In SQL Server, it can hold maximum 8000 bytes. VARCHAR in SQL Server corresponds to VARCHAR2 in Oracle. Again, their width is different (Oracle VARCHAR2 4000, SQL Server VARCHAR 8000).

There are also differences in numeric data types. In Oracle, there is pretty much just one numeric data type, aptly named NUMBER. By defining its precision and scale, it matches to SQL Server's tinyint, smallint, int, bigint, and numeric data types. In Oracle, you can create a sequence, which can match SQL Server's Identity field.

For binary data types, Oracle has RAW, LONG RAW, and BLOB. They should be compatible with the varbinary and image data type in SQL Server. I say "should" because I didn't test this myself. Maybe I will do a binary data type comparison as my next project :-). For more details on data types, please consult Microsoft SQL Server BOL and Oracle documentation.

For an Oracle table, to create a corresponding table in SQL Server, the best method is to use DTS Import wizard to generate the CREATE TABLE DDL statement. However, if the Oracle table has a TIMESTAMP column, you will have problems, which I will address in the next section.

Issues with Oracle TIMESTAMP and Microsoft SQL Server datetime conversion

In Oracle, the TIMESTAMP datatype enables you to resolve time to the billionth of a second. Although SQL Server has a type called timestamp, it is not the same as the timestamp data type defined in the SQL-92 standard. Its name is misleading for a lot of users. Typically, a timestamp data type in SQL Server is used as a mechanism for version-stamping table rows. Therefore, it does not match the timestamp in Oracle. The closest data type to Oracle's timestamp is datetime in SQL Server.

In SQL Server, the DATETIME data type has an accuracy of one three-hundredth of a second (equivalent to 3.33 milliseconds or 0.00333 seconds). Values are rounded to increments of .000, .003, or .007 seconds. This inconsistency will cause problems if you try to do DTS data transformation from Oracle to SQL Server, or when you try to run a query via linked server that reference the timestamp column in Oracle.

Within DTS, if you use Microsoft ODBC driver for Oracle, this is the message you will get:
ODBC Error

Within DTS, if you use Microsoft OLE DB Provider for Oracle, this is the message you will get
OLE DB Error

You can reproduce those error by following the steps below:

  1. Create a table in Oracle by using this DDL:
    create table t1 (c1 varchar2(20), c2 timestamp(3));

    Note: The parameter of the timestamp column does not make a difference as far as this discussion is concerned. The transformation of timestamp data will fail no matter what kind of parameter you use. I tested this myself;

  2. Insert some values into this Oracle test table, for example:
    insert into t1 (c1, c2) values ('Hello World', systimestamp); commit;
  3. In SQL Server Enterprise Manager, assuming you have Oracle Client installed and set up correctly, the process of which may warrant another article, you can use DTS designer and create a Data Transformation task from Oracle to SQL Server. When you try to preview data from t1, you will see the error I described above;
  4. Now create a linked server. I may write a separate article for this. After this is done, you can issue a query like this:
    select * from MyLinkedServer..MYSCHEMA.T1.

    This is the error message you will get:

    Server: Msg 7354, Level 16, State 1, Line 1
    OLE DB provider 'MSDAORA' supplied invalid metadata for column 'C2'. The data type is not supported.
    OLE DB error trace [Non-interface error:  Column 'C2' (ordinal 1) of object '"MYSCHEMA"."T1"' reported an unsupported value for DBTYPE of 13].
  5. If you run the linked server query using OpenQuery like this:
    select * from openquery(MyLinkedServer, 'select * from MYSCHEMA.T1')

    this is the message you will get:

    Server: Msg 7399, Level 16, State 1, Line 1
    OLE DB provider 'MSDAORA' reported an error.  
    [OLE/DB provider returned message: Oracle error occurred, but error message could not be retrieved from Oracle.]
    [OLE/DB provider returned message: Data type is not supported.]
    OLE DB error trace [OLE/DB Provider 'MSDAORA' ICommandPrepare::Prepare returned 0x80004005:   ].

How to work around this problem

To work around this problem, you have to somehow cast Oracle's timestamp value to a type that SQL Server understands. One tradeoff is that you may lose some precision over this, maybe in the neighborhood of 3 milliseconds.

The PL/SQL function to use is TO_CHAR. If you are using Linked Server, use a query like this:

select * from openquery(MyLinkedServer, 'select TO_CHAR(systimestamp, ''YYYY-MM-DD HH24:MI:SSXFF3'') from dual')

. Please note that you have to use OpenQuery.

If you are using DTS, there are 2 ways to get it work. The first approach is to create a view in Oracle and use TO_CHAR to cast the timestamp value as a value that SQL Server understands. The other approach is to use a SQL statement as the data source and embed the TO_CHAR function within the SQL statement.

Conclusion

In this article, I described a few subtle differences between Oracle and SQL Server. Specifically, I listed some techniques dealing with

Oracle timestamp values. Hopefully they can help you in solving your data interoperability issues.

Rate

4.44 (18)

Share

Share

Rate

4.44 (18)

Related content

Worst Practice - Bad Comments

This one is pretty interesting, Andy discusses a few things he sees in comments that not only fail to add value, they end up costing extra time. There's room for discussion here, but definitely a discussion worth having - comments can make you or break you, here's a chance to think about what you think is important in commenting and pass that on to your development team.

4 (2)

2003-01-23

9,441 reads

What is the Maximum Page Size in SQL Server 2000?

I have always read that 8060 bytes is the maximum size. This is stated over and over again in Books Online, the MS site and numerous other sites, including this one. However a post in our forum recently questioned this. I decided to verify the problem and do a little research.

4.55 (11)

2006-05-19 (first published: )

36,462 reads