PLSQL编程【语法、plsql控制语句、异常、游标、触发器、存储过程】

1、              PLSQL的语法–块编程

a)       概念:procedural language  struct query language

b)      PLSQL书写语法

declare

--声明块

begin

--执行块

exception—异常块

when XXX异常 then—捕获异常的语法

--异常处理

end;

c)       变量的定义

变量名[constant]数据类型 := 初始值;

d)      数据类型

Oracle数据类型:integer,number ,varchar2,char……

--声明一个变量,在变量中存储一个姓名王健,并打印欢迎王健同学来上课

declare

v_name varchar2(10);

begin

v_name :='王健';

dbms_output.put_line('欢迎'||v_name||'同学来上课!');

end;

会话输出打印开关

set serveroutput on;

--声明一个变量,在变量中存储一个姓名王健,并打印欢迎王健同学来上课

declare

v_name varchar2(10):='王健' ;

v_age  number(3):=18;

begin

--给变量v_name赋值

v_name := '&学生姓名';

v_age := &年龄;

dbms_output.put_line('欢迎'||v_name||v_age||'同学来上课!');

end;

e)       伪类型

1)      列伪类型emp.ename%type

2)      行伪类型emp%rowtype

--编写一段plsql块,完成功能把scott用户的姓名存储到v_ename变量中,工资存储到v_sal变量中并打印变量存储的值

declare

v_ename emp.ename%type; --列伪类型

v_sal  emp.sal%type;

begin

select ename,sal into v_ename,v_sal from emp where ename='SCOTT';

dbms_output.put('员工的姓名:'||v_ename);

dbms_output.put_line(',员工的工资:'||v_sal);

end;

--编写一段plsql块,完成功能把scott用户的所有信息存储并打印出来

declare

v_emprow  emp%rowtype;--行伪类型

begin

select*into v_emprow from emp where ename ='SCOTT';  dbms_output.put_line(v_emprow.empno||v_emprow.ename||v_emprow.job);

end;

f)        变量赋值有几种方式?

1.:=[初始化、语句赋值]

2.select 字段名 into 变量名 from 表

3.替代变量&变量描述

2、              PLSQL编程控制语句语法–编程思想

a)       if条件分支

if 条件 then

--操作语句

elsif条件 then

--操作语句

else

--操作语句

end if;

b)      case多分支

case 比较变量

when 比较值 then

--操作语句

when 比较值 then

--操作语句

when 比较值 then

--操作语句

when 比较值 then

--操作语句

……

else

--缺省值

end case;

c)       循环之while循环

While 循环条件

Loop

--执行语句

end loop;

d)      循环之dowhile循环 loop循环

loop

--执行语句

Exit when 退出条件

end loop;

e)       循环之for循环

For 循环变量 in 开始值..结束值

Loop

end loop;

f)        Goto :问题-多重循环跳出问题【循环不能超过三层,垃圾代码】

一、         条件分支语句

a)       简单的条件判断 if- then

--编写一个块,可以输入一个雇员名,如果该雇员的工资低于2000,就给该雇员工资增加10%

declare

v_ename emp.ename%type;

v_sal emp.sal%type;

begin

v_ename :='&雇员姓名';

select sal into v_sal from emp_bak where ename=v_ename;

if v_sal<2000then

update emp_bak set sal= sal*1.1where ename=v_ename;

endif;

end;

a)       二重条件分支 if then else

--编写一个块,可以输入一个雇员名,如果该雇员的补助不是0就在原来的基础上增加100;如果补助为0就把补助设为200

--编写一个块,可以输入一个雇员名,如果该雇员的补助不是0就在原来的基础上增加100;

--如果补助为0就把补助设为200

declare

v_ename emp.ename%type;

v_comm emp.comm%type;

declare

v_ename emp.ename%type;

v_comm emp.comm%type;

begin

v_ename :='ALLEN';

select nvl(comm,0)into v_comm from emp_bak where ename=v_ename;

if v_comm<>0then

