PL/SQL之高级篇

原文地址:http://www.cnblogs.com/sin90lzc/archive/2012/08/30/2661117.html

参考文献:《Oracle完全学习手册》

1.概述

本文主要介绍PL/SQL中的有名程序块:存储过程、函数、包头/包体及触发器的使用。而这些的基础是PL/SQL无名块的编写,这在PL/SQL之基础篇 中已经讲述过了。

这四种程序块到底是什么东西呢?

存储过程可以认为它是一个无返回值的函数(排除参数返回);

函数则是一个带返回值的函数,但函数只能用于表达式中,不能像存储过程那样直接调用;

包头/包体与Java中的接口/实现类比较的话,包头就好比接口,而包体就好比实现类。

触发器则可以认为是一个事件处理函数,它能在某个事件发生时自动地执行。

2.存储过程

2.1存储过程的创建及修改

语法:

复制代码
CREATE [OR REPLACE] PROCEDURE procedure_name
[(parameter_name [IN | OUT | IN OUT] datatype [{(:= | DEFAULT ) defaultvalue}] [, ...])]
{IS | AS}
BEGIN
procedure_body
END procedure_name;
复制代码

语法解析:

IN:输入参数;

OUT:输出参数;

IN OUT:即可输入也可输出的参数;

datatype:参数的数据类型,此处不能带精度。

:=|DEFAULT:用于设置参数的默认值。

 

Example:

复制代码
--注意,在声明参数类型时,不能带精度,如VARCHAR2(20)后面的(20)
CREATE OR REPLACE PROCEDURE test_procedure(name IN VARCHAR2 default 'Tim',age IN NUMBER :=20,sex IN OUT VARCHAR2,realname OUT VARCHAR2)
ISrn VARCHAR2(10) default 'Tim Leung';
BEGINIF name='Tim' THENrealname:=rn;END IF;IF sex='1' THENsex:='男';ELSEsex:='女';END IF;DBMS_OUTPUT.PUT_LINE(name || ' age:'||age||' sex:'||sex||' realname:'||realname);
END test_procedure;
复制代码

 

2.2 过程的调用

复制代码
declare result_sex varchar(3):='1';result_rn varchar(10) default null;
begintest_procedure('Tim',sex => result_sex,age => 20,realname => result_rn);--可以使用符号=>来传参DBMS_OUTPUT.PUT_LINE('sex:'||result_sex);DBMS_OUTPUT.PUT_LINE('realname:'||result_rn);
end;/*运行结果:
Tim age:20 sex:男 realname:Tim Leung
sex:男
realname:Tim Leung
*/
复制代码

 

2.3 删除过程

复制代码
DROP PROCEDURE test_procedure;
复制代码

 

3.函数

过程用来完成一项任务,可能不返回值,也可能返回多个值,过程的调用是一条PL/SQL语句;函数包含RETURN子句,用来进行数据操作,并返回一个单独的函数值,函数的调用只能在一个表达式中

3.1创建及修改函数

语法:

复制代码
CREATE [OR REPLACE] FUNCTION function_name
[(parameter1 {IN | OUT | IN OUT} datatype] [,...])]
RETURN datatype
{ IS | AS }
BEGIN
function_body
END function_name;
复制代码

 

Example:

复制代码
CREATE OR REPLACE FUNCTION test_function(name IN VARCHAR2 default 'Tim',age IN NUMBER :=20,sex IN OUT VARCHAR2,realname OUT VARCHAR2)
RETURN VARCHAR2
ISrn VARCHAR2(10) default 'Tim Leung';
BEGINIF name='Tim' THENrealname:=rn;END IF;IF sex='1' THENsex:='男';ELSEsex:='女';END IF;RETURN (name || ' age:'||age||' sex:'||sex||' realname:'||realname);
END test_function;
复制代码

 

3.2调用函数

复制代码
declare result_sex varchar(3):='1';result_rn varchar(10) default null;
begin--可以使用符号=>来传参DBMS_OUTPUT.PUT_LINE(test_function('Tim',sex => result_sex,age => 20,realname => result_rn));
end;/*运行结果:
Tim age:20 sex:男 realname:Tim Leung
*/
复制代码

 

 

4.包头/包体

4.1包头创建及修改

语法:

