当前位置:文档之家› SQL Server与oracle区别总结

SQL Server与oracle区别总结

●开发语法

A.SQL 语法

两者的SQL语法基本上是相同的,只是一些细节方面的问题

一: 表的管理:修改表的结构,如增加,删除列,創建表

修改表

1.修改表的列的數據類型,大小的定義不同,如下面修改數據類型。

Ms sql是ALTER TABLE table_name ALTER COLUMN col DECIMAL (5, 2)

Oracle是 Alter TABLE table_name modify(col decimal(5,2))

2.增加和刪除表的列,兩者是相同的

Alter tabe table_name add(col definition)

Alter tabe table_name drop column col_name

3 .Oracle如果不要用某列,然後又不想刪除,就可以将某个列标记为未用

Alter tabe table_name set unused(tel_no)

.创建临时表

Oracle 的語法是:

Create global temporary table aa(col number) on commit preserve rows;

临时表只在用户会话时存在的表,或其数据在用户事务处理期间可

持续存在的表,创建临时表时可以指定该表是否应当在用户会话

期间持续存在(使用on commit preserve rows)

On commit delete rows 表示事务处理完成后删除它的行

Ms sql的語法是:

Select * into #temptable from existedtable

二 查询方面:

1.查表的前N行记录

oracle 是用rownum 如select * from table_name where rownum


Ms sql 是用top 如select top n * from table_name



2.查詢表的結構

Orace 可以通過desc来查看表的结构 语法是:desc table_name

或者使用数据字典表user_tab_coumns也可以查看到

Select column_name,data_type from user_tab_coumns

Where table_name=''

Ms sql可以通過一些系統的存儲過程來看表的結構

語法是:exec sp_help table_name

3.将一个表的数据添加到另外一个表中

a.新表存在前提下:兩者語法是一樣的,如

insert into newtable(col1)select col1 from old_table

b.新表不存在前提下,可以用

oracle 可以用Create tabe new _table_name as select * from old_table

ms sql 可以用 Select * into new_table from old_table

三 操作符

1.連接操作符

Oracle是 ‘||’; Ms sql是‘+’

2. Oracle的比较操作符中不等于除了'<>'之外,还有一个 '!='

3. 算术操作符,都是+-*/;逻辑操作符都是and,not,or(相同點)

4. oracle集合操作符除了union,union all之外还加入intersect,minus

Intersect是仅返回两个查询都有行,minus返回第一个查询有第

二个查询没有的行

四 函數

1.轉換函數

Oracle 中有to_char(),to_date(),to_number()

Ms sql 中有cast,convert


2.系统日期:

Oracle: sysdate

Ms sql: getdate()



Select sysdate from dual 一定要from子句

Select getdate() 不一定要from子句

3.Decode函数相当if else,或者ms 中的case语句

语法是decode(value,if1,then1,if2,then2....)

如decode(col1,'1','true','0','fase')

4.常规函数

Nvl 语法是NVL(EXP1,EXP2) 表示如果ex1为空则返回ex2

Nvl2 语法是nvl(exp1,exp2,exp3)表示如果ex1为空,则返回ex3,否则返回ex2

Nullif 语法是nullif(ex1,ex2) 如果这两个表达式相等则返回空

coalesce语法是coalesce(ex1,ex2,....exn)返回第一个非空表达式

5.分組函數

Oracle 中的分組函數Rollup,cube

Rollup返回的结果集包含分组行和小计行,cube产生交叉报表

如:

Select a,b,sum(c) from tabname group by rollup(a,b)

Select a,b,sum(c) from tabname group by cube(a,b)

Ms sql中的分組函數 compute 和 compute by

Compute子句为行聚集函数生成汇总值,该汇总值做为一个附加的行显示

在结果集中。没有GROUP BY 子句的情况下,也可以使用关键字COMPUTE.

此关键字使用MAX,MIN,SUM,COUNT,AVG等函数生成汇总值,而compute by

则在控制中断时给出该汇总值,compute by 必须包括在order by 子句中。

還有很多函數,諸如日期函數,字符串函數等等,就不一一作比較了。

Oracle中還有很多比較好的分析函數,也不列舉了。

五.Oracle中的数据库对象

同义词

作用:简化SQL语句;隐藏对象的名称和所有者,提供对象的公共访问等。

语法:CREATE PUBLIC SYNONYM seqname FOR OBJECT

序列

用来生成唯一、边续的整数,它通常用来自动生成主键或唯一值的键。

