初学者可以从查询到现在的pl/sql的内容都可以在我这里的笔记中找到,希望能帮到大家,视频资源在 资源,
我自己的全套笔记在 笔记
在pl/sql中可以继续使用的sql关键字有:update delete insert select--into commit rollback savepoint ,在这里需要注意的是查询跟以前有些不一样了
plsql由三个块组成:声明部分,执行部分,异常处理部分
declare:在此声明pl/sql用到的变量,类型及游标,以及局部的存储过程的和函数
begin:执行部分:过程及sql语句,即程序的主要部分
exception:执行异常部分,错误处理
end
其中执行部分是必要的
pl/sql之helloworld
set SERVEROUTPUT ON --首先必须执行此语句,否则没有输出
begin
dbms_output.put_line('hello world');
end; --下图前三个均是没有执行set serveroutput on 语句的执行结果,在执行完此语句才能有输出
其中只有begin部分,和结束end,因为此语句不需要变量声明就省去了declare部分,和exception错误部分
变量常量等的命名规则,下列标红的就是建议使用的命名的开头
实例:用pl/sql查询出tno为t001的老师的名字并输出
下面的select 语句是把查询结果放到了变量v_name中然后输出
declare
v_name TEACHER.TNAME%TYPE; --这里是动态的获取teacher表中tname字段的类型
v_tno varchar2(10);
begin
--普通查询语句 :select * from teacher where tno ='t001';
select tno,tname into v_tno,v_name from teacher where tno ='t001';
SYS.DBMS_OUTPUT.PUT_LINE(v_name||','||v_tno);
end;
记录类型:是把逻辑相关的数据作为一个单元存储起来,其作用是存放互不相同但逻辑相关的信息,类似java中一个类的概念一样
注意不能将select语句中的列赋值给布尔变量
declare
--在为一个变量赋值的时候的格式 : v_tno number(10) :=10; 自这里 “:=”是赋值,判断为=
--type 自定义名1 is record
type teacher_mas is record (
v_name TEACHER.TNAME%TYPE, --逗号
v_tno varchar2(10) --无标点符号
);
-- 定义一个记录类型的成员变量
--自定义2 自定义名1 在这就相当于创建了一个对象
v_teacher_mas teacher_mas;
--如果字段特别多的话 我们可以使用:v_teacher_mas teacher%rowtype; 表示与teacher表中的所有的类型都一直 ,下面就直接可以查询 * into v_teacher_mas 了
begin
--普通查询语句 :select * from teacher where tno ='t001';
select tno,tname into v_teacher_mas from teacher where tno ='t001';
SYS.DBMS_OUTPUT.PUT_LINE(v_teacher_mas.v_name||','||v_teacher_mas.v_tno);
end;
流程控制语句:
if 语句结构: if 《条件表达式》 then ---- end if; 相当于 java中 if() {}
if 《条件表达式》 then -- else-- end if; 相当于java中的 if(){} else {}
if 《条件表达式》 then -- els if《条件表达式》-- endif;这里是elsif 不是elseif 相当于java中的多重判断了就 :if(){} elseif (){} eles{}
实例:--查询sno为s001的学生的c001课程的成绩,如果大于60输出及格 小于60输出不及格 其他输出一般
每次的if或者elsif必须跟一个分隔符 用end if作为结束标志,当然同一个if后可以加and
declare
v_score SC.SCORE%type;
begin
select score into v_score from sc where sc.sno='s001' and CNO='c001';
if v_score<60 then SYS.DBMS_OUTPUT.PUT_LINE('不及格');
elsif v_score >=60 then SYS.DBMS_OUTPUT.PUT_LINE('及格');
else SYS.DBMS_OUTPUT.PUT_LINE('一般');
end if;
end;
case语句结构:case 值
when 表达式 then
when 表达式 then
else
end;
由于case比较恶心,sno为s001的学生的c001课程的成绩为78.9,看下查询sql,在这里case跟Java、中的switch一样
case 一个值,when 后 只能跟常量,并且 then后不能赋值,输出等,只可以返回结果
declare
v_score SC.SCORE%type;
v_mas varchar2(30);
begin
select score into v_score from sc where sc.sno='s001' and CNO='c001';
v_mas :=
case v_score when 78.9 then '及格'
when 60 then '不及格'
else '一般'
end;
SYS.DBMS_OUTPUT.PUT_LINE(v_mas);
end;
循环结构: 实例 输出1--100 用循环结构
1. loop...exit...where ....end loop
declare
v_min number(3):=1;
begin
loop
SYS.DBMS_OUTPUT.PUT_LINE(v_min);
exit when v_min >= 100;
v_min := v_min +1;
end loop;
end;
2. while<布尔表达式> loop 要执行的语句 end loop;
declare
v_i number(3):=1;
begin
while v_i <=100 loop
SYS.DBMS_OUTPUT.PUT_LINE(v_i);
v_i := v_i +1;
end loop;
end;
3. for 循环计数器 in【reverse】 上限 .. 下限 loop 要执行的语句 end loop;不要忘记上限于下限中间有两个点
每循环一次变量自动+1,使用关键字reverse自动-1 ,跟在in reverse 后面的数字必须是从小到大的顺序,而且必须是整数,不能是变量或者表达式,可以使用exit 退出循环
begin
for c in 1..100 loop
SYS.DBMS_OUTPUT.PUT_LINE(c);
end loop;
end;
标号与goto:无条件的跳到指定的标号去的意思
实例 :打印1到100 ,当打印到50的时候,打印结束循环,然后结束整个循环
declare
v_i number(3):=1;
begin
while v_i<=100 loop
if v_i=50
then goto label;
end if;
SYS.DBMS_OUTPUT.PUT_LINE(v_i);
v_i := v_i+1;
end loop;
<<label>>
SYS.DBMS_OUTPUT.PUT_LINE('结束循环');
end;
游标的使用:类似java中的迭代器Iterator,游标是一个指向上下文的句柄或指针,通过游标,可以处理多行记录
1. 显示游标处理
显示游标处理四步骤
1. 定义游标:cursor --is -- 在指定数据类型时,不能使用长度约束
2. 打开游标:open -- : 程序不能用open语句重复打开一个游标
3. 提取游标:fetch--into--
4. 关闭游标: close--
游标实例:打印出80号部门的所有员工的信息
declare
--记录类型
type emp_mas is record(
v_empid employees.employee_id%type,
v_name employees.last_name%type,
v_sal employees.salary%type
);
--记录类型对象
emp_mas_record emp_mas;
--定义游标
cursor emp_ens_mas is select employee_id,last_name,salary from employees where department_id=80;
begin
--打开游标
open emp_ens_mas;
--提取游标
fetch emp_ens_mas into emp_mas_record;
--emp_ens_mas%found 相当于java中的hashNext
while emp_ens_mas%found loop
SYS.DBMS_OUTPUT.PUT_LINE(emp_mas_record.v_empid||','||emp_mas_record.v_name||','||emp_mas_record.v_sal);
fetch emp_ens_mas into emp_mas_record;
end loop;
--关闭游标
close emp_ens_mas;
end;
2. 游标的for循环:pl/sql提供了游标for循环,自动执行游标的open,fetch,close语句和循环语句的功能,当进入循环时,游标for循环语句自动打开游标,并提取
第一行游标数据,当程序处理完当前所提取的数据而进入下一次循环时,游标for循环语句会东子提取下一行数据供程序处理,当提取完结果
集中的所有数据行后结束循环,并自动游标
格式:for 变量 in 游标 loop -----end loop;
与上题一样,打印出80号部门的所有员工的信息
declare
--定义游标
cursor emp_ens_mas is select employee_id,last_name,salary from employees where department_id=80;
begin
for c in emp_ens_mas loop
SYS.DBMS_OUTPUT.PUT_LINE(c.employee_id||','||c.last_name||','||c.salary);
end loop;
end;
3. 异常的捕获与处理
1. 预定义异常,就是已经系统定义好的一些异常,这些异常由系统自动抛出,如下
declare
v_i number(30);
begin
select salary into v_i from employees where employee_id >=100;
SYS.DBMS_OUTPUT.PUT_LINE(v_i);
end;
由于employee_id >= 100 的员工的工资返回的结果不止一个 ,所以这里就会出现 返回值太多的一场
此时就可以在exception中捕获此异常并进行处理,如果不处理的话,系统报错并且程序整体终止
declare
v_i number(30);
begin
select salary into v_i from employees where employee_id >=100;
SYS.DBMS_OUTPUT.PUT_LINE(v_i);
exception
when Too_many_rows then SYS.DBMS_OUTPUT.PUT_LINE('返回值太多了!!');
when others then SYS.DBMS_OUTPUT.PUT_LINE('其他错误!!');
end;
上面捕获的是系统预定义异常Too_many_rows ,如果产生其他不知道的异常可以使用others 进行捕获并处理
2. 非预定义异常的处理
对于非预定异常的处理,首先必须对非定义的oracle错误进行定义,步骤
1. 在pl/sql块的定义部分定义异常情况:<异常情况>exception;
2. 将其定义好的异常情况,与标准的oracle错误连接起来,使用 pragma exception_init 语句:pragma exception_init(<异常情况>,<异常代码>);
3. 在pl/sql块的异常情况处理部分对异常情况做出相应的处理
我们来删除employee_id = 100的用户
declare
begin
delete from employees where employee_id =100;
end;
这时候由于100号员工有子记录,employee_id 等于 本表的manager_id,所以删除不了
上面爆出来的错误代码 2292 没有在oracle中的预定义异常,我们这时候就只能自己定义错误名与此错误号相关联
declare
my_exception exception;
pragma exception_init(my_exception,-2292);
begin
delete from employees where employee_id =100;
exception
when my_exception then SYS.DBMS_OUTPUT.PUT_LINE('违反约束 非预定义异常!!');
end;
3. 用户自定义的异常处理
用户自定义异常是通过显示使用 raise 语句来触发的,当引发一个异常错误的时候,控制就转向到exception块异常错误部分
对于这类异常情况的处理步骤如下
1. 在pl/sql块的定义部分定义异常情况 <异常情况>exception;
2. raise <异常情况>
3. 在pl/sql块的异常情况处理部分对异常情况做出相应的处理。
实例:查询employee_id 为100 号员工的工资,如果工资>1w则抛出异常“工资高”
declare
my_exception exception;
v_i number(5) ;
begin
select salary into v_i from employees where employee_id =100;
if v_i>10000 then
raise my_exception; --出发自定义异常
end if;
exception
when my_exception then SYS.DBMS_OUTPUT.PUT_LINE('工资高!!');
end;
存储函数与存储过程
Oracle 提供可以把pl/sql程序存储在数据库中,并可以在任何地方来运行他,这样就叫存储过程或函数
过程和函数的唯一区别是函数总向调用者返回数据,而过程不返回
创建一个函数: 创建函数时如果重名直接覆盖创建
1. 建立内嵌函数
语法: create or replace function 函数名 (id number ,name varchar2)
return number
is --需要使用的变量游标等可以在这里定义
begin --函数体
exception --异常接受处理
end;
实例,写一个可以返回helloworld 的函数(无参函数)
create or replace function get_helloWorld
return varchar2
is
begin
return 'Hello World';
end;
函数创建完成调用此函数:1. select GET_HELLOWORLD from dual;
2. begin
SYS.DBMS_OUTPUT.PUT_LINE(GET_HELLOWORLD);
end;
(有参函数):create or replace function get_helloWorld(name varchar2) --不需要指定长度
return varchar2
is
begin
return 'Hello World ' || name;
end;
调用:select GET_HELLOWORLD('纯菜鸟') from dual;
2. 关于out函数:pl/sql程序可以通过out型的参数实现有多个返回值
in参数标记表示传递给函数的值在该函数执行中不改变;out标记表示一个值在函数中进行计算并通过该参数传递给调用语句,in out 标记标识传递给函数的值可以变化
并传递给调用语句。若省去标记,则参数隐含为in 。return 包含返回结果的数据类型
实例:定义一个函数,获取给定部门的工资总和 和 该部门的员工总数(定义为out类型的参数)
要求:部门号定义为参数,工资总额定义为返回值
创建函数: create or replace function get_salary(empid number,empNum out number)
return number
is
v_sal number(6) :=0;
cursor my_emp_cur is select salary from employees where department_id = empid;
begin
empNum :=0; --参数只能在函数体中赋值,如果不对请指正
for c in my_emp_cur loop
v_sal := c.salary + v_sal; --工资
empNum := empNum+1;
end loop;
return v_sal;
end;
调用函数:declare
v_count_people_number number(3);--存储人数的变量
begin
SYS.DBMS_OUTPUT.PUT_LINE( get_salary(80,v_count_people_number));
SYS.DBMS_OUTPUT.PUT_LINE(v_count_people_number);
end;
--从调用函数这就可以看到,在上面out函数中并没有显示返回人数,但是在调用的时候,Oracle会带回参数并存到自己定义的变量中,此时输出只会输出函数返回的结果,而输出待会的参数
存储过程创建:获取给定部门的工资总和(out) ,要求:部门号和工资总额定义为参数
create or replace procedure get_sal(empid number,sum_sal out number)
is
cursor my_emp_cur is select salary from employees where department_id = empid;
begin
sum_sal :=0;
for c in my_emp_cur loop
sum_sal := sum_sal+c.salary;
end loop;
end;
我们发现存储过程的语法格式与存储函数的语法格式只是相差 过程是 procedure 无return,,而函数是function 有return
调用:declare
v_count_people_number number(7);
begin
get_sal(80,v_count_people_number);
sys.dbms_output.put_line(v_count_people_number);
end;
触发器:类似过程和函数,都有声明,执行,和异常处理过程的pl/sql块,区别与存储过程,存储过程是由程序调用,而触发器是由事件触发调用,触发器不能接受参数,Oracle事件指的是对表或视图的增删改
可以在增删改操作前或者操作后进行触发,可以对每个行或语句操作上进行触发。
触发器的组成:
1. 触发事件:增删改
2. 触发时间:before after
3. 触发器本身 :
4. 触发频率:语句级(statement)触发器 和 行级(row)触发器:例如更改一个表的工资,如果更改一个人的触发一次就是行级,如果整个表更改前或后触发就是语句级
创建触发器的语法
create [or replace ] trigger 名字
before | after
insert | update | delete [of column]
on table
[for each row] --行级还是语句级的,写上的话就是行级的,不写就是语句级的
where ---
在teacher 表上的 tname 上添加触发器:当更新update tname的时候 输出:tname被更改
create or replace trigger tea_tname_up
after --事件之前被触发
update of tname on teacher --作用在teacher 表上的tname列中,也可以直接作用在表上,去掉行就行 直接on table
--不写就是语句级的,写for each row 就是行级的
begin --被触发后做的事情
SYS.DBMS_OUTPUT.PUT_LINE('tname被更改');
end;
当更新:update teacher set tname ='纯菜鸟' where tid=1; 时
:new 和 :old修饰符:比如更改表中的数据,用这两个就可以看到更新前和更新后的数据
修改上面的触发器,使其tname更改后,输出更改前的和更改后的
create or replace trigger tea_tname_up
after
update of tname on teacher
for each row --作用与每行,使用new 和old 必须加上这个
begin
SYS.DBMS_OUTPUT.PUT_LINE('修改前的:'||:old.tname||' 修改后的:'||:new.tname);
end;
更改tname:update teacher set tname ='懒蛋' where tid=1;
实例:当删除teacher 表中的数据的时候,吧删除的数据备份到 teacher_bak;
teacher中的数据
teacher_bak中的数据
触发器创建:create or replace trigger teacher_two_bak
after
delete on teacher
for each row
begin
insert into teacher_bak values (:old.tid,:old.tname);
end;
测试:delete from teacher where tid = 1;
执行完后,teacher 与 teacher_bak 中的数据分别是
......
Oracle-4 - :超级适合初学者的入门级笔记:plsql,基本语法,记录类型,循环,游标,异常处理,存储过程,存储函数,触发器的更多相关文章
-
Oracle数据库游标,序列,存储过程,存储函数,触发器
游标的概念: 游标是SQL的一个内存工作区,由系统或用户以变量的形式定义.游标的作用就是用于临时存储从数据库中提取的数据块.在某些情况下,需要把数据从存放在磁盘的表中调到计算机内存中进行处理, ...
-
Oracle-1 - :超级适合初学者的入门级笔记,CRUD,事务,约束 ......
Oracle 更改时间: 2017-10-25 - 21:33:49 2017-10-26 - 11:43:19 2017-10-27 - 19:06:57 2017-10-28 - ...
-
Oracle-3 - :超级适合初学者的入门级笔记--用户权限,set运算符,高级子查询
上一篇的内容在这里第二篇内容, 用户权限:创建用户,创建角色,使用grant 和 revoke 语句赋予和回收权限,创建数据库联接 创建用户:create user xxx identified b ...
-
Oracle-2 - :超级适合初学者的入门级笔记--定义更改约束,视图,序列,索引,同义词
接着我上一篇的写,在这感觉到哇 内容好多啊 上一篇,纯手打滴,希望给个赞! 添加约束的语法: 使用 alter table 添加或删除约束,但是不能修改约束 有效化或无效化约束 添加not nul ...
-
Oracle学习2 视图 索引 sql编程 游标 存储过程 存储函数 触发器
---视图 ---视图的概念:视图就是提供一个查询的窗口,来操作数据库中的数据,不存储数据,数据在表中. ---一个由查询语句定义的虚拟表. ---查询语句创建表 create table emp a ...
-
Oracle学习(十二):存储过程/存储函数
1.知识点 --第一个存储过程 /* 打印Hello World create [or replace] PROCEDURE 过程名(參数列表) AS PLSQL子程序体: 调用存储过程: 1. ex ...
-
oracle存储过程和存储函数&;触发器
oracle存储过程和存储函数 指存储在数据库*所有用户程序调用的子程序叫存储过程,存储函数 存储过程和存储函数的相同点:完成特定功能的程序 存储过程和存储函数的区别:是否用return语句返回值 ...
-
Java代码调用Oracle的存储过程,存储函数和包
Java代码调用存储过程和存储函数要使用CallableStatement接口 查看API文档: 上代码: java代码调用如下的存储过程和函数: 查询某个员工的姓名 月薪 职位 create or ...
-
oracle 存储过程,存储函数,包,
http://heisetoufa.iteye.com/blog/366957 认识存储过程和函数 存储过程和函数也是一种PL/SQL块,是存入数据库的PL/SQL块.但存储过程和函数不同于已经介绍过 ...
随机推荐
-
BOOST.Asio——Tutorial
=================================版权声明================================= 版权声明:原创文章 谢绝转载 啥说的,鄙视那些无视版权随 ...
-
MMORPG大型游戏设计与开发(客户端架构 part3 of vegine)
无论在何处在什么地方,我们都或多或少的接触到数学知识.特别是在客户端中,从打开界面的那一刻起就有太多与数学扯上的关联,如打开窗口的大小,窗口的位置,窗口里面的元件对象,以及UI的坐标等等.而在进入游戏 ...
-
iBatis.net入门指南
iBatis.net入门指南 - 1 - 什么是iBatis.net ? - 3 - iBatis.net的原理 - 3 - 新人指路 - 3 - iBatis.net的优缺点 ...
-
CF 13E. Holes 分块数组
题目:点这 跟这题BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊 一模一样 分析: 分块数组入门题. 具体的可以学习这篇博文以及做国家集训队2008 - 苏煜<对块状链表的一 ...
-
基于visual Studio2013解决C语言竞赛题之0514单词统计
题目 解决代码及点评 /************************************************************************/ /* 14. 有一行字 ...
-
不创建类将json数据转换
一般,取到json数据之后,都会将json数据转换为对象,通过属性取得里面的属性值,这样做可以很好地利用vs的智能提示,让开发更轻松,但是代价就是,你需要手动的创建json数据相对应的类. 也有其他方 ...
-
springboot 定时任务部署至linux服务器上后会执行两次问题
springboot定时任务在本地运行时,正常执行且只执行一次,但是在maven打包成war包,部署至linux服务器上之后,定时任务奇怪的执行了两次. 由于未做负载均衡,所以可以先排除是因为多台服务 ...
-
Gson全解析(下)-Gson性能分析
前言 在之前的学习中,我们在Gson全解析(上)Gson使用的基础到分别运用了JsonSerializer和JsonDeserializer进行JSON和java实体类之间的相互转化. 在Gson全解 ...
-
27、ArrayList和LinkedList的区别
在Java的List类型集合中,ArrayList和LinkedList大概是最常用到的2个了,细看了一下它们的实现,发现区别还是很大的,这里简单的列一下个人比较关心的区别. 类声明 ArrayLis ...
-
CentOS 系统新装每次必看,直到背下。。
1.CentOS7 mini 修改网卡信息: vi /etc/sysconfig/network-scripts/ifcfg-ens192 ONBOOT = yes vi /etc/resolv.co ...