Oracle数据库和PLSQL

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;

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值