2019-04-02 oracle

select * from tab;

sql 分类 ddl 数据定义语言

dml 数据操作语音
dcl 数据控制语言 安全 授权 grant revoke
dql 数据查询语言 select from 字句 where 字句
select {列名 }from 表名 where 条件 groupby 分组条件 having过滤 orderby 排序
select * from tcp;
select 1+1; 在mysql中为2 orcle中报错
select 1+1 from dual; oracle中的虚表 主要用来补齐语法结构的
select * from dual;
/

别名查询 使用as关键字 可以省略
有特殊字符或关键字 用""
/
select eanme "xing ming",sal gongzi from emp;
select distinct job from emp; 单列去除重复的
select distinct job,deptno from emp; 多列去除重复 每一列都一样才算重复
查询中的四则运算
select 1+1 from dual;
查询员工年薪
select sal * 12 from emp;
查询员工年薪+奖金
注意 null值 代表不确定的 不可预知的内容 不可以做四则运算
nvl 函数 如果参数1为null 就返回参数2
select sal
12 + nvl(comm,0) from emp;
字符串拼接
java : + 号拼接
oracle : || 拼接 oracle特有的连接符
查询员工姓名 姓名 scott
select ename from emp;
在oracle “”注要是别名的使用 ‘’使用的是值 是字符
select '姓名:'||ename from emp;
concat(str1,str2)函数 MySQL oracle 都有 拼接
select concat('姓名:',ename) from emp;
条件查询 where后面的写法 比较运算符 关系运算符>< = <= != <>
逻辑运算服 and or not
其他运算服 like 模糊查询 int(set)在某个集合内
between and 在某个区间内
is null 判断为null is not null 判断不为null
查询每月能得到奖金的员工信息
select * from emp where comm is not null;
查询工资在1500-3000之间的员工信息
select * from emp where sal between 1400 and 3000
select * from emp where sal > 1500 and sal <=3000
查询名字在某个范围内的员工('jones','scoott','ford')
select * from emp where ename in ('jones','scoott');
模糊查询 like %匹配多个字符 — 匹配单个字符

查询员工姓名第三个字符是o的员工
select *from emp where ename like '__o%'
查询员工姓名中,包含% 的员工信息 如果有特殊字符,可以使用escape
select * from emp where ename like '%%%' escape '';
排序:order by 升序 asc 降序 desc
查询员工信息 按照奖金由搞到低的排序 排序注意null问题 nulls first | last
同时排序多列的话,用,分开
select * from emp order by comm desc nulls last;
查询工资,和部门编号 按照部门升序排序 工资降序 排序
select deptno,sal from emp order by deptno asc,sal desc;
函数:必须要有返回值 单行函数 和多行函数 对某一列的所有行进行处理 1.直接忽略空值
max() min count sum avg
统计员工工资总和
select sum(sal) from emp;
统计员工奖金总和
select sum(comm) from emp;
统计员工个数 14
select count(1) from emp;
统计员工的平均奖金 会有null值干扰
函数 ceil 单行函数 对某一行中的某个值进行处理
数值函数 字符函数 日期函数 通用函数 转换函数
select sum(comm)/count(1)from emp;//存在奖金为null值隐患
select ceil(sum(comm)/count(1))from emp;

数值函数
select ceil(45.926) from dual; 46
select floor(45.926) from dual; 45
四舍五入
select round(45.926,2) from dual; 45.93
select round(45.926,1) from dual;46
select round(45.926,-1)from dual;50
select round(44.926,-1)from dual;40
select round(45.926,-2)from dual;0
select round(55.926,-2)from dual;100
截断
select trunc(45.926,2) from dual; 45.93
select trunc(45.926,1) from dual;45.9
select trunc(45.926,-1)from dual;45
select trunc(44.926,-1)from dual;40
select trunc(45.926,-2)from dual;0
select trunc(55.926,-2)from dual;0
求余
select mod(9,3)from dual; 0
select mod(9,4) from dual;1

字符函数 substr(str1,起始索引,长度)
注意 起始索引不管写0 还是1都是从第一个开始
select substr('abcdefg',0,3) from dual;abc
select substr('abcdefg',1,3) from dual;abc

