您的位置:首页 > 数据库 > Oracle

Oracle与MSSQL的相互转化技巧

2012-10-11 11:15 411 查看
这两天写数据库升级脚本,发现MSSQL和Oracle之间的转化还是比较容易的。

以下面两个过程为例。两者的功能相似。

1.MSSQL脚本

Begin

declare @tempPoTableName varchar(50) --性能对象表名

declare @tempPoSpName varchar(50) --性能过程名

declare @errorInfo varchar(200) --错误信息

declare @cnt int --计数器

declare @tempSQL varchar(1000)

--定义表名、同步表名和存储过程游标

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)

OPEN allValues_Cursor

--判断是否由符合游标条件的行,如果没有则关闭和释放游标,异常返回

IF(@@CURSOR_ROWS = 0 )

BEGIN

CLOSE allValues_Cursor

DEALLOCATE allValues_Cursor

set @errorInfo = '没有指定表名或存储过程名!'

print @errorInfo

return

END

print '开始更改原有表名……'

FETCH NEXT FROM allValues_Cursor INTO @tempPoTableName,@tempPoSpName

--根据给定的表名、存储过程名 创建相应的数据存储存储过程

WHILE (@@FETCH_STATUS <> -1)

BEGIN

print @tempPoTableName

IF (EXISTS (SELECT name from sysobjects WHERE name=@tempPoTableName))

BEGIN

set @tempSQL = 'ALTER TABLE '+ @tempPoTableName+' DROP

constraint PK_'+@tempPoTableName

EXEC (@tempSQL)

set @tempSQL = @tempPoTableName+'_TMP'

EXEC Sp_rename @tempPoTableName,@tempSQL

END

ELSE

BEGIN

print '没有找到表'+@tempPoTableName;

END

IF (EXISTS (SELECT name from sysobjects WHERE name=@tempPoSpName))

BEGIN

set @tempSQL = 'DROP PROCEDURE '+@tempPoSpName;

EXEC (@tempSQL)

END

ELSE

BEGIN

print '没有找到过程'+@tempPoSpName;

END

FETCH NEXT FROM allValues_Cursor INTO @tempPoTableName,@tempPoSpName

END

CLOSE allValues_Cursor

DEALLOCATE allValues_Cursor

print '结束更改原有表名……'

print '------------------------'

END

GO

2.ORACLE脚本

BEGIN

DECLARE

tempPoTableName varchar2(50); --性能对象表名

tempPoSpName varchar2(50); --性能过程名

errorInfo varchar2(200); --错误信息

tempSQL varchar2(1000);

cnt1 number(1);

cnt2 number(2);

--定义表名、同步表名和存储过程游标

Cursor allValues_Cursor is

select UPPER(TRIM(POTABLENAME)),UPPER(TRIM(POSPNAME)) from

PM_NEPODEF_TABLE WHERE POID>110499 and POID<110580;

BEGIN

OPEN allValues_Cursor;

--判断是否由符合游标条件的行,如果没有则关闭和释放游标,异常返回

DBMS_OUTPUT.PUT_LINE('开始更改原有表名……');

FETCH allValues_Cursor INTO tempPoTableName,tempPoSpName;

--根据给定的表名、存储过程名 创建相应的数据存储存储过程

WHILE allValues_Cursor%found LOOP

cnt1:=0;

cnt2:=0;

BEGIN

SELECT 1 INTO cnt1 FROM dual WHERE exists(SELECT table_name

FROM user_tables WHERE table_name = tempPoTableName);

SELECT 1 INTO cnt2 FROM dual WHERE exists(SELECT OBJECT_NAME

FROM user_procedures WHERE OBJECT_NAME = tempPoSpName);

exception

WHEN no_data_found THEN

null;

END;

IF cnt1 = 1 THEN

DBMS_OUTPUT.PUT_LINE(tempPoTableName);

tempSQL := 'ALTER TABLE '||tempPoTableName||' DROP constraint

PK_'||tempPoTableName;

EXECUTE IMMEDIATE tempSQL;

tempSQL := 'ALTER TABLE '||tempPoTableName||' RENAME

TO '||tempPoTableName||'_TMP';

EXECUTE IMMEDIATE tempSQL;

ELSE

DBMS_OUTPUT.PUT_LINE('没有找到表'||tempPoTableName);

END IF;

IF cnt2 = 1 THEN

tempSQL := 'DROP PROCEDURE '||tempPoSpName;

EXECUTE IMMEDIATE tempSQL;

ELSE

DBMS_OUTPUT.PUT_LINE('没有找到过程'||tempPoSpName);

END IF;

FETCH allValues_Cursor INTO tempPoTableName,tempPoSpName;

END LOOP;

CLOSE allValues_Cursor;

DBMS_OUTPUT.PUT_LINE('结束更改原有表名……');

DBMS_OUTPUT.PUT_LINE('------------------------');

END;

END;

/

上面两个是无名存储过程,不需要考虑是否已经存在该过程。对于有名的过程需要考虑对象是否已经存在。

我是从MSSQL向Oracle转化的。

第一步,修改整体结构。

MSSQL的总体结构如下,只需要一个begin和end,中间加入变量声明。

Begin

declare --变量

--过程

END

GO

Oralce的总体结构如下,需要两个begin和end,一个是整个过程,一个是除去申明之外的过程。

BEGIN

DECLARE

--变量

BEGIN

--过程

END;

END;

/

第二步,修改声明变量。

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的游标是在变量中声明定义的,然后在过程中使用。其结构如下:

--声明中

Cursor allValues_Cursor is

select UPPER(TRIM(POTABLENAME)),UPPER(TRIM(POSPNAME))

from PM_NEPODEF_TABLE WHERE POID>110499 and POID<110580;

--1.声明游标

--过程中

OPEN allValues_Cursor;

--2.打开游标

WHILE allValues_Cursor%found LOOP

FETCH allValues_Cursor INTO tempPoTableName,tempPoSpName;

--3.处理数据

END LOOP;

CLOSE allValues_Cursor;

--4.关闭游标

第四步修改赋值语句和比较语句。MSSQL中使用Set语句来赋值,Oracle中使用:=来赋值。此外MSSQL中的变量习惯前面增加一个@字符,在Oracle中可以删除。

第五步修改逻辑结构。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。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  Oracle 区别 cursor