复制代码
CREATE [OR REPLACE] PACKAGE package_name
{ IS | AS }
package_specification  --存储过程,函数,变量声明部分
END package_name;
复制代码

 

Example:

复制代码
CREATE OR REPLACE PACKAGE test_package
IS
v_name VARCHAR2(20);--声明公有变量
PROCEDURE getName(id NUMBER);--声明过程getName
PROCEDURE getName(p_name VARCHAR2);--声明重载过程getName
FUNCTION getAge RETURN NUMBER;--声明函数getAge
END test_package;
复制代码

 

4.2包体的创建及修改

语法:

复制代码
--包体名必须与包头名一致!
CREATE [OR REPLACE] PACKAGE BODY package_name
{ IS | AS}package_implement  --存储过程,函数实现部分BEGINpackage_init  --包初始化部分,在包被第一次调用时执行END;
--注意!!!包体不能有END;子句
复制代码

 

Example:

复制代码
CREATE OR REPLACE PACKAGE BODY test_package IS --包体名与包头名要一致/*创建私有过程output,以供其他过程或函数调用,必须在其他过程或函数调用前创建*/PROCEDURE output(output_str VARCHAR2) ISBEGINDBMS_OUTPUT.PUT_LINE(output_str);END output;/*创建公有过程getName*/PROCEDURE getName(id NUMBER) ISBEGINoutput('do getName('||id||')');END getName;/*重载过程getName,重载的意思即有相同的过程名或函数名,相同的返回类型,不同的参数列表!*/PROCEDURE getNAME(p_name VARCHAR2) ISBEGINoutput('do getNAME('||p_name|| ')!');END getNAME;/*创建函数getAge*/FUNCTION getAge RETURN NUMBER ISBEGINRETURN 20;END getAge;/*包的初始化块,在包被第一次调用时执行。初始化块只能在包体的末尾编写*/BEGINv_name:='Tim';END;--注意!!包体不能有END;子句
复制代码

 

4.3 包的调用

复制代码
declare 
beginDBMS_OUTPUT.PUT_LINE(test_package.v_name);test_package.getName(10);test_package.getName('Tim');DBMS_OUTPUT.PUT_LINE('getAge:' || test_package.getAge);
end;/*运行结果:
Tim
do getName(10)
do getNAME(Tim)!
getAge:20
*/
复制代码

 

5.触发器

5.1触发器的分类

触发器主要有DML触发器、替代触发器、系统触发器及DDL触发器几种类型。

  • DML触发器
    DML触发器可以处理INSERT、UPDATE和DELETE事件。DML触发器可以在语句级或行级操作上被触发,语句级触发器对于每一个SQL语句只触发一次,行级触发器对SQL语句受影响的表中的每一行都触发一次

  • 替代触发器
    替代触发器主要针对处理视图的DML操作事件(INSERT、UPDATE和DELETE)。替代触发器只能在行级操作上被触发,不能在语句级上被触发。

  • 系统触发器
    分为数据库级(Database)和模式级(Schema)两种。数据库级触发器的触发事件对于所有用户都有效,模式级触发器仅被指定模式的用户触发。系统触发器支持的触发事件有:LOGON、LOGOFF、SERVERERROR、STARTUP和SHUTDOWN。

  • DDL触发器
    即由DDL语句(CREATE、ALTER或DROP等)触发的触发器。

5.2创建及修改触发器

语法:

复制代码
CREATE [OR REPLACE] TRIGGER trigger_name
{BEFORE | AFTER | INSTEAD OF} trigger_event
ON event_target
[FOR EACH ROW]
[WHEN condition]
BEGINtrigger_body
END trigger_name;
复制代码

 

语法解析:

INSTEAD OF:仅用于替代触发器,即event_target必须为视图,而且必须带FOR EACH ROW子句

trigger_event:触发的事件。可以是DML事件(INSERT、UPDATE、DELETE、INSERT OR UPDATE、UPDATE OF column_name),系统事件(STARTUP、SHUTDOWN等)。

event_target:即指trigger_event事件是发生在哪个对象上的。如DML事件,那么event_target应该是表名或视图名,如果是系统事件,那么event_target就应该是DATABASE或SCHEMA

FOR EACH ROW:如果带此子句,即表示该触发器是行级触发器,如果省略,则是语句级触发器。

WHEN condition :用于限制行级触发器,只有满足condition条件,才会触发触发器。

