Datatypes translation is one of the most important things you need to consider when migrate your application from one database to the other. This is an article in the series that we talking about translate SQL query among different databases.
This article will focused on conversion of those datatypes: character, binary strings between Oracle and SQL Server. We will talk about conversion of other datatypes such as nunber, float, date and etc in other articles later.
When you convert character datatypes from Oracle to SQL Server or vice verse, you not only need to find corresponding datatype name but also need to find out how string was stored in database. Is this string stored in character or byte? and you must be aware of the maximum length of datatype in source and target databases.
In SQL Server, char [ ( n ) ] is fixed-length, non-Unicode character data with a length of n bytes. n must be a value from 1 through 8,000. You can easily find corresponding datatype name “char” in Oracle, but char in oracle with a maximum length of 2000 bytes. So you can’t migrate char(2048) in your SQL Server script to Oracle without any changes, you should use clob instead if n > 2000.
In Oracle database, char[(size)] can be also be used in fixed-length character data of length size in characters. When you use char qualifier, for example char(10 char), then you supply the column length in characters. A character is technically a code point of the database character set. Its size can range from 1 byte to 4 bytes, depending on the database character set. When translate this datatype to SQL Server, target datatype can be char(10) or char(40) depends on the database character set in source database(Oracle).
Detailed information about Oracle datatypes and SQL Server datatypes: including datatype name, description and what’s the corresponding datatype in other databases.
Below are summary tables show how Character and binary string datatypes translated from Oracle to SQL Server and vice verse.
Oracle(source) | SQL Server(target) |
CHAR [(size [BYTE | CHAR])] | char[(size)] |
VARCHAR2(size [BYTE | CHAR]) | varchar(size) |
NCHAR[(size)] | nchar[(size)] |
NVARCHAR2(size) | nvarchar(size) |
long | varchar(max) |
long raw | varbinary(max) |
raw(size) | varbinary(size) |
blob | varbinary(max) |
clob | varchar(max) |
nclob | ntext |
bfile | N/A |
How Character and binary string datatypes translated from SQL Server to Oracle.
SQL Server(source) | Oracle(target) |
char [ ( n ) ] | char[(n)], 1<=n<=2000; clob, n>2000 |
varchar [ ( n | max ) ] | varchar2(n), 1<=n<=4000; clob (n>4000) |
text | clob |
nchar [ ( n ) ] | nchar[(n)], 1<=n<=2000; nclob(n>2000) |
nvarchar [ ( n | max ) ] | nvarchar2[(n)], 1<=n<=4000; nclob( n>4000 ) |
ntext | nclob |
binary [ ( n ) ] | raw(1)(n was omitted); raw(n), 1<=n<=2000; blob(n>2000) |
varbinary [ ( n | max) ] | raw(1)(n was omitted); raw(n), 1<=n<=2000; blob(n>2000) |
image | blob |
Datatypes translation between Peoplesoft and Oracle :
Note: LONG
columns cannot appear in these parts of SQL statements:
GROUP
BY
clauses, ORDER
BY
clauses, or CONNECT
BY
clauses or with the DISTINCT
operator in SELECT
statements
The UNIQUE
operator of a SELECT
statement
The column list of a CREATE
CLUSTER
statement
The CLUSTER
clause of a CREATE
MATERIALIZED
VIEW
statement
SQL built-in functions, expressions, or conditions
SELECT
lists of queries containing GROUP
BY
clauses
SELECT
lists of subqueries or queries combined by the UNION
, INTERSECT
, or MINUS
set operators
SELECT
lists of CREATE
TABLE
... AS
SELECT
statements
ALTER
TABLE
... MOVE
statements
SELECT
lists in subqueries in INSERT
statements
TO_LOB函数是一个很特殊的函数,特殊之处在于,这个函数可以处理LONG类型数据,而且这个函数和LONG类型一样,拥有很多的限制。不过,这些还不是很特殊的地方,下面简单看一下TO_LOB这个函数。
Oracle的LONG类型可谓“臭名昭著”,由于LONG类型的限制太多,以至于Oracle很少去提LONG类型有哪些限制条件,而一般都是通过说明在哪些情况下,可以使用LONG类型。
正是这些限制阻止了LONG的使用,Oracle也在推出了大对象类型——LOB之后,强烈建议用户不要在使用LONG类型。
但是,具有讽刺意味的是,Oracle建议用户不要再使用LONG类型,可是数据字典中,随处可以看到LONG的身影。而且,即使是目前使用的最高版本10R2,LONG类型仍然在数据字典中随处可见。不知道Oracle是考虑兼容性的问题还是其他什么原因,反正Oracle仍然没有把LONG类型从数据字典中移出去。不知道11g中是否有所改观。
虽然Oracle自己没有做到,但是仍然建议用户不要在使用LONG,并使用BLOB、CLOB来替换现有系统中的LONG字段。而且LONG类型的限制也确实使人头疼,将LONG类型转化为LOB类型的工具,就是TO_LOB函数。
TO_LOB函数和LONG类型一样,限制有很多。简单的说,TO_LOB一般只用在CREATE TABLE或INSERT TABLE语句后面的子查询中。在其他地方使用会报错,比如UPDATE语句。
这还不是最大的问题,最大的问题在于,TO_LOB函数似乎并没有真正的将LONG类型转化为LOB数据类型。个人感觉,Oracle只是对LONG类型做了一些处理,使之可以存放到一个LOB类型中去。
SQL> CREATE TABLE T1 (ID NUMBER, TEXT CLOB);
表已创建。
SQL> CREATE TABLE T2 (ID NUMBER, TEXT VARCHAR2(4000));
表已创建。
SQL> INSERT INTO T1 SELECT ROWNUM, TEXT FROM DBA_VIEWS;
INSERT INTO T1 SELECT ROWNUM, TEXT FROM DBA_VIEWS
*第 1 行出现错误:
ORA-00997: illegal use of LONG datatype
SQL> INSERT INTO T1 SELECT ROWNUM, TO_LOB(TEXT) FROM DBA_VIEWS;
已创建2268行。
SQL> COMMIT;
提交完成。
使用TO_LOB可以将LONG数据插入到CLOB字段中,但是如果想要将LONG数据插入到VARCHAR2中:
SQL> INSERT INTO T2 SELECT ROWNUM, TEXT FROM DBA_VIEWS;
INSERT INTO T2 SELECT ROWNUM, TEXT FROM DBA_VIEWS
*第 1 行出现错误:
ORA-00997: illegal use of LONG datatype
SQL> INSERT INTO T2 SELECT ROWNUM, DBMS_LOB.SUBSTR(TO_LOB(TEXT), 4000, 1) FROM DBA_VIEWS;
INSERT INTO T2 SELECT ROWNUM, DBMS_LOB.SUBSTR(TO_LOB(TEXT), 4000, 1) FROM DBA_VIEWS
*第 1 行出现错误:
ORA-00932: inconsistent datatypes: expected - got LONG
直接插入肯定不行,但是刚才已经得到了CLOB类型,那么将CLOB转化为VARCHAR2不就可以了?但是结果确出人意料。观察错误信息,Oracle认为返回的数据类型是LONG。似乎TO_LOB并没有进行数据类型的转化。下面再验证一下:
SQL> SELECT DUMP(TO_LOB(TEXT)) FROM DBA_VIEWS;
SELECT DUMP(TO_LOB(TEXT)) FROM DBA_VIEWS
*第 1 行出现错误:
ORA-00932: inconsistent datatypes: expected - got LONG
SQL> SELECT DUMP(TEXT) FROM T1;
SELECT DUMP(TEXT) FROM T1
*第 1 行出现错误:
ORA-00932: inconsistent datatypes: expected - got CLOB
从这个对比中已经可以清楚的看到,TO_LOB函数并不像想象中的那样返回CLOB类型,而实际上返回的仍然是LONG类型。
SQL> INSERT INTO T2 SELECT ROWNUM, TO_LOB(TEXT) FROM DBA_VIEWS;
已创建2268行。
直接使用TO_LOB似乎可以插入,但是仔细对比一下结果就会发现,LONG类型数据没有真正的插入到表中:
SQL> COL TEXT FORMAT A50
SQL> SET LONG 50
SQL> SELECT * FROM T2 WHERE ROWNUM < 3;
ID TEXT
---------- --------------------------------------------------
1
2
SQL> SELECT * FROM T1 WHERE ROWNUM < 3;
ID TEXT
---------- --------------------------------------------------
1 select OWNER, TABLE_NAME, TABLESPACE_NAME, CLUSTER
2 select a.apply_name, a.queue_name, a.queue_owner,