Pl/SQL 编程
Pl/SQL 编程
一:前言
二:Pl/Sql 概述
二 —— 1: Pl/Sql块结构
View Code1 SQL> set serveroutput on; 2 SQL> 3 SQL> declare 4 2 a int:=10; 5 3 b int:=200; 6 4 c number; 7 5 begin 8 6 c:=(a+b)/(a-b); 9 7 dbms_output.put_line(c); 10 8 exception 11 9 when zero_divide then 12 10 dbms_output.put_line('除数不许为零'); 13 11 end; 14 12 / 15 16 -1.10526315789473684210526315789473684211 17 18 PL/SQL procedure successfully completed 19 20 SQL>
二 —— 2: 代码注释和标识符
二 —— 2_____1:单行注释
View Code1 SQL> set serveroutput on; --在服务器端 输出结果 2 SQL> declare 3 2 4 3 Num_sal number; --- 声明一个数值变量 5 4 Var_ename varchar(20); --- 声明一个字符串变量 6 5 begin 7 6 select e.ename,e.sal into Var_ename,Num_sal from emp e where empno=7839; --检索指定的值并储存到变量中 8 7 dbms_output.put_line(Var_ename||'工资是'||Num_sal); 9 8 end; 10 9 11 10 12 11 / 13 14 KING工资是5000 15 16 PL/SQL procedure successfully completed
二 —— 2_____2:多行注释
View Code1 set serveroutput on; /*在服务器端 输出结果*/ 2 declare 3 Num_sal number; 4 Var_ename varchar2(20); 5 begin 6 /*检索指定的值并储存到变量中*/ 7 select e.ename,e.sal into Var_ename,Num_sal from emp e where empno=7839; --检索指定的值并储存到变量中 8 dbms_output.put_line(Var_ename||'工资是'||Num_sal); 9 end; 10 /
二 —— 2_____3:PL/SQL字符集
三:数据类型与定义变量和常量
三 —— 1:基本数据类型
三 —— 1_____1:数值类型
三 —— 1_____2:字符类型
三 —— 1_____3:日期类型
三 —— 1_____4:布尔类型
三 —— 2 :特殊数据类型
三 —— 2_____1: %TYPE 类型
View Code1 SQL> set serveroutput on /*在服务器端 输出结果*/ 2 SQL> declare 3 2 var_ename emp.ename%type; /*声明与ename 列类型相同的变量*/ 4 3 var_job emp.job%type; /*声明与job列类型相同的变量*/ 5 4 begin 6 5 select ename,job into var_ename,var_job from emp where empno=7839 ;/*检索数据,并保存在变量中*/ 7 6 dbms_output.put_line(var_ename||'工资是'||var_job); 8 7 end; 9 8 / 10 11 KING工资是PRESIDENT 12 13 PL/SQL procedure successfully completed
三 —— 2_____2: record 类型
View Code1 set serveroutput on /**/ 2 declare 3 type emp_type is record 4 ( 5 var_ename varchar2(20), /*定义字段--成员变量 */ 6 var_job varchar2(20), 7 var_sal number 8 ); 9 empinfo emp_type; /*定义变量*/ 10 begin 11 select ename,job,sal into empinfo from emp where empno=7839 ;/*检索数据*/ 12 dbms_output.put_line( '雇员'||empinfo.var_ename||'的职位是'||empinfo.var_job||'、工资是'||empinfo.var_sal); 13 14 end; 15 /
三 —— 2_____3: %rowtype 类型
View Code1 SQL> set serveroutput on 2 SQL> declare 3 2 rowVar_emp emp%rowtype;/*定义能够储存emp表中一行数据的变量 rowVar_emp*/ 4 3 begin 5 4 select * into rowVar_emp from emp where empno=7839 ;/*检索数据*/ 6 5 dbms_output.put_line( '雇员'||rowVar_emp.ename||'的职位是'||rowVar_emp.job||'、工资是'||rowVar_emp.sal); 7 6 8 7 end; 9 8 / 10 11 雇员KING的职位是PRESIDENT、工资是5000 12 13 PL/SQL procedure successfully completed 14 15 SQL>
三 —— 3: 定义变量和常量
四 :流程控制语句
四 —— 1:选择语句 if …then 语句
View Code1 SQL> set serveroutput on 2 SQL> declare 3 2 var_name1 varchar2(50); --//定义2个字符串变量 4 3 var_name2 varchar2(50); 5 4 6 5 begin 7 6 var_name1 :='East'; --//给2个变量赋值 8 7 var_name2 :='xiaoke'; 9 8 10 9 if length(var_name1)<length(var_name2) then 11 10 /*输出比较后的结果*/ 12 11 dbms_output.put_line('字符串 “'||var_name1||'”的长度比字符串“'||var_name2||'”的长度小'); 13 12 end if; 14 13 end; 15 14 / 16 17 字符串 “East”的长度比字符串“xiaoke”的长度小 18 19 PL/SQL procedure successfully completed 20 21 SQL>
四 ——1_____ 2:选择语句 if …then … else 语句
View Code1 SQL> set serveroutput on 2 SQL> declare 3 2 age int:=55;/*定义整型变量并赋值*/ 4 3 begin 5 4 if age >=56 then 6 5 dbms_output.put_line('您可以申请退休了!'); 7 6 else 8 7 dbms_output.put_line('您小于56岁,不可以申请退休了!'); 9 8 end if; 10 9 end; 11 10 / 12 13 您小于56岁,不可以申请退休了! 14 15 PL/SQL procedure successfully completed 16
四 ——1_____3:选择语句 if …then … elseif 语句
View Code1 SQL> set serveroutput on 2 SQL> declare 3 2 month int :=10; /*声明整型变量并赋值*/ 4 3 5 4 begin 6 5 if month >=0 and month<=3 then /*判断春节*/ 7 6 dbms_output.put_line('这是春季'); 8 7 elsif month >=4 and month <=6 then /*片段夏季*/ 9 8 dbms_output.put_line('这是夏季'); 10 9 elsif month >=7 and month<=9 then 11 10 dbms_output.put_line('这是秋季'); 12 11 elsif month >=10 and month<=12 then 13 12 dbms_output.put_line('这是冬季'); 14 13 else 15 14 dbms_output.put_line('对不起,月份不合法!'); 16 15 end if; 17 16 end; 18 17 / 19 20 这是冬季 21 22 PL/SQL procedure successfully completed 23 24 SQL>
四 ——1_____4:选择语句 case 语句
View Code1 SQL> set serveroutput on 2 SQL> declare 3 2 season int:=3;/*定义整型变量并赋值*/ 4 3 aboutInfo varchar2(50);/*声明月份信息*/ 5 4 begin 6 5 case season /*片段月份*/ 7 6 when 1 then 8 7 aboutInfo := season || '季度包括 1,2,3月份'; 9 8 when 2 then 10 9 aboutInfo := season || '季度包括 4,5,6月份'; 11 10 when 3 then 12 11 aboutInfo := season || '季度包括 7,8,9月份'; 13 12 when 4 then 14 13 aboutInfo := season || '季度包括 10,11,12月份'; 15 14 else 16 15 aboutInfo := season || ' 季度不合法'; 17 16 end case ; 18 17 19 18 dbms_output.put_line(aboutInfo); 20 19 21 20 end; 22 21 / 23 24 3季度包括 7,8,9月份 25 26 PL/SQL procedure successfully completed 27 28 SQL>
四 ——2:循环语句
四 ——2_____1: loop 语句
View Code1 set serveroutput on 2 declare 3 sum_i int:=0; /*定义整数变量,存储整数和*/ 4 i int:=0;/*定义整数变量 储存自然数*/ 5 begin 6 loop /*循环累加自然数*/ 7 i:= i+1; /*得出自然数*/ 8 sum_i := sum_i + i;/*计算前n个自然数的和*/ 9 exit when i=100; /*当循环100次后,程序退出循环体*/ 10 end loop; 11 dbms_output.put_line('前100个自然数的和是'||sum_i);/*计算前100个自然数的和*/ 12 end; 13 / 14
四 ——2_____2: while 语句
View Code1 set serveroutput on 2 declare 3 sum_i int:=0;/*定义变量并赋值*/ 4 i int :=0;/*定义变量并赋值*/ 5 begin 6 while i<99 loop 7 i:=i+1;/*当i的值等于100时,程序退款while循环*/ 8 sum_i :=sum_i +i;/*计算前n个自然数的和*/ 9 end loop; 10 dbms_output.put_line('前100个自然数的和是'||sum_i);/*计算前100个自然数的和*/ 11 end; 12 /
四 ——2_____3: for 语句
View Code1 set serveroutput on 2 declare 3 sum_i int :=0;/*定义变量并赋值*/ 4 begin 5 for i in 1..100 loop /*遍历前100个自然数*/ 6 if mod(i,2)=0 then /*判断是否为偶数*/ 7 sum_i:=sum_i +i; /*计算偶数和*/ 8 end if; 9 end loop; 10 dbms_output.put_line('前100个自然数的和是'||sum_i);/*计算前100个自然数的和*/ 11 end; 12 /
五 :Pl/Sql 游标
五 —1:显示游标
五 ——1_____1:声明游标
五 ——1_____2:打开游标
五 ——1_____3: 读取游标
View Code1 2 set serveroutput on 3 declare 4 /*声明游标,检索雇员信息*/ 5 cursor cur_emp(var_job varchar2 := 'SALESMAN') is 6 select empno, ename, sal from emp where job = var_job; 7 type record_emp is record /*声明一个记录类型 record 类型*/ 8 ( 9 /*定义当前记录的成员变量*/ 10 var_empno emp.empno%type, 11 var_ename emp.ename%type, 12 var_sal emp.sal%type); 13 emp_row record_emp; /*声明一个record_emp 类型变量*/ 14 begin 15 open cur_emp('MANAGER'); /*打开游标*/ 16 fetch cur_emp 17 into emp_row; /*先让指针指向结果集中的第一行,并将值保存到emp_row 中*/ 18 while cur_emp%found loop 19 dbms_output.put_line(emp_row.var_ename || '的编号是' || emp_row.var_empno || 20 ',工资是' || emp_row.var_sal); 21 22 fetch cur_emp 23 into emp_row; /*让指针指向结果集的下一行,并将值保存到emp_row中*/ 24 end loop; 25 close cur_emp; /*关闭游标*/ 26 end; 27 /
五 ——1_____4: 关闭游标
五 ——2: 游标的属性
View Code1 set serveroutput on 2 declare 3 var_ename varchar2(50);/*声明变量,用来储存雇员名称*/ 4 var_job varchar2(50);/*声明变量,用来储存雇员的职务*/ 5 /*声明游标,检索指定员工编号的雇员信息*/ 6 cursor cur_emp /*定义游标,检索指定编号的记录信息*/ 7 is select ename ,job from emp where empno=7499; 8 begin 9 open cur_emp;/*打开游标*/ 10 fetch cur_emp into var_ename,var_job ;/*读取游标,并且储存雇员名称和职务*/ 11 if cur_emp%found then /*若检索到数据记录,则输出雇员信息*/ 12 dbms_output.put_line('编号是7499的雇员名称为'||var_ename||',职务是:'||var_job); 13 else 14 dbms_output.put_line('无数据记录');/*提示无记录信息*/ 15 end if; 16 end; 17 /
五 ——3: 隐式游标
View Code1 /*在scott 用户下,把emp 表中销售员(即:SALESMAN)的工资上调20% 然后使用隐式游标sql的%rowcount属性输出上调工资的员工数量*/ 2 set serveroutput on 3 begin 4 update emp set sal=sal*(1+0.2) where job='SALESMAN';/*把销售员工的工资上调20%*/ 5 if sql%notfound then 6 dbms_output.put_line(' 没有雇员需要上调工资'); 7 else 8 dbms_output.put_line('有'||sql%rowcount||'个雇员工资上调20%'); 9 end if; 10 end; 11 /
五 ——3: 通过for 语句循环游标
View Code1 /*使用隐式游标和for语句检索出职务是销售员的雇员信息并输出*/ 2 set serveroutput on 3 begin 4 for emp_record in(select empno,ename,sal from emp where job='SALESMAN') /*遍历隐式游标中的记录*/ 5 loop 6 dbms_output.put_line('雇员编号:'|| emp_record.empno); /*输出雇员编号*/ 7 dbms_output.put_line('雇员名称:'|| emp_record.ename);/*输出雇员名称*/ 8 dbms_output.put_line('雇员工资:'|| emp_record.sal); /*输出雇员工资*/ 9 end loop; 10 end; 11 /
View Code1 /*使用显示游标 和 for 语句检索出部门编号是30的雇员信息并输出 */ 2 set serveroutput on 3 declare 4 cursor cur_emp is select * from emp where deptno =30; /*检索部门编号为30的雇员信息*/ 5 begin 6 for emp_rocord in cur_emp/*遍历雇员信息*/ 7 loop 8 dbms_output.put_line('雇员编号:'|| emp_rocord.empno); /*输出雇员编号*/ 9 dbms_output.put_line('雇员名称:'|| emp_rocord.ename);/*输出雇员名称*/ 10 dbms_output.put_line('雇员职务:'|| emp_rocord.job); /*输出雇员工资*/ 11 end loop; 12 end; 13 /
六 : PL/SQL 异常处理
六 ——1_____1: 预定义异常
View Code1 /*使用select into语句检索emp 表中部门编号为10 的雇员编号记录信息 然后使用too_many_rows一定*/ 2 3 4 set serveroutput on 5 declare 6 var_empno number ;/*定义变量,储存雇员编号*/ 7 var_ename varchar2(50);/*定义变量,储存雇员名称*/ 8 begin 9 select empno,ename into var_empno,var_ename from emp where deptno=10;/*查询部门编号为10的雇员的信息*/ 10 if sql%found then /*如果检索成功,则输出雇员信息*/ 11 dbms_output.put_line('雇员编号:'||var_empno||';雇员名称:'||var_ename); 12 end if; 13 exception /*捕获异常*/ 14 when too_many_rows then /*若 select into 语句返回的记录超过一行*/ 15 dbms_output.put_line('返回记录超出一行'); 16 when no_data_found then /*若select into 语句的返回结果为0行*/ 17 dbms_output.put_line('无数据记录'); 18 end; 19 /
六 ——2: 自定义异常
六 ——2_____1: 错误编号异常
View Code1 2 set seroutput on 3 declare 4 primary_iterant exception;/*定义野怪异常变量*/ 5 pragma exception_init(primary_iterant,-00001);/*关联错误号 和 异常变量名*/ 6 begin 7 /*向dept表中插入一条与已有主键值重复的记录,以便引发异常*/ 8 insert into dept values(10,'rrr','rrr'); 9 exception 10 when primary_iterant then /*若Oracle系列捕获到的异常为-000001异常*/ 11 dbms_output.put_line('主键不允许重复!'); /*输出异常描述信息*/ 12 end; 13 /
六 ——2_____2: 业务逻辑异常
View Code1 set serveroutput on 2 declare 3 null_exception exception ;/*声明一个exception 类型的异常变量*/ 4 dept_row dept%rowtype; /*声明rowtype 类型的变量 dept_now*/ 5 begin 6 dept_row.deptno :=66; /*给部门编号变量赋值*/ 7 dept_row.dname := '公关部';/*给部门名称变量赋值*/ 8 insert into dept values(dept_row.deptno,dept_row.dname,dept_row.loc);/*向dept表插入一条记录*/ 9 if dept_row.loc is null then 10 raise null_exception; /*引发 null 异常 程序进入exception部分*/ 11 end if; 12 exception 13 when null_exception then /*当 raise 引发的异常是 null_exception 时*/ 14 dbms_output.put_line('loc 字段的值不允许为null'); /*则输出异常提示信息*/ 15 rollback; /*回滚插入的数据记录*/ 16 end ; 17 /
六 ——2_____3: Oracle存储过程的异常处理
注:本段内容来源于:《Oracle存储过程的异常处理》
1、为了提高存储过程的健壮性,避免运行错误,当建立存储过程时应包含异常处理部分。
2、异常(EXCEPTION)是一种PL/SQL标识符,包括预定义异常、非预定义异常和自定义异常;
3、预定义异常是指由PL/SQL提供的系统异常;非预定义异常用于处理与预定义异常无关的Oracle错误(如完整性约束等);自定义异常用于处理与Oracle错误的其他异常情况。
4、RAISE_APPLICATION_ERROR用于自定义错误消息,并且消息号必须在-20000~-20999之间命名的系统异常 产生原因
access_into_null 未定义对象
case_not_found case中若未包含相应的when,并且没有设置
collection_is_null 集合元素未初始化
curser_already_open 游标已经打开
dup_val_on_index 唯一索引对应的列上有重复的值
invalid_cursor 在不合法的游标上进行操作
invalid_number 内嵌的 sql 语句不能将字符转换为数字
no_data_found 使用 select into 未返回行,或应用索引表未初始化的
too_many_rows 执行 select into 时,结果集超过一行
zero_divide 除数为 0
subscript_beyond_count 元素下标超过嵌套表或varray的最大值
subscript_outside_limit 使用嵌套表或 varray 时,将下标指定为负数
value_error 赋值时,变量长度不足以容纳实际数据
login_denied pl/sql 应用程序连接到 oracle 数据库时,提供了不正确的用户名或密码 确的用户名或密码
not_logged_on pl/sql 应用程序在没有连接 oralce 数据库的情况下访问数据 问数据
program_error pl/sql 内部问题,可能需要重装数据字典& pl./sql系统包 统包
rowtype_mismatch 主游标变量与 pl/sql 游标变量的返回类型不兼容
self_is_null 使用对象类型时,在 null 对象上调用对象方法
storage_error 运行 pl/sql 时,超出内存空间
sys_invalid_id 无效的 rowid 字符串
timeout_on_resource oracle 在等待资源时超时1 --自定义异常处理 2 CREATE OR REPLACE PROCEDURE stu_proc 3 ( 4 --多个用逗号隔开 5 v_id IN NUMBER 6 ) IS 7 --多个用分号隔开 8 v_max_id NUMBER; 9 v_name VARCHAR2(20); 10 v_raise EXCEPTION; 11 BEGIN 12 SELECT MAX(a.id) INTO v_max_id FROM student a; 13 IF v_id>v_max_id THEN 14 RAISE v_raise; 15 END IF; 16 SELECT o.sname INTO v_name FROM student o WHERE o.id=v_id; 17 dbms_output.put_line('学生名称为:'||v_name); 18 EXCEPTION 19 WHEN v_raise THEN 20 RAISE_APPLICATION_ERROR(-20010, 'v_id not exists!'); 21 WHEN NO_DATA_FOUND THEN 22 RAISE_APPLICATION_ERROR(-20011, 'ERROR:不存在!'); 23 END stu_proc;
——————————————
——————————————————————————————————————————————————————————
学问:纸上得来终觉浅,绝知此事要躬行
为事:工欲善其事,必先利其器。
态度:道阻且长,行则将至;行而不辍,未来可期
.....................................................................
------- 桃之夭夭,灼灼其华。之子于归,宜其室家。 ---------------
------- 桃之夭夭,有蕡其实。之子于归,宜其家室。 ---------------
------- 桃之夭夭,其叶蓁蓁。之子于归,宜其家人。 ---------------
=====================================================================
* 博客文章部分截图及内容来自于学习的书本及相应培训课程以及网络其他博客,仅做学习讨论之用,不做商业用途。
* 如有侵权,马上联系我,我立马删除对应链接。 * @author Alan -liu * @Email no008@foxmail.com
转载请标注出处! ✧*꧁一品堂.技术学习笔记꧂*✧. ---> https://www.cnblogs.com/ios9/