select substr('abcdefg',2,3) from dual;bcd
获取字符串的长度
select length('abcdefg')from dual;7
去除字符串左右两边的空格
select trim(' hello ')from dual;
select ceil(-12.5) from dual;-12
select floor(-12.5) from dual;-13
select floor(12.5) from dual;12
替换字符串
select replace('hello','1','a')from dual;
日期函数
查询今天的日期
select sysdate from dual;
查询3个月后的今天的日期
select add_months(sysdate,3)from dual;
查询3天后的日期
select sysdate +3 from dual;
多表查询
内连接
等值连接
inner join
外连接
left outer join
right outer join
oracle 特有的写法(+)
内连接的连接
select * from emp e1 emp t1 where e1.mgr=t1.empno;
t1表里面的所有记录都会显示出来,如果t1.empno 在e1.mgr中没有对应的记录,就加null值
select * from emp e1 emp t1 where e1.mgr(+)=t1.empno;
查询不是领导的员工编号
select empno from emp where empno not in(select mgr from emp where mgr is not null)
获取员工的名字和部门的名字
select e.ename,d.ename from emp e,dept d where e.deptno=d.deptno;
使用子查询的方式来完成
select ename,deptno from emp;
select ename,deptno,deptno from emp;
关联子查询,子查询依赖外部查询的条件
select ename,deptno,(select dname from dept d where d.deptno=e.deptno) aa from emp e;

   select * from emp; 
   select * from dept;
   第三天
   创建表空间
   oracle体系结构
 数据库 数据库实例  表空间 用户里面创建表 --数据文件       
 地球 中国           省份(人民)           土地山川河流
 雄安新区 人(炒房地产)
   
 创建表空间 逻辑单位,通常我们新建一个项目,就会去新建表空间,在表空间中创建新的用户
    语法 
    create tablespace 表空间的名称
    datafile '文件的路径(服务器上)'
    size 大小
    autoextend on 自动扩展
    next 每次扩展的大小

切换到system账号下创建
创建一个表空间 汉东
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 dakang default tablespace hangdong;
授权
grant 角色 | 权限 to 用户
grant connect to dakang
授予 dba的角色
grant dba to dakang;
select * from scott.emp;
列的类型
varchar,在oracle中 目前是支持的,但是不保证以后还支持
varchar2(长度)可变字符长度 varchar2(10) hello 占5个字符
char(长度) 固定长度 char(10) hello 占10个字符,用空格填充
number(总长度,小数长度) 数字类型 小数长度不能大于等于总长度
date 年月日 时分秒
timestamp 时间戳 比date类型更加精确

create table test1(
name1 varchar2(10);
name2 char(10);
age number(2,3)
);
insert into test1(name1,name2)values('hello','hello');
select * from test1;
select * from test1 where name1 like 'hello';可以查询出数据
select * from test1 where name2 like 'hello';查不出数据
insert into test1(age)values(2.3);
select current_date from dual;
select current_timestamp from dual;
long/clog :存放一本小说
blog: 存放电影 java 存进去 再读取出来
使用子查询的方式创建表
create table 表名 as 查询语句;复制表
注意:只会复制表结构个表中的数据,不会复制列的约束
如果查询语句有结果,就是复制 表结构和数据
如果查询语句没有结构就是复制表结构

select * from scott.emp;
create table emp as select * from scott.emp;