Example:

复制代码
CREATE OR REPLACE TRIGGER test_trigger
AFTER INSERT OR UPDATE OF sal OR DELETE 
ON emp
FOR EACH ROW
BEGINCASEWHEN INSERTING THEN  --当事件为INSERT时,INSERTING为TRUE/*:NEW关键字可以获取新记录的数据,它只能用于行级触发器*/DBMS_OUTPUT.PUT_LINE('INSERT INTO EMP VALUES('||:NEW.empno||','||:NEW.ename||','||:NEW.job||','||:NEW.mgr||','||:NEW.hiredate||','||:NEW.sal||','||:NEW.comm||','||:NEW.deptno||')');WHEN UPDATING THEN  --当事件为UPDATE时,UPDATING为TRUEDBMS_OUTPUT.PUT_LINE('UPDATING emp which empno='||:OLD.empno||'to sal:'||:NEW.sal);--:OLD关键字可以获取旧记录的数据,它只能用于行级触发器WHEN DELETING THEN  --当事件为DELETE时,DELETING为TRUEDBMS_OUTPUT.PUT_LINE('DELETING emp which empno='||:OLD.empno);--:OLD关键字可以获取旧记录的数据,它只能用于行级触发器ELSENULL;END CASE;
EXCEPTIONWHEN DUP_VAL_ON_INDEX THENNULL;WHEN OTHERS THENRAISE_APPLICATION_ERROR(SQLCODE,SQLERRM);
END test_trigger;
复制代码

 

执行DML操作触发上面的触发器,效果如下:

5.3修改触发器的状态

触发器有ENABLED和DISABLED两种状态。

修改某个触发器的状态可以执行下面的SQL:

复制代码
ALTER TRIGGER trigger_name ENABLE | DISABLE;
复制代码

 

使某个表上的所有触发器有效或无效:

复制代码
ALTER TABLE table_name {ENABLE | DISABLE} ALL TRIGGERS;
复制代码

 

5.4删除触发器

复制代码
DROP TRIGGER trigger_name;
复制代码

转载于:https://www.cnblogs.com/m-xy/p/3276838.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/400250.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

下拉四级联动插件

http://www.jq22.com/jquery-info6023

Charles使用

主要还是移动端的使用技巧 常规使用:同一个wifi,设备开启代理,地址写本机,端口看Charles中的设置 下面说点不怎么常用但是蛮有用的 1.https 这个应该是蛮容易遇到的,设置其实也是蛮简单的 先来看下,未设置之…

最短路打印路径

#include <iostream>#include<string.h>#include<stack>#define M 100#define N 100using namespace std;typedef struct node{ int matrix[N][M]; //邻接矩阵 int n; //顶点数 int e; //边数 }MGraph; boo…

JS实现的五级联动菜单效果完整实例

https://www.jb51.net/article/106525.htm 本文实例讲述了JS实现的五级联动菜单效果。分享给大家供大家参考&#xff0c;具体如下&#xff1a; js实现多级联动的方法很多&#xff0c;这里给出一种5级联动的例子&#xff0c;其实可以扩展成N级联动,在做项目的时候碰到了这样一…

【RK3399Pro学习笔记】十五、ROS中launch启动文件的使用方法

目录Launch文件语法<launch><launch><launch><node><node><node>参数设置<param>/<rosparam><param>/<rosparam><param>/<rosparam><arg><arg><arg><remap><remap><…

关于有多少个1的计算

1、题目 输入一个十进制的数&#xff0c;输出 &#xff08;1&#xff09;、给定n&#xff0c;求出从1到n的所有整数中1的个数。&#xff08;暂用用f(n)表示&#xff09; &#xff08;2&#xff09;、求满足nf(n)的最小整数&#xff08;1除外&#xff09;。 #include <ios…

ABP+AdminLTE+Bootstrap Table权限管理系统第八节--ABP错误机制及AbpSession相关

返回总目录:ABPAdminLTEBootstrap Table权限管理系统一期 上一节我们讲到登录逻辑,我做的登录逻辑很简单的,我们来看一下abp module-zero里面的登录代码. #region Login / Logoutpublic ActionResult Login(string returnUrl ""){if (string.IsNullOrWhiteSpace(ret…

JQuery DataTables Editor---只修改页面内容