update emp_bak set comm = comm+100where ename = v_ename;

else

update emp_bak set comm =200where ename = v_ename;

endif;

end;

b)      多重条件分支 if-then elsif – else[CASE 实现]

--编写一个块,可以输入一个雇员编号,如果该雇员的职位是PRESIDENT就给他的工资增加1000,如果该雇员的职位是MANAGER就给他的工资增加500,其它职位的雇员工资增加200

二、         循环语句– loop

编写一个过程,可输入用户名,并循环添加10个用户到users表中,用户编号从1开始

--编写一个过程,可输入用户名,并循环添加10个用户到users表中,用户编号从1开始

 

 

3、              异常【系统异常、通用异常、自定义异常、应用程序异常】

a)       系统异常

--使用替代变量输入数据,实现向emp表插入数据,并在插入前检查是不是违反主键约束,

declare

v_empno emp.empno%type;

v_ename emp.ename%type;

v_sal  emp.sal%type;

begin

v_empno :=&empno;

v_ename :='&ename';

v_sal :=&sal;

insertinto emp_bak(empno,ename,sal)values(v_empno,v_ename,v_sal);

exception

when Dup_val_on_index then

dbms_output.put_line('员工编号已经存在!');

end;

b)      通用异常【others】SQLCode异常编码  sqlerrm异常错误消息

--查询?部门的所有员工打印结果

declare

v_emprow emp%rowtype;

v_deptno emp.deptno%type;

begin

v_deptno :=&deptno;

select*into v_emprow from emp where deptno = v_deptno;

exception

/*

    when No_data_found then

      dbms_output.put_line('输入的部门不存在!');

      when Too_many_rows then

          dbms_output.put_line('返回的行数太多!');

          */

whenothersthen

dbms_output.put_line('错误编号:'||SQLCode||',错误信息:'||SQLErrM);

end;

c)       自定义异常

--编写PLSQL块,完成限制输入的数字范围1到10,并正确处理异常

declare

v_num number(2);

--1、定义一个异常

MY_ERR exception;

begin

v_num :=0;

--2、经过判断后抛出异常.

if v_num <1or v_num >10then

raise MY_ERR;

endif;

dbms_output.put_line(v_num);

--3、捕获异常

exception

when MY_ERR then

dbms_output.put_line('输入的数字必须在1~10之间');

end;

d)      应用程序异常反馈

pragma exception_init(异常名称,sqlcode);

raise_application_error(sqlcode,sqlerrm) sqlcode错误编码-20000  ~  -20999

declare

v_num number(2);

--1、定义一个异常

MY_ERR exception;

pragmaexception_init(MY_ERR,-20001);

begin

v_num :=0;

--2、经过判断后抛出异常.

if v_num <1or v_num >10then

raise_application_error(-20001,'输入的数字必须在1~10之间');

endif;

dbms_output.put_line(v_num);

--3、捕获异常

exception

whenothersthen

dbms_output.put_line('错误编号:'||SQLCode||',错误信息:'||SQLErrM);

end;

4、              游标cursor-处理多行数据

a)       隐式游标sql

b)      显式游标

c)       动态游标(REF游标)

d)      公有属性

%found 影响一行或多行数据的时候此属性为true

%notfound 没有影响行数此属性为true

%rowcount  行数

%isopen  游标的打开

e)       案例一:隐式游标-修改scott的工资为2000块

--隐式游标-查询SCOTT的工资并进行打印

declare

v_sal emp.sal%type;

begin

select sal into v_sal from emp where ename ='SCOTT';

ifsql%foundthen

dbms_output.put_line(sql%rowcount);

endif;

end;

--隐式游标-修改30号部门的工资为2000块

Begin

update emp_bak set sal =2000where deptno =30;

ifsql%foundthen

dbms_output.put_line(sql%rowcount);

else

dbms_output.put_line(‘输入的部门编号不存在!’);

endif;

end;

f)        案例二:显式游标-查询30号所有员工信息

--查询30部门所有员工信息

declare