如果查询语句是没有任何的结果的
select * from scott.emp where 1=2;
select * from emp1 as  select * from scott.emp where 1=2;;
  修改表
  添加列 修改列 varchar2(10)
  删除列
  修改列名
  
  重命名表
  
  sql分类:
  ddl:数据定义语言:修改的结构 alert create drop truncate
  dml:数据操作语言:操作表中数据 insert update delete
  dcl:是数据控制语言 grant
  dq
  
  
  create table stu(
  stuid number,
         sname varchar(10) 
  );
  comand window 用sql指令查询
  添加一列l:
  alter table stu add phones varchar2(11)
  alter table stu add(
        mobile varchar2(11),
        sex varchar2(2)
  );
  修改列的类型
  alter table stu modify sex varchaer2(4);
  修改列名 sex -- gender
  alter table stu rename column sex to gender;
  
   删除列
   alter table stu drop column gender;
   修改表名
   rename stu to student;
   删除表
   drop table student;
   表的五大约束
   列的约束:约束主要是用来约束表中数据的规则
   主键约束:primary key 不能为空,必须唯一
   非空约束
   唯一约束
   检查约束 check(条件) 在mysql中是可以写的,但是在mysal直接忽略了检查约束
   
   外建约束 主要是用来约束从表a中的记录,必须是存在b中
   男,女,人妖 
   create table student(
          student number primary key;
          sname varchar2(10)  unique;
          age varchar2(10) not null;
          gender varchaer2(4) check(gender in('男'),'女','人妖')
          
   );
   唯一约束违反
   insert into student values(1,'张三','31','男');
       insert into student values(1,'张三','31','男');
  select * from stu;
  非空约束
        insert into student values(1,'张三',null,'男');
 检查约束
        insert into student values(1,'张三','31','妖');
   商品分类表和商品表
   
   商品分类表
   create table category(
          cid number primary key;
          cname varchar2(20);
   );
   创建一个商品表
   create table product(
          pid number primary key,
          pname varchar2(20),
          cno number
   );
   insert into category values(1,'手机数码');
   insert into product values(10,'锤子',11); 插入失败
   select * from category;
   select * from product;
   添加外建约束
   alter table product add foreign key(con) references
   category (cid);
   首先主表中必须存在11号,先往主表中插入数据,再往从表中插入数据
   insert into category values(2,'电脑办公');
   insert into product values(11,'外星人','2')
   删除dategory
   drop table category; 表中记录被外建关联无非删除
   强制删除表(不建议使用):先删除外建关联表的外建约束,然后再删除自己 先删除product 的外建约束,再删除category
   drop table category cascade constraint;
   drop table product;
   级联删除
   添加外建约束,使用级联约束,在删除的时候使用级联删除
      alter table product add foreign key(con) references category(cid) on delete cascade;
     
   级联删除: 首先去从表中找有没有关联数据 ,如果在从表中找到关联数据,先删除从表中关联数据,
   然后在删除主表中的数据
   delete from category where cid=2;

   truncate table product;
   
   插入数据:
   insert into 表名 values(所有列的值都要对应写上)
   insert into 表名(列1,列2)values(值1,值2)
   使用子查询插入数据
   insert into 表名 查询语句
   select * from emp1;
   select * from emp;
   将emp中10号部门的员工信息,插入到emp1中
   insert into emp1 select * from emp where deptno=10;
   更新数据
   update 表名 set列名=列的值(where 条件)
   update emp1 set ename='HUAAN' where ename='king'
   select * from emp1;
   删除数据
   delete from 表名 where 条件
   delete from emp1 where empno=7839;
   delete 和truncate 区别
   delete dml 逐条删除    truncate 先删除表再创建表 ddl
   dml 支持事务操作        不支持事务操作
                              执行效率要高
    事务:就是一系列的操作,要么都成功,要么都失败
    四大特性:原子性,隔离性,持久行,一致性
    如果不考虑隔离级别,脏读,虚度,不可重复读
    mysql中隔离级别
    read uncomitten ,read commited,repeateble read ,serialliazable
    oracle 中隔离级别: read committed serializable read only
    默认隔离级别:read committed
    提交:commit
    事务的保存点/回滚点:savepoint 保存点的名称  
    回滚: rollback
    
    create table louti(
           lou number primary key
    );
    insert into louti values(1);
      insert into louti values(2);
      savepoint dangban;
        insert into louti values(3);
          insert into louti values(4);
          rollback to dangban
          submit;
          
          declare
               begin
                       insert into louti values(3);
          insert into louti values(4);
                 savepoint dangban;
                 insert into louti values(5);
                 insert into louti values(6);
                 commit;
           exception 捕获异常
                     when other then
                       rollback to dangban;
                      end;
                    select * from louti;
                    
                    视图:是对查询结果的一个封装
                     视图里面所有的数据,都是来自了它查询的那张表,视图
                     本身不存储任何数据
                    1.能够封装复制的查询结果
                    2.屏蔽表中的细节
                    语法
                    create(or replace) view 视图的名称 as 查询语句
                    [with read only]
                    创建一个视图
                    create or replace view view_test1 as select ename,job,mgr
                    from emp;
                    通过视图修改数据
                    update view_test1 set ename='smith2' where ename='smith'
                    select * from view_test1;
                    注意:通常不要通过视图去修改,视图创建的时候,通常要加上with read only
                    创建一个只读视图
                       create or replace view view_test1 as select ename,job,mgr from emp with read only;
                       
                    视图封装复杂的查询语句
                    create view view test3 as ()
 同义词的概念
 create synonym dept for view_Test3;
 
 
 create synonym yuangong for view_Test2;
 
 select * from emp;
 
 
 select * from dept; 
 序列的概念·生成类似于auto_increment 这种id自动增长
 1,2,3,4,5
        auto_increment 这个是mysql
  语法:create sequence 序列的名称
  start with 从几开始
  increment by 每次增长多少
  maxvalue 最大值|nomaxvalue
  minvalue 最小值|nominvalue
  cycle|nocycle 是否循环 1,2,3,1,2,3
  cache 缓存的数量3 |nocache 1.2.3.4.5.6
  创建一个1,3,5,7.。,30
  create sequence seq_test1
  start with 1 increment by 2
  maxvalue 30
  minvalue 0
  cycle cache 10;
  如何从序列中获取值
  currval 当前值
  nextval 下一个值
   注意 currval 需要在调用nextval 之后才能使用
   序列用的最多的一种写法
   create sequence seq_test2;
   select seq_test2.nextval from dual;
   
   select seq_test.nextval from dual;
   select seq_test1.curral from dual; 
            
   索引:相当于一本书的目录,提高查询效率
   如果某一列,你经常用来作为查询条件,那么就有必要创建
   索引,数据量比较大的情况
   语法:
         create index 索引的名称 on 表名(列)
         注意:主键约束自带主键索引,唯一约束自带唯一索引
         五百万数据测试
         create table wubaiwan(
                name varchar2(30),
                address varchar2(20)
                
         );
         insert into wubaiwan values('')
         插入500万条数据
         declare
                begin 
                  for 1 in 1..5000000 loop
                    insert into wubaiwan values('姓名'||i,'地址'||i);
                  end loop;
                end
         在没有添加索引的情况下,去查询 name='姓名3000000'
         select * from wubaiwan where name='姓名3000000';2.95秒
         
         创建索引name 再去查询name='姓名3000000'
         create index ind_wubaiwan on wubaiwan(name);
          select * from wubaiwan where name='姓名3000000';0.016秒
         
         在没有添加复合索引的情况下,再去查询name='姓名3000000'and'地址3000000'
          select * from wubaiwan where name='姓名3000000'and address='地址3000000'; 0.032秒     
         创建复合索引的情况下,再去查询
         create index inde_wubaiwan2 on wubaiwan (name,address);
         select * from wubaiwan where name='姓名3000000'and address='地址3000000';0.015秒  f5
         sql:优化  建立索引
         1.cost cpu调用次数
         2.cardinality影响行数
         索引原理:
         btree balance Tree 平衡二叉树
         如果某列作为查询条件的时候,可以提高查询效率,但是修改的时候,会变慢
         索引创建好之后,过了一段时间,dba都会去做重构索引
         sql调优:
         查看执行计划 f5
         1.cost cpu调用次数
         2.cardinality影响次数
         
         ddl表空间操作
         创建表空间
         创建用户
         授权
        创建表
                子查询创建表
         修改表:添加列,删除列,修改列,修改列名,修改表名
         约束
         主键约束,唯一约束,非空约束,检查约束,外建约束
         外建约束; 强制删除 级联删除
         dml表中数据
         插入数据
         子查询插入数据
         更新数据
         删除数据:delete 和truncate
          事务操作:
          savepoint  保存点
          rollback to 保存点
          oracle事务隔离级别:默认是read comitted
          视图:就像窗户一样:封装查询结果,通常视图创建只读视图
          序列:主要是用来实现id自增长的  不回头
          
          索引:相当于是书的目录,能够提高查询效率 原理:平衡二叉树,每隔一段时间dba都需要去重建索引
          同义词:create synonym 名称 for 对象的名称
          1.列出至少有三个员工的所有部门和部门信息
          1.分组统计每个部门的员工数量 
         
          select deptno ,count(1) from emp group by deptno;     
           找出员工数量至少3
                 select deptno ,count(1) from emp group by deptno having count(1)>=3;       
           查询出部门信息
           select * from ( select deptno ,count(1) from emp group by deptno having count(1)>=3) t1,detp d1
           where t1.deptno=d1.deptno;
           2.列出受雇日期早于直属上级的所有员工的编号,姓名,部门名称(dept)
           ---查询员工的编号,姓名,员工的受雇日期,经理的编号,经理的受雇日期
           select e1.empno,e1.ename,e1.hiredate,m1.empno,m1.hiredate
           from emp e1,emp m1
           where e1.mgr=m1.empno;
           早于
            select e1.empno,e1.ename,e1.hiredate,m1.empno,m1.hiredate
           from emp e1,emp m1
           where e1.mgr=m1.empno and e1.hiredate();
           PlSQL编程:p'roceduce language 过程语言 oracle对sql的一个扩展
                 让我们能够像在java中一样写 if else else if 条件 还可以编写循环逻辑 for while 
           declare 声明变量
                  变量名 变量类型;
                  变量名 变量类型 :=初始值;
                    vsal emp.sal%type; --引用型的变量
                    vrow emp %rowtype; --声明记录型变量
           begin 
             --业务逻辑
             end;
             dbms_output.put_line()相当于java中sysc
           
           declare 
             i varchar2(10) :='张三';
           begin
             dbms_output.put_line(i);
            end;
          查询7369的工资,并且打印出来 
                  
           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_line(vsal);
               end;
           查询7369的员工信息,并且打印出来       
           select * from emp where empno =7369;
           declare
                vrow emp %rowtype;
            begin
              select * into vrow from emp where empno =7369;
              dbms_output_line('姓名:'||vrow.ename || '工资'||vrow.sal)
             end;
             
             pl条件判断
             if then
               elseif then
                 else 
               end if;
 根据不同年纪,输出相关内容
 declare
    age number :=&aaa;
 begin
   if age <18 then  dbms_output.put_line('小屁孩')
     elseif age>=18 and age <=24 then
        dbms_output.put_line('年轻人')
      elseif age>24 and age <40 then
         dbms_output.put_line('老司机')
        else
           dbms_output.put_line('老年人')
          end if;
 end;
 
 循环操作
 while 循环
   while 条件 loop
     end loop;
     
   for 循环
    for 变量 in reverse 起始值 .. 结束值 loop
      end loop;
      loop循环

