这两天写数据库升级脚本,发现MSSQL和Oracle之间的转化还是比较容易的。
以下面两个过程为例。两者的功能相似。
1.MSSQL脚本 1/**//** 更改表名 **/
2Begin
3 declare @tempPoTableName varchar(50) --性能对象表名
4 declare @tempPoSpName varchar(50) --性能过程名
5 declare @errorInfo varchar(200) --错误信息
6 declare @cnt int --计数器
7
8 declare @tempSQL varchar(1000)
9
10 --定义表名、同步表名和存储过程游标
11 set @tempSQL = declare allValues_Cursor cursor for +CHAR(13) + CHAR(10)
12 set @tempSQL = @tempSQL + select POTABLENAME,POSPNAME from PM_NEPODEF_TABLE WHERE POID>110499 and POID<110580
13 EXEC (@tempSQL)
14
15 OPEN allValues_Cursor
16
17 --判断是否由符合游标条件的行,如果没有则关闭和释放游标,异常返回
18 IF(@@CURSOR_ROWS = 0 )
19 BEGIN
20 CLOSE allValues_Cursor
21 DEALLOCATE allValues_Cursor
22 set @errorInfo = 没有指定表名或存储过程名!
23 print @errorInfo
24 return
25 END
26
27 print 开始更改原有表名……
28 FETCH NEXT FROM allValues_Cursor INTO @tempPoTableName,@tempPoSpName
29 --根据给定的表名、存储过程名 创建相应的数据存储存储过程
30 WHILE (@@FETCH_STATUS <> -1)
31 BEGIN
32 print @tempPoTableName
33
34 IF (EXISTS (SELECT name from sysobjects WHERE name=@tempPoTableName))
35 BEGIN
36 set @tempSQL = ALTER TABLE + @tempPoTableName+ DROP constraint PK_+@tempPoTableName
37 EXEC (@tempSQL)
38 set @tempSQL = @tempPoTableName+_TMP
39 EXEC Sp_rename @tempPoTableName,@tempSQL
40 END
41 ELSE
42 BEGIN
43 print 没有找到表+@tempPoTableName;
44 END
45
46 IF (EXISTS (SELECT name from sysobjects WHERE name=@tempPoSpName))
47 BEGIN
48 set @tempSQL = DROP PROCEDURE +@tempPoSpName;
49 EXEC (@tempSQL)
50 END
51 ELSE
52 BEGIN
53 print 没有找到过程+@tempPoSpName;
54 END
55
56 FETCH NEXT FROM allValues_Cursor INTO @tempPoTableName,@tempPoSpName
57 END
58 CLOSE allValues_Cursor
59 DEALLOCATE allValues_Cursor
60 print 结束更改原有表名……
61 print ------------------------
62END
63GO
2.ORACLE脚本
1BEGIN
2DECLARE
3 tempPoTableName varchar2(50); --性能对象表名
4 tempPoSpName varchar2(50); --性能过程名
5 errorInfo varchar2(200); --错误信息
6 tempSQL varchar2(1000);
7 cnt1 number(1);
8 cnt2 number(2);
9
10 --定义表名、同步表名和存储过程游标
11 Cursor allValues_Cursor is
12 select UPPER(TRIM(POTABLENAME)),UPPER(TRIM(POSPNAME)) from PM_NEPODEF_TABLE WHERE POID>110499 and POID<110580;
13
14BEGIN
15 OPEN allValues_Cursor;
16
17 --判断是否由符合游标条件的行,如果没有则关闭和释放游标,异常返回
18
19 DBMS_OUTPUT.PUT_LINE(开始更改原有表名……);
20 FETCH allValues_Cursor INTO tempPoTableName,tempPoSpName;
21 --根据给定的表名、存储过程名 创建相应的数据存储存储过程
22 WHILE allValues_Cursor%found LOOP
23
24 cnt1:=0;
25 cnt2:=0;
26 BEGIN
27 SELECT 1 INTO cnt1 FROM dual WHERE exists(SELECT table_name FROM user_tables WHERE table_name = tempPoTableName);
28 SELECT 1 INTO cnt2 FROM dual WHERE exists(SELECT OBJECT_NAME FROM user_procedures WHERE OBJECT_NAME = tempPoSpName);
29 exception
30 WHEN no_data_found THEN
31 null;
32 END;
33
34 IF cnt1 = 1 THEN
35 DBMS_OUTPUT.PUT_LINE(tempPoTableName);
36 tempSQL := ALTER TABLE ||tempPoTableName|| DROP constraint PK_||tempPoTableName;
37 EXECUTE IMMEDIATE tempSQL;
38 tempSQL := ALTER TABLE ||tempPoTableName|| RENAME TO ||tempPoTableName||_TMP;
39 EXECUTE IMMEDIATE tempSQL;
40 ELSE
41 DBMS_OUTPUT.PUT_LINE(没有找到表||tempPoTableName);
42 END IF;
43
44 IF cnt2 = 1 THEN
45 tempSQL := DROP PROCEDURE ||tempPoSpName;
46 EXECUTE IMMEDIATE tempSQL;
47 ELSE
48 DBMS_OUTPUT.PUT_LINE(没有找到过程||tempPoSpName);
49 END IF;
50
51 FETCH allValues_Cursor INTO tempPoTableName,tempPoSpName;
52 END LOOP;
53 CLOSE allValues_Cursor;
54 DBMS_OUTPUT.PUT_LINE(结束更改原有表名……);
55 DBMS_OUTPUT.PUT_LINE(------------------------);
56 END;
57END;
58/上面两个是无名存储过程,不需要考虑是否已经存在该过程。对于有名的过程需要考虑对象是否已经存在。
我是从MSSQL向Oracle转化的。
第一步,修改整体结构。
MSSQL的总体结构如下,只需要一个begin和end,中间加入变量声明。
1Begin
2 declare --变量
3 --过程
4END
5GO
Oralce的总体结构如下,需要两个begin和end,一个是整个过程,一个是除去申明之外的过程。
1BEGIN
2 DECLARE
3 --变量
4 BEGIN
5 --过程
6 END;
7END;
8/
第二步,修改声明变量。
MSSQL需要在每个变量前面加 declare标示,Oracle只需要一个declare标示。此外注意修改各自的数据类型。
第三步,修改游标。复杂的过程中离不开游标。因此更改游标结构经常用到。
MSSQL的游标是全局的,需要建立之后再清空。而Oracle的游标类似于局部变量,使用完之后,自动清除。
MSSQL游标结构如下:
set @tempSQL = declare allValues_Cursor cursor for +CHAR(13) + CHAR(10)
set @tempSQL = @tempSQL + select POTABLENAME,POSPNAME from PM_NEPODEF_TABLE WHERE POID>110499 and POID<110580
--游标语句
EXEC (@tempSQL)
--1.创建游标
OPEN allValues_Cursor
--2.打开游标
--判断是否由符合游标条件的行,如果没有则关闭和释放游标,异常返回
IF(@@CURSOR_ROWS = 0 )
BEGIN
CLOSE allValues_Cursor
DEALLOCATE allValues_Cursor
set @errorInfo = 没有指定表名或存储过程名!
print @errorInfo
return
END
WHILE (@@FETCH_STATUS <> -1)
BEGIN
FETCH NEXT FROM allValues_Cursor INTO @tempPoTableName,@tempPoSpName
--3进行数据处理
END
CLOSE allValues_Cursor
--4.关闭游标
DEALLOCATE allValues_Cursor
--5.注销游标
Oracle的游标是在变量中声明定义的,然后在过程中使用。其结构如下:
1--声明中
2 Cursor allValues_Cursor is
3 select UPPER(TRIM(POTABLENAME)),UPPER(TRIM(POSPNAME)) from PM_NEPODEF_TABLE WHERE POID>110499 and POID<110580;
4 --1.声明游标
5--过程中
6 OPEN allValues_Cursor;
7 --2.打开游标
8
9 WHILE allValues_Cursor%found LOOP
10 FETCH allValues_Cursor INTO tempPoTableName,tempPoSpName;
11 --3.处理数据
12
13 END LOOP;
14 CLOSE allValues_Cursor;
15 --4.关闭游标
第四步修改赋值语句和比较语句。MSSQL中使用Set语句来赋值,Oracle中使用:=来赋值。此外MSSQL中的变量习惯前面增加一个@字符,在Oracle中可以删除。
第五步修改逻辑结构。MSSQL中使用IF()....ELSE....
,结构体之间都要用BEGIN和END框起来。而Oracle则使用IF...THEN...ELSE..END IF结构,中间不必使用BEGIN和END。此外While结构差别也类似。
第五步修改逻辑结构。MSSQL中使用IF()....ELSE....,结构体之间都要用BEGIN和END框起来。而Oracle则使用IF...THEN...ELSE..END IF结构,中间不必使用BEGIN和END。此外While结构差别也类似。
第六步修改各自的调用方法和函数。常见的是MSSQL的EXEC (@tempSQL),对应Oracle的EXECUTE IMMEDIATE tempSQL。MSSQL的print函数,对应Oracle的DBMS_OUTPUT.PUT_LINE()函数。此外还有各自使用的数据表,有所不同。例如MSSQL中所有的对象都在sysobjects表中,而Oracle中的表在user_tables中,过程在user_procedures中等。这些需要积累一些经验。
最后不要忘了检查,Oracle的所有句子,必须要有分号表示结束。而MSSQL中不需要,即使加了也不错。几步下来,MSSQL过程就转化成Oracle。