oracle 学习(三)

--获取员工的名字和部门的名字
select e1.ename ,d1.dname from emp e1,dept d1 where e1.deptno=d1.deptno;
--使用子查询完成来完成
select ename ,deptno from emp;
select ename ,deptno,(select dname from dept d where d.deptno=e.deptno) deptname from emp e;

select *from emp;
select *from dept;
select *from salgrade;
/*
DDL
DML
DCL
*/

/*
oracle 体系结构
  数据库 -->数据库实例-->表空间(用户里面创建表)-->数据文件
   地球--> 中国       -->省份(人民)            -->土地山川河流               
创建表空间:逻辑单位,通常我们创建一个项目,就会去新建表空间,在表空间中创建用户来创建表
   语法:
     create tablespace 表空间的名称
     datafile '文件的路径(服务器上)
     size 大小
     autoextend on 自动扩展
     next 每次扩展的大小 
*/
--切换到system账号下创建  session --> login on
--创建一个表空间--汉东  (insufficient privileges)
create tablespace handong
datafile 'd:/myorcl/handong.dbf'
size 100m
autoextend on 
next 10m;
--删除表空间
drop tablespace handong;
/*
 创建用户
  create user 用户名
  identified by 密码
  default tablespace 表空间的名称
*/
create user tianmao 
identified by tianmao
default tablespace handong;


---登录 ORA-01045:user DAKANG lacks CREATE SESSION privilege ;logon denied
/*
用户赋权限
  1.connect --是授予最终用户的典型权限,最基本的
  2.resource 角色 --一般授予开发人员的 
  3.dba 角色
       拥有全部特权,是系统最高权限,只有DBA才可以创建数据结构,并且系统权限也需要DBA授出
       ,且DBA用户可以操作全体用户的任意基表,包括删除
  
  grant 角色|权限 to 用户
*/
grant connect to tianmao;
--授予dba权限  
grant dba to tianmao;  
select *from scott.emp; 

/*
创建表 
  create table 表名(
    列名 列的类型(列的约束)
    列名 列的类型(列的约束)
    );
  列的类型:
    varchar 在oracle中,目前是支持的,但是不保证以后还支持
    varchar2(长度) 可变字符长度  varchar2(10) hello 占5个字符
    char(长度) 固定长度字符      char(10)     hello 占10个字符,用空格填充
    number(总长度,小数长度)    数字类型    --小数长度不能大于等于总长度
    date                       年月日时分秒  2019/3/2 星期六 14:03:11
    timestamp                  时间戳,比date类型更加精确  02-MAR-19 02.03.47.750000 PM +08:00
    
    LONG/CLOB :存放一本小说
    BLOB :      存放电影  java 存进去,再读取出来
 使用子查询的方式创建表
     create table 表名 as 查询语句;   
 
*/

create table test1(
 name1 varchar2(10),
 name2 char(10),
 age   number(2,3)
);

insert into test1(name1,name2) values('hello','world');
select *from test1 where name1 like 'hello';--可以查询数据
select *from test1 where name2 like 'world';--查不出数据

--valus larger than specified precision allowed for this column
insert into test1(age) values(2.33);--error

select current_date from dual;--2019/3/2 星期六 14:03:11
select current_timestamp from dual;--02-MAR-19 02.03.47.750000 PM +08:00
/*
 复制表
 使用子查询的方式创建表
     create tbale 表名 as 查询语句; 
        注意:只会复制表结构和表中的数据,不会复制列的约束
              如果查询语句有结果,就是复制表结构和数据
              如果查询语句没有结果,就是复制表结构 
*/



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

--如果查询语句是没有任何结果的
select *from scott.emp where 1=2;
create table emp1 as (select *from scott.emp where 1=2);
select *from emp1; 