输出 1-10
declate
i number :=1;
begin
where 1<=10 loop
dbms_output.put_line(i);
i:=i+1;
end loop;
end;

 输出 1-1o
 declare
 begin
   for i in 1..10  loop
     dbms_output.put_line(i)
    end loop;
    end;
    loop循环
 --输出 1-1o
 loop 
   exit when 条件
   end loop;
   
   输出1-10
   declare
       i number :=1;
       begin 
         loop
           exit whenn i>10;
           dbms_output.put_line(i);
           i:=i+1;
           end loop;
          end;
          
          *
         ***
         
         使用plsql输出菱形
     declare 
         m number :=2;
     begin
       for x in  -m..m loop
         for y in -m..m loop
           if abs(y)+abs(x)<=m then
             dbms_output.put('*')
             else 
               dbms_output.put(' ');
               end if;
            end loop;
            dbms_output.new_line();
           end loop;
       end;
    序列 oracle使用来模拟id自动增长的
    create sequence seq_test4;
    create table test2(
           tid number primary key,
           tname varchar2(10)
    );
    insert into test2 values(seq_test4.nextval,'张三');

select * from test2;
plsql编程:过程语言,编写一些复杂的业务逻辑
输出*号
sal emp.sal%type ---引用型变量
row emp%rowtype ---记录型变量