創建序列: create sequence seqname [increment by 1] start with 1 maxvalue 10

minvalue 1 cycle cache

访问序列:

Select seqname.nextval from dual 将返回序列的初始值

Select seqname.currval from dual 返回序列的当前值

簇(cluster):

簇是共享相同数据块的一组表,因为这些表具有相同的列,并且经常一起使用。

当两个或多个表的存储在物理上十分接近时,可以通过簇来提高使用这些表的

SQL联接语句的性能。簇是存储表的方法

应该先创建簇,然后再创建簇中的表,

六.Oracle中的对象类型

1. 抽象数据类型

此类型是包含一个或多个子类型的数据类型,并且这些数据类型并不局限

于标准的oracle数据类型

如:create or replace type t_mm as object(col number(3),

col2 varchar2(20))/

此时可以在创建表时

使用该类型,如下

Create table test (aa varchar2(5),bb t_mm, cc number(10))

插入记录:

Insert into test values('cccc', t_mm(1,'col'))

类型声明:

用户定义的数据类型也可以声明为 final,not final,instantiable,

not instantiabe

Not final表示允许类型派生子类型。默认是final

create or replace type t_mm as object(col number(3),

col2 varchar2(20)) Not final

not instantiabe表示类型没有构造函数。

2. 可变数组

可变数组有助于在单个行中存储和重复记录的属性。

数据与表中的其它数据是存储在一起的,有限数目的行,不能被索引

创建可变数组的 语法是:

create type array1 as varray(5) of varchar2(5)

向可变数组中插入记录

Insert into test1 values ('2ee', array1('1','2','3','4','5') )

Select * from test1 结果集如下

2ee

'1','2','3','4','5'

Select col2 from test1 结果集如下

'1','2','3','4','5'

Select * from table(select t.col2 from test1 where col1='2ee'); 结果集如下

1

2

3

4

5

3. 嵌套表

它是包含在表中的表,对每行数据项数目没有限制,一个表在

另一表中是作为一列,主表中的每一行的嵌套表可以包含若干行。

创建嵌套表

先创建一个类型

Create type ord_ty as object(itemcode varchar2(5),qty _ord number(5),

Qty_held number(5));

创建另一个抽象数据类型,即嵌套表数据类型

Create type ord_nt as table of ord_ty

创建嵌套表

Create table order_mas (orderno varchar2(5),odate date,

vencode varchar2(5), dets ord_nt) nested table dets store as ord_nt_tab;

向嵌套表中插入数据:

