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;
版权声明:本文标题:INFORMIX迁移到ORACLE 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.freenas.com.cn/free/1705342054h481770.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论