/*
   修改表
      添加列
      修改列 varchar2(10)
      删除列
      修改列名
      
      重命名表
 SQL分类:
   DDL:数据定义语言 修改的结构  alert create drop truncate
   DML:数据操作语言 操作表中数据 insert update delete 
   DCL:数据操作语言  grant
   DQL: select 
   
*/
create table stu(
  stuid number,
  sname varchar(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 gender;
--删除列
alter table stu drop column phone;

--修改表名
rename stu to student;

--删除表
drop table student;
/*
表的五大约束
列的约束:约束主要四是用来约束表中数据的规则
  主键的约束  primary key 不能为空,必须唯一
  非空的约束
  唯一的约束
  检查约束     在mysql中时可以写的,但是mysql直接忽略了检查约束
  
  外键约束
    主要是用来约束从表中的记录,必须是存在于主表中
*/

create table student (
  stuid number primary key,
  sname varchar2(20) unique,
  age varchar2(10) not null,
  gender varchar2(4) check (gender in ('男','女','人妖'))
);
--主键约束
insert into student values(1,'Tom','31','男');
insert into student values(1,'Tom','31','男');
--唯一约束
insert into student values(2,'张三丰','31','男');
insert into student values(3,'张三丰','31','男');
--非空约束
insert into student values(4,'李白',null,'男');
--check约束
insert into student values(4,'李白','18','man');
select *from student;

/*
   商品分类表和商品表
*/
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);--插入失败

--添加外键约束
truncate table product;
alter table product add foreign key(cno) references category(cid);

--1.首先主表住必须存在11号,先往主表中插入数据,再往从表中插入数据
insert into category values(2,'电脑办公');
insert into product values(10,'联想电脑',2);

--删除category
drop table category;--表中记录被外键关联无法删除
--强制删除表:先删除外键关联表的外键约束,然后在删除自己,先删除product的外键约束,在删除category
drop table category cascade constraint;

drop table product;

--级联删除
--添加外键约束 ,使用级联约束,在删除的时候吗,使用级联删除
alter table product add foreign key(cno) references category(cid) on delete cascade;
insert into category values(2,'电脑办公');
insert into product values(10,'联想电脑',2);
--级联删除:首先去从表中找有没有关联数据,如果在从表中找到从表数据,先删除从表中关联数据
--再删除主表中的数据
delete from category where cid=2;

select *from category;
select *from 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='华安' where ename='MILLER';

/*
  删除数据
    delete from 表名 [where 条件]
    delete 和truncate 区别:
    1.delete: 
       DML
       逐条删除
       支持事务操作
    2.truncate:
       DDL
       先删除表,在创建表
       不支持事务操作
       执行效率要高
*/
delete from emp1 where empno=7839;
/*
  事务:就是一系列的操作,要么都成功,要么都失败
     事务四大特性:
        1.原子性
        2.隔离性
        3.持久性
        4.一致性
      如果不考虑隔离级别,脏读,虚读,不可重复读
         MYSQL隔离级别: READ UNCOMMITTED ,READ COMMITTED ,REPEATABLE READ,SERIALIAZABLE 
         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);
insert into louti values(3);
insert into louti values(4);
insert into louti values(5);
savepoint dangban;
insert into louti values(5);
insert into louti values(6);
rollback to dangban;
commit;

declare 
begin 
  insert into louti values(1);
  insert into louti values(2);
  insert into louti values(3);
  insert into louti values(4);
  insert into louti values(5);
  savepoint dangban;
  insert into louti values(5);
  insert into louti values(6);
exception --捕获异常
   when others then 
      rollback to dangban;
      commit;
end;
select *from louti;
  
/*
  视图:是对查询结果的一个封装
            视图里面所有的数据,都是来自于原表(查询的那张表),视图本身不存储任何数据
       1.能够封装复杂的查询结果
       2.屏蔽表中的细节
     语法:
       create [or replace ] view 视图的名称 as 查询语句 [with read only]
     注意:通常不要通过视图去修改数据,视图创建的时候,通常要加上with read only
*/
select *from emp;
--创建一个视图
create or replace view view_test1 as select ename ,job,mgr from emp;
--通过视图修改数据,原表也被修改
update view_test1 set ename='SMITH2' where ename='SMITH';
--创建一个只读视图
create or replace view view_test2 as select ename ,job,mgr from emp with read only;
update view_test2 set ename='SMITH4' where ename='SMITH3';--不可修改
select *from view_test2;
select *from emp;
--视图封装复杂的查询语句
create or replace view view_test3 as 
select 
  sum(cc) Total ,
  sum(case yy when '1980' then cc end) as "1980",
  sum(case yy when '1981' then cc end) as "1981",
  sum(case yy when '1982' then cc end) as "1982",
  sum(case yy when '1987' then cc end) as "1987"
from
  (select to_char(hiredate,'yyyy') yy,count(1) cc from emp  group by to_char(hiredate,'yyyy')) tt;
  
--同义词
create synonym dept for view_test3;
select *from dept;

select *from view_test3;

/*
  序列:生成类似于 auto_increatment 这种id自动增长
     auto_increatment --这个是mysql
  语法:
      create sequence 序列的名称
      start with 从几开始
      increment by 每次增长多少
      maxvalue 最大值 | nomaxvalue
      minvalue 最小值 | nominvalue
      cycle | nocycle 是否循环  1,2,3,1,2,3
      cache 缓存的数量| nocache 1,2,3,4,5,6...
      
      如果从序列中获取值
         currval:当前值
         nextval:下一个值
             注意:currval 需要在调用nextval之后才能使用
*/
--创建一个1,3,5,7,9...30,1,3,5...
create sequence seq_test1
start with 1
increment by 2
maxvalue 30
cycle
cache 10;

select seq_test1.nextval from dual;
select seq_test1.currval from dual;

--序列用的最多的一种写法
create sequence seq_test2;

select seq_test2.nextval from dual;
select seq_test2.currval from dual;

create sequence seq_test3
start with 1
increment by 2
maxvalue 30
minvalue 0
cycle
cache 10;

select seq_test3.nextval from dual;
select seq_test3.currval from dual;

/*
  索引:相当于一本书的目录,能够提高我们的查询效率
    如果某一列,你经常用来作为查询条件,那么就有必要创建索引,数据量比较大的情况下
   
   语法:
       create index 索引的名称 on 表名(列)
   注意:主键约束自带索引,唯一约束自带唯一索引 
   
  索引的原理:btree  balance Tree 平衡二叉树
          如果某列作为查询条件的时候,可以提高查询效率,但是修改额时候,会变慢
          索引创建好之后,过了一段时间,DBA都会去做重构索引
   SQL调优:
       1.查看执行计划 F5  Tools ---> Explain Plan
       2.分析里面的cost和影响行数,想办法降低
*/
--五百万数据测试
create table wubaiwan(
   name varchar2(30),
   address varchar2(30)
);

--插入500万条数据
declare 
begin
    for i in 1..5000000 loop
       insert into wubaiwan values('姓名'||i,'地址'||i);
    end loop; 
    commit;
end;
--在没有添加索引的情况下,去查询name='姓名3000000'
select *from wubaiwan where name='姓名3000000';--0.25s
--创建索引 name 再去查询name='姓名3000000'
create index ind_wubaiwan on wubaiwan(name);
select *from wubaiwan where name='姓名3000000';--0.094s
--在没有添加复合索引的情况下,再去查询name='姓名3000000' and address='地址3000000'
select *from wubaiwan where name='姓名3000000' and  address='地址3000000';--0.157

--创建复合索引的情况下,再去查询
create index ind_wubaiwan2 on wubaiwan(name,address);
select *from wubaiwan where name='姓名3000000' and  address='地址3000000';--0.031
/*
 DDL 表空间操作
    创建表空间
    创建用户
    授权
    
    创建表 
       子查询创建表
     修改表:添加列,修改列,修改列名,修改表名
     
     约束
        1.主键约束 2.唯一约束 3.非空约束 4.检查约束 5.外键约束
             外键约束 
                强制删除
                级联删除
     DML表中数据
        插入数据
           子查询插入数据
        更新数据
        删除数据
            delete 和truncate 
        
        
        事务操作
           savepoint 保存点
           rollback to 保存点
        oracle 事务隔离级别
              默认 read committed 
              
        视图:就像窗户一样,封装查询结果,通常视图创建只读视图
        序列:主要用来实现id自增长   永不回头,往下去数据 ,无论发生异常 ,还是回滚
        索引:相当于是书的目录,能够提高查询效率     原理:平衡二叉树 ,每隔一段时间 dba都需要重建索引
        同义词: create synonym 名称 for 对象的名称
*/

--1.列出至少有有5个员工的所有部门和部门信息
--统计每个部门员工的数量
select deptno,count(1) c from emp group by deptno;
--找出员工数量至少5个的部门
select deptno ,count(1) from emp group by deptno having count(1)>=5;
--查询出部门信息
select d.*from dept d,(select deptno,count(1) c from emp group by deptno) tt where d.deptno=tt.deptno and tt.c>=5;

--2.列出受雇日期遭遇直接上级的所有员工的编号,姓名,部门名称
--查询员工的编号,姓名,员工的受雇日期,  经理的编号,经理的受雇日期
select e.empno,e.deptno,e.ename,e.hiredate ,e.mgr ,e2.hiredate mgr_hiredate from emp e,emp e2 where e.mgr=e2.empno; 
--员工的受雇日期早于直接上级的
select e.empno,e.deptno,e.ename,e.hiredate ,e.mgr ,e2.hiredate mgr_hiredate 
from emp e,emp e2 
where e.mgr=e2.empno and e.hiredate <e2.hiredate;
--加上部门名称
select tt.empno,tt.ename,d.dname 
from dept d ,
(select e.empno,e.deptno,e.ename,e.hiredate ,e.mgr ,e2.hiredate mgr_hiredate 
from emp e,emp e2 
where e.mgr=e2.empno and e.hiredate <e2.hiredate) tt
where tt.deptno=d.deptno;

--17 统计薪资大于薪资最高的员工所在部门的平均工资和薪资最低的员工所在部门的平均工资的平均工资的员工信息
--两个部门的平均工资
--大于这两个部门的平均工资的员工
--1.薪资最高的员工
  select max(sal) from emp;
--2.薪资最高的员工的部门编号 
 select deptno from emp where sal=(select max(sal) from emp);--10
--3.部门的平均工资 --2916
 select avg(sal) from emp where deptno=( select deptno from emp where sal=(select max(sal) from emp));

--4.薪资最低
select min(sal) from emp;
--5.薪资最低的员工所在部门  --20
select deptno from emp where sal=(select min(sal) from emp);
--6.部门的平均工资 --2175
select avg(sal)  from emp where deptno=(select deptno from emp where sal=(select min(sal) from emp));
--7.查询上面两个部门的平均工资
select  (tt1.avg1+tt2.avg2)/2 avg_sal from dual ,
(select avg(sal) avg1 from emp where deptno=( select deptno from emp where sal=(select max(sal) from emp))) tt1,
(select avg(sal) avg2 from emp where deptno=(select deptno from emp where sal=(select min(sal) from emp))) tt2;
--8.工资大于上面两个部门的平均工资的员工
select *from emp 
where 
sal>(select  (tt1.avg1+tt2.avg2)/2 avg_sal from dual ,
(select avg(sal) avg1 from emp where deptno=( select deptno from emp where sal=(select max(sal) from emp))) tt1,
(select avg(sal) avg2 from emp where deptno=(select deptno from emp where sal=(select min(sal) from emp))) tt2);
/**
PLSQL编程:procedure 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中sys...out()
  
*/

declare 
  i varchar2(10):= 'Jack';
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 
  select * into vrow from emp where empno=7369;
  dbms_output.put_line('name:'||vrow.ename||',sal:'||vrow.sal);
end;
/*
  PL条件判断
     if then
        elsif then 
          else  
     end if;
根据不同年龄,输出相关内容
*/

declare
 age number := &aaa; --弹出输入框
begin 
  if age<18 then 
    dbms_output.put_line('未成年人');
  elsif age>=18 and age<24 then
    dbms_output.put_line('young');
  elsif 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 起始值..结束值 loop
        end loop;
    loop 循环
*/
--输出1~10
declare 
  i number :=1;
begin 
  while i<=10 loop
    dbms_output.put_line(i);
    i :=i+1;
  end loop;
end;
--输出1~10
declare 
begin 
  for i in reverse 1..10 loop  --reverse 反转
     dbms_output.put_line('i='||i);
  end loop;
end;
--输出1~10
declare
 i number :=1; 
begin 
  loop 
     exit when i>10;
     dbms_output.put_line(i);
     i := i+1;
   end loop;
end;

/*
  *
 ***
*****
 ***
  *
  
  输出m
    x:=[-m,m]
    y:=[-m,m]
    输出所有满足条件的 abs(y) +abs(x) <=m
    m取值
*/
--使用PLSQL输出一个菱形

declare
  m number :=20;
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;

--使用PLSQL输出三角形
declare
  m number :=20;
begin
  for x in -m..0 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;


select *from emp;
select *from dept;

猜你喜欢

转载自blog.csdn.net/u011206291/article/details/89762173