Insert into order_mas values(‘001’,to_date('18-07-08','DD-MM-YY'),

'V009',ord_nt( ord_ty('i001',10,5),ord_ty('i002',34,2));

更新嵌套表的值:

Update table(select e.dets from order_mas e where e.orderno='001') p

Set value(p) =ord_ty('i090',8,9) where p.itemcode='i001';

删除嵌套表的值:

Delete from table(select e.dets from order_mas e where e.orderno='001') p

where p.itemcode='i001';

4. 对象表

在对象表中每一行都是一个行对象,对象表与关系表不同:

对象表中的每一行都有一个OID值,即对象标识符值。该值是在创建行时

分配的。可以使用create table 命令来创建对象表。

在创建对象类型时,Oracle 中是不允许为属性定义约束条件,但是

可以在创建对象表时为对象类型的属性指定约束条件。

Create table vend

_master of vend_ty(vencode constraint vc_pk primary key);

创建对象表与关系表语法不同

表的使用方法不同 插入数据可以使用抽象数据类型的构造函数,如果对象

表所基于抽象数据类型又基于另一抽象数据类型,则必须多个构造函数的嵌

套调用。

Insert into vend_master values (vend_ty());

5. 对象视图

借助对象视图可以将面向对象的结构(如抽象数据类型)应用于现有已经

投入使用的表,而不需重建整个应用程序

B.PL/SQL與T_SQL语法


一批處理

SQL的能力畢竟有限,諸如事務處理方面,批處理於是oracle與ms 都把它進行了擴展,oracle 的擴展叫PL/SQL由声明部分,可执行部分,异常处理部分组成顺序如下:

Declare declarations

Begin

Executable statements

Exception

Handles

End

Ms 的擴展叫 Transact_SQL,簡稱T_SQL.

批处理:就是一次执行处理一组命令的过程。GO关键字樗着批处理的结束。

如use master

go

复杂一点也是由三部分組成:声明部分,可执行部分,异常处理部分。

不同的是,異常處理部分一般用跳轉語句來實現。

例如:

Declare declarations

Begin

Excutable statements

IF @ERROR <>0 GOTO ERROR

End

ERROR:

BEGIN

RAISERROR(20058, 16, -1)

return (1)

END

二逻辑控制语句

1. 控制结构:

Oracle

If condition then ........

End if

Case selector

when exp1 then statements

Else statements

End case

SQL SERVER

IF condition

Sql statements

ELSE

Sql statements

Case selector

When ex1 then statements

Else statements

End

2. 迭代结构

oracle

Loop statements end loop;

While condition

Loop statement end loop;

Sql server

While condition

Begin

Sql statement

End

面象对象编程涉及的概念有对象,类,属性和方法,面向对象的三大特性是:

封装,继承和多态。

将数据和函数包装到一个单元中的过程称为封装。不能从外部访问数据,只能包装在

类中的那些函数才能访问数据

继承可以是SQL类型的继承和方法的继承。

多态是一个对象可以呈现多种形式的能力,这使得不同的对象可以具有相同的名称

的方法,这些方法实现的任务相似,但实现方式却不同。

三.變量與常量



Pl/sql变量与常量可以具有属性,支持的属性类型有

%type,%rowtype

声明引用数据库列或变量的数据类型的变量时,可以使用%type属性。如:

Declare

Variable_name table_name.col_name %type

使用这个优点是,不需要知道列vencode的准确数据类型

%rowtype属性提供表示表中行的记录类型。

四.過程與函數(Procedure & Function)

a. 建立存儲過程的語法不同:

Ms sql 的語法是:

Create procedure procedure_name

(

@Id int =null,

@name varchar(10) out[put]

)

as

[變量定義區]

begin sql_statement end

--------------------------------------------------------------------

CREATE FUNCTION function_name (@DATE datetime)

RETURNS int

AS begin sql statement end

面向對象的特性之一是封裝,程序包就是对相关PL/SQL类型,子程序,游标,异常,变量,和常量的封装,它包含两部分程序包规格说明和程序包主体

在包规格说明书中,可以声明类型,变量,常量,异常,游标,子程序

程序包主体实现在程序包规格中定义的游标、子程序

包頭語法部分:

Create or replace package package_name is|as

Public type and item declarations

Subprogram specifications

End package_name

實例如下:

Create or replace package pack_me is

Procedure order_proc(orno varchar2);

Function order_fun(ornos varchar2) return varchar2;

End pack_me

包體語法部分:

Create or replace package body package_name is|as

Private type and item decarations

Subprogram bodies

End package_name;

包體具體實例就不寫了,包頭隻是起一個聲明作用,具體實現部分都在包體裡面。

下面是创建存储过程的语法:

Create [or replace] procedure procedure_name[arg1 in|out|in out]type {is|as}

[變量定義區]

Begin

Execute Sql statement

Exception handlers

End

注意:參數列表那裡,oracle是先定義參數是輸入還是輸出參數,然後再定義

參數類型; 而sql server正好相反

创建函数的语法:

Create function function_name argument

Return datatype is|as

Local decaration

Begin

Excutable statement

Exception

Handles

End;

b.變量賦值

1. Oracle里的用法:存储过程中边查询边给变量赋值。

select 某一列名 into 变量名 from table where ..;

相当于sql server中的select 变量名=列. From table where ….

注意:select * /某一列名 into 表名

2. Oracle 直接赋值的符号是:' := '

五 觸發器(Trigger)

Oracle

Create or replace trigger trigger_name [before/after]


[insert/update/delete] on table_name

变量声明

begin

Sql statement

end

Ms sql

Create trigger trigger_name on table

{for |after|instead of} [insert|update|delete] as sql_statements

六 遊標(Curcor)

Oracle中提供两种游标类型,它们是静态游标和ref游标

静态游标又分为隐式游标与显式游标

Ref游标,游标变量是一种引用 类型

隐式游标属性包括%notfound,%found,%rowcount,%isopen

如:

Begin

Delete from ta where ord='ddd'

If sql%notfound then

Dbms_output.put_line(''未找到值)

Else

Dbms_output.put_line(找到并删除之)

End if

End

显示游标:可以用下面语句控制游标

Open cursorname

Fetch cursor_name into var_name

Close cursor_name

创建游标语法:

Oracle:

declare variable

Cursor test is select * from order

Sql server

Declare test cursor for select * from order

七 .错误处理(Exception & test & debug)

有两种类型的异常:一种预定义,另外一种是用户自定义

預定義的類型有很多,如No_data_found,Cursor_already_open

對於Oracle的調試,可以借助第三方工具,如toad,Pl.sql Developer,

对于sql server采用 变量或者print 形式进行调试

Oracle异常定义部分的示例:

Exception

When then statements

When others then

Statements

End;

其中是系统预定义的名字。

Raiser_application_error用于创建用户定义的错误信息的过程,用户定义的错误消息

可以指定的异常描述的更详细

Sql server在错误处理上多采用自定义。或者是用goto跳转的方式

如:

Begin

Sql statements

if @error<>0 goto error

end

Error:

Return;

或是直接用raiserror

if @error<>0

begin

raiserror('发生错误.',-1,-1)

return (1)

end

模式匹配

SQL Server的LIKE关键字提供了有用的通配符搜索功能,这个功能在Oracle中不支持

除了所有的RDBMS都支持的(%)和(_)通配符以外,SQL Server还支持([ ])和([^])通配符。

([ ])字符用来查询在一个范围内的所有单个字符。例如,如果你需要查询包含一个从a到f的字符的数据,

你可以这样写:“LIKE '[a-f]'”或者“LIKE '[abcdef]'”。这些附加的通配符的有效性在下表中给出。

Oracle Microsoft SQL 

SELECT * FROM STUDENT_ADMIN.STUDENT

WHERE LNAME LIKE 'A%'

OR LNAME LIKE 'B%'

OR LNAME LIKE 'C%' SELECT * FROM STUDENT_ADMIN.STUDENT

WHERE LN

AME LIKE '[ABC]%'

 

[^]通配符用来标记那些不在特定范围内的字符。例如,如果除了a到f以外的所有字符都是可以接受的,你可以这样书写:

LIKE '[^a - f]'或者LIKE '[^abcdef]'。

欲了解关于LIKE关键字的详细信息,请参阅SQL Server联机手册。

 

在比较中使用NULL

尽管Microsoft SQL Server传统上支持SQL-92标准的和一些非标准的NULL行为,但是它还是支持Oracle中的NULL的用法。

为了支持分布式查询,SET ANSI_NULLS必须设定为ON。

在进行连接的时候,SQL Server的SQL Server ODBC驱动程序和OLE DB提供者自动把SET ANSI_NULLS设定为ON。

这个设置可以在ODBC数据源、ODBC连接属性、或者是在连接到SQL Server之前在应用程序中设置的OLE DB连接属性中进行配置。

在从DB-Library应用程序中连接时,SET ANSI_NULLS缺省为OFF。

当SET ANSI_DEFAULTS为ON时,SET ANSI_NULLS被允许。

欲了解关于NULL用法的详细信息,请参阅SQL Server联机手册。

 

字串连接

Oracle使用两个管道符号(||)来作为字串连接操作符,SQL Server则使用加号(+)。这个差别要求你在应用程序中做小小的修改。

Oracle Microsoft SQL 

SELECT FNAME||' '||LNAME AS NAME

FROM STUDENT_ADMIN.STUDENT

-----------------------------------------------

SELECT FNAME +' '+ LNAME AS NAME

FROM STUDENT_ADMIN.STUDENT

 

流控制(Control-of-Flow)语言

流控制语言控制SQL语句执行流,语句块以及存储过程。PL/SQL和Transact-SQL提供了多数相同的结构,但是还是有一些语法差别。

 

关键字

这是两个RDBMS支持的关键字。

语句 Oracle PL/SQL ---------------------Microsoft SQL Server Transact-SQL

声明变量 DECLARE DECLARE

语句块 BEGIN...END; BEGIN...END

条件处理 IF…THEN,

ELSIF…THEN,

ELSE

ENDIF;

--------------------------------------------------------

IF…[BEGIN…END]

ELSE

[BEGIN…END]

ELSE IF

CASE expression

无条件结束 RETURN------------ RETURN

无条件结束当前程序块后面的语句 EXIT BREAK

重新开始一个WHILE循环 N/A CONTINUE

等待指定间隔 N/A (dbms_lock.sleep) WAITFOR

循环控制 WHILE LOOP…END LOOP;

------------

LABEL…GOTO LABEL;

FOR…END LOOP;

LOOP…END LOOP;

WHILE

BEGIN… END

LABEL…GOTO LABEL

程序注释 /* … */, -- /* … */, --

打印输出 RDBMS_OUTPUT.PUT_LINE PRINT

引发程序错误(Raise program error) RAISE_APPLICATION_ERROR --------------------RAISERROR

执行程序 EXECUTE----------------------EXECUTE

语句终止符 Semicolon ( ------------------N/A

 

声明变量

Transact-SQL和PL/SQL的变量是用DECLARE关键字创建的。Transact-SQL变量用@标记,

并且就像PL/SQL一样,在第一次创建时,用空值初始化。

O

racle Microsoft SQL 

DECLARE

VSSN CHAR(9);

VFNAME VARCHAR2(12);

VLNAME VARCHAR2(20);

VBIRTH_DATE DATE;

VLOAN_AMOUNT NUMBER(12,2);

-----------------------------------------

DECLARE

@VSSN CHAR(9),

@VFNAME VARCHAR2(12),

@VLNAME VARCHAR2(20),

@VBIRTH_DATE DATETIME,

@VLOAN_AMOUNT NUMERIC(12,2)

 

Transact-SQL不支持%TYPE和%ROWTYPE变量数据类型定义。一个Transact-SQL变量不能在DECLARE命令中初始化。

在Microsoft SQL Server数据类型定义中也不能使用Oracle的NOT NULL和CONSTANT关键字。

像Oracle的LONG和LONG RAW数据类型一样。文本和图形数据类型不能被用做变量定义。

此外,Transact-SQL不支持PL/SQL风格的记录和表的定义。

 

给变量赋值

Oracle和Microsoft SQL Server提供了下列方法来为本地变量赋值。

Oracle Microsoft SQL 

Assignment operator (:=) ---------------------SET @local_variable = value

SELECT...INTO syntax for selecting column values from a single row

-------------------------

SELECT @local_variable = expression [FROM…] for assigning a literal value,

an expression involving other local variables, or a column value from a single row

FETCH…INTO syntax------------------------------- FETCH…INTO syntax

 

这里有一些语法示例

Oracle Microsoft SQL 

DECLARE VSSN CHAR(9);

VFNAME VARCHAR2(12);

VLNAME VARCHAR2(20);

BEGIN

VSSN := ?'

SELECT FNAME, LNAME INTO VFNAME, VLNAME FROM STUDENTS WHERE SSN=VSSN;

END;

------------------------------------------------------------------------------

DECLARE @VSSN CHAR(9),

@VFNAME VARCHAR(12),

@VLNAME VARCHAR(20)

SET @VSSN = ?'

SELECT @VFNAME=FNAME, @VLNAME=LNAME FROM STUDENTS WHERE SSN = @VSSN

 

语句块

Oracle PL/SQL和Microsoft SQL Server Transact-SQL都支持用BEGIN…END术语来标记语句块。

Transact-SQL不需要在DECLARE语句后使用一个语句块。

---------------------------------------------------------------------------------

-如果在Microsoft SQL Server

中的IF语句和WHILE循环中有多于一个语句被执行,则需要使用BEGIN…END语句块。

Oracle Microsoft SQL 

DECLARE

DECLARE VARIABLES ...

BEGIN -- THIS IS REQUIRED SYNTAX

PROGRAM_STATEMENTS ...

IF ...THEN

STATEMENT1;

STATEMENT2;

STATEMENTN;

END IF;

WHILE ... LOOP

STATEMENT1;

STATEMENT2;

STATEMENTN;

END LOOP;

END; -- THIS IS REQUIRED SYNTAX DECLARE

DECLARE VARIABLES ...

BEGIN -- THIS IS OPTIONAL SYNTAX

PROGRAM_STATEMENTS ...

IF ...

BEGIN

STATEMENT1

STATEMENT2

STATEMENTN

END

WHILE ...

BEGIN

STATEMENT1

STATEMENT2

STATEMENTN

END

END -- THIS IS REQUIRED SYNTAX

 

条件处理

Microsoft SQL Server Transact-SQL的条件语句包括IF和ELSE,但不包括Oracle PL/SQL中的ELSEIF语句。

可以用嵌套多重IF语句来到达同样的效果。对于广泛的条件测

试,用CASE表达式也许更容易和可读一些。

Oracle Microsoft SQL 

DECLARE

VDEGREE_PROGRAM CHAR(1);

VDEGREE_PROGRAM_NAME VARCHAR2(20);

BEGIN

VDEGREE_PROGRAM := 'U'

IF VDEGREE_PROGRAM = 'U' THEN

VDEGREE_PROGRAM_NAME := 'Undergraduate'

ELSIF VDEGREE_PROGRAM = 'M' THEN VDEGREE_PROGRAM_

NAME := 'Masters'

ELSIF VDEGREE_PROGRAM = 'P' THEN VDEGREE_PROGRAM_

NAME := 'PhD'

ELSE VDEGREE_PROGRAM_

NAME := 'Unknown'

END IF;

END;

-----------------------------------------------------

DECLARE

@VDEGREE_PROGRAM CHAR(1),

@VDEGREE_PROGRAM_NAME VARCHAR(20)

SELECT @VDEGREE_PROGRAM = 'U'

SELECT @VDEGREE_PROGRAM_

NAME = CASE @VDEGREE_PROGRAM

WHEN 'U' THEN 'Undergraduate'

WHEN 'M' THEN 'Masters'

WHEN 'P' THEN 'PhD'.

ELSE 'Unknown'

END

 

重复执行语句(循环)

Oracle PL/SQL提供了无条件的LOOP和FOR LOOP。Transact-SQL则提供了WHILE循环和GOTO语句。

WHILE Boolean_expression

{sql_statement | statement_block}

[BREAK] [CONTINUE]

 

WHILE循环需要测试一个布尔表达式来决定一个或者多个语句的重复执行。

只要给定的表达式结果为真,这个(些)语句就一直重复执行下去。如果有多个语句需要执行,则这些语句必须放在一个BEGIN…END块中。

Oracle Microsoft SQL 

DECLARE

COUNTER NUMBER;

BEGIN

COUNTER := 0

WHILE (COUNTER <5) LOOP

COUNTER := COUNTER + 1;

END LOOP;

END;

------------------------------------------------------

DECLARE

@COUNTER NUMERIC

SELECT@COUNTER = 1

WHILE (@COUNTER <5)

BEGIN

SELECT @COUNTER =

@COUNTER +1

END

 

语句的执行可以在循环的内部用BREAK和CONTINUE关键字控制。BREAK关键字使WHILE循环无条件的结束,

而CONTINUE关键字使WHILE循环跳过后面的语句重新开始。BREAK关键字同Oracle PL/SQL中的EXIT关键字是等价的。

而在Oracle中没有和CONTINUE等价的关键字

GOTO语句

Oracle和Microsoft SQL Server都有GOTO语句,但是语法不同。GOTO语句使Transact-SQL跳到指定的标号处运行,

在GOTO语句后指定标号之间的任何语句都不会被执行。

Oracle Microsoft SQL 

GOTO label;

<

来封闭文本。

 

从存储过程返回

Microsoft SQL Server和Oracle都有RETURN语句。RETURN使你的程序从查询或者过程中无条件的跳出。RETURN是立即的、

完全的、并且可以用于从过程、批处理或者语句块的任意部分跳出。在REUTRN后面的语句将不会被执行。

Oracle Microsoft SQL 

RETURN expression: RETURN [integer_expression]

 

引发程序错误(Raising program errors)

Transact-SQL的RAISERROR返回一个用户定义的错误消息,并且设置一个系统标志来记录发生了一个错误。

这个功能同PL/SQL的raise_application_error异常处理器的功能是相似的。

RAISERROR语句允许客户重新取得sysmessages表的一个入口,或者用用户指定的严重性和状态信息动态的建立一条消息。

在被定义后,消息被送回客户端作为系统错误消息。

RAISERROR ({msg_id | msg_str}, severity, state

[, argument1 [, argument2>

[WITH options]

 

在转换你的PL/SQL程序时,也许用不着使用RAISERROR语句。在下面的示例代码中。

PL/SQL程序使用raise_application_error异常处理器,但是Transact-SQL程序则什么也没用。

包括raise_application_error异常处理器是为了防止PL/SQL返回不明确的未经处理的异常错误消息。

作为代替,当一个不可预见的问题发生的时候,异常处理器总是返回Oracle错误消息。

当一个Transact-SQL失败时,它总是返回一个详细的错误消息给客户程序。因此,除非需要某些特定的错误处理,

一般是不需要RAISERROR语句的。

Oracle Microsoft SQL 

CREATE OR REPLACE FUNCTION

DEPT_ADMIN.DELETE_DEPT

(VDEPT IN VARCHAR2) RETURN NUMBER AS

BEGIN

DELETE FROM DEPT_ADMIN.DEPT

WHERE DEPT = VDEPT;

RETURN(SQL%ROWCOUNT);

EXCEPTION

WHEN OTHER THEN

RAISE_APPLICATION_ERROR

(-20001,SQLERRM);

END DELETE_DEPT;

------------------------------------------------------

/ CREATE PROCEDURE

DEPT_ADMIN.DELETE_DEPT

@VDEPT VARCHAR(4) AS

DELETE FROM DEPT_DB.DBO.DEPT

WHERE DEPT = @VDEPT

RETURN @@ROWCOUNT

GO

 

实现游标

Oracle在使用SELECT语句时总是需要游标,不管从数据库中请求多少行。在Microsoft SQL Server,

SELECT语句并不把在返回客户的行上附加游标作为缺省的结果集合。这是一种返回数据给客户应用程序的有效的方法。

SQL Server为游标函数提供了两种接口。当在Transact-SQL批处理或者存储过程中使用游标的时候,SQL语句可用来声明、

打开、和从游标中抽取,就像定位更新和删除一样。当使用来自DB-Library、ODBC、或者OLEDB程序的游标时,SQL Server

显式的调用内建的服务器函数来更有效的处理游标。

当从Oracle输入一个PL/SQL过程时,首先判断是否需要在Transact-SQL中采用游标来实现同样的功能。如果游标

仅仅返回一

组行给客户程序,就使用非游标的SELECT语句来返回缺省的结果集合。如果游标用来从行中一次取得一个数据给本地过程变量,

你就必须在Transact-SQL中使用游标。

 

语法

下表显示了使用游标的语法。

操作 Oracle Microsoft SQL Server

声明一个游标 CURSOR cursor_name [(cursor_parameter(s))]

IS select_statement;

----------------------------------------------------

DECLARE cursor_name CURSOR

[LOCAL | GLOBAL]

[FORWARD_ONLY | SCROLL]

[STATIC | KEYSET | DYNAMIC | FAST_FORWARD]

[READ_ONLY | SCROLL_LOCKS | OPTIMISTIC]

[TYPE_WARNING]

FOR select_statement

[FOR UPDATE [OF column_name [,…n>]

打开一个游标 OPEN cursor_name [(cursor_parameter(s))];

----------------

OPEN cursor_name

从游标中提取(Fetching) FETCH cursor_name INTO variable(s)

-------------------------------------------------------------------------------------------

FETCH FROM] cursor_name

[INTO @variable(s)]

更新提取行 UPDATE table_name

SET statement(s)…

WHERE CURRENT OF cursor_name; UPDATE table_name

SET statement(s)…

WHERE CURRENT OF cursor_name

删除提取行 DELETE FROM table_name

WHERE CURRENT OF cursor_name; DELETE FROM table_name

WHERE CURRENT OF cursor_name

关闭游标 CLOSE cursor_name; CLOSE cursor_name

清除游标数据结构 N/A DEALLOCATE cursor_name

 

声明一个游标

尽管Transact-SQL DECLARE CURSOR语句不支持游标参数的使用,但它确实支持本地变量。当游标打开的时候,

它就使用这些本地变量的值。Microsoft SQL Server在其DECLARE CURSOR中提供了许多附加的功能。

INSENSITIVE选项用来定义一个创建数据的临时拷贝以被游标使用的游标。游标的所有请求都由这个临时表来应答。因此

对原表的修改不会反映到那些由fetch返回的用于该游标的数据上。这种类型的游标访问的数据是不能被修改的。

应用程序可以请求一个游标类型然后执行一个不被所请求的服务器游标类型支持的Transact-SQL语句。SQL Server返回一个错误,

指出该游标类型被改变了,或者给出一组参数,隐式的转换游标。欲取得一个触发SQL Server 7.0隐式的把游标从一种类型转换为

另一种类型的参数的完整列表,请参阅SQL Server联机手册。

SCROLL选项允许除了前向的抽取以外,向后的、绝对的和相对的数据抽取。一个滚动游标使用一种键集合的游标模型,在该模型中,

任何用户提交的对表的删除和更新都将影响后来的数据抽取。只有在游标没有用INSENSITIVE选项声明时,上面的特性才起作用。

如果选择了READ ONLY选项,对游标中的行的更新就被禁止。该选项将覆盖游标的缺省选项棗允许更新。

UPDATE [OF column_list]语句用来在游标中定义一个可更

新的列。如果提供了[OF column_list],那么仅仅是那些列出的列可以被修改。

如果没有指定任何列。则所有的列都是可以更新的,除非游标被定义为READ ONLY。

重要的是,注意到一个SQL Server游标的名字范围就是连接自己。这和本地变量的名字范围是不同的。

不能声明一个与同一个用户连接上的已有的游标相同名字的游标,除非第一个游标被释放。

 

打开一个游标

Transact-SQL不支持向一个打开的游标传递参数,这一点和PL/SQL是不一样的。当一个Transact-SQL游标被打开以后,

结果集的成员和顺序就固定下来了。其它用户提交的对原表的游标的更新和删除将反映到对所有未加INSENSITIVE选项定义

的游标的数据抽取上。对一个INSENSITIVE游标,将生成一个临时表。

 

抽取数据

Oracle游标只能向前移动棗没有向后或者相对滚动的能力。SQL Server游标可以向前或者向后滚动,具体怎么滚动,

要由下表给出的数据抽取选项来决定。只有在游标是用SCROLL选项声明的前提下,这些选项才能使用。

卷动选项 描述

NEXT 如果这是对游标的第一次提取,则返回结果集合的第一行;否则,在结果结合内移动游标到下一行。

NEXT是在结果集合中移动的基本方法 。NEXT是缺省的游标提取(fetch)。

PRIOR 返回结果集合的前一行。

FIRST 把游标移动到结果集合的第一行,同时返回第一行。

LAST 把游标移动到结果集合的最后一行,同时返回最后一行。

ABSOLUTE n 返回结果集合的第n行。如果n为负数,则返回倒数第n行

RELATIVE n 返回当前提取行后的第n行,如果n是负数,则返回从游标相对位置起的倒数第n行。

 

Transact-SQL的FETCH语句不需要INTO子句。如果没有指定返回变量,行就自动作为一个单行结果集合返回给客户。但是,

如果你的过程必须把行给客户,一个不带游标的SELECT语句更有效一些。

在每一个FETCH后面,@@FETCH_STATUS函数被更新。这和在PL/SQL中使用CURSOR_NAME%FOUND和CURSOR_NAME%NOTFOUND变量是相似的

。@@FETCH_STATUS函数在每一次成功的数据抽取以后被设定为0。如果数据抽取试图读取一个超过游标末尾的数据,则返回一个为-1的值。

如果请求的行在游标打开以后从表上被删除了,@@FETCH_STATUS函数就返回一个为-2的值。只有游标是用SCROLL选项定义的情况下,

才会返回-2值。在每一次数据抽取之后都必须检查该变量,以确保数据的有效性。

SQL Server不支持Oracle的游标FOR循环语法。

CURRENT OF子句

更新和删除的CURRENT OF子句语法和函数在PL/SQL和Transact-SQL中是一样的。在给定游标中,在当前行上执行定位的UPDATE和DELETE。

 

关闭一个游标

T

ransact-SQL的CLOSE CURSOR语句关闭游标,但是保留数据结构以备重新打开。PL/SQL 的CLOSE CURSOR语句关闭并且释放所有的数据结构。

Transact-SQL需要用DEALLOCATE CURSOR语句来清除游标数据结构。DEALLOCATE CURSOR语句同CLOSE CURSOR是不一样的,

后者保留数据结构以备重新打开。DEALLOCATE CURSOR释放所有与游标相关的数据结构并且清除游标的定义。

 

游标示例

下面的例子显示了在PL/SQL和Transact-SQL等价的游标语句。

Oracle Microsoft SQL 

-----------------------------------------------------------------------------------------------------------

DECLARE

VSSN CHAR(9);

VFNAME VARCHAR(12);

VLNAME VARCHAR(20);

-----------------------------------------------------------------------------------------------------------

DECLARE

@VSSN CHAR(9),

@VFNAME VARCHAR(12),

@VLNAME VARCHAR(20)

CURSOR CUR1

IS

SELECT SSN, FNAME, LNAME

FROM STUDENT ORDER BY LNAME;

BEGIN

OPEN CUR1;

FETCH CUR1 INTO VSSN, VFNAME, VLNAME;

WHILE (CUR1%FOUND) LOOP

FETCH CUR1 INTO VSSN, VFNAME, VLNAME;

END LOOP;

CLOSE CUR1;

END;

-----------------------------------------------------------------------------------------------------------

DECLARE curl CURSOR FOR

SELECT SSN, FNAME, LNAME

FROM STUDENT ORDER BY SSN

OPEN CUR1

FETCH NEXT FROM CUR1

INTO @VSSN, @VFNAME, @VLNAME

WHILE (@@FETCH_STATUS <> -1)

BEGIN

FETCH NEXT FROM CUR1 INTO @VSSN, @VFNAME, @VLNAME

END

CLOSE CUR1

DEALLOCATE CUR1


相关主题
文本预览
相关文档 最新文档