ORACL深入浅出 主讲人:邹振兴 深入浅出Oracle 主讲:邹振兴
第一章 事务与锁 什么是事务? 如何Oracle使用事务。 在Java中使用事务。 什么是锁? 演示更新丢失的问题。 锁的分类。 阻塞与死锁。 深入浅出Oracle 主讲:邹振兴
什么是事务 什么是事务? 事务四大特性(ACID) 事务是一种机制,这种机制能保证在事务内的DML(数据操作语句)做为一个不可分割的单元进行执行。 举例说明事务。 演示sql servert2005事务处理。 演示Oracle事务处理。 事务四大特性(ACID) 原子性(A) 一致性(C) 隔离性(I) 永久性(D) 深入浅出Oracle 主讲:邹振兴
什么是事务 事务处理的两种方式 比较sql server 2005与Oracle事务处理方式的区别。 显示事务:用户通过编码方式开启事务 隐式事务:数据库默认认为所有操作都是事务 比较sql server 2005与Oracle事务处理方式的区别。 深入浅出Oracle 主讲:邹振兴
如何Oracle使用事务 Oracel事务关键字 讲解Oracel程序员一天 Savepoint a ; 设置事务保存点 Rollback to a ;回滚到事务保存点a,事务不结束 Commit ;提交事务,事务结束 Rollback; 回滚所有事务,事务结束 讲解Oracel程序员一天 深入浅出Oracle 主讲:邹振兴
在Java Jdbc中使用事务 演示如何在Java Jdbc中如何使用事务 驱动包位置:oracle安装路径->oracle->jdbc->lib->classes12.jar 演示案例:DBUtil.java 深入浅出Oracle 主讲:邹振兴
什么是锁 生活中的锁: Oracle中的锁: 为什么会有锁的出现。 锁的作用就是保护私有的空间。 演示Oracle中更新丢失的问题。 讲解此问题的两种思路:一、在第一个用户修改之前不允许其它用户修改。二、在修改之前,查看此数据的版本号。 深入浅出Oracle 主讲:邹振兴
锁的分类 悲观锁定 此锁持悲观态度,认为在用户修改数据期间,一定会有用户再对其修改。那么此锁会在用户事务内一直保持锁定状态,其它用户无法进行修改。 在查询语句后接 for update nowait此可加锁。查询多少数据,锁定多少数据。 乐观锁定 此锁持乐观态度,认为在用户修改数据期间,其它用户不会再对其修改,直到最后提交数据时才判断数据是否已更改。 深入浅出Oracle 主讲:邹振兴
锁的分类 乐观锁定的实现方式: 增加标识列来区分是否已修改 通过Oracle ORA_ROWSCN机制来实现乐观锁定
阻塞与死锁 如果你有两个会话,每个会话都持有另一个会话想要的资源,此时就会出现死锁(deadlock)。例如,如果我的数据库中有两个表A 和B,每个表中都只有一行,就可以很容易地展示什么是死锁。我要做的只是打开两个会话(例如,两个SQL*Plus 会话)。在会话A 中更新表A,并在会话B 中更新表B。现在,如果我想在会话B 中更新表A,就会阻塞。会话A 已经锁定了这一行。这不是死锁;只是阻塞而已。我还没有遇到过死锁,因为会话A 还有机会提交或回滚,这样会话B 就能继续。 深入浅出Oracle 主讲:邹振兴
阻塞与死锁 如果我再回到会话A,试图更新表B,这就会导致一个死锁。要在这两个会话中选择一个作为“牺牲品”,让它的语句回滚。例如,会话B 中对表A 的更新可能回滚,得到以下错误:想要更新表B 的会话A 还阻塞着,Oracle 不会回滚整个事务。只会回滚与死锁有关的某条语句。会话B 仍然锁定着表B 中的行,而会话A 还在耐心地等待这一行可用。收到死锁消息后,会话B 必须决定将表B 上未执行的工作提交还是回滚,或者继续走另一条路,以后再提交。一旦这个会话执行提交或回滚,另一个阻塞的会话就会继续,好像什么也没有发生过一样。 深入浅出Oracle 主讲:邹振兴
总结 开发多用户、数据库驱动的应用时,最大的难点之一是:一方面要力争取得最大限度的并发访问,与此同时还要确保每个用户能以一致的方式读取和修改数据。为此就有了锁定(locking)机制,这也是所有数据库都具有的一个关键特性,Oracle 在这方面更是技高一筹。不过,Oracle 的这些特性的实现是Oracle所特有的,就像SQL Server 的实现只是SQL Server 特有的一样,应用执行数据处理时,要正确地使用这些机制,而这一点要由你(应用的开发人员)来保证。 深入浅出Oracle 主讲:邹振兴
第五章 使用PL/SQL PL/SQL简介 变量、常量 数据类型 流程控制 异常处理 深入浅出Oracle 主讲:邹振兴
PL/SQL简介 PL/SQL是Oracle在sql标准上的加强,使用Oracle能够基于对象编程 T-SQL是基于事务的结构化查询语言
PL/SQL块简介 PL/SQL 块是构成 PL/SQL 程序的基本组织单元,可以编写存储过程、函数、包、触发器等。 深入浅出Oracle 主讲:邹振兴
PL/SQL块简介 演示:PL/SQL打印Hello World。 演示:如何在PL/SQL块中向表中增加一条记录。 演示:查询学员'张秋丽'的年龄。 深入浅出Oracle 主讲:邹振兴
PL/SQL块 小结 每一个PL/SQL块将会自动开启一个事务,在PL/SQL块中必须结束事务,否则,将会阻塞。 PL/SQL块中不能执行select语句进行显示。 在命令行中执行pl-sql块需加/。 在命令行中打印变量需set serverout on; 深入浅出Oracle 主讲:邹振兴
变量与常量 在PL/SQL块的声明部分声明变量或常量 语法: declare sal number; pi constant number := 3.14; 赋值 1、使用赋值运算符“:=” 2、使用 SELECT INTO 语句 3、接收用户输入 深入浅出Oracle 主讲:邹振兴
变量与常量示例 Declare myname varchar2(20) not null :=‘张三’; myage number ; mypi constant number :=3.14; Begin myage:=26; select ename into myname from emp where empno=7369; --输出 End; 注意: 1、变量如果声明为not null,则必须初始化值 2、常量一旦定义则不能修改 深入浅出Oracle 主讲:邹振兴
日期时间 日期时间类型 declare mydate date; mytime timestamp; begin 存储日期和时间数据 常用的两种日期时间类型 DATE TIMESTAMP declare mydate date; mytime timestamp; begin select sysdate into mydate from dual; select sysdate into mytime from dual; dbms_output.put_line(mydate); dbms_output.put_line(mytime); end; 深入浅出Oracle 主讲:邹振兴
布尔类型(boolean) 用于存储逻辑值(TRUE、FALSE和NULL) 不能向数据库中插入BOOLEAN数据 深入浅出Oracle 主讲:邹振兴
属性类型 用于引用数据库列的数据类型,以及表示表中一行的记录类型 列类型%type,语法:表名.列名%type 行类型%rowtype,语法:表名%rowtype 优点 不需要知道被引用的表列的具体类型 如果被引用对象的数据类型发生改变,PL/SQL 变量的数据类型也随之改变 深入浅出Oracle 主讲:邹振兴
属性类型示例 问题1:假设现在不知道emp表Job列的类型,但要保存员工7369的岗位到变量中,如何定义? declare myjob emp.Job%type; begin select Job into myjob from emp where empno=7369; dbms_output.put_line(myjob); end; 深入浅出Oracle 主讲:邹振兴
属性类型示例 问题2:假设要输出emp表员工7369的所有信息,怎么办?定义8个列类型变量,依次输出? declare myemp emp%rowtype; begin select * into myemp from emp where empno=7369; dbms_output.put_line(myemp.ename||myemp.job); end; 深入浅出Oracle 主讲:邹振兴
异常处理 在运行程序时出现的错误叫做异常 发生异常后,语句将停止执行,控制权转移到 PL/SQL 块的异常处理部分 异常有两种类型: 预定义异常 - 当 PL/SQL 程序违反 Oracle 规则或超越系统限制时隐式引发 用户定义异常 - 用户可以在 PL/SQL 块的声明部分定义异常,自定义的异常通过 RAISE 语句显式引发 深入浅出Oracle 主讲:邹振兴
预定义异常 Others 处理所有异常 在用户试图将重复的值存储在使用唯一索引的数据库列中时出现 在将字符串转换为数字时出现 DUP_VAL_ON_INDEX 在将字符串转换为数字时出现 INVALID_NUMBER 在表中不存在请求的行时出现 NO_DATA_FOUND 在执行SELECT INTO语句后返回多行时出现 TOO_MANY_ROWS 在以零作为除数时出现 ZERO_DIVIDE 深入浅出Oracle 主讲:邹振兴
预定义异常 declare myname emp.ename%type; begin select ename into myname from emp; Exception when too_many_rows then dbms_output.put_line('值过多'); end; 深入浅出Oracle 主讲:邹振兴
预定义异常 declare myname emp.ename%type; begin select ename into myname from emp where empno=1; Exception when no_data_found then dbms_output.put_line('没有数据'); end; 深入浅出Oracle 主讲:邹振兴
用户自定义异常 declare myException Exception; begin if ... then raise myException; end if; Exception when myException then ... end; 深入浅出Oracle 主讲:邹振兴
流程控制 条件结构 If语句 Case语句 循环结构 Loop循环 While循环 For循环 深入浅出Oracle 主讲:邹振兴
条件结构 1) if...then...end if; 2) if...then...else if...end if ….end if; 嵌套if 3) if...then...elsif...then...else...end if; 多重if 4)case...when...end case; 编写一个PL/SQL块,用户输入一个员工名,如果该员工的工资低于2000,则将该员工工资增长10%。 深入浅出Oracle 主讲:邹振兴
接收用户输入的两个数,通过条件结构判断两个数的关系 declare num1 number; num2 number; begin num1:=‘&请输入一个数’; num2:='&num2';--接收用户输入'&name' if num1<num2 then dbms_output.put_line('小于'); elsif num1>num2 then dbms_output.put_line('大于'); else dbms_output.put_line('等于'); end if; end; 深入浅出Oracle 主讲:邹振兴
when 'A' then dbms_output.put_line('优秀'); declare grade varchar2(10); begin grade:='&grade'; case grade when 'A' then dbms_output.put_line('优秀'); when 'B' then dbms_output.put_line('良好'); when 'C' then dbms_output.put_line('一般'); when 'D' then dbms_output.put_line('差'); else dbms_output.put_line('没这个'); end case; end; 深入浅出Oracle 主讲:邹振兴
循环结构 使用三种循环实现输出100次我爱你 深入浅出Oracle 主讲:邹振兴
dbms_output.put_line(counter||':我爱你'); --if counter=100 then 1)无条件(无限)循环 --跳出循环 exit,exit when... declare counter number:=0; begin loop counter:=counter+1; dbms_output.put_line(counter||':我爱你'); --if counter=100 then -- exit;--退出循环 --end if; exit when counter=100; end loop; end; 深入浅出Oracle 主讲:邹振兴
dbms_output.put_line(counter||':我爱你'); end loop; end; 2)有条件循环 declare counter number:=0; begin while(counter<100) loop counter:=counter+1; dbms_output.put_line(counter||':我爱你'); end loop; end; 深入浅出Oracle 主讲:邹振兴
dbms_output.put_line(num||':我爱你'); end loop; end; 3)循环固定次数:数字区间:下限..上限 begin for num in 1..100 loop dbms_output.put_line(num||':我爱你'); end loop; end; 深入浅出Oracle 主讲:邹振兴
动态SQL 应用: 1、DDL 语句命令和会话控制语句不能在 PL/SQL 中直接使用,但是可以通过动态 SQL 来执行 深入浅出Oracle 主讲:邹振兴
动态SQL 动态 SQL 是指在PL/SQL程序执行时生成的 SQL 语句 执行语法: execute immediate 'sql语句' [into 变量列表] --将查询的值赋值给变量 [using 参数列表] --使用参数填补占位符(:name) 深入浅出Oracle 主讲:邹振兴
Eg:利用动态SQL建表 begin execute immediate 'create table test ( tid number)'; end; 问题:能否建表后执行插入数据操作? 深入浅出Oracle 主讲:邹振兴
Eg:根据员工编号获得员工姓名 declare myname emp.ename%type; begin execute immediate 'select ename from emp where empno=:no' into myname using '&no'; dbms_output.put_line(myname); end; 问题:如果Sql语句有多个条件怎么写? 深入浅出Oracle 主讲:邹振兴
总结 1、:=赋值运算符 2、||连接操作符 3、'&name'接受用户输入参数值 4、:name 动态SQL中占位符,使用using填补 深入浅出Oracle 主讲:邹振兴
第六章 游标管理 什么是游标 显示游标的使用 游标类型的使用 隐式游标的使用 深入浅出Oracle 主讲:邹振兴
什么是游标 提问:请编写pl-sql块,打印出所有的参加考试的学员信息。 分析问题:pl-sql块中无法使用select语句,使用变量也无法保存多行数据。 解决问题:要是Oracle提供类似于Java集合的结构就能轻松解决问题。 深入浅出Oracle 主讲:邹振兴
显示游标1 显式游标在 PL/SQL 块的声明部分定义查询,该查询可以返回多行 显式游标的操作过程: 关闭游标 变量 打开游标 数据库 30 George 3 44 Roger 2 45 James 1 Stud_mrks Stud_name stud_no 打开游标 数据库 提取行 关闭游标 变量 深入浅出Oracle 主讲:邹振兴
显示游标2 定义: CURSOR <游标名> IS <SELECT 语句>[FOR UPDATE | FOR UPDATE OF 字段] ; 操作: OPEN <游标名>; --打开游标 FETCH <游标名> INTO 变量1,变量2,变量3,....变量n; 或者 FETCH <游标名> INTO 行对象; --取出游标当前位置的值 CLOSE <游标名>; --关闭游标 深入浅出Oracle 主讲:邹振兴
显示游标属性 %NOTFOUND --如果FETCH语句失败,则该属性为"TRUE",否则为"FALSE"; %ROWCOUNT --返回游标当前的行数; %ISOPEN --如果游标是开的则返回"TRUE",否则为"FALSE"; 深入浅出Oracle 主讲:邹振兴
输出所有员工编号与姓名 declare rowemp emp%rowtype;--行变量 cursor empcur is select * from emp;--定义游标 begin open empcur;--打开游标 loop fetch empcur into rowemp; dbms_output.put_line(rowemp.empno||rowemp.ename); exit when empcur%notfound; end loop; close empcur;--关闭游标 end; 深入浅出Oracle 主讲:邹振兴
For循环游标 循环游标用于简化游标处理代码 自动打开游标,提取记录,关闭游标 当用户需要从游标中提取所有记录时使用 循环游标的语法如下: FOR <record_index> IN <cursor_name> LOOP <executable statements> END LOOP; <record_index>是类型为%rowtype的记录变量 使用游标for循环的时候不能使用open语句,fetch语句和close语句, 否则会产生错误。 深入浅出Oracle 主讲:邹振兴
输出所有员工编号与姓名 declare cursor empcur is select * from emp;--定义游标 begin for rowemp in empcur loop dbms_output.put_line(rowemp.empno||rowemp.ename); end loop; end; 深入浅出Oracle 主讲:邹振兴
带参数的游标 提高游标的灵活性 语法: CURSOR <游标名>(参数列表) IS <SELECT 语句> ; 深入浅出Oracle 主讲:邹振兴
根据部门编号输出该部门员工姓名 declare cursor empcur(dtno emp.deptno%type) is select * from emp where deptno=dtno;--定义游标 begin for rowemp in empcur(20) loop dbms_output.put_line(rowemp.ename); end loop; end; 深入浅出Oracle 主讲:邹振兴
游标加锁 [FOR UPDATE | FOR UPDATE OF 字段] 即在程中有“UPDATE”,“INSERT”,“DELETE”语句对数据库操作时,游标自动给指定的表或者字段加锁,防止同时有别的程序对指定的表或字段进行“UPDATE”,“INSERT”,“DELETE”操作。 在使用“DELETE”,“UPDATE”后还可以在程序中使用CURRENT OF <游标名> 子句引用当前行进行更新操作。 深入浅出Oracle 主讲:邹振兴
使用游标更新工资,翻倍 declare cursor mycursor is select sal from emp for update; begin for r in mycursor loop update emp set sal=sal*2 where current of mycursor; end loop; end; 深入浅出Oracle 主讲:邹振兴
REF游标与游标变量 REF 游标和游标变量用于处理运行时动态执行的 SQL 查询 创建游标变量需要两个步骤: 声明 REF 游标类型 TYPE <ref_cursor_name> IS REF CURSOR [RETURN <return_type>]; 打开游标变量的语法如下: OPEN cursor_name FOR select_statement; 深入浅出Oracle 主讲:邹振兴
获取部门10的工资 declare Type salcursor is ref cursor;--声明游标类型 salcurvar salcursor;--定义游标变量 mysal number; begin open salcurvar for select sal from myemp where deptno=10; loop fetch salcurvar into mysal; dbms_output.put_line(mysal); exit when salcurvar%notfound; end loop; end; 深入浅出Oracle 主讲:邹振兴
游标变量优点 游标变量的功能强大,可以简化数据处理。 游标变量的优点有: 可从不同的 SELECT 语句中提取结果集 可以作为过程的参数进行传递 可以引用游标的所有属性 可以进行赋值运算 深入浅出Oracle 主讲:邹振兴
使用游标变量执行动态Sql declare Type salcursor is ref cursor;--声明游标类型 salcurvar salcursor;--定义游标变量 mysal number; begin open salcurvar for 'select sal from myemp where deptno=:dno'--动态SQL字符串 using ‘&no’;--填补占位符的参数 loop fetch salcurvar into mysal; dbms_output.put_line(mysal); exit when salcurvar%notfound; end loop; end; 深入浅出Oracle 主讲:邹振兴
隐式游标 在PL/SQL中使用DML语句时自动创建隐式游标 隐式游标自动声明、打开和关闭,其游标名称为 SQL 深入浅出Oracle 主讲:邹振兴
隐式游标属性 %NOTFOUND --如果DML语句没有影响到任何行时,则该属性为"TRUE",否则为"FALSE"; %ROWCOUNT --返回DML语句影响的行数; %ISOPEN - 游标是否打开,隐式游标始终为FALSE 使用:游标名称+属性 SQL%NOTFOUND 深入浅出Oracle 主讲:邹振兴
隐式游标属性 begin update emp set comm=100 where empno=7369; if SQL%Found=true then dbms_output.put_line('更新成功'); dbms_output.put_line('受影响的行数'||SQl%rowcount); end if; If SQL%NotFound=true then dbms_output.put_line(‘不存在'); end; 深入浅出Oracle 主讲:邹振兴
总结 游标用于处理查询结果集中的数据 游标类型有:隐式游标、显式游标和 REF 游标 隐式游标由 PL/SQL 自动定义、打开和关闭 显式游标用于处理返回多行的查询 在声明 REF 游标时,不需要将 SELECT 语句与 其关联 深入浅出Oracle 主讲:邹振兴
第七章 子程序与程序包 什么是子程序 子程序一:存储过程 子程序二:函数 子程序三:自主事务处理 组织子程序:程序包 深入浅出Oracle 主讲:邹振兴
子程序1 命名的 PL/SQL 块,编译并存储在数据库中。 子程序的各个部分: 子程序的分类: 声明部分 可执行部分 异常处理部分(可选) 过程 - 执行某些操作 函数 - 执行操作并返回值 深入浅出Oracle 主讲:邹振兴
子程序2 子程序的优点: 模块化 可重用性 可维护性 安全性 将程序分解为逻辑模块 可以被任意数目的程序调用 简化维护操作 通过设置权限,使数据更安全 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 过程是用于完成特定任务的子程序 例如: 在柜台购买车票 前往售票厅 排队等候 询问关于车票的信息 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 创建简单过程 create or replace procedure SayHi as begin dbms_output.put_line('hi'); end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 调用 --1、在命令窗口下 execute SayHi; --2、在SQL Window下 begin SayHi(); end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 带参数过程,参数不用指定长度 create or replace procedure SayHi(str varchar2) as begin dbms_output.put_line(str); end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 根据员工编号查询员工姓名,并打印,没找到数据则异常处理 create or replace procedure SearchName(emp_no number) is empname varchar(20); begin select ename into empname from emp where empno=emp_no; dbms_output.put_line(empname); end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 过程参数的三种模式: IN OUT IN OUT 用于接受调用程序的值 默认的参数模式 用于向调用程序返回值 用于接受调用程序的值,并向调用程序返回更新的值 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 根据员工编号返回员工姓名给另一程序 create or replace procedure SearchName(emp_no in number,empname out varchar2) is begin select ename into empname from emp where empno=emp_no; end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 declare emp_no number; empname varchar2(20); begin emp_no:='&no'; SearchName(emp_no,empname); dbms_output.put_line(empname); end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 交换两个数 create or replace procedure Swap(num1 in out number,num2 in out number) is temp number; begin temp:=num1; num1:=num2; num2:=temp; end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 declare num1 number:=10; num2 number:=20; begin dbms_output.put_line('num1='||num1); dbms_output.put_line('num2='||num2); Swap(num1,num2); dbms_output.put_line('调用过程后'); end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 --返回游标的存储过程 create or replace procedure getAllEmp(returnCursor out sys_refcursor) as begin open returnCursor for select * from emp; end; --使用存储过程返回的游标 declare type classcursor is ref cursor; mycursor classcursor; var_emp emp%rowtype; begin getAllEmp(returnCursor => mycursor); loop fetch mycursor into var_emp; dbms_output.put_line(var_emp.ename); exit when mycursor%notfound; end loop; end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 创建过程的语法: create [or replace] procedure 过程名称[(参数列表)] is|as [变量] begin 可执行部分; [Exception] end; 深入浅出Oracle 主讲:邹振兴
子程序一:存储过程 使用Java程序调用几种存储过程。 Test.java 深入浅出Oracle 主讲:邹振兴
子程序二:函数(function) 函数是可以返回值的命名的 PL/SQL 子程序。 参数与返回值类型不用指定长度 深入浅出Oracle 主讲:邹振兴
子程序二:函数 简单函数 create or replace function FSayHi return varchar2 is begin return 'Hi'; end; 深入浅出Oracle 主讲:邹振兴
子程序二:函数 调用函数 1、结合查询 select FSayHi from dual; 2、返回值给变量 declare str varchar2(20); begin str:=FSayHi; dbms_output.put_line(str); end; 深入浅出Oracle 主讲:邹振兴
子程序二:函数 带参函数 create or replace function FSayHi(str varchar2) return varchar2 is begin return str; end; select FSayHi('大家好') from dual; 深入浅出Oracle 主讲:邹振兴
子程序二:函数 --通过员工编号返回员工姓名 create or replace function FSearchName(emp_no number) return varchar2 is empname varchar2(20); begin select ename into empname from emp where empno=emp_no; return empname; end; select FSearchName(7369) from dual; 深入浅出Oracle 主讲:邹振兴
子程序二:函数 创建函数语法 create [or replace] function 函数名称[(参数列表)] return is | as begin 可执行部分; [Exception] end; 深入浅出Oracle 主讲:邹振兴
子程序二:函数 删除过程与函数 授予其他用户执行子程序的权限 drop procedure 过程名; drop function 函数名; grant execute on 子程序名 to 用户名; 深入浅出Oracle 主讲:邹振兴
过程与函数比较 过 程 函 数 作为 PL/SQL 语句执行 作为表达式的一部分调用 在规格说明中不包含 RETURN 子句 函 数 作为 PL/SQL 语句执行 作为表达式的一部分调用 在规格说明中不包含 RETURN 子句 必须在规格说明中包含 RETURN 子句 不返回任何值 必须返回单个值 可以包含 RETURN 语句,但是与函数不同,它不能用于返回值 必须包含至少一条 RETURN 语句 深入浅出Oracle 主讲:邹振兴
子程序三:自主事务处理 自主事务处理 PRAGMA AUTONOMOUS_TRANSACTION 用于标记子程序为自主事务处理 主事务处理启动独立事务处理 然后主事务处理被暂停 自主事务处理子程序内的 SQL 操作 然后终止自主事务处理 恢复主事务处理 PRAGMA AUTONOMOUS_TRANSACTION 用于标记子程序为自主事务处理 深入浅出Oracle 主讲:邹振兴
子程序三:自主事务处理 自主事务处理测试: 创建过程1,执行删除员工7369操作,并回滚 创建过程2,执行删除员工7499操作,并调用过程1 创建程序调用过程2 问哪个删除操作会回滚? 深入浅出Oracle 主讲:邹振兴
子程序三:自主事务处理 create or replace procedure testp1 is --pragma autonomous_transaction;--标识子程序为自主事务处理 begin delete from myemp where empno=7369; rollback; end; 深入浅出Oracle 主讲:邹振兴
子程序三:自主事务处理 create or replace procedure testp2 is begin delete from myemp where empno=7499; testp1; end; 深入浅出Oracle 主讲:邹振兴
组织子程序:程序包 程序包是对相关过程、函数、变量、游标和异常等对象的封装 程序包由规范和主体两部分组成 声明程序包中公共对象。包括类型、变量、常量、异常、游标规范和子程序规范等 程序包 规范 声明程序包私有对象和实现在包规范中声明的子程序和游标 主体 深入浅出Oracle 主讲:邹振兴
组织子程序:程序包 如何将众多的函数与过程组织起来? 定义包 create or replace package mypack is 根据员工编号判断用户是否存在 (函数) 如果存在则打印出员工姓名 (过程) 定义包 create or replace package mypack is procedure PrintName(eno number); function IsHaveEmp(eno number) return boolean; end; 深入浅出Oracle 主讲:邹振兴
create or replace package body mypack 包主体 create or replace package body mypack is procedure PrintName(eno number) mybool boolean; myname varchar2(20); begin mybool:=IsHaveEmp(eno); if mybool =true then select ename into myname from emp where empno=eno; dbms_output.put_line(myname); else dbms_output.put_line('不存在该员工'); end if; end; function IsHaveEmp(eno number) return boolean counter number; select count(*) into counter from emp where empno=eno; if counter>0 then return true; return false; 深入浅出Oracle 主讲:邹振兴
组织子程序:程序包 返回查询结果集(游标) 包主体 create or replace package testpack as Type mytype is ref cursor; procedure GetAllEmp(mycur out mytype,tname in varchar2); end; 深入浅出Oracle 主讲:邹振兴
create or replace package body testpack as 包规范 create or replace package body testpack as procedure GetAllEmp(mycur out mytype,tname in varchar2) str varchar2(100); begin str:='select * from '|| tname; open mycur for str; end; 深入浅出Oracle 主讲:邹振兴
总结 Pl-sql块是oracle编程中最重要的结构。 游标是oracle编程中最生要的工具。 包可以多个存储过程与函数组织起来。 深入浅出Oracle 主讲:邹振兴