拓展用法
1.视图
(1)概念
视图提供一个查询的窗口,所有数据来源于原表
(2)示例
查询语句创建表
create table emp as select * from scott.emp;
select * from emp;
创建视图【必须有dba权限】
create view v_emp as select ename,job from emp;
查询视图
select * from v_emp;
修改视图[不推荐]也会修改原表的数据
update v_emp set job = 'AllEN' where ename = 'SMITH';
commit;
创建只读视图
create view v_emp1 as select ename,job from emp with read only;
视图的作用
1.视图可以屏蔽掉一些敏感字段(例如:不让新员工看见工资列)
2.保证总部和分布数据及时统一(更常用)
2.索引
(1)概念
索引就是在表的列上构建一个二叉树(类似于书上的目录),达到大幅度提高查询效率的目的,但是索引会影响增删改的效率
(2)示例
单列索引
创建单列索引
create index idex_ename on emp(ename);
单列索引触发规则,条件必须是索引列中的原始值
单行函数,模糊查询,都会影响索引的触发
select * from emp where ename='SCOTT'
复合索引
创建复合索引
create index idex_enamejob on emp(ename,job);
符合索引中第一列为优先检索列
如果要触发符合索引,必须包含有优先检索列中的原始值
select * from emp where ename='SCOTT' and job = 'xxx'; --触发复合索引
select * from emp where ename='SCOTT' or job = 'xxx'; --不触发索引(ename:触发索引,job:不触发索引;二者用or连接,不触发索引)
select * from emp where ename='SCOTT'; --触发单列索引
3.pl/sql编程语言
(1)概念
pl/sql编程语言是对Sql语言的扩展,使得sql语言具有过程化编程的特性。
pl/sql编程语言比一般的过程化编程语言,更加灵活高效。
pl/sql编程与语言主要用来编写存储过程和存储函数等。
(2)示例
声明方法
–赋值操作可以使用:=也可以使用into查询语句赋值
declare
i number(2) := 10;
s varchar2(10) :='小明';
ena emp.ename%type; --引用类型--把ename的字段类型、长度赋值给ena
emprow emp%rowtype; --记录型变量
begin
dbms_output.put_line(i); --相当于Java的System.out.print('xxx');
dbms_output.put_line(s);
select ename into ena from emp where empno = 7788;
dbms_output.put_line(ena);
dbms_output.put_line(emprow.ename || '的工作为:' ||emprow.job);
end;
pl/sql中的if判断
输入小于18的数字,输出未成年
输入大于18小于40的数字,输出中年人
输入大于40的数字,输出老年人
declare
i number(3) :=ⅈ
begin
if i<18 then
dbms_output.put_line('未成年');
elsif i<40then
dbms_output.put_line('中年人');
else
dbms_output.put_line('老年人');
end if;
end;
pl/sql中的loop循环
用三种方式输出1到10十个数字
while循环
declare
i number(2) :=1;
begin
while i<11 loop
dbms_output.put_line(i);
i :=i+1;
end loop;
end;
exit循环
declare
i number(2) :=1;
begin
loop
exit when i>10;
dbms_output.put_line(i);
i :=i+1;
end loop;
end;
for循环
declare
i number(2) :=1;
begin
for i in 1..10 loop
dbms_output.put_line(i);
end loop;
end;
4.游标
(1)概念
可以存放多个对象,多行记录–类似于Java中的集合
(2)示例
输出emp表中所有员工的姓名
declare
cursor c1 is select * from emp;
emprow emp%rowtype;
begin
open c1;
loop
fetch c1 into emprow;
exit when c1%notfound;
dbms_output.put_line(emprow.ename);
end loop;
close c1;
end;
指定部门员工涨工资
declare
cursor c2(eno emp.deptno%type)
is select empno from emp where deptno = eno;
en emp.empno%type;
begin
open c2(10);
loop
fetch c2 into en;
exit when c2%notfound;
update emp set sal = sal+100 where empno = en;
commit;
end loop;
close c2;
end;
查询10号部门员工信息
select * from emp where deptno =10;
5.存储过程
(1)概念
存储过程:就是提前已经编译好的一段pl/sql语言,放置在数据库端
可以直接被调用。这一段pl/sql一般都是固定步骤的业务。
(Java语言想操作数据库,必须从连接池中拿到connection对象,但是pl/sql语言本来就写在数据库端,不用通过连接池也可以操作数据库,但是不能写太复杂的业务。不利于维护)
(2)示例
给指定员工涨100块钱
create or replace procedure p1(eno emp.empno%type)
is
begin
update emp set sal = sal+100 where empno = eno;
commit;
end;
--测试结果
select * from emp where empno = 7788;
测试p1
declare
begin
p1(7788);
end;
6.存储函数
存储过程和存储函数的区别:
存储过程和存储函数的参数都不能带长度
存储函数的返回值类型不能带长度
通过存储函数实现计算指定员工的年薪
create or replace function f_yearsal(eno emp.empno%type) return number
is
s number(10);
begin
select sal * 12 + nvl(comm, 0) into s from emp where empno = eno;
return s;
end;
测试f_yearsal
存储函数在调用的时候,返回值需要接收
declare
s number(10);
begin
s := f_yearsal(7788);
dbms_output.put_line(s);
end;
out类型参数如何使用
使用存储过程来算年薪
create or replace procedure p_yearsal(eno emp.empno%type, yearsal out number)
is
s number(10);
c emp.comm%type;
begin
select sal*12,nvl(comm, 0) into s,c from emp where empno = eno;
yearsal :=s+c;
end;
测试p_yearsal
declare
yearsal number(10);
begin
p_yearsal(7788,yearsal);
dbms_output.put_line(yearsal);
end;
in和out类型参数的区别:
–凡是涉及到into查询语句赋值或者:=赋值操作的参数,都必须使用out来修饰,其他的都用in
存储过程和存储函数的区别:
(业务逻辑用Java代码来写,现在用存储过程写)
-
语法区别
关键字不一样(存储过程是:procedure,存储函数是:function)
存储函数比存储函数多了两个return -
本质区别:存储函数有返回值,而存储过程没有返回值
----如果存储过程想实现有返回值的业务,我们就必须使用out类型的参数
----即便是存储过程使用了out类型的参数,其本质也不是真的有了返回值
----而是在存储过程内部给out类型参数赋值,在执行完毕后,我们直接拿到输出类型参数的值
我们可以用存储函数有返回值的特性,来自定义函数
而存储过程不能用来自定义函数
案例需求:查询出员工姓名,员工所在部门名称
create table dept as select * from scott.dept;
使用传统方式来实现案例需求
select e.ename,d.dname
from emp e, dept d
where e.deptno = d.deptno;
使用存储函数来实现提供一个部门编号,输出一个部门名称
create or replace function fdna(dno dept.deptno%type) return dept.dname%type
is
dna dept.dname%type;
begin
select dname into dna from dept where deptno = dno;
return dna;
end;
使用fdna存储来实现查询出员工姓名,员工所在部门名称
select e.ename, fdna(e.deptno)
from emp e;
7.触发器
(1)概念
就是指定一个规则,在我们做增删改操作的时候
只要满足该规则,自动触发,无需调用
- 语句级触发器:不包含for each row的触发器
- 行级触发器:包含for each row的就是行级触发器
加for each row是为了使用:old或者:new对象或者一行记录
(2)示例
语句级触发器
插入一条记录,输出一个新员工入职
create or replace trigger t1
after
insert
on person
declare
begin
dbms_output.put_line('一个新员工入职');
end;
触发t1
insert into person values(2,'Lenka');
commit;
select * from person;
--行级别触发器
--不能给员工降薪
--raise_application_error(-20001~-20999之间,'错误提示信息');
create or replace trigger t2
before
update
on emp
for each row
declare
begin
if :old.sal>:new.sal then
raise_application_error(-20001,'不能给员工降薪');
end if;
end;
触发t2
select * from emp where empno = 7788;
update emp set sal=sal-1 where empno = 7788;
commit;
触发器实现主键自增
分析:在用户做插入操作之前,拿到即将插入的数据。
给该数据中的主键列赋值。
create or replace trigger autoid
before
insert
on person
for each row ---行级触发器
declare --声明函数
begin
select s_person.nextval into :new.pid from dual;
end;
查询person表数据
select * from person;
使用autoid实现主键自增
insert into person(pname) values('a');
commit;
- 常用Oracle版本
oracle10g ojdbc14.jar
oracle11g ojbc6.jar