https://www.cnblogs.com/zjf1987/p/Editor.html

关于JAVA_HOME, CLASSPATH和PATH的设置

http://bbs.csdn.net/topics/120079565 1、PATH&#xff0c;这个是给WINDOWS操作系统用的&#xff0c;告诉命令行里&#xff0c;执行的命令行工具在那里&#xff0c;比如java,javac这都是命令行工具,你在运行里随便敲一个命令&#xff0c;操作系统怎么就知道你这个命令对应的程…

P2327 [SCOI2005]扫雷

题目描述 输入输出格式 输入格式&#xff1a; 第一行为N&#xff0c;第二行有N个数&#xff0c;依次为第二列的格子中的数。&#xff08;1< N < 10000&#xff09; 输出格式&#xff1a; 一个数&#xff0c;即第一列中雷的摆放方案数。 输入输出样例 输入样例#1&#xff…

天津海运[600751]股票

2019独角兽企业重金招聘Python工程师标准>>> 天津海运[600751]股票 转载于:https://my.oschina.net/chworld/blog/425583

【RK3399Pro学习笔记】十六、ROS中的常用可视化工具

目录测试rqt_consolerqt_graphrqt_plotrqt_image_viewrqtrvizgazebo平台&#xff1a;华硕 Thinker Edge R 瑞芯微 RK3399Pro 固件版本&#xff1a;Tinker_Edge_R-Debian-Stretch-V1.0.4-20200615 记录自【古月居】古月ROS入门21讲 | 一学就会的ROS机器人入门教程 —— 古月居G…

datatables 基本增删改查(php)

http://www.datatables.club/example/user_share/basic_curd.html

基于leveldb,levigo做二次开发

Leveldb是一个C库&#xff0c;它有提供标准的C接口&#xff0c;头文件在include/leveldb/c.h中 levigo是leveldb 的一个go wrapper,它主要基于Leveldb中inlude/leveldb/c.h提供的方法做二次开发 开发过程&#xff0c;以添加一个简单的计算功能为例&#xff1a; 修改leveldb源码…

Cocos2d-x 3.2:通过ClippingNode实现一个功能完善的跑马灯公告(1)

Cocos2d-x 3.2&#xff1a;通过ClippingNode实现一个功能完善的跑马灯公告&#xff08;1&#xff09; 本文转载至深入理解Cocos2d-x 3.x&#xff1a;一步一步通过ClippingNode实现一个功能完善的跑马灯公告&#xff08;1&#xff09; 这篇文章主要是通过一步一步实现一个功能完…

option columns.render 渲染列(1) 添加checkbox

http://www.datatables.club/manual/daily/2016/04/25/option-columns-render1.html

【STC15库函数上手笔记】1、建立工程

目录新建工程添加文件到工程中main.c时钟STC实验箱4 IAP15W4K58S4 Keil uVision V5.29.0.0 PK51 Prof.Developers Kit Version:9.60.0.0 在STC官网发现了库函数&#xff0c;大受震撼&#xff1a; 宏晶科技官方网站 直接搜“库函数”&#xff0c;目前仅有STC15和STC8系列有库函…

vsUnit单元测试

在自定义的方法名上【右键】然后选择【创建单元测试】&#xff0c;之后在项目中就添加了一个单元测试的项目&#xff0c;找到对应的单元测试的方法[TestMethod()]特性修饰&#xff0c;将单元测试的方法中最后一句&#xff1a;Assert.Inconclusive("验证此测试方法的正确性…

hdu 6086 Rikka with String(AC自动机+状压dp)

题目链接&#xff1a;hdu 6086 Rikka with String 题意&#xff1a; 给你n个只含01的串&#xff0c;和一个长度L,现在让你构造出满足s[i]≠s[|s|−i1] for all i∈[1,|s|] &#xff0c;长度为2L&#xff0c;并且包含给出的n个串&#xff0c;问能有多少种这样的串。 题解&#x…

简单文件传输TFTP服务器搭建 Linux RHEL6

Tftp 的应用场合1、交换机或路由器升级或备份2、无盘工作站 存放boot loader3、嵌入式开发时装载系统4、大规模的服务安装布署安装1、# yum install xinetd# yum install -y tftp-server2、检查是否开机启动# chkconfig --list | grep xinetxinetd 0:off 1:off 2:…