数据库体系结构
物理存储结构与Oracle启动时关系是 依次打开 参数(startup nomount)、控制(startup mount)、数据文件(open)
物理存储结构:指实际的文件存储形式
数据文件:扩展名.dbf。主要用来存放系统数据、数据字典、索引、表等信息
数据字典:V$DATAFILE
数据字典:Oracle数据库字典通常是在创建和安装数据库时被创建的,Oracle数据字典是Oracle数据库系统工作的基础,没有数据字典的支持,Oracle数据库系统就不能进行任何工作
临时文件:属于数据文件, 存放在临时表空间中
控制文件:扩展名.ctl。是一个二进制文件。主要用来保存数据库中物理结构信息。
联机重做日志文件:扩展名.log。一个包含数据变更记录的文件集合。
日志操作模式:联机日志、归档日志。
数据块:存储空间中能够读写的最小逻辑存储单位。
区:由一个或多个数据块构成。通过一次分配获得特定数量的相邻数据块,用于分配存储空间。
段:由一个或多个区构成,用于存储特定类型的信息。
表空间:由多个段构成。是逻辑存储结构中最大的存储单位,是物理存储结构中的数据文件对应的。
数据字典:DBA_TABLESPACES DBA_DATAFILES
Oracle数据库的内存结构:
系统全局区(SGA):数据库缓冲区、重做日志缓冲区、共享池、大型池、JAVA池、数据流池、固定的SGA
程序全局区(PGA):SQL工作区、会话内存、私有SQL区
用户全局区 软件代码区
Oracle数据库的进程结构:
客户端进程(用户进程):当运行一个应用程序后,操作系统就会创建一个客户端进程来运行应用程序。
服务端进程:接收客户端进程中的请求,也就是用来建立客户端与数据库的通信
后台进程:一种特使的服务器进程,完成数据库的后台管理工作。
Oracle实例(instance):是唯一访问数据块的方法;一个实例管理一个数据库。
总结:Oracle的体系结构由存储结构与软件结构组成,存储结构由物理存储结构与逻辑存储结构组成,Oracle对数据的组织与存储是使用逻辑存储结构来进行管理的;而软件结构由内存结构与后台进程结构组成,他们组成了Oracle的实例。
表空间
概念:表空间由多个逻辑区域构成的,把数据库分成了不同的区域,每个表空间中存放多个数据文件。表空间由系统表空间和非系统个表空间组成。系统自带SYSTEM(默认表空间)和SYSAUX两个表空间。
创建表空间:CREATE [TEMPORARY] TABLESPACE tablespace_name
TEMPFILE|DATAFILE ‘xx.dbf’ SIZE integer[K|M]
[AUTOEXTEND[OFF|ON [NEXT integer[K|M]|MAXSIZE [UNLIMITED|integer[K|M]]
[MINMUN EXTENT integer[K|M]]]
[ONLINE|OFFLINE]
[TEMPORARY]:创建临时表空间,否则就是永久表空间
TEMPFILE|DATAFILE:创建表空间中临时文件或数据文件
AUTOEXTEND OFF:不允许自动扩展数据文件大小。
AUTOEXTEND ON :允许扩展数据文件的大小。
ONLINE|OFFLINE:选择ONLINE时,表空间创建完成后可以直接使用;选择OFFLINE时,表空间创建完成后暂时不能使用,只有将表空间状态更改成ONLINE状态才能使用。默认情况下,创建完表空间就是ONLINE状态。
例子:创建一个名为tablespace_test,数据文件为testdatafile_1,大小为10MB,不允许自扩数据文件大小的表空间。
Create tablespace tablespace_test
Datafile ‘testdatafile_1.dbf’ size 10m
Autoextend off;
设置默认表空间、临时表空间:ALTER USER username
DEFAULT|TEMPORARY TABLESPACE tablespace_name
修改表空间:ALTER TABLESPACE tablespace_name
[ADD DATAFILE|TEMPFILE xx.dbf SIZE integer[K|M]]
[DROP DATAFILE|TEMPFILE file_name]
[RENAME oldname TO newname]
[AUTOEXTEND[OFF|ON [NEXT integer[K|M] | MAXSIZE[UNLIMITED|integer[K|M]]
[MINMUM EXTEND integer[K|M]]]]
[ONLINE|OFFLINE]
ADD子句:用于添加数据文件。
DROP子句:用于删除数据文件,但是不能删除表空间中第一个数据文件。
RENAME子句:用于重命名表空间。
例子:在表空间tablespace_test中添加一个名为test_datafile1的数据文件
ALTER TABLESPACE table_test
ADD DATAFILE ‘test_datafile1.dbf’ SIZE 1M;
删除表空间:DROP TABLESPACE tablespace_name
[INCLUDING CONTENTS[{AND|KEEP}DATAFILES]]
[CASCADE CONSTRAINTS]
INCLUDING CONTENTS子句:用于将表空间中的数据库对象也一并删除,如果在其后面加上了AND DATAFILES子句,用于将表空间中的数据文件也一并删除;如果在其后面加上了KEEP DATAFILES子句,表示在删除表空间之后,保留表空间中的数据文件。
CASCADE CONSTRAINTS子句:用于删除表空间中的数据文件,但是只能删除表空间中最新创建的数据文件。
例子:删除表空间tablespace_test同时将其中的数据文件一并删除
DROP TABLESPACE tablespace_test
INCLUDING CONTENTS AND DATAFILES;
连接模式:用connect usrename/password as sysdba
前提是需要配置监听
模式(schema)
模式是一个逻辑容器,你可以把模式理解为文件夹,方便我们对一组数据库对象进行管理。通常,一个大的系统由许多小的系统组成,我们可以给每个小的系统创建一个模式,把该系统中用到的数据库对象都创建在这个模式中。例如,每个公司都会有员工,我们可以创建一个模式 HR,然后在 HR 中创建一个表 EMPLOYEES 来维护员工信息,如果需要在其他模式中访问 EMPLOYEES 表,我们需要指定它的全名 HR.EMPLOYEES。
模式对象(schema object)
在模式中创建表(table),分区(partition),视图(view),索引(index),包(package),存储过程(procedure),函数(function),触发器(trigger),类型(type),序列(sequence),同义(synonym)等数据库对象都是模式对象。
非模式对象
其他数据库对象。如用户、权限、表空间等。
Oracle服务器的类型或操作模式
专用服务器模式:在用户登录时,oracle会创建一个新的服务进程,这个服务器进程会在会话生存期中专门为这个连接服务。对于每个会话,都会生成一个新的专用服务器进程,会话与专用服务器进程之间存在一对一的映射关系。
专用服务器模式适用场景:
1:只有少量的客户端连接系统或数据仓库系统。数据集市系统等
2:联机事务处理系统(OLTP)。当然联机事务处理系统必须要符合下面两个条件
A 用户连接请求数大于共享进程
B 事务大部分是长事务或者大事务
共享服务器模式:是一种多线程服务器模式,采用这种方式连接,不会对每条用户连接创建另外的线程或新的进程。
操作数据库的工具:SQL Plus、SQL Developer、企业管理器(Oracle Enterprise Manager,OEM)
正确理解数据库网络连接及其配置与使用
配置监听服务:作用是帮助用户来创建客户端到服务器之间的连接。
过程:配置监听程序→为该监听程序配置监听服务用于监听某个数据库。
监听服务的是安装在bin文件夹中的LSNRCTL.EXE
启动监听服务命令:LSNRCTL START 监听服务名
停止监听服务命令:LSNRCTL STOP 监听服务名
查看监听服务状态:LSNRCTL STATUS 监听服务名
配置网络服务名:实际上并不需要每一个客户端都安装oracle数据库的客户端和服务端,而只要在一个专门的服务器安装一个oracle服务端,每个用户只需要安装oracle客户端即可。这样能保证开发过程中数据库的共享性也方便开发人员开发。每个客户端使用网络服务名来访问oracle数据库的服务端。
配置监听服务和网络服务名都可以在oracle自带的Net Configuration Assistant创建配置。
管理数据库服务
启动数据库服务的方式:1.在windows操作系统的服务中启动;2.在DOS界面用net start 服务名 来启动。
启动数据库服务器实例:STARTUP [NOMOUNT|MOUNT|OPEN]
NOMOUNT:只启动数据库实例
MOUNT:启动实例并加载数据文件
OPEN:默认的数据库启动方式。用这个也提供了两个选项(OPEN READ ONLY(只读)和OPEN READ WRITE(读写模式打开))。
停止数据库服务的方式:1.在windows操作系统的服务器停止;2.在DOW界面用net stop 服务名 来停止
停止数据库服务器实例:SHUTDOWN[IMMEDIATE|NORMAL|TRANSACTIONAL|ABORT]
IMMEDIATE:立即关闭数据库,将所有事务回滚。
NORMAL:默认选项。停止数据库服务,不允许在创建数据库连接。
TRANSACTIONAL:以事务的方式来关闭,等待用户的事务完全执行完成后关闭数据库服务。
ABORT:终止所有正在执行的事务,立即停止数据库服务。这个选项停止是最快的,但是再次启动就会花较多的时间。
约束、事务概念与应用
约束概念:约束是用来束缚表中数据的,提高表中数据的完整性。为表提供的约束有主键约束、非空约束、唯一约束、检查约束、外键约束。
1主键约束:每个表中只能有一个,但是可以由多个列构成一个主键约束,作用是标识记录的唯一性。主键约束值的列不能为空,oracle会为主键约束列生成索引。当这些列作为条件查询时,会提高查询速度。
添加主见约束:
①列级添加法:(只能为一个列设置主键约束)
CREATE TABLE table_name(
列名1 数据类型 [CONSTRAINT 约束名] PRIMARY KEY,
列名2 数据类型,
……
);
②表级添加法:(能为多个列设置主键约束)
CREATE TABLE table_name(
列名1 数据类型,
列名2 数据类型,
……
[CONSTRAINT 约束名] PRIMARY KEY(列名1,列名2, …)
);
主键约束名通常以pk开头,比如给id列设置主键约束,就可以命名为pk_id
修改表时添加主键约束:
ALTER TABLE table_name
ADD CONSTRAINT 约束名 PRIMARY KEY(列名1,列名2, …);
删除主键约束:
ALTER TABLE table_name
DROP CONSTRAINT 约束名;
或
ALTER TABLE table_name
DROP PRIMARY KEY;
2非空约束
在表中,有些列的值是必须要添加才有是有意义的。为了避免无效的表记录,可为表中必要添加值的列设置非空约束。
添加非空约束:(不能再表级设置非空约束)
CREATE TABLE table_name(
列名1 数据类型 NOT NULL,
列名2 数据类型 NOT NULL,
……
[CONSTRAINT]
)[TABLESPACE tablespace_name]
修改表时设置非空约束:(每次只能为一列设置非空约束)
ALTER TABLE table_name
MODIFY 列名 NOT NULL;
去除非空约束:(不需要删除,直接改成NULL)
ALTER TABLE table_name
MODIFY 列名 NULL;
3唯一约束:
用UNIQUE关键字表示,确保该列的值唯一。
与主键约束的相同点:两者都能能够保证列值的唯一性;
不同点:唯一约束允许列中有一个值是空值。
添加唯一约束:
① 列级添加法:
CREATE TABLE table_name(
列名1 数据类型[CONSTRAINT 约束名] UNIQUE,
列名2 数据类型[CONSTRAINT 约束名] UNIQUE,
……
[CONSTRAINT]
)[TABLESPACE tablespace_name]
②表级添加法:
CREATE TABLE table_name(
列名1 数据类型,
列名2 数据类型,
……
[CONSTRAINT 约束名]UNIQUE(列名1),
[CONSTRAINT 约束名]UNIQUE(列名2),
……
)[TABLESPACE tablespace_name]
UNIQUE前的[CONSTRAINT 约束名]可以省略,这样不用给约束命名。命名通常以uq开头。
在修改表时添加唯一约束:
ALTER TABLE table_name
ADD CONSTRAINT 约束名 UNIQUE(列名);
删除唯一约束:
ALTER TABLE table_name
DROP CONSTRAINT 约束名;
4检查约束:
用CHECK关键字表示,作用是检查每一列输入的值是否能满足标的需求。比如输入用户评分时,要求只输入1-5分。
添加检查约束:
① 列级添加法:
CREATE TABLE table_name(
列名1 数据类型[CONSTRAINT 约束名] CHECK(表达式),
列名2 数据类型[CONSTRAINT 约束名] CHECK(表达式),
……
);
“表达式”的结果是布尔型的。比如rating>0,其中rating是列名。
② 表级添加法:
CREATE TABLE table_name(
列名1 数据类型,
列名2 数据类型,
……
[CONSTRAINT 约束名]CHECK(表达式),
[CONSTRAINT 约束名]CHECK(表达式),
……
);
检查约束名一般以CHK开头,如果省略命名,系统会自动生成。
修改表时添加检查约束:
ALTER TABLE table_name
ADD CONSTRAINT 约束名 CHECK(表达式) ;
删除检查约束:
ALTER TABLE table_name
DROP CONSTRAINT 约束名;
5外键约束
外键约束是唯一一个设计两张表之间关系的约束。作用是保证数据的一致性。
创建外键约束:
① 建表时创建外键约束:
CREATE TABLE 表1(
列名1 数据类型[CONSTRAINT 约束名] REFERENCES 表2(列名),
列名2 数据类型,
……
);
这里表2是主表,列名是表2的主键。
②表级创建法:(一般使用表级创建)
CREATE TABLE 表1(
列名1 数据类型,
列名2 数据类型,
……
[CONSTRAINT 约束名]FOREIGN KEY(列名1)
REFERENCES 表2(列名)[ON DELETE CASCADE]
);
外键名称以FK开头。如果省略命名,系统会自动生成外键约束名。
[ON DELETE CASCADE]作用是表2中数据删除后,也会将表1联系的数据一并删除。
修改表时添加外键约束
ALTER TABLE 表1
ADD CONSTRAINT 约束名 FOREIGN KEY(列名1)
REFERENCES 表2(列名)
[ON DELETE CASCADE];
删除外键约束:
ALTER TABLE 表1
DROP CONSTRAINT 约束名;
修改约束:
除了非空约束,主键约束、唯一约束、外键约束、检查约束这4种约束在ORACLE中可以修改。
修改约束名称:
ALTER TABLE table_name
RENAME CONSTRAINT 旧名 TO 新名;
修改约束状态:
ALTER TBALE table_name
DISABLE|ENABLE CONSTRAINT 约束名;
事务
事务具有确保数据库中数据一致性和完整性的作用。
事务的特性:
①原子性:一个语句执行错误,那么全部语句都不执行。保证数据准确性。
② 一致性:只有数据提交后才能被查看。保证数据完整性。
③ 隔离性:事务之间不会出现互相干扰。避免“脏读”发生。
④ 持久性:一旦事务提交完成,将是对数据永久的修改。
事务的应用:
游标:
1定义游标
Declare
Cursor 游标名 IS SELECT 字段1,字段2,…FROM 表名 WHERE 条件;
定义对应字段;
2打开游标
Begin
Open 游标名;
3读取数据
Fetch 游标名 INTO 定义的字段;
操作语句;(必要时应该给游标定义对象,对象可以直接引用字段);
4关闭游标
Close 游标名;
连接查询、子查询的概念及使用
内连接
使用比较运算符根据每个表共有的列的值匹配两个表中的行。
包括等值连接(=)和非等值连接(<、>、<=、>=、!=、<>等)。
语法:
SELECT 表1名.列名,表2名.列名
FROM 表1 INNER JOIN 表2
ON 表1.同名列=表2.同名列;
--INNER可以忽略。
外连接
能查询出除了满足条件以外的数据。
包括左外连接、右外连接、全外连接。
语法:
SELECT 表1.列名,表2.列名
FROM 表1 RIGHT(LEFT/FULL) OUTER JOIN 表2
ON 表1.同名列=表2.同名列;
交叉连接查询
会产生笛卡尔积,产生“相乘”结果集的效果,同样也是不指定个条件。
语法:
SELECT * FROM 表1 CROSS JOIN 表2;
子查询
子查询就是嵌套查询,或说是在一个查询中包含另一个查询。
WHERE子句中的子查询:
例如:查询courses中price大于courses表中平均price的coursename和price。
SELECT coursename,price FROM courses WHERE price>(SELECT AVG(price) FROM courses);
Where可以使用的运算符:ANY(符合的其中一个数据) SOME(同左) ALL(满足的所有结果) IN(表示范围)
FROM子句中的子查询:
将FROM后面的查询作为结果集来查询。
例如:查询比AVG(price)高的coursename和price(其中a和b分别为表的别名)。
SELECT coursename,price FROM courses a,(SELECT typeid,AVG(price) AS avgprice FROM courses GROUP BY typeid) b WHERE a.typeid=b.typeid AND a.price>avgprice;
GROUP BY
将查询结果根据某列分组
例子:统计同名课程的数量
SELECT courseanme,COUNT(*) FROM courses
GROUP BY coursename;
带条件分组查询:(HAVING)
如果对分组的查询还要添加限制条件的话,用HAVING接条件
例子:统计每类课程的平均价格,并且要求显示平均价格大于200的类型及价格
SELECT typeid,AVG(price) FROM courses
GROUP BY typeid
HAVING AVG(price)>200;
排序
对有数值的列可以在查询后进行排序
例子:统计每类课程的平均价格,并按照平均价格降序排序。
SELECT typeid,AVG(price) FROM courses
GROUP BY typeid
ORDER BY AVG(price) DESC;
子查询大作业例子:
查询与自己同一工资级别的员工信息
select e.empno,e.deptno,e.ename,e.sal,s.grade from
emp e join salgrade s on
s.grade=(select s.grade from
emp e join salgrade s on
s.sal=(select sal from emp where
ename=’WUSIYUE’) and
e.sal between s.losal and s.hisal)and
e.sal between s.losal and s.hisal;
索引
类型:B树索引、位图索引、基于函数的索引、分区索引、域索引
B树索引:默认索引类型,是平衡树。用来存放物理地址ROWID。
位图索引:由二进制位组成,为每一个索引列值存储一个位图。不适于用对表数据频繁地增删改操作。
创建索引:(B树索引)
Create index 索引名
On 表名(列名);--非唯一索引
Create unique index 索引名
On 表名(列名);--唯一索引
(位图索引)
Create bitmap index 索引名
On 表名(列名);
不能为同一列设置多次索引。
Plsql编程、函数、 存储过程、触发器的概念及其使用
PL/SQL是oracle中用于编写语句块以实现复杂功能的语句。
PL/SQL中,数据类型包括系统预定义类型和用户自定义类型两种。
PL/SQL的语句的基本框架:
DECLARE
--变量和常量的定义部分
BEGIN
--具体操作部分
END;
流程控制语句:
1.IF语句
IF … THEN …;
END IF;
2.CASE语句
CASE …
WHEN …. THEN ….;
WHEN … THEN…;
…
ELSE …;
END CASE;
3.循环语句
①LOOP-EXIT-END
LOOP …;
IF… THEN…;
EXIT;
END IF;
END LOOP;
✖LOOP结束后一定要有EXIT不然会死循环。
②LOOP-EXIT-WHEN-ENP LOOP
LOOP
…;
EXIT WHEN
…;
END LOOP;
③WHILE-LOOP-END LOOP
WHILE …
LOOP
…;
END LOOP;
⑤ ④FOR-IN-LOOP-END LOOP
FOR 变量 IN 开始数…结尾数
LOOP
…;
END LOOP;
函数
数值函数
1绝对值
ABS(数) ABS(-122) 返回122
2取余函数
MOD(被除数,除数) MOD(5,3) 返回2
3取整函数
CEIL(数) 返回大于等于输入参数的最小整数 CEIL(5.22) 返回6
FLOOR(数) 返回小于等于输入参数的最大整数 FLOOR(5.22) 返回5
4四舍五入函数
ROUND(数,保留位数) ROUND(45.987,2) 返回45.99
5幂函数
POWER(数,次方) POWER(-3,3) 返回-27
6平方根函数
SQRT(数) SQRT(100) 返回10
7三角函数
SIN(数) SIN(30) 返回1/2
COS(数) COS(60) 返回1/2
TAN(数) TAN(45) 返回1
…..
字符函数
1字符长度函数
LENGTH(‘字符’) LENGTH(‘ABCD’) 返回4
LENGTH(132.45) 返回6
LENGTH(‘AA C D’) 返回6
2截取字符串函数
SUBSTR(字符串,开始位置,结束位置);
SUBSTR(‘123ABCabc’,1,3) 返回123
SUBSTR(‘123ABCabc’,4,3) 返回ABC
3字符大小写转换函数
LOWER(字符) 大写转小写 LOWER(‘A’) 返回a
UPPER(字符) 小写转大写 UPPER(‘a’) 返回A
4首字母大写转换函数
INITCAP(字符) INITCAP(‘anny’) 返回 Anny
日期函数
1获取系统时间
Select sysdate from 表; 返回格式为 DD-MON-RR 日-月-年
转换函数
聚合函数
1平均数
AVG(列名)
2最大值最小值
MAX(列名) MIN(列名)
存储过程
特点:一次编译多次使用,减少了语句的运行时间。
无参的存储过程
CREATE [OR REPLACE] PROCEDURE 存储过程名
{IS|AS}
BEGIN
…..;
END;
IS和AS在存储过程(PROCEDURE)和函数(FUNCTION)中没有区别,在视图(VIEW)中只能用AS不能用IS,在游标(CURSOR)中只能用IS不能用AS。
例子:创建存储过程读取用户信息表(userinfo)中全部数据。
CREATE PROCEDURE pro_test1
AS
CURSOR cursor_test
IS SELECT * FROM userininfo;
cur_record userinfo%ROWTYPE;
BEGIN
OPEN cursor_test;
LOOP
FETCH cursor_test INTO cur_record;
EXIT WHEN cursor_test%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(‘用户编号:’||cur_record.userid);
DBMS_OUTPUT.PUT_LINE(‘用户名:’||cur_record.username);
DBMS_OUTPUT.PUT_LINE(‘密码:’||cur_record.userpwd);
END LOOP;
CLOSE cursor_test;
END;
/
带参存储过程
CREATE [OR REPLACE] PROCEDURE 存储过程名(变量名1 IN|OUT 数据类型,变量名2 IN|OUT数据类型,…)
{IS|AS}
BEGIN
…..;
END;
例子:创建存储过程,根据输入的用户名输出密码。
CREATE PROCEDURE pro_test2(p_name IN VARCHAR2)
AS
CURSOR cursor_test
IS SELECT * FROM userinfo WHERE username=p_name;
cur_record userinfo%ROWTYPE;
BEGIN
OPEN cursor_test;
LOOP
FETCH cursor_test INTO cur_record;
EXIT WHEN cursor_test%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(‘密码:’||cur_record.userpwd);
END LOOP;
CLOSE cursor_test;
END;
/
%TYPE说明
为了使一个变量的数据类型与另一个已经定义了的变量(尤其是表的某一列)的数据类型相一致,Oracle提供了%TYPE定义方式。当被参照的那个变量的数据类型改变了之后,这个新定义的变量的数据类型会自动跟随其改变,容易保持一致,也不用修改PL/SQL程序了。当不能确切地知道被参照的那个变量的数据类型时,就只能采用这种方法定义变量的数据类型。
2 %ROWTYPE说明
如果一个表有较多的列,使用%ROWTYPE来定义一个表示表中一行记录的变量,比分别使用%TYPE来定义表示表中各个列的变量要简洁得多,并且不容易遗漏、出错。这样会增加程序的可维护性。
为了使一个变量的数据类型与一个表中记录的各个列的数据类型相对应、一致,Oracle提供%ROWTYPE定义方式。当表的某些列的数据类型改变了之后,这个新定义的变量的数据类型会自动跟随其改变,容易保持一致,也不用修改PL/SQL程序了。当不能确切地知道被参照的那个表的结构及其数据类型时,就只能采用这种方法定义变量的数据类型。
一行记录可以保存从一个表或游标中查询到的整个数据行的各列数据。一行记录的各个列与表中一行的各个列有相同的名称和数据类型。
调用存储过程的语句
1.EXEC 存储过程名;
或
2.BEGIN
存储过程名
END;
触发器
概念:它是与表事件相关的特殊的存储过程,它的执行不是由程序调用,也不是手工启动,而是由事件来触发,比如当对一个表进行操作( insert,delete, update)时就会激活它执行。触发器经常用于加强数据的完整性约束和业务规则等。
按操作分类:
数据操作语言(DML)触发器:insert update delete
数据定义语言(DDL)触发器: create alter drop
复合触发器
INSTEAD OF触发器
用户和系统事件触发器
创建DML触发器
例子:
对emp表的工资(sal)进行修改时,当工资总额超过最高总额100000的限制时,系统必须拒绝修改员工的工资并在屏幕上输出提示
Create or replace trigger tri_sal
Before update of sal
On emp
For each row
Declare
V_sum number(8);
PRAGMA AUTONOMOUS_TRANSACTION;
Begin
Select sum(:new.sal) into v_sum from emp;
If
V_sum>100000
Then
Raise_application_error(-20016,’不允许总工资超过100000!’);
End if;
Commit;
End;
/