v_emprow emp%rowtype;

--定义游标

cursor cur_erow  isselect*from emp where deptno =30;

begin

--获取游标

for v_emprow in cur_erow

loop

dbms_output.put_line('雇员姓名:'||v_emprow.ename);

endloop;

end;

案例三:带参显式游标 -显式游标-查询?号所有员工信息

--查询30部门所有员工信息

declare

v_emprow emp%rowtype;

--定义游标

cursor cur_erow(v_deptno emp.deptno%type)isselect*from emp where deptno = v_deptno;

begin

--获取游标

for v_emprow in cur_erow(&deptno)

loop

dbms_output.put_line('雇员姓名:'||v_emprow.ename);

endloop;

end;

练习:将score_bak表中的每个学生的成绩改成这门课的平均成绩

declare

v_vwrow vw_avg_scr%rowtype;

cursor cur_avg isselect*from vw_avg_scr;

begin

for v_vwrow in cur_avg

loop

update score_bak set scr = v_vwrow.avg_scr where cno = v_vwrow.cno;

endloop;

end;

g)       案例四:loop循环游标

--查询30号部门所有员工信息

declare

v_erow emp%rowtype;

--定义游标

cursor cur_erow isselect*from emp where deptno =30;

begin

--打开游标

open cur_erow;

--获取游标

loop

fetch cur_erow into v_erow;

dbms_output.put_line('员工姓名:'||v_erow.ename);

exitwhen cur_erow%notfound;

endloop;

--关闭游标

if cur_erow%isopenthen

close cur_erow;

endif;

end;

h)      案例五:动态游标/ref游标

--使用动态游标打印员工信息和部门信息

declare

v_erow emp%rowtype;

v_drow dept%rowtype;

--1、定义一个动态游标类型

--弱类型的动态游标

type cur1 isrefcursor;

--强类型的动态游标

type cur2 isrefcursorreturn emp%rowtype;

--2、使用动态游标类型定义一个动态游标

cur_row  cur1;

begin

--3、打开游标并给游标赋值

open cur_row forselect*from emp;

--4、使用loop循环获取游标

dbms_output.put_line('员工信息:');

loop

fetch cur_row into v_erow;

dbms_output.put_line(v_erow.ename);

exitwhen cur_row%notfound;

endloop;

--5、关闭游标

if cur_row%isopenthen

close cur_row;

endif;

--6、重新打开游标并重新给游标赋值

open cur_row forselect*from dept;

--7、使用loop循环获取游标

dbms_output.put_line('部门信息:');

loop

fetch cur_row into v_drow;

dbms_output.put_line(v_drow.dname);

exitwhen cur_row%notfound;

endloop;

--8、关闭游标

if cur_row%isopenthen

close cur_row;

endif;

end;

1、             
Oracle的自定义函数

2、             
Oracle的触发器

3、             
Oracle的存储过程

知识点一:自定义函数

语法:create [or replace] function 函数名(参数)

return返回值类型—必须

is

--变量的声明

begin

--执行语句

--return 返回变量

--exception 异常块(return 异常编号)

end;

Java:

int add(int
no1,int no2)

{

int sum = no1+no2;

return sum;

}

Oracle

--使用PLSQL developer创建自定义函数,实现两个数字相加

createorreplacefunction fun_add(num1 number,num2 number)

returnnumber

is

v_result number(2);

begin

  v_result := num1+num2;

return v_result;

 

exception

whenothersthen

            
dbms_output.put_line
('输入错误!');

return-1;

end;

调用函数

方式一:

select
fun_add(50,50) from dual;

方式二:

declare

v_num1 number(2);

v_num2 number(2);

v_result number(2);

begin

  v_num1 :=&加数1;

  v_num2 :=&加数2;

  v_result := fun_add(v_num1,v_num2);

 

 
dbms_output.put_line
(v_result);

exception

whenothersthen

              
dbms_output.put_line
('输入的数据有误!!');

end;

2017-10-31 18:36:17

05-11 22:59