一、SQL Server vs Oracle 简单语法比较此为本人将ORACLE 函数和存储过程转换为SQL SERVER遇到的一些语法问题的经验总结,肯定不能包括所有的语法不同点。
注:简单的语法异同1、SQL SERVER变量必须以@开头。
2、SQL SERVER语句后不需要写分号结束符。
3、oracle变量类型number 可以修改为sql server的decimal4、oracle变量类型varchar2 可以修改为sql server的varchar5、SQL SERVER定义变量及传递参数,最好加上参数大小数值,例如:varchar(50)5、SQL SERVER 不能用ROWID, ROWNUM (但可以用TOP代替)6、oracle里的nvl函数,在SQL SERVER里使用ISNULL函数取代7、SQL SERVER自定义函数不允许修改全局表数据(只允许修改自定义函数范围内表数据), 所以发生表修改的最好用存储过程实现而非函数。
1 create函数或存储过程异同点Oracle 创建函数或存储过程一般是create or replace ……SQL SERVER 则是在创建之前加一条语句,先判断是否已经存在,如果存在删除已有的函数或存储过程。
函数语句if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[函数名]') and xtype in (N'FN', N'IF', N'TF')) drop function [dbo].[函数名]GO存储过程if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[存储过程名]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)drop procedure [dbo].[存储过程名]GO2 结构异同点ORACLECreate 部分IS 定义部分BEGIN … END; 实现部分SQL SERVERCreate 部分AS 定义和实现部分(AS 下面的代码一般用BEGIN … END 包含)3 调用参数ORACLE输入参数参数名In 参数类型ORACLE输出参数参数名Out 参数类型SQL SERVER输入参数参数名参数类型IN(IN可以不写,系统默认)SQL SERVER输出参数参数名参数类型OUTPUT4 变量命名及赋值ORACLE1、变量名随便取2、定义格式为变量名变量类型;3、给变量赋值为变量名:= 值;SQL SERVER1、变量名前面一般加@2、定义格式为declare 变量名变量类型3、SET变量名=变量类型5 IF语句ORACLEIF … THEN….ELSE...END IF;SQL SERVERIF ... BEGIN……ENDELSE BEGIN……END或者IF ...BEGIN……ENDELSEBEGIN……END6 case语句ORACLEIF … THEN….ELSE...END IF;SQL SERVERIF ... BEGIN……ENDELSE BEGIN……END或者IF ...BEGIN……ENDELSEBEGIN……END7 游标的定义及使用及循环操作ORACLE定义游标CURSOR CurA IS SELECT a FROM tab where …;SQL SERVER定义游标DECLARE CurA CURSOR LOCAL FOR SELECT a FROM tab where … ;ORACLE使用游标Open CurA; -- 打开游标Fetch CurA Into ISUserUnitPri;IF CurA%NOTFOUND THEN -- 注:如果为CurA%FOUND,看下面相同位置注释ISUserUnitPri := 1;END IF;Close CurA; -- 关闭游标SQL SERVER使用游标Open CurA -- 打开游标Fetch next from CurA Into @ISUserUnitPriIF @@fetch_status <> 0 BEGIN -- 注:则@@fetch_status = 0 SET @ISUserUnitPri = 1 -- 没有选到记录给默认值1ENDClose CurA -- 关闭游标DEALLOCATE CurA -- 释放占用资源ORACLE循环操作游标(超级简洁)FOR ISUserUnitPri IN CurA LOOP…–- 做操作END LOOP;注:想循环中间退出循环,用EXITSQL SERVER循环操作游标Open CurA -- 打开游标Fetch next from CurA Into @ISUserUnitPriWhile ( @@fetch_status = 0 ) BEGIN…. –- 做操作Fetch next from CurA Into @ISUserUnitPriENDClose CurA -- 关闭游标DEALLOCATE CurA -- 释放占用资源注:想循环中间退出循环,用BREAK注意:SQL SERVER 使用游标完后,需要删除游标引用(DEALLOCATE cursor_name)。
8 计算时间差ORACLEOracle 两个时间相减得到一个以天为单位的带小数的值,需要根据自己的需要再换算成秒值。
-- 这里为取START_QUEUE_TIME到当前时间的秒数(SYSDATE - START_QUEUE_TIME)*24*60*60SQL SERVERSQL SERVER两个时间相减得到还是时间(从1900-01-01 00:00:00.000开始的时间)。
所以想得到以秒的时间差,这么做就麻烦了。
SQL SERVER取时间差,专门有一个DATEDIFF函数,具体看SQL SERVER帮助。
-- 这里为取START_QUEUE_TIME到当前时间的秒数DATEDIFF(second, START_QUEUE_TIME,GETDATE())9 top N 问题在sql server中,top N 问题很容易解决,如下例:从表stbdbdj中选取排序后的第一行数据进行赋值。
在sql中解决方法很简单,在select 后面加上:top n 即可,其中n 代表行数。
select top1@entrust_date= entrust_date,@entrust_no= entrust_nofrom run2k..stbdbdjwhere entrust_date =@dateand entrust_no >@entrust_no_qand report_status ='1'order by entrust_date,entrust_no;在oracle中,没有top n这个命令,我们采取把两层查询方式解决:首先,把需要查找的字段值直接进行排序,然后在外面进行第二次查询,并使用rownum决定行数。
select entrust_date,entrust_nointo@entrust_date, @entrust_nofrom ( select entrust_date,entrust_nofrom stbdbdjwhere entrust_date =@dateand entrust_no >@entrust_no_qand report_status ='1'order by entrust_date,entrust_no )where rownumber <=1 ;10 如何解决结果集返回时,* 和变量同时存在的问题下面例子表示,在用游标返回结果集时,同时返回一个变量的值,在sql server中代码如下所示:select a.*,an_idfrom run2k..stbbp a,run2k..stkaccoarg bwhere a.date =@entrust_dateand a.serial_no =@serial_noand a.branch_no = b.branch_noand a.exchange_type = b.exchange_type;但在oracle中却没有这种用法,’*’后面必需跟from。
解决方法如下:1)我们可以把'*' 变成所需要选择的字段,就是说采用表中需要显示的全部字段表示*。
例如:open p_cursor forselect branch_no,...,organ_idwhere...2)如果这个字段或者说变量是从另外一张表中取出来的,同样可以采用下面的办法。
open p_cursor forselect a.*,an_id;from stkaccoentrust a, stkaccoarg bwhere a.branch_no = b.branch_noand a.exchange_type = b.exchange_typeand a.init_date = v_entrust_dateand a.serial_no = v_serial_no;11 外联接问题Sql server <---> oraclea = *b <---> a(+)= ba *=b <---> a = b(+)12 多条记录求和问题select sum(A+B+C)into Dfrom ...where ...group by ...单条记录求和select A+Binto Cfrom ...where ...13 用SQL SERVER里CASE函数替换DECODE函数替换ORACLEdecode(client_status,'0','正常,'1','冻结','2','挂失','3','销户','未知');SQL SERVER 没有DECODE函数case client_statuswhen '0' then '正常'when '1' then '冻结'when '2' then '挂失'when '3' then '销户'else '未知'end注:有趣的是ORACLE的CASE函数,在SQL SERVER里没有找到替代的,只好用IF ELSE 语句解决。