select sal into vsal from emp where empno=7788;

abs(y)+abs(x)<=m
declare
m number :=3;
begiin
for y in -m .. m loop
for x in -m .. m loop
if abs(y)+abs(x)<=m then
dbms_output.put_line('*');
else
dbms_output.put_line(' ');
end if;
end loop;
dbms_output.new_line();
end loop;
end;
游标:是用来操作查询结果集,相当于jdbc中resultSet
select * from emp;
语法:curscr 游标名(参数名 参数类型) is 查询结果集
开发步骤:
1.声明游标
2.打开游标 open 游标名
3.从游标中取数据 fetch 游标名 into 变量
游标名%found :找到数据
游标名%notfound: 没有找到游标

  4.关闭游标 close游标名
  输出员工表中所有的员工姓名和工资(不带参数游标)
  结果集 :所有员工
  声明一个变量,用来记录一行数据 %rowtype
  declare
     cursor vrows is select * from emp;
     --声明变量,记录一行数据
     vrow emp%rowtype;
  begin
    --1.打开游标
    open vrows;
    --2.从游标中提取数据
    --循环取数据
    loop
         fetch vrows into vrow;
         exit when vrows%not found;  
        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
1.打开游标,指定10号部门
open vrows(10);
循环遍历,取数值
loop
fetch vrows into vrow;
exit when vrows%notfound;
dbms_output.put_line('姓名:'||vrow.ename || '工资: ' || vrow.sal)
end loop;
close vrow;
end;
系统引用游标
1.声明游标:游标名 sys_reference
2.打开游标:open 游标名 for 结果集
3.游标中取数据
4.关闭游标
输出员工表中所有员工姓名和工资
declare
声明系统引用游标
vrows sys_reference;
声明一个变量
vrow emp%rowtype;
begin
打开游标
open vrow for select * from emp;
取数据
loop
fetch vrows into vrow;
exit when vrow%notfound;
dbms_output.put_line('姓名:'||vrow.ename || '工资:'||vrow.sal)
end loop;
end;
扩展内容————使用for循环遍历游标
declare
声明一个游标
curscr vrows is select * from emp;
begin
for vrow in vrows loop
dbms_output.put_line('姓名:'||vrow.ename || '工资:'||vrow.sal)
end loop;
end ;
for 循环遍历游标:
不需要声明额外游标
按照员工工作给所有员工涨工资,总裁涨1000,经理800 其他人400
游标:所有员工
声明一个记录一行数据
declare
声明一个游标
cursor vrows is select * from emp
声明一个变量
vrow emp%rowtype;
begin
打开游标
open vrows;
循环取数据
loop
退出的条件
exit when vrows%notfound;
根据不同的职位,涨工资总裁涨1000,经理800 其他人400
if vrow.job='presidret' then
update emp set sal =sal+1000 where empno=vrow.empno;
elseif vrow.job='manager' then
update emp set sal =sal+800 where empno=vrow.empno
else
update emp set sal =sal+400 where empno=vrow.empno
end if;
end loop;
根据不同的职位,涨工资
关闭游标
close vrows;
提交事务
commit;
end;
例外:(意外)程序运行的过程中发生异常,相当于java中的异常
declare
--声明变量
begin
--业务逻辑
exception
--处理异常
when 异常:then
when 异常2 then
... 处理其他异常
end;
zero_divide:处零异常
value_error:类型转换异常
too_many_row:查询出多行记录,但是赋值给了rowtype记录一行数据变量
no_date_found:没有找到数据
declare
vi number;
vrow emp%rowtype;
begin
vi:=8/0;
vi:='aaa';
select * into vrow from emp where empno=1234567;
exception
when zero_divide then
dbms_output.put_line('发生了处理异常');
when value_error then
dbms_output.put_line('发生了类型转换异常');
when too_many_rows then
dbms_output.put_line('查询出多行记录,但是赋值给了rowtype记录一行数据变量');
when no_data_found then
dbms_output.put_line('没有找到数据异常');
when others then
dbms_output.put_line('发生了其他异常'|| sqlerrm);
end;
自定义异常:
异常名 exception:
raise 异常名
查询指定编号的员工,如果没有找到,则抛出自定义的异常
1.声明一个变量rowtype 2.查询员工信息,保存起来 3.判断员工信息是否为空, 4.如果是,则抛出异常 declare 1.声明一个变量rowtype
vrow emp%rowtype
2.声明一个自定义的异常
no_emp exception;

