<五> 存储过程/函数

<1>、SQL SERVER端语法说明

1、语法:

CREATE PROC[EDURE] [owner.]procedure_name [;number]

[ (parameter1[, parameter2]…[, parameter255])]

[ {FOR REPLICATION} | {WITH RECOMPILE}

[ {[WITH] | [ , ] } ENCRYPTION ] ]

AS

sql_statement [
n]

其中,Parameter = @parameter_name datatype [=default] [output]


说明:T-SQL中存储过程的结构大致如下

CREATE PROCEDURE procedure_name


/**//*输入、输出参数的声明部分*/

AS

DECLARE


/**//*局部变量的声明部分*/

BEGIN


/**//*主体SQL语句部分*/


/**//*游标声明、使用语句在此部分*/

END


2、示例:

IF EXISTS(SELECT 1 FROM sysobjects

WHERE name = 'titles_sum' AND type = 'P')

DROP PROCEDURE titles_sum

GO


CREATE PROCEDURE titles_sum

@TITLE varchar(40) = '%', @SUM money OUTPUT

AS

BEGIN

SELECT 'Title Name' = title

FROM titles

WHERE title LIKE @TITLE

SELECT @SUM = SUM(price)

FROM titles

WHERE title LIKE @TITLE

END


<2>、ORACLE端PROCEDURE语法说明

1、语法:

CREATE [OR REPLACE] PROCEDURE procedure_name

[ (parameter1 [ {IN | OUT | IN OUT } ] type ,

…

parametern [ {IN | OUT | IN OUT } ] type ) ]

{ IS | AS }

[BEGIN]

sql_statement [
n] ;

[END] ;


说明:PL/SQL中存储过程的结构大致如下

CREATE OR REPLACE PROCEDURE procedure_name


( /**//*输入、输出参数的声明部分*/ )

AS


/**//*局部变量、游标等的声明部分*/

BEGIN


/**//*主体SQL语句部分*/


/**//*游标使用语句在此部分*/

EXCEPTION


/**//*异常处理部分*/

END ;


2、示例:

CREATE OR REPLACE PROCEDURE drop_class

( arg_student_id IN varchar2,

arg_class_id IN varchar2,

status OUT number )

AS

counter number ;

BEGIN

status := 0 ;

-- Verify that this class really is part of the student’s schedule.

select count (*) into counter

from student_schedule

where student_id = arg_student_id

and class_id = arg_class_id ;


IF counter = 1 THEN

delete from student_schedule

where student_id = arg_student_id

and class_id = arg_class_id ;

status := -1 ;

END IF ;

END ;

<3>ORACLE端FUNCTION语法说明

(1) 语法

CREATE [OR REPLACE] FUNCTION function_name

