精编推荐Oracle存储过程开发规范与技巧.docx

上传人:b****5 文档编号:5344924 上传时间:2022-12-15 格式:DOCX 页数:41 大小:46.30KB
下载 相关 举报
精编推荐Oracle存储过程开发规范与技巧.docx_第1页
第1页 / 共41页
精编推荐Oracle存储过程开发规范与技巧.docx_第2页
第2页 / 共41页
精编推荐Oracle存储过程开发规范与技巧.docx_第3页
第3页 / 共41页
精编推荐Oracle存储过程开发规范与技巧.docx_第4页
第4页 / 共41页
精编推荐Oracle存储过程开发规范与技巧.docx_第5页
第5页 / 共41页
点击查看更多>>
下载资源
资源描述

精编推荐Oracle存储过程开发规范与技巧.docx

《精编推荐Oracle存储过程开发规范与技巧.docx》由会员分享,可在线阅读,更多相关《精编推荐Oracle存储过程开发规范与技巧.docx(41页珍藏版)》请在冰豆网上搜索。

精编推荐Oracle存储过程开发规范与技巧.docx

精编推荐Oracle存储过程开发规范与技巧

【精编推荐】Oracle存储过程开发规范与技巧

存储过程开发规范与技巧

开发规范

1.书写规范

1):

程序头书写规范

程序头开始部分应说明程序整体的功能,存储过程名称,编写人,编写日期,修改人,修改日期,版本号以及过程涉及的表和视图。

示例如下:

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

/*

名称及实现功能:

版本:

(版本号标示:

新建V1.0.0小的修改变为V1.0.1大的修改V1.1.0重构V2.0.0)

Createby***CreateDate2006-06-29

Updateby***updateDate2006-06-30

修改原因:

Updateby***updateDate2006-06-31

修改原因:

涉及的表或视图:

dump_init辅助表(DM):

记录存储过程中使用的物化视图日志序号

mlog$_acrcusmrsecindex源表(ODS):

客户第一索引物化视图日志,使用同义词

ft_gld_customerdata目标表(DM):

客户事实表

*/

CREATEORREPLACEPROCEDURE*******

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

2):

代码书写规范

1.语句中出现的所有表名、字段名全部小写,系统保留字、内置函数名、Sql保留字大写。

2.连接符or、in、and、以及=、<=、>=等前后加上一个空格。

3.where子句书写时,每个条件占一行,语句令起一行时,以保留字或者连接符开始,连接符右对齐。

 

4.查询的WHERE过滤,原则应使过滤记录数最多的条件放在最前面。

5.多表连接时,使用表的别名来引用列。

6.查找数据库表或视图时,只能取出确实需要的那些字段,不要使用*来代替所有列名。

7.功能相似的过程和函数,尽量写到同一个包中,加强管理。

示例如下:

BEGIN

--查询员工及对应的部门名称

SELECTemp.name,dept.name

FROMl_deptdept,l_employeeemp

WHEREemp.dept_id=dept.dept_id;

END;

3)注释书写规范

为了提高可读性,应该使用一定数量的注释。

注释大约占总行数的1/5。

1:

注释风格:

注释单独成行、放在语句前面。

 

2:

应对不易理解的分支条件表达式加注释;

3:

对重要的计算应说明其功能;

4:

过长的函数实现,应将其语句按实现的功能分段加以概括性说明;

5:

每条SQL语句均应有注释说明

6:

对于程序的整体功能,应在程序开始部分说明,可采用单行/多行注释。

(--或/**/方式)

2.命名规范

命名对象

规则

样例

存储过程、包、方法

1业务相关以模块代码开头

gld_assist_check_p

2如果区分全量和增量,在最后加标识

gld_load_to_etl

gld_load_to_etl_full

3全局使用,以global开头

global_procedure_check

变量

以v开头

v_updatemode1

游标

以c开头

c_tablist

内存表

以m开头

m_table1

临时表

以t开头

t_tmpTable

存储过程技术

1.存储过程样例