begin

     2.查询员工信息,保存起来
     select * into vrow from emp where empno=8888;
     if vrow.sal is null then
       raise no_emp; 抛出自定义的异常
       end if;
       exception
         when no_emp then
           dbms_output.put_line('输出了其他异常'||salerrm)
end;       

 查询指定编号的员工,如果没有找到,则抛出自定义的异常
 
 游标来判断
 $found $notfound
 声明一个游标
 声明一个变量,记录数据
 从游标中取记录
 如果有则 不管它
 如果没有就抛出自定义的异常
 declare
 声明游标
 curreor vrow is select * from emp where empno=8888;
 声明一个记录型的变量
 vrow emp$rowtype;
 声明一个自定义异常
 no_emp exception;
 begin
   打开游标
   open vrows;
   取数据
   fetch vrows into vrow;
   判断 游标是否有数据
   if vrows%notfound then;
      raise no_emp;
   end if;
   close vrows;

exception
when no_emp then
dbms_output.put_line('发生了自定义的异常');
emd;
存储过程:实际是封装在服务器上的一段plsql的代码片段
1.客户端去调用存储过程,执行效率就会非常高
2.语法:create[or replace] procedure 存储过程的名称
(参数名 in|out 参数类型)is | as
声明变量
begin
业务逻辑
end;

