Oracale学习
1.什么是Oracle数据库、Oracle数据库的逻辑存储结构、Oracle数据类型、Oracle权限体系
- Oracle是一种关系数据库管理系统(RDBMS)。关系数据库是按照二维表结构方式组织的数据集合,每个表体现了集合理论中定义的数学概念————关系。它是一个数据容器,包含了表、索引、视图、过程、函数、包等对象,并对这些对象进行统一的管理。用户只有和一个确定的数据库连接,才能使用和管理该数据库中的数据。
- oracle存储结构分为物理存储结构和逻辑存储结构
物理存储结构是数据文件、日志文件、参数文件、控制文件
逻辑存储结构是块(block)>区(extent)>段(segment)>表空间(tablespace)
块(block),oracle用于管理存储的最小单元,也是逻辑存储结构的最小。块的大小在数据库创建是就已经决定了不能修改,oracle以块为单位进行输入输出操作。
一般数据存放在一个块中,而如果一条数据过大,就会连续占用几个块,将数据分在存储在几个块,这个过程为行链接。
当用户在做update更新时,原本在一个数据块中的数据,使这条记录变长,已经无法容纳这条数据,oracle会将整条数据迁移到另一个新的数据块,在原先的数据块中做一个指针指向新的数据块。这叫行迁移。
区(extent),由一个或多个连续的块组成,oracle在进行存储空间的分配和回收的最小单位,段中的区空间不足时,会为该段分配新的区。
段(segment),由一个或多个区组成,可以是连续的,也可以不连续,是一个独立的逻辑结构,是存储对象、表、索引的数据对象,一个段属于一个数据对象,每创建一个新的的数据对象,就会创建新的独立段。不同类型的数据对象有不同的段:数据段、索引段、回滚段、临时段。
表空间(tablespace),逻辑结构最高级,一个Oracle数据库由一个或多个表空间组成,一个表空间则对应着一个或多个物理的数据文件,建立数据库是会创建一些默认的表空间,比如system表空间,sysaux表空间等,几种常见的表空间:数据表空间、系统表空间、回滚表空间、临时表空间。 - 常用的数据类型有:
一.数值类型
number:
在Oracle中取消了在mysql中的int类型,使用number代替,如果你在创建
数据库表的时候使用了int类型会自动转换成number类型,并且Oracle没有
这个”auto_increment”属性,所以它没法像MySQL般在表内定义自增主键。
但是,Oracle里的序列(SEQUENCE),可间接实现自增主键的作用;
number有两个参数:
number(m,n):m用来表示有几位有效数字最大是38位,n表示小数点以后可以
有几位,多出来的位数要四舍五入。
二:字符类型
char:
用于存储固定长度的字符串,一个空间占用1个字节,最多存储2000个字节,
并且在存数据的时候,给的数据占不满给定的空间也会自动用空格补满空间,如果长
度超出了就会报错;
varchar2:
是Oracle特有的数据类型,Oracle中不提倡使用varchar; varchar2用于存储可
变长度的字符串。最大长度是char的两倍,也就是4000个字节,在存数据的时候,
给的数据占不满给定的空间会自动截断,省空间,如果长度超出了会补长,不会报
错;并且它将原本varchar可以存储空字符串的特性转换成了可以存储null值,提供
了向后兼容的能力;
但是为什么不直接全部使用varchar2呢?
1.VARCHAR2虽然比CHAR节省空间,但是假如一个VARCHAR2列经常被修改,而且每次
被修改的数据的长度不同,这会引起‘行迁移’(RowMigration)现象,而这会造成多
余的I/O,是数据库设计和调整中要尽力避免的,在这种情况下用CHAR代替VARCHAR2会
更好一些;
2.还有就是当我们存储已知固定长度的数据时,比如:手机号(11位)、身
份证号码(18位)等,可以考虑使用 char。因为,在查询数据时,对于 char 类型
字段,是全字符整体匹配;而 varchar2 是一个字符一个字符的进行匹配;
3.并且char的效率要比varchar2高一些,为了提高效率就必须牺牲一些空间。
nchar:
用于存储固定长度的字符串,一个空间占用2个字节,最多存储2000个字节,并且
在nchar中存储字符,数字和文字都是占用两个字节;
nvarchar2:
用于存储可变长度的字符串,一个空间占用2个字节,最大长度是 NCHAR 的两倍,
也就是4000个字节。
三:日期类型
Oracle日期类型主要使用 date 和 timestamp 数据类型。
date:
用于存储日期和时间类型,date 类型的默认格式为:DD-MM-YYYY。
timestamp:
时间戳类型,与 date相比较,timestamp类型具有小数位毫秒数,比 DATE 的精
度更高。
四:大数据类型与二进制类型
long:
用于存储可变长度的超长字符串,最大长度为2G,通常用于存储备注字段,或者
varchar2 和 nvarchar2 不够存储时。
lob:
lob又分为三个:
clob :是一种字符型大型对象(Character Large Object),最大长度为4G,
存储与字符集相关。
nclob:根据字符集而定的字符数据,最大长度为4G。
blog:是一种二进制大型对象(Binary Large Object),最大长度为4G,适用于
存储非文本的字节流数据,如:视频、音频等。
raw:固定长度的二进制数据,最大长度 2000个字节,可存储多媒体视频、音频格式等。
long raw:可变长度的二进制数据,最大长度2G,与 RAW 类似。
bfile:存储在数据库之外的二进制数据,最大长度4G。
rowid:
行地址,十六进制串,表示行在所在的表中唯一的行地址,该数据类型主要用于返回
ROWID伪列,常用在可以将表中的每一条记录都加以唯一标识的场合。数据表中记录的
唯一行号,占10个字节。
nrowid:
二进制数据表中记录的唯一行号,最大长度4000个字节。
2.索引、同义词、序列 (Sequences)、视图(View)
- 视图
什么是视图?
视图是一个虚 表 \color{red}{虚表}虚表
视图建立在已有表的基础上,视图赖以建立的这些表称为基 表 \color{red}{基表}基表
向视图提供数据内容的语句为s e l e c t 语 句 \color{red}{select 语句}select语句,可以将视图理解为存 储 起 来 的 s e l e c t 语 句 \color{red}{存储起来的select语句}存储起来的select语句
视图向用户提供基表数据的另一种表现形式
最 大 的 优 点 就 是 简 化 复 杂 的 查 询 。 \color{red}{最大的优点就是简化复杂的查询。}最大的优点就是简化复杂的查询。 - 序列
在很多数据库中都存在一个自动增长的列,如果现在要想在oracle中完成自动增长的功能,则只能依靠序列完成,所有的自动增长操作,需要用户手工完成处理。并且Oracle将序列值装入内存可以提高访问效率。
序列:可供多个用户用来产生唯一数值的数据库对象:
自动提供唯一的数值
共享对象
主要用于提供主键值
将序列值装入内存可以提高访问效率 - 索引
索引是用于加速数据存取的数据对象。合理的使用索引可以大大降低i/o的次数,从而提高数据访问性能。
一种独立于表的模式对象,可以存储在与表不同的磁盘或表空间中
索引被删除或损坏,不会对 表产生影响,其影响的只是查询的速度
索引一旦建立,Oracle管理系统会对其进行自动维护,而且由Oracle管理系统决定何时使用索引,用户不用再查询语句中指定使用哪个索引
再删除一个表时,所有基于该表的索引会自动被删除
通过指针加速Oracle服务器的查询速度
通过快读定位数据的方法,减少磁盘 I/O - 同义词
方便范文其它用户的对象
缩短对象名字的长度
3.SQL常用语句(DML\DDL\DCL)
oracle安装成功之后,执行一下语句进行优化:
在cmd输入sqlplus然后用system用户登录
ALTER SYSTEM SET DEFERRED_SEGMENT_CREATION=FALSE; /关闭空表不分配空间/
ALTER SYSTEM SET SEC_CASE_SENSITIVE_LOGON = FALSE; /关闭大写敏感/
ALTER PROFILE DEFAULT LIMIT PASSWORD_LIFE_TIME UNLIMITED;/关闭用户口令过期/
ALTER PROFILE DEFAULT LIMIT FAILED_LOGIN_ATTEMPTS UNLIMITED;/关闭口令尝试错误次数限制/
alter system set processes=800 scope=spfile;
alter system set sessions=885 scope=spfile;
alter user SYSTEM identified by manager;
grant ALTER SESSION to connect;
grant CREATE DATABASE LINK,CREATE VIEW,CREATE SYNONYM to resource;
- 创建表空间
sqlplus
system
conn sys/oracle as sysdba
create tablespace test1_tablespace datafile ‘test1file.dbf’ size 10m;
create temporary tablespace temptest1_tablespace tempfile ‘tempfile.dbf’ size 10m;
select file_name from dba_data_files where tablespace_name = ‘TEST1_TABLESPACE’; - Oracle的SQL
DDL(Data Definition Language)数据定义语言
DML(Data Manipulation Language)数据操作语言
DCL(Data Control Language)数据控制语言
TCL(Transaction Control Language)事务控制语言
常用的DDL语句包括
create table:创建数据库表
create index:创建数据库表的索引
drop table:删除数据库表
drop index:删除数据库表的索引
truncate:删除表中的所有行
alter table:更改表结构,增加,修改,删除列。
alter table add constraint:在已有的表上增加约束
常用的DML语句包括
insert:添加数据到数据库中
update:修改数据库中的数据
delete:删除数据库中的数据
select:选择(查询)数据
常用的DCL语句包括
grant:将权限或角色授予用户或其他角色(授予访问权限)
revoke:从用户或数据库角色回收权限(撤销访问权限)
lock:对数据库的特定部分进行锁定
常用的TCL语句
commit:提交事务处理
rollback:事务处理回退
savepoint:设置保存点
4.存储过程(Procedure)、自定义函数(Function)
5.事务(Transaction)、异常处理
5.1事务
5.1.1事务的相关概念
-
什么是事务?
事务用于保证数据的一致性,它是一组相关的数据改变SQL语句,这组SQL语句对数据的改变要么同时成功,要么同时失败。常用的事物sql语句有insert,update,delete。事务的目的是改变数据库中的数据。
应用场景:网上转帐 -
事务的ACID属性(是指数据库管理系统在写入或更新资料的过程中,为保证事务是正确可靠的,所必须具备的四个特点)
原子性:指整个数据库事务是不可分割的工作单元。原子性确保在事务中的所有操作要么都发生,要么都不发生。(举例:张三给李四转帐,张三转帐,李四收钱,这两步必须同时发生或同时不发生)
一致性:一旦一个事务结束了,不论成功与否,系统所处的状态和它的业务规则是一致的。即数据应当不会被破坏。(举例:张三李四一共有100元,张三转帐李四收钱后总共还是100元)
隔离性:指多个事物同时操作一个数据时,每个事务都有各自完整的数据空间。即避免多个事务并发执行时由于交叉执行而导致数据的不一致
持久性:指一个事务一旦完成,事务的结果应该持久化。即对数据的修改就是永久的,即便系统故障也不会丢失。 -
Oracle中的事务只用insert,update,delete需要使用commit(举例insert,演示系统)。因为在oracle中,有个“缓冲区"的概念,数据库会将数据加载到缓冲区中,而SQL语句操作的是缓冲区中的数据,并不会影响(改变)数据库中的数据,如果想要改变数据库中的数据,需要使用commit命令。
·事务相关的环境变量一AUTOCOMMIT
-Oracle数据库服务器默认为非自动提交事务模式。
. SHOWRUTOCOMMIT;–查看
. SET AuTocOMMIT ON|OFF;–更改
在oracle中自动提交默认是关的(在cmd中输入命令如下图)。
-
为什么oracle中自动提交默认是关的?
这样更加合理,以免误操作时可以rollback回滚
·隐式事务控制:
一自动隐式提交事务:
·执行一个DDL语句、执行一个DCL语句、从SQLPlus正常退出(exit.quit)
一自动隐式回滚事务:
·强行退出SQLPlus、客户端到服务器的连接异常中断、系统崩溃。
·显示事务控制:(建议使用)
一提交和结束事务:COMMIT;
一回滚事务:ROLLBACK TO 回滚点;ROLLBACK ;回滚到最初;_-设置事务回滚点: SAVEPOINT回滚点;
举例:在cmd中演示userinfo表;
5.1.2事务的隔离级别
-
事务的隔离级别(oracle默认READ COMMITTED,Oracle提供read committed和serializable,并提供了一个非SQL标准的read-only级别。Serializable隔离级别提供了read-only事务所提供的读一致性,同时又允许DML(update/insert/delete)操作。)
数据库允许多个并发事务同时对数据进行读写和修改的能力。隔离性可以防止多个事务并发执行时由于交叉执行而导致数据的不一致。事务隔离分为不同级别,包括读未提交(Read uncommitted)、读提交(read committed)、可重复读(repeatable read)和串行化(Serializable)。
读未提交(Read uncommitted)
读未提交是指,一个事务还没提交时,它做的变更就能被别的事务看到。(举例:公司发工资了,领导把5000元打到张三的账号上,但是该事务并未提交,而张三正好去查看账户,发现工资已经到账,是5000元整,非常高兴。可是不幸的是,领导发现发给张三的工资金额不对,是2000元,于是迅速回滚了事务,修改金额后,将事务提交,最后张三实际的工资只有2000元,张三空欢喜一场。)
读提交(read committed)
读提交是指,一个事务提交之后,它做的变更才会被其他事务看到。(举例:张三拿着工资卡去消费,系统读取到卡里确实有2000元,而此时他的老婆也正好在网上转账,把张三工资卡的2000元转到另一账户,并在张三之前提交了事务,当张三扣款时,系统检查到张三的工资卡已经没有钱,扣款失败,张三十分纳闷,明明卡里有钱,怎么会扣款失败。)
可重复读(repeatable read)
可重复读是指,一个事务执行过程中看到的数据,总是跟这个事务在启动时看到的数据是一致的。当然在可重复读隔离级别下,未提交变更对其他事务也是不可见的。(举例:张三的老婆工作在银行部门,她时常通过银行内部系统查看张三的信用卡消费记录。有一天,她正在查询到张三当月信用卡的总消费金额为80元,而张三此时正好在外面胡吃海塞后在收银台买单,消费1000元,即新增了一条1000元的消费记录,并提交了事务,随后张三的老婆将张三当月信用卡消费的明细打印到A4纸上,却发现消费总额为1080元,张三的老婆很诧异,以为出现了幻觉,幻读就这样产生了。)
注:MySQL的默认隔离级别就是Repeatable read。
串行化(Serializable)
串行化,顾名思义是对于同一行记录,“写”会加“写锁”,“读”会加“读锁”。当出现读写锁冲突的时候,后访问的事务必须等前一个事务执行完成,才能继续执行。Serializable是最高的事务隔离级别,同时代价也花费最高,性能很低,一般很少使用,在该级别下,事务顺序执行,不仅可以避免脏读、不可重复读,还避免了幻像读。
-
事先不采取隔离机制会引发的并发问题
-第一类丢失更新:撤消一个事务时,把其它事务已提交的更新数据也撤消了。(举例:取款事务A查询余额为100,存款事务B查询也是100,然后B存入100提交事务,A取100,但撤回事务,此时余额为100(实际应为200))
-脏读:一个事务读到另一个事务未提交的更新数据。举例:取款事务A查询余额为200,然后A取出100提交事务。存款事务B此时查询为100,然后B存入100提交事务,此时A撤回事务。此时余额为200(实际应为300))
-不可重复读:一个事务读到另一个事务已经提交的更改数据。
-第二类丢失更新:一个事务覆盖另一个事务已经提交的更新数据。
-幻读:一个事务读到另一个事务已提交的新增或已删除数据。 -
设置Oracle的隔离级别
Oracle设置事务的隔离级别:
设置一个事务的隔离级别:
Set transaction isolation level read committed;
Set transaction isolation level serializable;
Set transaction read only;
设置整个会话的隔离级别:
Alter session set isolation level serializable;
Alert session set isolation level read committed; -
Java设置数据库的隔离级别
在Java中使用隔离级别: Connection.setTransaction(Connection.TRANSACTION_READ_COMMITTED);
5.1.3oracle中事务的锁
锁是实现并发的主要手段,在数据库中应用频繁,但很多都由数据库自动管理,当事务提交后会自动释放锁。
1、锁表原因
- 可能是修改表中的数据,忘了提交事务会造成锁表。
- Oracle数据库操作中,我们有时会用到锁表查询以及解锁和kill进程等操作。
2、锁表查询的代码有以下的形式
select count(*) from v$locked_object;
select * from v$locked_object;
3、查看哪个表被锁
select b.owner,b.object_name,a.session_id,a.locked_mode
from v$locked_object a,dba_objects b
where b.object_id = a.object_id;
4、查看是哪个session引起的
select a.OS_USER_NAME, c.owner, c.object_name, b.sid, b.serial#, logon_time
from v$locked_object a, v$session b, dba_objects c
where a.session_id = b.sid
and a.object_id = c.object_id
order by b.logon_time;
5、杀掉对应进程
需要用户有管理员的权限操作,其中1025为sid,41为serial#。
alter system kill session '1025,41';
6、如何避免锁表
常见问题是用户更新操作没有提交事务,所以:如果单独更新操作,需要写2个操作 SQL,一个是更新操作SQL语句,另一个是commit语句提交事务。
7.隐式锁和显式锁
表的隐式锁定
在Oracle数据库中,修改数据操作时需要一个隐式的独占锁,以锁定修改的行,直到修改被提交或撤销为止。如果一个会话锁定了数据,那么第二个会话要想对数据进行修改,只能等到第一个会话对修改使用COMMIT命令进行提交或使用ROLLBACK命令进行回滚撤销后,才开始执行。因此应养成一个良好的习惯:执行修改操作后,要尽早地提交或撤销,以免影响其他会话对数据的修改。
对emp表的SCOTT雇员记录进行修改,测试隐式锁。
步骤1:启动第一个SQL*Plus,以SCOTT账户登录数据库(第一个会话),修改SCOTT记录,隐式加锁。
UPDATE emp SET sal=3500 where empno=7788;
步骤2:启动第二个SQL*Plus,以SCOTT账户登录数据库(第二个会话),进行记录修改操作。
UPDATE emp SET sal=4000 where empno=7788;
步骤3:对第一个会话进行解锁操作:
COMMIT;
步骤4:查看第二个会话,此时有输出结果:
步骤5:提交第二个会话,防止长时间锁定。
表的显式锁定
锁定行
对emp表的部门10的雇员记录加显式锁,并测试。对部门10加显式锁:
步骤1:对部门10加显式锁:
SELECT empno,ename,job,sal FROM emp WHERE deptno=10 FOR UPDATE;
步骤2:启动第二个SQL*Plus(第二个会话),以SCOTT账户登录数据库,对部门10的雇员CLARK进行修改操作。
UPDATE emp SET sal=sal+100 where empno=7782;
步骤3:在第一个会话进行解锁操作:
COMMIT;
步骤4:查看第二个会话,有输出结果:
锁定表
LOCK语句用于对整张表进行锁定。
对表的锁定可以是共享(SHARE)或独占(EXCLUSIVE)模式。共享模式下,其他会话可以加共享锁,但不能加独占锁。在独占模式下,其他会话不能加共享或独占锁。
【训练1】 对emp表添加独占锁(排它锁/写锁:这种模式的锁防止资源的共享,用做数据的修改。假如有事务T给数据A加上该锁,那么其他的事务将不能对A加任何的锁,所以此时只允许T对该数据进行读取和修改,直到事务完成将该类型的锁释放为止。)。
步骤1:对emp表加独占锁:
LOCK TABLE emp IN EXCLUSIVE MODE;
允许的操作:在一个表中只能有一个事务对该表实行排它锁,排它锁仅允许其它的事务查询该表。
禁止的操作:拥有排外锁的事务禁止其它事务执行其它任何DML类型的语句或在该表上加任何其它类型的锁。
insert into emp values('7935','MILLER','CLERK','7782',to_date('1982-01-23 10:00:00', 'YYYY-MM-DD HH24:MI:SS'),'1300','','10');
步骤2:对表进行解锁操作:
COMMIT;
【训练2】 对emp表添加共享锁(读锁:该模式锁下的数据只能被读取,不能被修改。如果有事务T给数据A加上共享锁后,那么其他事务不能对其加排他锁,只能加共享锁。加了该锁的数据可以被并发地读取。)。
步骤1:对emp表加共享锁:
Lock Table emp In Share Mode;
在该锁定模式下,不允许任何用户更新表。但是允许其他用户发出 select…from for update 命令对表添加RS锁。
允许的操作:一个共享锁由一个事务控制,仅允许其它事务查询被锁定的表。一个有效的共享锁明确地用Select … For update形式锁定行,或执行Lock Table TableName In Share Mode语法锁定整个表,不允许被其它事务更新。
禁止的操作:一个共享锁由一个事务来控制,防止其它事务更新该表或执行下面的语句:
LOCK TABLE TableName IN SHARE ROW EXCLUSIVE MODE;
LOCK TABLE TableName IN ROW EXCLUSIVE MODE
步骤2:对表进行解锁操作:
COMMIT;
1) 共享模式
不允许其他用户插入,更新和删除行,多个用户可以同时在同一表上设置共享锁,这样设置锁的多个用户都只能执行查询
lock table emp in share mode;
2)共享更新模式(in share update mode)
允许多个用户同时锁定表的不同行, 允许其他用户进行DML(insert update delete
select)操作 , 除了已锁定的行
如: lock table emp in share update mode;
select * from emp where deptno=30 for update //锁定的行
其他用户不能delete ,update 部门30的雇员信息
其他用户可以查看锁定的行: select * from emp where deptno=30
3)排他锁模式(限制性强)
不允许其他用户插入,更新和删除行, 允许查看数据,但只有一个用户可以在表中放置排他锁
lock table emp in exclusive mode;
三) 死锁
如:USERA: lock table scott.emp in share mode;
USERB: lock table scott.emp in share mode ;
USERA: update scott.emp set ename='Smith' where empno=7369;
USERB: update scott.emp set job='CLERK' where empno=7521;
发生死锁
5.2异常
5.2.1预定义异常
Oracle预定义的异常,有24个,对这种异常的处理无需在程序中定义,由Oracle自动引发。
-
举例zero_divide异常
–除数为0时不抛出异常报错
declare
n1 number(2) := 1;
n2 number(2) :=0;
result number;
begin
result := n1/n2;
dbms_output.put_line(result);
end;
–除数为0时抛出异常报错
declare
n1 number(2) := 1;
n2 number(2) :=0;
result number;
begin
result := n1/n2;
dbms_output.put_line(result);
exception
when zero_divide then
dbms_output.put_line(‘除数不能为0’);
end; -
举例值转换异常
declare
x number;
begin
x:= ‘a123’;–向NUMBER类型的变量x中赋值字符串,导致异常
dbms_output.put_line(x);
exception
when VALUE_ERROR then
DBMS_OUTPUT.PUT_LINE(‘数据类型错误’);
end;
5.2.2非预定义异常
其他标准的Oracle异常,对这种异常的处理,需用户在程序中定义,然后由Oracle自动将其引发。非预定义的异常只有编号没有名称。
1.在声明部分声明异常情况
异常情况(异常名) EXCEPTION;
2.将声明好的异常与标准的Oracle错误联系起来,使用EXCEPTION——INIT
PRAGMA EXCEPTION_INIT(异常情况(异常名),错误代码);
3.在程序块的异常处理部分对异常做相应处理。
在EXCEPTION块中做处理。
注:预定义的异常也可通过这种方式修改名称。
处理未命名的异常(非预定义)必须使用OTHERS处理或者用PRAGMA为异常确定名称;
- 举例ORA-02292
有一个异常:ORA-02292,没有名称,含义是当删除被子表引用的父表中的相关记录时发生。
表emp有外键关联表dept的主键,当部门10有员工时,不能删除部门10。如果我们做了这样的操作,就违反了约束条件。
父表:dept表
子表:emp表
delete from dept where deptno=10;
提示:违反完整性约束条件
declare
myexception exception;
pragma exception_init(myexception,-02292);
begin
delete from dept where deptno=10;
exception
when myexception then
dbms_output.put_line(‘10部门有员工,不能删除’);
when others then
dbms_output.put_line(‘其他异常’);
end;
5.2.3自定义异常
由用户在程序自定义的异常,当出现某种用户认为的非正常情况时,显式地在程序中将其引发。
1.在声明部分声明异常情况
语法:
异常情况(异常名) EXCEPTION;
2.通过raise语句触发。手动抛出异常。
语法:
raise 异常情况(异常名);
3.在程序块的异常处理部分对异常做相应处理。
在EXCEPTION块中做处理。
若自定义的异常抛出后没有在EXCEPTION中处理,会报“用户自定义的异常错误未得到处理”的错误。
- 举例:在emp表中查询james的工资,如果工资小于5000,则引发自定义异常
declare
myexception exception;
v_sal emp.sal% type;
begin
select sal into v_sal from emp where ename=‘JAMES’;
IF v_sal<5000 then
raise myexception;
end if;
dbms_output.put_line(‘JAMES的工资是:’||v_sal);
exception
when myexception then
dbms_output.put_line(‘工资太少了’);
when no_data_found then
dbms_output.put_line(‘没有这个员工’);
end;