select * from emp
select * from dept
select 1+1 from dual
select ename 姓名 from emp
--去除重复的东西
select distinct job from emp
--查询员工的年薪
select sal*12 from emp
--查询员工的年薪加奖金 nvl括号表示如果comm为空则使用0替换
select sal*12 + nvl(comm,0) from emp
/*
字符串拼接
java :+号拼接
oracle:|| 拼接
oracle中双引号主要是别名的时候使用,单引号是使用的值是字符
*/
--查询员工姓名:形式 姓名:scott
select '姓名:' || ename from emp
--使用函数拼接
select concat('姓名',ename) from emp
/*
条件查询
关系运算符 > < = >= <= != <>
逻辑运算符 and or not
其他运算符 like in between is null判断为空 is not null 判断不为空
*/
select * from emp where comm >0
select * from emp where sal between 1500 and 3000
select * from emp where sal>=1500 and sal<=3000
select * from emp where ename in ('Smit','allen')
/*
模糊查询
like
%表示匹配多个字符 _表示匹配一个字符
*/
--查询员工姓名中第三个字符为O的员工信息
select * from emp where ename like '__O%'
--查询员工姓名中,包含%的员工,escape表示的是后面写的东西是转义字符,这的话可以替换为其他,例如#
select * from emp where ename like '%\%%' escape '\'
/*
升序和降序
order by
asc ascend 升序
desc descend 降序
排序空值问题:nulls first nulls last
同时排列多列,用逗号隔开
*/
--查询员工按照奖金从高到低排序,空值在后面,不写nulls last默认空值是在前面的
select * from emp order by comm desc nulls last
--查询部门编号和按照工资,按照部门升序,工资降序,这里的话是每个部门薪资按照降序排列
select deptno , sal from emp order by deptno asc , sal desc
/*
函数:必须有返回值
单行函数:对某一行中的某个值进行处理
数值函数
字符函数
日期函数
转换函数
通用函数
多行函数:对某一列所有行进行处理
max( ) min count sum avg
*/
--查询员工的工资总和
select sum(sal) from emp
select * from emp where hiredate > to_date('1980-01-01','yyyy-mm-dd')
--如果是算平均奖金的话有空值 的原因,所以需要特别注意,不能直接使用avg,可以使用下面的这种方法
select sum(comm)/count(*) from emp
--数值函数
select ceil(45.5) from dual --46
select floor(45.525) from dual --45
select ceil(-12.5) from dual -- -12
select floor(12.5) from dual --12
--四舍五入
select round(45.525,2) from dual --45.53
select round(45.525,1) from dual --45.5
select round(45.525,0) from dual --46
select round(45.925,-1) from dual --50
select round(45.525,-2) from dual --0
select round(50.525,-2) from dual --100
--截断
select trunc(45.525,2) from dual --45.52
select trunc(45.525,1) from dual --45.5
select trunc(45.525,0) from dual --45
select trunc(45.925,-1) from dual --40
select trunc(45.525,-2) from dual --0
select trunc(50.525,-2) from dual --0
--求余
select mod(9,3) from dual --0
select mod(9,4) from dual --1
--字符函数
--substr(str1,起始索引,长度)
--注意:起始索引不管写0还是1都是从第一个字符开始截取
select substr('abcde' ,0,3) from dual --abc
select substr('abcde' ,1,3) from dual --abc
select substr('abcde' ,2,3) from dual --bcd
--获取字符串的长度
select length('abcdef') from dual --6
--去除字符左右两边的空格
select trim(' abcd ') from dual
--替换字符
select replace('hello','l','a') from dual
--日期函数
--查询一下今天的日期
select sysdate from dual --2019/4/25 20:44:24
--查询三个月后的今天的日期
select add_months(sysdate ,3) from dual --2019/7/25 20:45:32
--查询三天后的日期
select sysdate +3 from dual --2019/4/28 20:46:12
--查询员工入职的天数
select sysdate - hiredate from emp
select ceil(sysdate - hiredate) from emp
--查询员工入职的周数
select ceil(sysdate - hiredate)/7 from emp
select ceil(ceil(sysdate - hiredate)/7) from emp
--查询员工入职的月数
select months_between(sysdate , hiredate) from emp
--查询员工入职的年份
select months_between(sysdate , hiredate)/12 from emp
--转换函数 数值转字符 字符转数值 日期转字符
--字符转数值 to_number(str)
select 110+'10' from dual --120 默认帮我们自动转换了
select 110+to_number('10') from dual --120
--数值转字符 to_char
select to_char(sal,'$9,999.99') from emp -- $3,000.00
select to_char(sal,'L9,999.99') from emp -- ¥3,000.00
select to_char(21,'0000099') from dual -- 0000021
--日期转字符
select to_char(sysdate,'yyyy-mm-dd') from dual --2019-04-25
select to_char(sysdate,'yyyy-mm-dd hh:mi:ss') from dual --2019-04-25 09:01:26
select to_char(sysdate,'d') from dual --5 表示一个星期中的第几天 星期四
select to_char(sysdate,'dd') from dual --25 表示一个月中的第几天
select to_char(sysdate,'ddd') from dual --115 表示一年中的第几天
select to_char(sysdate,'day') from dual --星期四
select to_char(sysdate,'dy') from dual --星期四
--字符转日期
select to_date('2017-04-01','yyyy-mm-dd') from dual --2017/4/1
--查询1981年到1985年入职员工的信息
select * from emp where hiredate between to_date('1981' ,'yyyy') and to_date('1985','yyyy')
select * from emp where hiredate < to_date('1985','yyyy')
/*
通用函数
nvl(参数1,参数2) 如果参数1为null,则参数1的值为参数2
nvl2(参数1,参数2,参数3) 如果参数1为null,则参数1的值为参数3,否则为参数2
nullif(参数1,参数2) 如果参数1==参数2,则返回null,如果 不相等,结果等于第一个数值
coalesce:返回第一个不为null的值
*/
select nvl2(null,2,3) from dual --3
select nvl2(1,2,3) from dual --2
select nullif(2,3) from dual --2
select nullif(2,2) from dual --null
select coalesce(null,null,2,3) from dual --2
select coalesce(null,null,null,3) from dual --3
/*
条件表达式
case 字段:
when 值1 then 值
when 值1 then 值
else
默认值
end
case.....when mysql和oracle都可以用
oracle特有的:decode(字段,if1,then,if2,then2,else1)
*/
--给表中姓名取一个中文名
select
case ename
when 'SMITH' then '刘备'
when 'ALLEN' then '诸葛'
else '路人甲'
end
from emp
select decode(ename,'SMITH','刘备','ALLEN','诸葛','路人甲') from emp
/*
分组表达式 group by
select 分组条件,分组之后的操作 from 表名 group by 分组条件 having 过滤条件
sql 的编写顺序
select ..from..where..group by..having..order by
执行顺序
from..where..group by..having..select..order by
where 和having的区别,可以接单行函数
where后面不能跟聚合函数,
having是在group by之后执行,可以接聚合函数
*/
--分组统计出所有部门的平均工资,找出平均工资大于1500的部门,这里的话不能使用where,因为where中不能使用avg这种
select deptno ,avg(sal) from emp group by deptno having avg(sal)>1500
select deptno ,avg(sal) from emp where deptno = 20 group by deptno
/*
多表查询
笛卡尔积:实际上就是两张表的乘积,在实际开发没什么意义
*/
select * from emp e,dept d
select * from emp e,dept d where e.deptno = d.deptno
/*
内连接
隐式内连接:
1.等值内连接 where e.deptno = d.deptno
2.不等值内连接 where e.deptno <> d.deptno
3.自连接:自己连接自己
显示内连接:
select * form 表1 inner join 表2 on 连接条件
inner可以省略
*/
--查询员工编号,员工姓名,部门名称,经理编号,经理的姓名
select e.empno,e.ename,e.mgr,a.empno from emp e,emp a where e.mgr = a.empno
select * from emp
--查询员工编号,员工姓名,员工的部门名称,部门名称,经理编号,经理的姓名
select e.empno,e.ename,e.mgr,a.empno,d.dname from emp e,emp a,dept d
where e.mgr = a.empno and e.deptno = d.deptno
--使用显示内连接查询员工姓名和员工部门所处位置
select * from emp e1 inner join dept d1 on e1.deptno = d1.deptno
/*
外连接:
左外连接:left outer join 左表中所有记录,如果右表中没有对应记录,就显示为空
右外连接: right outer join 右表中所有记录,如果左表中没有对应记录,就显示为空
outer 可以省略
oracle中的外连接(+)实际上如果没有对应的记录就加上空值,和左外连接相同
select * from emp e1,dept d1 where e1.deptno=d1.deptno(+)
*/
select * from emp e1 left outer join dept d1 on e1.deptno = d1.deptno
select * from emp e1 right outer join dept d1 on e1.deptno = d1.deptno
select * from emp e1,dept d1 where e1.deptno=d1.deptno(+)
select * from emp e1,dept d1 where e1.deptno(+)=d1.deptno
/*
子查询:查询语句中嵌套查询语句
单行子查询:> >= < <= <> !=
多行子查询
*/
--查询最高工资的员工信息
--1.查询出高工资
select max(sal) from emp
--2.工资等于最高工资
select * from emp where sal = 5000
select * from emp where sal =(select max(sal) from emp)
--查询出比员工7654的工资高,同时和7788从事相同工作的员工信息
select * from emp where sal>(select sal from emp where empno = 7654) and job = (select job from emp where empno = 7788)
--查询每个部门最低工资的员工信息和他所在的部门信息
--1.查询每个部门的最低工资,按分组统计
select deptno, min(sal) from emp group by deptno
--这里的话把按组分类的部门也看成是一张表
select * from emp e,
(select deptno, min(sal) minsal from emp group by deptno ) t ,
dept d
where e.deptno = t.deptno and e.sal = t.minsal and e.deptno=d.deptno
/*
内连接,单行子查询,多行子查询
in
not in
any
all
exists
通常情况下,数据库中不要出现null
null值不代表不占空间,char(100) null也是占100个字符
*/
--大于集合所有
select * from emp where sal>all(select sal from emp where deptno = 20)
/*
exists(查询语句):存在的意思
当做布尔值来处理
当查询语句有结果的时候,就是返回true,否则返回false
数据量比较大的时候是非常高效的
*/
--这里的exists里面的结果是有值的,所以为true,where true的时候查询的是所有的值
select * from emp where exists(select * from emp where deptno = 20)
/*
rownum:系统自动生成的一列,伪列
rownum是oracle中特有的用来表示行号的,默认起始值为1,在查询出结果之后,再加1
rownum不能做大于号判断,只能做小于号判断
*/
--查询rownum值大于2的所有记录
select rownum,e.* from emp e where rownum>2 --没有任何记录
--查询rownum值大于等于1的所有记录
select rownum,e.* from emp e where rownum>=1--所有记录
select rownum,e.* from emp e where rownum>1--没有记录
--等于大于1的数查到的也是没有记录
select rownum,e.* from emp e where rownum=2--没有记录
--查询rownum值小于6等于的所有记录
select rownum,e.* from emp e where rownum<6
--sql执行顺序: from ..where ..group by ..having..select ..rownum...order by
--rownum排序
--找到员工表中工资最高的前三名
select * from emp order by sal desc--这里按照薪资从大到小排序,把这个当做一个表来使用
select rownum ,t.* from (select * from emp order by sal desc) t where rownum<=3
--查询员工表中薪水大于本部门平均薪水的员工
select deptno ,avg(sal) avgsal from emp group by deptno
select e.* from emp e,(select deptno,avg(sal) avgsal from emp group by deptno) t where e.sal>t.avgsal and e.deptno = t.deptno
--统计每年入职员工的人数
select to_char(hiredate,'yyyy'),count(1) from emp group by to_char(hiredate,'yyyy')
/*
使用rownum进行分页
oracle中只能用子查询加rownum用来分页
mysql中使用limin来做分页查询
*/
--查询第6到第10 条数据
select * from (select rownum hanghao,e.* from emp e) t where t.hanghao between 6 and 10
/*
rowid 伪列 每行记录所存放的真实位置
*/
select rowid,e.* from emp e
/*
集合运算
交集
并集
差集
*/
--工资大于2000或者是部门20号的员工
select * from emp where sal>2000 or deptno = 20
--工资大于2000
select * from emp where sal>2000
--部门编号为20
select * from emp where deptno = 20
--并集运算: union union all
/*
union:会去除重复的,并重新排序
union all:不会去除重复的
*/
select * from emp where sal>2000
union
select * from emp where deptno = 20
/*
交集:intersect
*/
select * from emp where sal>2000
intersect
select * from emp where deptno = 20
/*
差集:minus
*/
select * from emp where sal>2000
minus
select * from emp where deptno = 20
/*
集合运算中的注意事项
1.列的类型要一致
2.按照顺序写
3.列的数量要一致,如果不一致就用null代替
*/
select * from emp
select * from dept
/*
oracle体系结构
数据库-->数据库实例-->表空间(用户里面的创建表)-->数据文件
创建表空间:逻辑单位,通常我们新建一个项目,就回去新建表空间,在表空间中创建用户来创建表
语法:
create tablespace 表空间的名称
datafile '文件的路径(服务器上)'
size大小
autoextend on 自动扩展
next 每次扩展的大小
*/
--创建一个表空间 -----汉东
create tablespace handong
datafile 'c:\handong.dbf'
size 100m
autoextend on
next 10m;
--删除表空间
drop tablespace handong
/*
创建用户
create user 用户名
identified by 密码
default tablespace 表名称空间
*/
create user dakang
identified by 123456
default tablespace handong
/*
创建表
create table 表名(
列名 列的类型 [ 列的约束],
列名 列的类型 [ 列的约束]
);
列的类型
varchar,在oracle中,目前是支持的,但是不能保证以后还支持
varchar2(长度) 可变字符长度 varchar(10) hello 占5个字符
char(长度) 固定长度字符 char(10) hello 占10个字符 ,用空格填充
number(总长度,小数长度) 数字类型 小数长度不能大于总长度
date 年月日时分秒 2019/5/3 16:52:11
timestamp 时间戳 比data类型更加精确 03-5月 -19 04.52.28.639000 下午 +08:00
使用子查询的方式创建 表
create table 表名 as 查询语句 复制表
注意:只会复制表结构和表中的数据,不会复制表约束
如果查询语句有结果,就是复制表结构和数据
如果没有结果,就是复制表结构
*/
create table test1(
name1 varchar2(10),
name2 char(10),
age number(2,1)
)
insert into test1(name1,name2) values('hello','hello');
select * from test1 where name1 like 'hello';--查询到数据
select * from test1 where name2 like 'hello';--查不出数据
select current_timestamp from dual
-- create table 表名 as 查询语句 复制表
//这里可以指定查询哪个用户的表
select * from scott.emp
create table emp as select * from scott.emp
select * from emp
/*
修改表
添加列
修改列
删除列
修改列名
重命名表
SQL分类:
DDL:数据定义语言,修改表结构 alter create drop modify
DML:数据操作语言,操作表中的数据 insert update delete
DCL:数据控制语言,grant
DQL: select
*/
create table stu(
stuid number,
sname varchar2(10)
);
--添加一列
alter table stu add phone varchar2(11);
--添加多列
alter table stu add (mobile varchar2(11), sex varchar2(2))
--修改列的类型
alter table stu modify sex varchar2(4)
--修改列名
alter table stu rename column sex to gander
--删除列
alter table stu drop column gander
--修改表名
rename stu to student
--删除表
drop table student
/*
列的约束
主键约束 primary key 不能为空,唯一
非空 not null
唯一约束 unique
检查约束 check
外键约束
主要是用来约束从表A中的记录表,必须是存在于主表B中
*/
create table teacher2(
stuid number primary key,
sname varchar2(10) unique,
age varchar2(10) not null,
gender varchar2(4) check(gender in ('男','女','人妖'))
)
/*
商品表和商品分类表
*/
--商品分类表
create table category(
cid number primary key,
cname varchar2(20)
)
--创建一个商品表
create table product(
pid number primary key,
pname varchar2(20),
cno number
)
--添加外键约束
alter table product add foreign key(cno) references category(cid)
insert into category values(1,'手机数码')
insert into product values(10,'锤子',1)
--删除表中的数据
truncate table product
--强制删除表(不建议使用):先删除外键关联的表的外键约束,然后在删除自己
drop table category cascade constraint;
--使用级联删除 推荐使用
alter table product add foreign key(cno) references category(cid) on delete cascade
/*
插入数据
insert into 表名(列1,列2) values(值1,值2)
insert into 表名 values(值1,值2)
使用子查询插入数据
insert into 表名 查询语句
*/
--将emp中10号部门的员工信息插入到emp1中
insert into emp1 select * from emp where deptno = 10;
/*
修改数据
update 表名 set 列名 = 值 [where 条件]
*/
update emp1 set ename = 'HUAAN' where ename = 'KING'
/*
删除数据
delete from 表名 [where 条件]
delete 和truncate区别
truncate:先删除表在创建表,不支持事务,执行效率高
delete:逐条删除,支持事务操作
*/
/*
事务
提交:commit
事务的保存点/回滚点:savepoint 保存点的名称
回滚:rollback
*/
create table lout(
lou number primary key
);
insert into lout values (1);
insert into lout values (2);
insert into lout values (3);
savepoint dangdan;
insert into lout values (4);
insert into lout values (5);
insert into lout values (6);
rollback to dangdan
commit;
declare
begin
insert into lout values (1);
insert into lout values (2);
insert into lout values (3);
savepoint dangdan;
insert into lout values (4);
insert into lout values (5);
insert into lout values (6);
commit;
exception --捕获异常
when others then
rollback to dangban;
commit;
end;
/*
视图:是对查询结果的一个封装
1.能够封装复杂的查询结果
2.屏蔽表中的细节
语法:
create [or replace] view 视图名称 as 查询语句 [with read only]
注意:通常不要使用视图去修改数据,视图创建的时候通常要加上with read only
*/
--创建一个视图
create or replace view view_1 as select ename,job from emp;
select * from view_1
--通过视图修改数据
update view_1 set ename = 'Smit2' where ename ='Smit'
--一般来说,视图只给查阅功能,不能通过视图修改表的数据,所以我们需要收回视图的权限
revoke update on 视图名 from oracle用户名; --------------- 收回此用户针对该视图的update权限 (update 可改成 insert 、 select、delete)
grant select on 视图名 to oracle用户名 ------------- 授予用户对视图的select 权限
/*
序列:用来生成类似 auto_increment这个id的自增长
auto_increment这个是mysql的
语法:
create sequence 序列名称
start with 从几开始
increment by 每次增长多少
maxvalue 最大值 | nomaxvalue
minvalue 最小值 | nominvalue
cycle | nocycle 是否循环
cache 缓存数量 | nocache
如何从序列中获取值
currval:当前值
nextval:下一个值
注意:currval需要在调用nextval之后才能使用
*/
--创建一个 1,3,5,7,9
create sequence seq_test
start with 1
increment by 2
maxvalue 30
cycle
cache 10;
select seq_test.nextval from dual
select seq_test.currval from dual
--序列用的最多的一种写法
create sequence seq_test2;
select seq_test2.nextval from dual
/*
索引:相当于是一本书的目录,能提高查询效率
如果某一列,你经常用来作为查询条件,那么就有必要创建索引,数据量比较大的时候
语法:
create index 索引的名称 on 表名(列)
注意:主键约束自带主键索引,唯一约束自带唯一索引
索引的原理:btree balance Tree 平衡二叉树
如果某列作为查询条件的时候可以提高查询效率,但是插入的时候会比较慢
索引创建好了之后,过了一段时间,DBA都会去做重构索引
SQL调优:
1.查看执行计划F5
2.分析里面的cost和影响行数
*/
--假设表wubaiwan中有五百万的数据 ,大概三秒
select * from wubaiwan where name = '3000000';
--创建索引,大概0.016秒
create index ind_wubaiwan on wubaiwan(name)
select * from wubaiwan where name = '3000000';
--创建复合索引,如果需要多条件查询的时候可以使用
create index ind_wubaiwan on wubaiwan(name,address)
PLSQL
/*
plsql编程
declare
--声明变量
变量名 变量类型
变量名 变量类型 :=初始值
vsal emp.sal%type; --引用型的变量
begin
--编写业务逻辑
end;
*/
declare
i varchar2(10) :='张三';
begin
dbms_output.put_line(i);
end;
--查询7369的工资
declare
vsal emp.sal%type;
begin
--将查询出的结果赋值给vsal
select sal into vsal from emp where empno =7369;
dbms_output.put_line(vsal);
end;
--查询7369的员工信息
declare
vrow emp%rowtype;
begin
--将查询出的结果赋值给vsal
select * into vrow from emp where empno =7369;
dbms_output.put_line('姓名'||vrow.ename);
end;
/*
pl条件判断
if then
elsif then
else
end if;
*/
--根据不同年纪,输出相关内容
declare
age number:=&a;--使用&可以进行输入
begin
if age<18 then
dbms_output.put_line('小屁孩');
elsif age>=18 and age<24 then
dbms_output.put_line('年轻人');
else
dbms_output.put_line('老年人');
end if;
end;
/*
循环
while循环
while 条件 loop
end loop;
for循环
for 变量 in [reverse] 起始值..结束值 loop --reverse表示倒序
end loop
loop循环
loop
exit when 退出条件;
end loop;
*/
--while循环
declare
i number :=1;
begin
while i<=10 loop
dbms_output.put_line(i);
i:=i+1;
end loop;
end;
--for循环
declare
begin
for i in 0..10 loop
dbms_output.put_line(i);
end loop;
end;
--loop循环
declare
i number :=1;
begin
loop
exit when i>10;
dbms_output.put_line(i);
i:=i+1;
end loop;
end;
/*
游标:主要是用来操作查询结果集,相当于jdbc中的ResultSet
语法:cursor 游标名[(参数名 参数类型)] is 查询结果集
开发步骤:
1.声明游标
2.打开游标 open 游标名
3.从游标中取数据 fetch 游标名 into变量
游标名%found:找到数据
游标名%notfound:没有找到数据
4.关闭游标 close 游标名
系统引用游标
1.声明游标:游标名 sys_refcursor
2.打开游标:open 游标名 for 结果集
3.从游标中取数据
4.关闭游标
*/
--输出所有员工姓名和工资
/*
结果集:所有员工
声明一个变量用来记录一行数据 %rowtype
*/
declare
--游标
cursor vrows is select * from emp;
--声明变量记录一行数据
vrow emp%rowtype;
begin
--打开游标
open vrows;
--循环取数据
loop
fetch vrows into vrow;
exit when vrows%notfound;
dbms_output.put_line('姓名'||vrow.ename||'工资'||vrow.sal);
end loop;
--关闭游标
close vrows;
end;
--输出指定部门的所有员工
/*
游标:指定部门的所有员工
声明一个变量记录一行数据
*/
declare
--游标
cursor vrows(dno number) is select * from emp where deptno = dno;
--声明变量记录一行数据
vrow emp%rowtype;
begin
--打开游标
open vrows(20);
--循环取数据
loop
fetch vrows into vrow;
exit when vrows%notfound;
dbms_output.put_line('姓名'||vrow.ename||'工资'||vrow.sal);
end loop;
--关闭游标
close vrows;
end;
--系统引用游标
--输出所有员工姓名和工资
declare
--声明系统引用游标
vrows sys_refcursor;
--声明变量记录一行数据
vrow emp%rowtype;
begin
--打开游标
open vrows for select * from emp;
--循环取数据
loop
fetch vrows into vrow;
exit when vrows%notfound;
dbms_output.put_line('姓名'||vrow.ename||'工资'||vrow.sal);
end loop;
--关闭游标
close vrows;
end;
/*
例外:(意外)程序运行的过程中发生异常
declare
--声明变量
begin
--业务逻辑
exception
--处理异常
when 异常1 then..
when 异常2 then..
when others then..
end;
zero_divide:除零异常
value_error:类型转换异常
too_mony_rows:查询出多行数据但是赋值给了rowtype一行记录
no_data_found:没有找到数据
自定义异常:
异常名 exception;
raise 异常名
*/
--查询指定编号的员工,如果没有找到,就抛出自定义异常
/*
1.声明一个变量 %rowtype
2.查询员工信息,保存起来
3.判断员工信息是否为空
4.如果是,抛出异常
*/
--这里抛出的不是自定义异常,是没有找到数据的异常,如果要使用自定义异常可以使用游标来判断
declare
-- 1.声明一个变量 %rowtype
vrow emp%rowtype;
--声明一个自定义异常
no_emp exception;
begin
--查询员工信息,保存起来
select * into vrow from emp where empno = 214321;
if vrow.sal is null then
raise no_emp;--抛出自定义异常
end if;
exception
when no_emp then
dbms_output.put_line('输出了自定义异常');
when others then
dbms_output.put_line('输出了其他异常'||sqlerrm);
end;
/*
存储过程:实际上是封装在服务器上的一段plsql代码片段,已经编译好了的代码
1.客户端调用存储过程,执行效率会非常高效
语法:create [or replace] procedure 存储过程的名称(参数名 in|out 参数类型)
is |as
--声明部分
begin
--业务逻辑
end;
*/
--给指定员工涨工资,并打印涨工资钱和涨工资后的工资
/*
参数:in员工编号
参数:in涨多少
声明一个变量:存储涨工资前的工资
查询出当前是多少
打印涨工资前的工资
更新工资
打印涨工资后的工资
*/
create or replace procedure proc_updatesal(vempno in number,vnum in number)
is
--声明变量,记录当前工资
vsal number;
begin
select sal into vsal from emp where empno = vempno;
dbms_output.put_line('涨工资前'||vsal);
--更新工资
update emp set sal = vsal +vnum where empno = vempno;
--输出涨工资后的工资
dbms_output.put_line('涨工资后'||vsal+vnum);
--提交事务
commit;
end;
--调用
--方式一
call proc_updatesal(7788,10);
--方式二 用的最多的方式
declare
begin
proc_updatesal(7788,10);
end;
/*
存储函数:实际上是一段封装在oracle服务器中的一段plsql代码片段,它实际上已经编译好的代码片段
create(or replace)function 存储函数名称(参数名 in|out 参数类型,参数名 in|out 参数类型)return 参数类型
is |as
begin
end;
存储函数和过程的区别
1.他们本质没有区别
2.函数存在的意义是给过程调用 存储过程里面调用存储函数
3.函数可以在sql语句中调用
4.存储过程能实现的,存储函数也能实现
默认是in输入类型
*/
--查询指定员工的年薪
/*
参数:员工的编号
返回:年薪
*/
create or replace function func_getsal(vempno number) return number
is
--声明变量,保存年薪
vtotalsal number;
begin
select sal*12 +nvl(comm,0) into vtotalsal from emp where empno = vempno;
return vtotalsal;
end;
--调用存储函数
declare
vsal number;
begin
vsal := func_getsal(7788);
dbms_output.put_line(vsal);
end;
/*
触发器:当用户执行了insert | delete | update 这些操作后,可以触发一系列的其他动作
作用:
在动作执行之前或之后触发业务处理逻辑
插入数据,做一些校验
语法:
create [or replace] triger 触发器名称
before | after
insert | delete | update
on 表名
[for each row]
declare
begin
end
触发器分类:
语句级触发器:不管影响多少行,都只会执行一次
行级触发器:影响多少行就触发多少次,加上for each row
*/
--新员工入职之后,输出一句话,欢迎加入
create or replace trigger tri_test1
after
insert
on emp
declare
begin
dbms_output.put_line('欢迎加入')
end;