CREATEORREPLACEPROCEDUREexample(

v_inputINNUMBER,--输入参数

v_outputOUTNUMBER--输出参数

IS

PRAGMAAUTONOMOUS_TRANSACTION;

CURSORc1--定义一个游标,在begin之前

IS

SELECTb.tablenamemlogtable,

MAX(remarks)KEEP(DENSE_RANKLASTORDERBYstarttime)

remarks

FROMproc_loga,table_procb

WHERETO_CHAR(starttime,'yyyy-mm-dd')<=--转换时间并做比较

TO_CHAR(SYSDATE-TO_DSINTERVAL(

TO_CHAR(intervaldays)||'00:

00:

00'),'yyyy-mm-dd')

ANDa.remarksLIKE'SUCCEEDED:

%'

ANDa.procedurename=b.procedurename

GROUPBYb.tablename);--定义结束

c1_recc1%ROWTYPE;--定义接受游标数据行的ROWTYPE

v_mlogtableVARCHAR(30);

v_postperiodCHAR

(2);

v_acctbalbeginseqNUMBER;

v_systimeDATE;

BEGIN

v_input:

=0;--变量赋值

v_systime:

=SYSDATE;

OPENc1;--打开游标

LOOP--循环

FETCHc1INTOc1_rec;--从当前游标行赋值c1_rec

EXITWHENc1%NOTFOUND;--游标没有数据退出

v_mlogtable:

=c1_rec.mlogtable;--从行取出具体数据赋给变量

CASETRIM(LOWER(v_mlogtable))--CASE起始

WHEN'String1'--当条件一

THEN--做条件一工作

BEGIN

v_remarks:

=REPLACE(v_remarks,'AA');

END;

WHEN'String2'--当条件二

THEN

BEGIN

END;

ELSE--其他条件

NULL;

ENDCASE;--CASE结束

IF(LOWER(SUBSTR(v_mlogtable,1,5))<>'mlog$')

THEN

SELECTlog_table

INTOv_mlogtable

FROMuser_snapshot_logs

WHERELOWER(MASTER)=LOWER(v_mlogtable);

ENDIF;

EXECUTEIMMEDIATE'deletefrom'

||v_mlogtable

||'wheresequence$$<='

||TO_CHAR(v_lognum);

EXITWHEN1>2;--循环跳出条件

ENDLOOP;--循环结束

CLOSEc1;--关闭游标

EXCEPTION

WHENOTHERS

THEN

ROLLBACK;

global_procedure_check.check_end('checkdataerror01',

v_systime,

1,

SQLCODE||''||SQLERRM

);

RAISE;

RETURN;

END;

ENDexample;

2.基本知识

1)基本结构

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

CREATEORREPLACEPROCEDUREexample(parameters)--过程声明区

IS

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

v_1NUMBER;--过程中变量声明区--------------------------------------------------------

BEGIN

v_1:

=0;--过程内容区

ENDexample;

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

2)基本类型

CHAR固定长度字符类型

VARCHAR2可变长字符类型

VARCHAR可变长字符类型(不建议使用)

NUMBER一切数值类型

DATE一切日期类型

3)参数

三种:

IN输入参数,OUT输出参数,INOUT输入输出参数。

4)变量的声明

在变量声明区声明变量的名称和类型

例:

v_postperiodCHAR

(2);

可赋初值

v_postperiodCHAR

(2):

=’01’;

(这里叫变量声明区可能并不恰当,因为游标、自定义类型等,一切需要事先声明的都应在这里声明。

5)变量的赋值

使用‘:

=’为变量赋值

1.直接使用基本类型赋值

例:

v_number:

=1;

2.使用函数赋值

例:

v_date:

=sysdate;

3.使用SQL语句为变量赋值

1〉通过sql直接赋值

SELECTCOUNT(*)

INTOv_tmpnumber

FROMetl_ods_masterdata_tablist;

2〉通过构造SQL赋值:

v_tmpsql:

=

'SELECTlog_tableFROMuser_snapshot_logs'

||v_dblink

||'WHEREUPPER(MASTER)=UPPER('''

||v_singletab

