admin 管理员组

文章数量: 887021


2024年1月16日发(作者:javaweb医药系统源码)

INFORMIX迁移到ORACLE

一、库表SQL写法问题

1.DATE字段

Informix中datetime year to second,datetime year to day等,统一改为oralce中的DATE字段。否则会报错:ORA-00907: 缺失右括号。

2.extent size属性

Informix中可以使用extent size 50000 next size 10000 lock mode row来限制建表属性,在oracle中不支持,直接去掉。

3.SQL语句中空行问题

在informix中,建表的语句中,可以允许有空行存在,但是在oracle的语句中,一条完整的语句中,不允许中间出现空白行,否则会报错:SP2-0734: 未知的命令开头。

解决办法是:去掉一条语句中无谓的空行。不同语句间存在空行是正常的。

4.Size,level等保留字段名

在informix中,可以定义一个字段名字为size,在oracle中,size属于保留字,直接使用会报错:ORA-00904: : 标识符无效

解决方法是:在类似于size这样的保留名称的字段名称中,在两边加上双引号即可。即:size-->"size",对应的程序代码,也都需要这样修改,特别需要注意的是,双引号内的字符是大小写敏感的,例如上面的"size",程序中用"SIZE"将操作失败。既然反正要改程序,为了防止后面的冲突,不采取这种修改方法,重新修改字段名。为了方便,我们统一在字段名前加上:db_。例如:size-->db_size, level-->db_level。

这样的字段有:size, level,comment,validate,file,number

5.byte大数据字段

在informix中,大数据使用byte类型,在oralce中,使用的是blob/clob类型(BLOB是纯二进制,CLOB是文本,我们选择使用blob),否则,会报错:ORA-00902: 无效数据类型byte

6.lvarchar大数据字段

在informix中,长点的文本数据使用lvarchar类型,此类型缺省长度是2048,最大长度是32767。在oralce中,没有此种类型,按理说,应该使用clob类型,但如果使用clob时,读写都很不方便。如果改用LONG类型来替换的,读写是方便了,但一个表,只允许存在一个LONG字段。为了方便,将INFORMIX的lvarchar改为ORACLE的varchar,如果lvarchar的长度超过4000的话,直接用4000代替。如果lvarchar的长度小于2048的话,直接用2048代替(ORACLE的字符字段长度最大为char 2000, varchar 4000)

7.数字类型长度问题

在informix中,定义一个字段decimal(3),在插入时,可以超过3位长度的数据,但是在oracle中,插入超过1000时,会报错:ORA-01438: 值大于为此列指定的允许精度。

解决办法是:修改此表的这个字段长度,例如:sessiontimeout decimal(3)改为sessiontimeout

decimal(8)。

8.serial/serial8问题

在informix中,可以定义一个序列字段serial/serial8,在oracle中,无此字段,用number(10)代替。在数据迁移时,直接迁移即可,但是在迁移完数据之后,还需要特殊处理。以下为解决样例。

9.boolean数据字段

在informix中,布尔数据使用boolean类型,在oralce中,没有boolean类型,需要使用number(1)类型代替,否则,会报错:ORA-00902: 无效数据类型

二、程序需要修改的地方

1.INFORMIX与ORACLE兼容原则

修改代码的原则是:

(1)凡是INFORMIX与ORACLE有冲突的地方,能够修改成一致,并且不影响原来的业务逻辑的,则直接修改代码。例如:INFORMIX中是size字段名,在oracle中是db_size字段名。那么,INFORMIX中也修改为db_size。

(2)对于无论如何修改,INFORMIX与ORACLE也不能共处的地方,则新加一段代码,这段新加的代码主要意思是:首先调用一个公用方法,获取当前的数据库类型,如果是oracle,则调用另外的一段新写的代码。否则,仍旧调用原来的代码。例如:数据查询分页问题,检查数据值是否为空问题。

(3)尽可能不使用数据库本身提供的函数。

2.Size,level等保留字段名

这样的字段有:size, level,comment,validate,file,number

需要在这些字段名字前加上“db_”,例如:size-->db_size。包括所有的增删改查语句。

注意:表名:check_jifang_bj,字段名遇到保留名字: level

注意:表名:diangan,字段名遇到保留名字: size

注意:表名:groupcircuit,字段名遇到保留名字: number