[(argument [{IN | OUT | IN OUT }] ) type,

…

[(argument [{IN | OUT | IN OUT }] ) type

RETURN return_type {IS | AS}

BEGIN

…

END;

关键字return 指定了函数返回值的数据类型。它可以是任何合法的PL/SQL数据类型。每个函数都必须有一个return 子句,因为在定义上函数必须返回一个值给调用环境。

(2)示例

CREATE OR REPLACE FUNCTION blanace_check(Person_Name IN varchar2)

RETURN NUMBER

IS

Balance NUMBER(10,2);

BEGIN

Select sum(decode(acton,’BOUGHT’,Amount,0))

INTO balance

FROM ledger

WHERE Person = Person_name;

RETURN (balance);

END;

(3)过程与函数的区别

函数可以返回一个值给调用环境;而过程不能,过程只能通过返回参数(带“OUT”或“IN OUT”)传回去数据。

<4>从SQL SERVER向ORACLE的迁移方案

通过比较上述SQL语法的差异,在迁移时必须注意以下几点:

1、对于有返回单值的MSSQL存储过程,在数据库移值最好转换成ORALCE的函数;对于MSSQL有大量数据的处理而又不需返回值的存储过程转换成ORACLE的过程

2、在T-SQL中,输入、输出参数定义部分在“CREATE…”和“AS”之间,前后

没有括号;而在PL/SQL中必须有“(”和“)”与其他语句隔开。

3、在T-SQL中,声明局部变量时,前面要有DECLARE关键字;

而在PL/SQL中不用DECLARE关键字。

4、在T-SQL中,参数名的第一个字符必须是“@”,并符合标识符的规定;

而在PL/SQL中,参数名除符合标识符的规定外没有特殊说明,T-SQL中,对于参数可其数据类型及其长度和精度;但是PL/SQL中除了引用%TYPE和%ROWTYPE之外,不能在定义参数数据类型时给出长度和精度,如下:

CREATE OR REPLACE PROCEDURE PROC_SELE_YS

(YSDM CHAR(6),GZ NUMBER(14,4))

AS

BEGIN

…

END;

是错误的,应如下定义

CREATE OR REPLACE PROCEDURE PROC_SELE_YS

(YSDM CHAR,GZ NUMBER)

AS

BEGIN

…

END;

或者

CREATE OR REPLACE PROCEDURE PROC_SELE_YS

(YSDM YSDMB.YSDM%TYPE,GZ YSDMB.GZ%TYPE)

AS

BEGIN

…

END;


5、对于T-SQL,游标声明在主体SQL语句中,即声明与使用语句同步;

而在PL/SQL中,游标声明在主体SQL语句之前,与局部变量声明同步。

6、对于T-SQL,在主体SQL语句中用如下语句对局部变量赋值(初始值或

数据库表的字段值或表达式):

“SELECT 局部变量名 = 所赋值(初始值或数据库表的字段值或表达式)”;

而在PL/SQL中,将初始值赋给局部变量时,用如下语句:

“局部变量名 : = 所赋值(初始值或表达式);” ,

将检索出的字段值赋给局部变量时,用如下语句:

“SELECT 数据库表的字段值 INTO 局部变量名 …” 。

7、在PL/SQL中,可以使用%TYPE来定义局部变量的数据类型。说明如下:

例如,students表的first_name列拥有类型VARCHAR2(20),基于这点,

我们可以按照下述方式声明一个变量:

V_FirstName VARCHAR2(20) ;

但是如果改变了first_name列的数据类型则必须修改该声明语句,因此可以采

用%TYPE进行变量数据类型声明:

V_FirstName students.first_name%TYPE ;

这样,该变量在存储过程编译时将由系统自动确定其相应数据类型。

8、对于T-SQL,没有定义语句结束标志,而PL/SQL用“END <过程名>;”结束语句。

9、存储过程的调用要注意:在MSSQLSERVER中的格式为“EXEC Procedure_Name {arg1,arg2,…},但在ORACLE中直接引用过程名即可,如要执行存储过程DefaltNo,其参数为“9”,则执行时为 Default(“9”)。

10、ORACLE 数据库的存储过程不支持用select 子句直接返回一个数据集,要做到通过程产生一记录集有两种方案:

方案一:采用包和游标变量

第一步,创建一个包,定义一个游标变量

create package p_name
is
type cursor_name is ref cursor;
end;

第二步,创建过程,但是基返回参数用包中的游标类型
create procedure procedure_name(s in out p_name.cursor_name) is
begin
open s for select * from table_name
;
end;

这样,通过存储过程就可以返回一个数据集了,但用到这种情况,过程的参数中只这返回结果的游标参数可以带关键字”OUT”,其它不能带”out”,否则,系统会出现导常。

方案二:通过中间表,建一中间表,其表格的列为所需数据列再加上一个序列字段。过程的处理为将数据插入到中间表中,同时通过

select userenv(‘sessionid’) from dual;取得当前连接会话的序号,将取得的序号值放置到序列字段中,同时存储过程返回连接会话的序号,前台PB程序直接访问中间表,数据窗口在检索时通过序号参数可将所需的数据检索出来。
posted on 2007-11-07 10:33
datasky 阅读(440)
评论(0) 编辑 收藏 网摘 所属分类:
Sql Server 、
Oracle