||''')';

EXECUTEIMMEDIATEv_tmpsql

INTOv_tmpvarchar;

6)循环

1.无限或简单循环

LOOP

EXITWHEN(退出循环条件);

ENDLOOP;

2.while循环

WHILEcondition

LOOP

executable_statements;

ENDLOOP;

3.for循环

基于数字的for循环:

FORfor_indexINlow_value..high_value

LOOP

executable_statements;

ENDLOOP;

基于游标的for循环:

FORrecord_indexINmy_cursor

LOOP

executable_statements;

ENDLOOP;

7)调用其他过程或方法

1.如果单独定义,直接使用

例:

v_retval0:

=

f_dump_init(v_updatemode,

v_systime,

'mlog$_glddocheader',

v_procname,

v_docheaderbeginseq,

v_docheaderendseq

);

2.如果定义在包下,使用包名+过程名

例:

global_procedure_check.check_run(v_procname);

3.固定用法和函数

标识

作用

用法或类型

固定用法:

SYSDATE

当前系统时间

DATE

SQLCODE

异常代码

VARCHAR2

SQLERRM

异常描述

VARCHAR2

NO_DATA_FOUND

未找到数据异常

与when搭配

OTHERS

其他所有异常

与when搭配

RAISE

抛出当前异常

RAISE;

DENSE_RANK

非选取字段排序

MIN(B)KEEP(DENSE_RANKFIRSTORDERBYA)

MAX(B)KEEP(DENSE_RANKLASTORDERBYA)

PRAGMAAUTONOMOUS_TRANSACTION

BULKCOLLECTINTO

SQL%ROWCOUNT

使用自治事务,可以使该过程被调用时单独提交

Begin之前使用PRAGMAAUTONOMOUS_TRANSACTION;

将前面执行结果大批放入后面的集合中

BULKCOLLECTINTOcolumntab;

前一个DML语句执行影响行数

作为NUMBER型使用

v_number:

=SQL%ROWCOUNT

DBMS_OUTPUT.put_line()

输出信息

函数

TO_CHAR

转换NCHAR、NVARCHAR2、CLOB、NCLOB

TO_CHAR(A)

转换DATE型为指定格式

TO_CHAR(time,'yyyy-mm-dd')

转换NUMBER型为指定格式

TO_CHAR(564.70,'$999.9')

TO_DATE

转换字符串为指定日期

to_date('1900-01-01','YYYY-MM-DD')

INSTR(string,substring(,postion)(,occurrence))

返回目标字符串中子字符串的位置。

(起始位置和出现次数为可选)

INSTR('bug-archie','archie')

INSTR('haracter?

archie','a',1,2)

LENGTH

获得指定字符串长度

LENGTH('CANDIDE')

LOWER

将指定字符串转换成小写

LOWER('LETTERS')

UPPER

将指定字符串转换成大写

UPPER('letters')

LPAD(str1,n,str2)

将str1用str2左补齐至n位

LPAD('55',10,'0')

RPAD(str1,n,str2)

将str1用str2右补齐至n位

RPAD('55',10,'0')

LTRIM

去掉指定字符串左侧的指定字符或字符集合,默认为空格

LTRIM('Way')

LTRIM('123123Way','123')

RTRIM

去掉指定字符串右侧的指定字符或字符集合,默认为空格

RTRIM('WayxyXxyxy','xy')

POWER(m,n)

计算m的n次方

POWER(2,3)

Extract(yearfromdate)

取出date的年

4.ROWTYPE的使用

可以使用%type和%rowtype属性实现使用其他变量、数据库列或表的数据类型的引用。

%type属性提供了所需要的变量的类型及长度。

%rowtype属性允许人们定义一个记录变量,它的成员变量拥有表中每一列正确的类型及长度,使用点符号引用记录中的每个成员变量。

这种动态赋值方法是非常有用的,比如变量引用的列的数据类型和大小改变了,如果使用了%TYPE,那么用户就不必修改代码,否则就必须修改代码。

CREATETABLEEMPLOYEE(

EMP_IDNUMBERNOTNULL,

EMP_NAMECHAR(20),

CREATE_DATEDATE)

DECLARE

v_studentrecordemployee%ROWTYPE;

nemployee.create_date%TYPE;

BEGIN

SELECT*

INTOv_studentrecord

FROMemployee

WHEREemp_id=1;

n:

=v_studentrecord.create_date;

DBMS_OUTPUT.put_line(n);

END;

5.内存表的使用

内存表主要作为数组用。

1):

一个字段:

PROCEDUREt1

IS

TYPEt_cISTABLEOFtesta.a1%TYPE

INDEXBYBINARY_INTEGER;

aat_c;

BEGIN

aa(0):

='aaa';

DBMS_OUTPUT.put_line(aa(0));

END;

2):

定义多个字段:

PROCEDUREt1

IS

TYPEt_rISRECORD(

t1VARCHAR(10),

t2VARCHAR(10)

);

TYPEt_tISTABLEOFt_r

INDEXBYBINARY_INTEGER;

aat_t;

BEGIN

aa(0).t1:

='aaa';

aa(0).t2:

='bbb';

DBMS_OUTPUT.put_line(aa(0).t1);

DBMS_OUTPUT.put_line(aa(0).t2);

END;

6.游标的使用

游标是用来处理使用SELECT语句从数据库中检索到的多行记录的工具。

借助于游标的功能,数据库应用程序可以对一组记录逐个进行处理,每次处理一行。

DECLARE

nNUMBER;

CURSORc

IS

SELECT*

FROMemployee;

BEGIN

FORv_cINc

LOOP

n:

=v_c.emp_id;

DBMS_OUTPUT.put_line(n);

ENDLOOP;

EXCEPTION

WHENOTHERS

THEN

DBMS_OUTPUT.put_line('error');

END;

7.跟踪调试

根踪调试主要是检查程序运行的情况,可以在需要检查程序是否执行正确作为输出的依据:

DBMS_OUTPUT.PUT_LINE(G_USERID(-2));

执行时设置:

setserveroutputon

8.临时表

临时表用于保存事务或者会话的中间结果,临时表中保存的数据只有对当时的会话是可见的,任何会话都不能看见其他会话的数据。

即使COMMIT之后也是不可见的。

对于临时表并行不是问题,即使锁定也不能阻止其他程序的访问。

每个数据库创建临时表一次,(ORACLE的DDL语句是一种消耗较大的动作)并不用每个程序创建一次,并且临时表总保持为空。

下面这个例子可以说明临时表的运行过程:

CREATEGLOBALTEMPORARYTABLEREPDB.L_EMP_DEPT_TEMP

EMP_IDVARCHAR(5),

EMP_NAMEVARCHAR(20),

DEPT_IDVARCHAR(5),

DEPT_NAMEVARCHAR(20)

1DECLARE

2DL_EMP_DEPT_TEMP%ROWTYPE;

3CURSORCIS

4SELECTE.EMP_IDAA,E.EMP_NAMEBB,D.DEPT_IDCC,D.NAMEDD

5FROML_EMPLOYEEE,L_DEPTD

6WHEREE.DEP_ID=D.DEPT_ID;

7BEGIN

8FORV_CINCLOOP

9INSERTINTOL_EMP_DEPT_TEMP

10VALUES(V_C.AA,V_C.BB,V_C.CC,V_C.DD);

11ENDLOOP;

12*END;

SQL>/

PL/SQL过程已成功完成。

SQL>SELECTCOUNT(*)

2FROML_EMP_DEPT_TEMP

3/

COUNT(*)

----------

3

SQL>COMMIT

2/

提交完成。

SQL>SELECTCOUNT(*)

2FROML_EMP_DEPT_TEMP

3/

COUNT(*)

----------

0

9.异常处理

例外是一个非致命事件,它立即中断程序的正常执行并引起一个非条件转移,跳转到当

前程序块的例外处理部分。

一些例外,像NO_DATE_FOUND或TO_MANY_ROWS,属于预定义例外用于处理常见的oracle错误,可以被认为是正常的处理部分。

部分ERROR这样的例外表明一个程序错误或一些意料之外的事件。

如下所示:

1):

正常处理的部分

1DECLARE

2NCHAR;

3BEGIN

4SELECTEMP_NAME

5INTON

6FROMEMPLOYEE;

7DBMS_OUTPUT.PUT_LINE('N');

8*END;

SQL>/

DECLARE

*

第1行出现错误:

ORA-01422:

实际返回的行数超出请求的行数

ORA-06512:

在line4

 

1DECLARE

2NCHAR;

3BEGIN

4SELECTEMP_NAME

5INTON

6FROMEMPLOYEE;

7DBMS_OUTPUT.PUT_LINE(N);

8EXCEPTIONWHENTOO_MANY_ROWSTHEN

9DBMS_OUTPUT.PUT_LINE('TOOMANYROWSRETURN');

10*END;

PL/SQL过程已成功完成。

输出结果为:

TOOMANYROWSRETURN

2):

非正常处理的部分,自定义异常

SQL>insertintol_employee

2values('4','dd','3',sysdate,'2000')

3/

insertintol_employee

*

第1行出现错误:

ORA-02291:

违反完整约束条件(REPDB.FK_EMP_DEPT)-未找到父项关键字

处理方法:

自定义异常

1declare

2eexception;

3pragmaexception_init(e,-2291);

4begin

5insertintol_employee

6values('6','dd','3',sysdate,'2000');

7exceptionwhenethen

8DBMS_OUTPUT.PUT_LINE('违反完整约束条件(REPDB.FK_EMP_DEPT)');

9*end;

SQL>/

PL/SQL过程已成功完成。

输出结果为:

违反完整约束条件(REPDB.FK_EMP_DEPT)

10.嵌套

程序块的内部可以有另一个程序块这种情况称为嵌套。

嵌套要注意的是变量,定义在最外部程序块中的变量可以在所有子块中使用,如果在子块中定义了与外部程序块变量相同的变量名,在执行子块时将使用子块中定义的变量。

子块中定义的变量不能被父块引用。

如果字块需要单独提交,应使用自

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 考试认证 > 财会金融考试

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1