注意:表名:groupuser,字段名遇到保留名字: level

注意:表名:guandao_segment,字段名遇到保留名字: size

注意:表名:pm_index,字段名遇到保留名字: level

注意:表名:renshoujing,字段名遇到保留名字: size

注意:表名:user_info_tab,字段名遇到保留名字: comment

3.serial/serial8问题

在informix中,可以定义一个序列字段serial/serial8,在oracle中,无此字段,用number(10)代替。此类型需要再次推敲。

注意:表名:pm_job_execution,字段名: executionid

注意:表名:pm_job_execution_cur,字段名: executionid

4.lvarchar大数据字段

在informix中,长点的文本数据使用lvarchar类型,此类型缺省长度是2048,最大长度是32767。在oralce中,没有此种类型,按理说,应该使用clob类型,但如果使用clob时,

读写都很不方便。如果改用LONG类型来替换的,读写是方便了,但一个表,只允许存在一个LONG字段。为了方便,将INFORMIX的lvarchar改为ORACLE的varchar,如果lvarchar的长度超过4000的话,直接用4000代替。如果lvarchar的长度小于2048的话,直接用2048代替。

5.boolean数据字段

在informix中,布尔数据使用boolean类型,在oralce中,没有boolean类型,需要使用number(1)类型代替,否则,会报错:ORA-00902: 无效数据类型。

6.名称超过30字节长度

在informix中,名称长度没有限制,但是,在oracle中,对长度有限制,不能超过30个,报错信息为:ORA-00972: 标识符过长。

解决办法是,缩短名字,包括:表名,字段名,索引名,触发器名,外键名,过程名等

注意:1. 如果是索引的话,只需要修改数据库语句,保证全库唯一,不冲突即可。

2. 如果是表名或字段名的话,那就要改程序了。

例如: create index idx_zhimai_segment_zhimai_branch on xxx。在informix中合法,在oracle中 idx_zhimai_segment_zhimai_branch过长(32个字符了)。

7.查询分页

这块需要重新修改。方法实例如下:

SELECT * FROM

(

SELECT A.*, ROWNUM RN

FROM (SELECT * FROM TABLE_NAME) A

WHERE ROWNUM < 41

)

WHERE RN >= 21

其中最内层的查询SELECT * FROM TABLE_NAME表示不进行翻页的原始查询语句。ROWNUM < 41和RN >= 21控制分页查询的每页的范围。

8.byte大数据字段

在oracle中,大数据使用BLOB类型(BLOB是纯二进制,CLOB是文本,我们选择使用blob,如果有需要使用CLOB的话,再议)。同时,数据读写的方式也要进行修改,不能使用原有的方法读写数据。

参考例子:

// 从数据库读一条二进制内容

public static void loadOneBlob(int id) {

Connection conn = null;

Statement stmt = null;

ResultSet rs = null;

String sql = "SELECT img_content FROM test_blob WHERE img_id='"

+ id + "'";

try {

conn = getConnect();

stmt = Statement();

rs = eQuery(sql);

while (())

{

Blob blob = b(1);

}

// 二进制内容的大小

int length = (int) ();

// 缓存的大小

byte[] by = new byte[length];

// 获得输入流(源)

InputStream is = aryStream();

// IO知识

(by);

();

String str = new String(by, "GBK");

n(str);

}

} catch (Exception e) {

tackTrace();

} finally {

close(rs, stmt, conn);

}

//批量将二进制数据写入数据库中

//1,需要在之前将所有的非二进制字段入库(在这里忽略此步)

//2,然后,再单独通过select获取到blob字段的游标

//3,单个写入blob字段(这里不能批量的)。

//drop table test_blob;

//create table test_blob (img_id varchar(64), img_content blob);