User user=new User();
public void getUser(int userid,user){
--
user.setName();
}
给指定员工涨薪,并打印涨薪前和涨薪后的工资
参数 :in 员工编号
参数:int 涨多少
声明一个变量:存储涨工资前的工资
查询出当前的工资是多少
打印涨薪前的工资
更新工资

create or replace procedure prcc_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;

打印涨薪后的工资

方式1
call proc_updatesal(7788,10);
方式2 用的最多的方式
declare
begin
proc_updatesal(7788,10);
end;

存储函数:实际上是一段封装是oracle服务器中的一段plsql代码片段,它是已经编译好的
语法:
create(or replace) function 存储函数的名称(参数名 in|out 参数名 in|out)
is | as
begin
end;
存储过程和存储函数的区别:
他们本质上没有区别
函数存在的意义是给过程来调用的 存储过程里面调用存储函数

默认是 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);
en;
查询员工的姓名,和他的年薪
select ename,func_gctsal(cmpno) from emp;
函数可以在sql语句中直接调用
存储过程能实现的,存储过程能实现的,存储函数也能实现,存储函数能实现的
存储过程也能实现
查询员工指定员工的年薪--存储过程来实现
输出:年薪
create or replace procedure proc_gettotalsal(empno in_number,vtotalsal out number)
is
begin
select sal*12 +nvl(comm,0) into vtotalsal from emp where empno=vempno;
end;
declare
begin
proc_gettotalsal(7788,vtotal);
dbms_output.put_line('年薪:'||vtotal)
end;

java调用存储过程
jdbc的开发步骤
1.导入驱动包
2.注册驱动
3.获取连接
4.获取执行sql的statement
5.封装参数
6,执行sql
7获取结果
8.释放资源
触发器
当用户执行了insert | update |delete 这些
操作之后,可以出发一系列其他的动作
triger trigerhandler
作用:
 在动作执行之前或者之后,出发业务处理逻辑
 插入数据,做一些校验
语法:
create[or replace] triger 触发器的名称
before | after
insert | update |delete
on 表名
(for each row)
declare
begin
  end;

新员工员工入职之后,输出一句话:欢迎加入黑马程序员

create or replace trigger tri_test1
after
insert
on emp
declare
begin
dbms_output.put_line('欢迎加入黑马程序员')
end;
insert into emp(empno,ename) values(9527,'huaan');
--数据校验,星期六老板不在,不能办理新员工入职
--在插入数据之前
--判断当前日期是否是周六
如果是周六,就不能拿插入
create or replace trigger tri_test2
before
insert
on emp
declare
--声明变量
vday varchar2(10);
begin
--查询当前
end;
select trim(to_char(sysdate,'day'))into vday from dual;
--判断当前日期
if vday='saturday' then
dbms_output.put_line('老板不在,不能办理入职')
--抛出系统异常
raise_application_error(-20001,'老板不在,不能办理入职');
end if;
end;
insert into emp(empno,ename) values(9527,'huaan');
触发器的分类
语句级触发器:不管影响多少行,都只会只会执行一次
行级触发器: 影响多少行,就触发多少次
:old.sal 100 代表旧的记录
:new 代表的是新的记录
--更新所有的工资 输出一句话
create or replace trigger tri_test3
after
update
on emp
for each row
declare
begin
dbms_output.put_line('更新了数据')
end;
update emp set sal=sal+10;
判断员工涨工资后的工资一定要大于涨工资前的工资
200--100
触发器 :before
旧的工资
新的工资
如果旧的工资大于新的工资,抛出异常,不让它执行成功
create or replace trigger tri_updatesal
before
update
on emp
for each row
declare

  begin
    if old.sal> :new sal then
      raise_application_error:-20002,'旧的工资不能大于新的工资'
      end if;
    end
    update emp set sal=sal+10;
    select * from emp;
    update emp set sal=sal-100;

你可能感兴趣的:(2019-04-02 oracle)