1. 概述
1.1 SQL Developer安装
见安装文件
1.2 PL/SQL的作用和第一个PL/SQL程序
-- 给员工涨工资 -- 总裁涨1000 -- 经理涨800 -- 其他员工涨400 plsql的作用: 操作oracle数据库效率最高 为后面存储过程打基础 -- 打印 hello world declare -- 说明部分(变量,光标或者例外) begin -- 程序体 dbms_output.put_line(‘Hello World‘); end; -- 打开输出开关 set serveroutput on
1.3 PL/SQL简介
PL/SQL(Procedure Language SQL) PL/SQL是Oracle对sql语言的过程化扩展 指在SQL命令语言中增加了过程处理语句(如分支、循环等),使SQL语言具有过程处理能力。 面向过程 不同数据库的SQL扩展 Oracle :PL/SQL DB2:SQL/PL SQL Server: Transac-SQL(T-SQL)
2. PL/SQL基础语法
2.1 PL/SQL基本变量类型
-- PL/SQL的程序结构 declare -- 说明部分(变量说明,光标声明或者例外说明) begin -- 语句序列(DML语句) exception -- 例外处理语句 end; -- 说明部分 -- 定义基本变量 类型:char varchar2 date number boolean long 举例: var1 char(15); married boolean := true; psal number(7,2); declare pnumber number(7,2); pname varchar(20); pdate date; begin pnumber:=1; DBMS_OUTPUT.put_line(pnumber); pname:=‘Tom‘; DBMS_OUTPUT.put_line(pname); pdate:=sysdate; DBMS_OUTPUT.put_line(pdate); --计算明天的日期 DBMS_OUTPUT.put_line(pdate+1); end;
2.2 PL/SQL引用型变量和记录型变量
-- 引用型变量 -- 举例 my_name emp.ename%type; set serveroutput on declare -- 定义引用型变量,查询并打印7839的项目和薪水 -- pname varchar2(20); -- psal number; pname emp.ename%type; psal emp.sal%type; begin --得到7839的姓名和薪水 select ename,sal into pname,psal from emp where empno=7839; -- 打印姓名和薪水 dbms_output.put_line(pname||‘的薪水是‘||psal); end; -- 记录型变量 -- 举例 emp_rec emp%rowtype; -- 记录型变量分量的引用 emp_rec.ename := ‘ADAMS‘; set serveroutput on declare -- 定义记录型变量,查询并打印7839的项目和薪水 emp_rec emp%rowtype; begin --得到7839的姓名和薪水 select * into emp_rec from emp where empno=7839; -- 打印姓名和薪水 dbms_output.put_line(emp_rec.ename||‘的薪水是‘||emp_rec.sal); end;
2.3 PL/SQL中if语句的使用
1. IF 条件 THEN 语句1; 语句2; END IF; 2. IF 条件 THEN 语句序列1; ELSE 语句序列2; END IF; 3. IF 条件 THEN 语句; ELSIF 语句 THEN 语句; ELSE 语句; END IF; -- 判断用户从键盘输入的数字 set serveroutput on accept num prompt ‘请输入一个数字‘; declare pnum number :=# begin if pnum=0 then dbms_output.put_line(‘你输入的数字是0‘); elsif pnum=1 then dbms_output.put_line(‘你输入的数字是1‘); elsif pnum=2 then dbms_output.put_line(‘你输入的数字是2‘); elsif pnum=3 then dbms_output.put_line(‘你输入的数字是3‘); elsif pnum=4 then dbms_output.put_line(‘你输入的数字是4‘); elsif pnum=5 then dbms_output.put_line(‘你输入的数字是5‘); elsif pnum=6 then dbms_output.put_line(‘你输入的数字是6‘); elsif pnum=7 then dbms_output.put_line(‘你输入的数字是7‘); elsif pnum=8 then dbms_output.put_line(‘你输入的数字是8‘); elsif pnum=9 then dbms_output.put_line(‘你输入的数字是9‘); else dbms_output.put_line(‘你输入的为其他数字‘); end if; end;
2.4 PL/SQL循环语句的使用
1. WHILE total<=25000 LOOP ... total := total+salary; END LOOP; eq: set serveroutput on declare pnum number :=1; begin while pnum <=10 loop dbms_output.put_line(pnum); pnum := pnum+1; end loop; end; 2. Loop EXIT [ WHEN 条件 ]; ... End loop; -- 推荐使用这种循环 eq: set serveroutput on declare pnum number :=1; begin loop exit when pnum>10; dbms_output.put_line(pnum); pnum:=pnum+1; end loop; end; 3. FOR I IN 1..3 LOOP 语句序列; END LOOP; eq: set serveroutput on declare pnum number:=1; begin for pnum in 1..10 loop dbms_output.put_line(pnum); end loop; end;
3. 光标(游标)
3.1 PL/SQL光标之光标的引入
-- 给员工涨工资 -- 总裁涨1000 -- 经理涨800 -- 其他员工涨400 set serveroutput on declare ptilte varchar(20); begin select job into ptilte from emp; if ptilte =‘PRESIDENT‘ then update emp set sal=sal + 1000; elsif ptilte =‘MANAGER‘ then update emp set sal=sal + 800; else update emp set sal=sal + 400; end if; end; -- error 光标 就是一个结果集(Result Set)
3.2 PL/SQL光标之光标的语法和第一个实例
-- 光标的语法 CURSOR 光标名 [(参数名 数据类型 [,参数名 数据类型] ... )] IS SELECT 语句; -- 一个具体的光标 cursor c1 is select ename from emp; -- 从光标中取值 -- 打开光标 执行查询 open c1; -- 关闭光标 释放资源 close c1; -- 取一行光标的值 fetch c1 into pename; fetch 的作用: 把当前指针指向的记录返回 将指针指向下一条记录 --光标的属性 %found %notfound -- 使用光标查询员工姓名和工资,并打印 set serveroutput on declare cursor cemp is select ename,sal from emp; pename emp.ename%type; psal emp.sal%type; begin open cemp; loop fetch cemp into pename,psal; exit when cemp%notfound; dbms_output.put_line(pename||‘的薪水是‘||psal); end loop; close cemp; end;
3.3 实例:给员工涨工资
-- 给员工涨工资 -- 总裁涨1000 -- 经理涨800 -- 其他员工涨400 set serveroutput on declare cursor cemp is select empno,empjob from emp; pempno emp.empno%type; pjob emp.empjob%type; begin rollback; open cemp; loop fetch cemp into pempno,pjob; exit when cemp%notfound; if pjob=‘PRESIDENT‘ then update emp set sal =sal+1000; elsif pjob=‘MANAMGR‘ then update emp set sal =sal+800; else update emp set sal =sal+400; end if; end loop; close cemp; -- 对于oracle,默认的事务隔离级别是 read committed commit; -- 事务提交 dbms_output.put_line(‘涨工资完成‘); end;
3.4 PL/SQL光标之光标的属性和光标数的限制
--光标的属性 %found -- true false %notfound %isopen -- 判断光标是否打开 打开为true 否则为false %rowcount -- 影响的行数 -- 光标数的限制 默认情况下,oracle数据库只允许在同一个会话中,打开300个光标 show parameter cursor NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ cursor_sharing string EXACT cursor_space_for_time boolean FALSE open_cursors integer 300 session_cached_cursors integer 50 修改光标数的限制 alter system set open_cursors =400 scope=both; scope的取值: both menory spfile(数据库需要重启) -- eq set serveroutput on declare cursor cemp is select empno,empjob from emp; pempno emp.empno%type; pjob emp.empjob%type; begin open cemp; if cemp%isopen then dbms_output.put_line(‘光标已经打开‘); else dbms_output.put_line(‘光标没有打开‘); end if; loop fetch cemp into pempno,pjob; exit when cemp%notfound; dbms_output.put_line(‘rowcount:‘||cemp%rowcount); end loop; close cemp; end;
3.5 PL/SQL光标之带参数的光标
CURSOR 光标名 [(参数名 数据类型 [,参数名 数据类型] ... )] IS SELECT 语句; -- 查询某个部门中员工的姓名 set serveroutput on declare cursor cemp(dno number) is select ename from emp where deptno=dno; pename emp.ename%type; begin open cemp(10); loop fetch cemp into pename; exit when cemp%notfound; dbms_output.put_line(pename); end loop; close cemp; end;
4. 例外(异常)
4.1 例外的概念和系统例外
例外是程序设计语言提供的一种功能,用来增强程序的健壮性和容错性 系统例外 no_data_found 没有找到数据 too_many_rows select...into语句匹配多个行 zero_divide 被零除 value_error 算术或装换错误 timeout_on_resource 在等待资源时发生超时 自定义例外
4.2 系统例外之no_data_found
-- 没有找到数据 set serverout on declare pename emp.ename%TYPE; begin -- 查询员工号是1234的员工姓名 select ename into pename from emp where empno=1234; exception when no_data_found then DBMS_OUTPUT.PUT_LINE(‘没有找到该员工‘); when others then DBMS_OUTPUT.PUT_LINE(‘其他例外‘); end; /
4.3 系统例外之too_many_rows
-- select...into语句匹配多个行 set serverout on declare pename emp.ename%TYPE; begin -- 查询所有10号部门的员工姓名 select ename into pename from emp where deptno=10; exception when too_many_rows then DBMS_OUTPUT.PUT_LINE(‘select...into语句匹配多个行‘); when others then DBMS_OUTPUT.PUT_LINE(‘其他例外‘); end; /
4.4 系统例外之zero_divide
-- 被零除 set serverout on declare pnum number; begin pnum:=1/0; exception when zero_divide then DBMS_OUTPUT.PUT_LINE(‘0不能做除数‘); DBMS_OUTPUT.PUT_LINE(‘被零除‘); when others then DBMS_OUTPUT.PUT_LINE(‘其他例外‘); end; /
4.5 系统例外之value_error
-- 算术或转换错误 set serverout on declare pnum number; begin pnum:=‘abc‘; exception when value_error then DBMS_OUTPUT.PUT_LINE(‘算术或转换错误‘); when others then DBMS_OUTPUT.PUT_LINE(‘其他例外‘); end; /
4.6 自定义例外
定义变量,类型是exception 使用raise 抛出自定义例外 -- 查询50号部门的员工姓名 set serverout on declare cursor cemp is select ename from emp where deptno=50; pename emp.ename%type; no_emp_found exception; begin open cemp; fetch cemp into pename; if cemp%notfound then raise no_emp_found; end if; close cemp; exception when no_emp_found then DBMS_OUTPUT.PUT_LINE(‘没有找到员工‘); when others then DBMS_OUTPUT.PUT_LINE(‘其他例外‘); end; /
5. 案例集锦
5.1 运用瀑布模型完成PLSQL程序的设计
需求分析 设计(1.概要设计 2. 详细设计) 编码(codeing) 测试 (testing) 上线 SQL语句 变量:1.初始值是多少 2.最终值如何得到
5.2 案例:统计每年入职的员工人数
SQL语句: select to_char(hiredate,‘yyyy‘) from emp; -> 光标-> 循环-> 退出条件:notfound 变量: 初始值 最终值如何得到 每年入职的员工人数 count80 number:=0; count81 number:=0; count82 number:=0; count87 number:=0; ---------------------------------------------------------------------------------------- set serverout on declare cursor cemp is select to_char(hiredate,‘yyyy‘) from emp; phiredate varchar2(4); count80 number:=0; count81 number:=0; count82 number:=0; count87 number:=0; begin open cemp; loop fetch cemp into phiredate; exit when cemp%notfound ; if phiredate=‘1980‘ then count80:=count80+1; elsif phiredate=‘1981‘ then count81:=count81+1; elsif phiredate=‘1982‘ then count82:=count82+1; else count87:=count87+1; end if; end loop; close cemp; DBMS_OUTPUT.PUT_LINE(‘Total:‘||(count80+count81+count82+count87)); DBMS_OUTPUT.PUT_LINE(‘count80:‘||count80); DBMS_OUTPUT.PUT_LINE(‘count81:‘||count81); DBMS_OUTPUT.PUT_LINE(‘count82:‘||count82); DBMS_OUTPUT.PUT_LINE(‘count87:‘||count87); exception when no_data_found then DBMS_OUTPUT.PUT_LINE(‘没有找到员工‘); when others then DBMS_OUTPUT.PUT_LINE(‘其他例外‘); end; /
5.3 案例:员工涨工资问题
为员工涨工资。从最低工资涨起每人涨10%,但工资总额不能超过5万元,请计算涨工资的人数和涨工资后的工资总额,并输入涨工资人数及工资总额。 SQL语句 select empno,sal from emp order by sal ; -> 光标-> 循环-> 退出条件:1.工资总额>5W 2. %notfound 变量: 初始值 最终值如何得到 涨工资的人数 countEmp number:=0; 涨后的工资总额: salTotal number; 1.select sum(sal) into salTotal from emp; 2.涨后的工资总额=涨前的工资总额+sal*0.1; ----------------------------------------------------------------------------------------------------------------- set serverout on declare cursor cemp is select empno,sal from emp order by sal; pempno emp.empno%type; psal emp.sal%type; countEmp number :=0; salTotal number; begin select sum(sal) into salTotal from emp; open cemp; loop exit when salTotal>50000; fetch cemp into pempno,psal; exit when cemp%notfound; update emp set sal=sal*1.1 where empno=pempno; countEmp:=countemp+1; salTotal:=salTotal +psal*0.1; end loop; close cemp; commit; DBMS_OUTPUT.PUT_LINE(‘人数:‘||countEmp); DBMS_OUTPUT.PUT_LINE(‘salTotal: ‘||salTotal); end; /
5.4 案例:涉及两张表的员工涨工资问题
按部门分段(6000以上、(6000,3000)、3000元以下)统计各工资段的职工人数、以及各部门的工资总额(工资总额中不包括奖金) SQL语句 1.有哪些部门 select deptno from dept; --> 光标-> 循环-> 退出条件:%notfound 2.部门中员工的薪水 select sal from emp where deptno=? --> 带一个参数的光标-> 循环-> 退出条件:%notfound 变量: 初始值 最终值如何得到 每个段的员工人数 count1 number; count2 number; count3 number; 每个部门的工资总额: saltotal number; 1.select sum(sal) into saltotal from emp where deptno=??? 2.累加 ---------------------------------------------------------------------------------- create table msg(deptno number,count1 number,count2 number,count3 number,saltotal number); set serverout on declare cursor cdept is select deptno from dept; pdeptno dept.deptno%type; cursor cemp(dno number) is select sal from emp where deptno =dno; psal emp.sal%TYPE; count1 number; count2 number; count3 number; saltotal number; begin open cdept; loop fetch cdept into pdeptno; exit when cdept%notfound; count1:=0;count2:=0;count3:=0; select sum(sal) into saltotal from emp where deptno=pdeptno; open cemp(pdeptno); loop fetch cemp into psal; exit when cemp%notfound; if psal <3000 then count1:=count1+1; elsif psal>=3000 and psal <6000 then count2:=count2+1; else count3:=count3+1; end if; end loop; close cemp; insert into msg values(pdeptno,count1,count2,count3,nvl(saltotal,0)); end loop; close cdept; commit; DBMS_OUTPUT.PUT_LINE(‘统计完成‘); end; /
PL/SQL基础
标签:超时 etc eve 基础 概述 output timeout otf varchar2
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://haodehen.cn/did117247