public static void saveStringToBlob(int num) {

Connection conn = null;

PreparedStatement pstmt = null;

String clearsql = "UPDATE test_blob SET

img_content=EMPTY_BLOB() WHERE img_id=?";

try {

conn = getConnect();

pstmt = eStatement(clearsql);

for (int k=1; k<=num; k++)

{

ing(1, "" + k);

ch();

}

eBatch();

Statement st = Statement();

String longStr = "hello BLOB数据 测试 end hello2 BLOB数据 测试 end2 hello3 BLOB数据 测试 end3n";

StringBuffer sql = new StringBuffer("select img_id,

img_content from test_blob where img_id in ('1'");

for (int k=2; k<=num; k++)

{

(", '"+k+"'");

}

(") for update");

ResultSet rs = eQuery(ng());

String id = "";

while (()) {

id = ing("img_id");

StringBuffer strbuf = new StringBuffer();

for ( int j=0; j<2; j++)

{

("id2 = " + id + ", time = "+(j+1) + "

");

(longStr);

}

byte[] byte_tmp =

ng().getBytes("GBK");

OutputStream outStream = null;

//得到对象后强制转换为

blob = ()

b("img_content");

outStream = aryOutputStream();

}

}

//是传入的byte数组,定义:byte[] bytes

(byte_tmp,0,byte_);

();

();

();

();

n("更新大数据成功!");

} catch (Exception e) {

tackTrace();

} finally {

close(null, pstmt, conn);

}

9.Null数据判断规则

字符类型的字段,在informix中,有''(空字符串)和null两种,在对应的查询时,要分成两种情况来对待。在oracle中,没有'',只有null。因此,程序中如果查询<>'' and is not null时,在informix中能查询到的值,在oracle中,将查询不到,必须改成is not null。在oracle中,' '(空格字符串,两个引号中间有一个或多个空格符)当成单个的空格字符,不作为空字符,也不是null。而在informix中,当成''同样的方式处理。即空字符或空格字符相同处理。

在条件查询中,判断某个字段是否为空值,

在INFORMIX里,条件是 FieldName='' or FieldName is null,

在oracle里,条件是 FieldName is null。因此,如果INFORMIX里只写了FieldName=''的话,程序需要修改。如果INFORMIX里只写了FieldName='' or FieldName is null的话,程序可以不修改。

在条件查询中,判断某个字段不为空值,

在INFORMIX里,条件是 FieldName<>'' and FieldName is not null,

在oracle里,条件是 FieldName is not null。

以下为查询实例:

drop table testtable;

create table testtable (a char(5),b char(5));

insert into testtable(a,b) values('1','1');

insert into testtable(a,b) values('2','2');

insert into testtable(a,b) values('3','');

insert into testtable(a) values('4');

insert into testtable(a,b) values('5',' ');

commit;

语句 INFORMIX ORACLE

未选定行 select * from testtable where a b

b='';

3

5

2 row(s) retrieved.

select * from testtable where a b

b=' ';

3

5

2 row(s) retrieved.

select * from testtable where b a b

is null;

4

1 row(s) retrieved.

select * from testtable where a b

b<>'';

1 1

2 2

2 row(s) retrieved.

select * from testtable where b a b

is not null;

1 1

2 2

3

5

4 row(s) retrieved.

select * from testtable where a b

b<>'1';

2 2

3

5

3 row(s) retrieved.

A B

----- -----

5

A B

----- -----

3

4

未选定行

A B

----- -----

1 1

2 2

5

A B

----- -----

2 2

5

10.使用数据库函数问题

此块的兼容性没有测试,应该主要在时间函数方面可能会存在冲突。对于报表或用到存储过程的地方,这块要重新写过了。我随意网上搜索的页面,看到里面说的差别太大了:/database/111/

三、其他的修改SQL地方

1.由于表名过长,所以,视图,触发器,存储过程未创建成功

视图有一个:。

create view "informix".fh_card_model (card_model_code,card_model) as

select _model_code ,_model

"informix".alarm_special_mapping_fh_sdh_card_model

x0 union select _model_code ,_model from "informix"

.alarm_special_mapping_fh_wdm_card_model x1 ;

from

2.序列

在oracle中,创建一个新的序列与informix中相同,但是,如果在迁移时,使用的序列值不是从定义的初始值开始的,

在informix中,是这样定义的:

create sequence pm_monitor_sequence increment by 1 start with 1 maxvalue 99999999 minvalue

1 cycle cache 20 order;

Alter sequence pm_monitor_sequence restart with 75;

在oracle中,要求这样定义(第二条语句是初始化,必须要求执行一遍):

create sequence pm_monitor_sequence increment by 1 start with 75 maxvalue 99999999 minvalue

1 cycle cache 20 order;

select pm_monitor_sequence .NEXTVAL from dual;


本文标签: 类型 使用 数据 修改 查询