oracle笔记

1.大二下课程



2.
Oracle 9internet
Oracle 10G
Oracle 11Grid 


www.oracle.com


3.安装与卸载
   Orcl 实例  完成一件事情的过程
   1.卸载软件
   2.更改注册表  打开注册表 regedit P11 
4.服务
   1.TNSListener  侦听服务  监视每次操作,确保安全。
   2.OracleServiceORCL 基础服务
   注意先后顺序


5.管理工具的认识
  net manager   iSQL/Plus  基于网络
  sql developer     SQL/PLUS (学习阶段使用)
  第三方  PL/SQL   developer 
    登录SQL/PLUS 用户名、密码  system/manager


6.登录SQL/PLUS


  system/Manager


7.sqlplus常用命令
   执行语句 ";"结尾 Enter
  remark ...
  show user  查看当前用户 
  exit  退出
  spool 'E:\Oracle\demo.txt'
  <需要输出的内容>
  spool off
  set LineSize 200  设置宽度
  set PageSize 200  设置页数
  edit   编辑  注意:编辑窗口打开的时候 不需要 “;”  保存之后退出。用 "/"执行
  desc   查看表结构 


8.用户
  安装之后有三个常用的用户
  管理员
  system /manager  
  sys /as sysdba
  普通用户
  scott/tiger
  所有的表都是基于用户的不是基于数据库,为了安全性考虑


9.切换用户的命令
  conn system/manager;


10.新安装的scott
   a.密码过期
   this password has expired;
   alter user scott identified by abc;
   b.scott 被锁定
   alter user scott account unlock;


11.创建表空间 
   tablespace (逻辑概念)  相当于SQL Server中的数据库 database
        create tablespace UserDB
  datafile 'E:\Oracle\UserDB.dbf'
        size 10m
        autoextend on
12.脱机与联机
alter tablespace <表空间名称> Offline temporary;
   ...
   联机  


  alter tablespace <表空间名称> online;


13.创建用户
  create user <名称>  identified by <密码>  deflaut tablespace <表空间的名称> temporary tablespace temp; 
   1.新创建用户没有任何权限


   create user demo identified by abc default tablespace UserTS temporary tablespace temp;
14.授权 身份 角色
   connect  resource dba; 
grant connnect to demo;

回顾
  1.服务
    linstener 监听会话的状态
    ServiceORCL
  2.实例 ORCL  完成操作Oracle数据库的过程
  3.SQLPLUS命令
    remark 
    show user;
    set linesize ;
    spool '<文件路径>'
    spool off;
    exit
    desc
    start ,@  用来执行SQL脚本
  4.表空间  tablespace 类似于 database
    create tablespace Demo
    datafile 'e:\Oracle\Demo.dbf'
    size 10m
    autoextend on;
  5.用户
    create user Demo identified by abc default tablespace demo temporary tablespace temp;
  6. 权限的管理
    
   系统权限:connect resource dba 
     grant connect to demo
    对象权限:insert delete update  select  all  
     
    收回权限 
     系统权限:
     revoke connect from demo
     对象权限
     revoke select on scott.emp from demo;


Lesson_2
1.数据类型
     a.数值型
     标准SQL 
     int  float double money byte
     number(p,s)
     p:精度 123456.7890000000000000000   38位 
     S:小数点后有效位数
     number (9,-4)
     123450.000
     兼容sql标准的数据类型
     b.字符型
     标准SQL 
      CHAR(10)  VARCHAR(10)  nvarchar(10)
     内存机制
      Oracle
       char(10)  varchar2(10)
     c.日期型
      SQL Server 
        datetime
      Oracle 
        date
     d.大对象
        SQL Server 
         Text
        Oracle
        CLOB BLOB
      long  2G  1024*1024*1024*2
     保留字 UID 
    TO_Date('1922-01-01','YYYY-MM-DD');
    To_char('1922-01-01','YYYY-MM-DD');
   
    理解会话: Session
    alter session set NLS_DATE_FORMAT='YYYY-MM-DD'
2.空类型 null
    ''的比较 
     
3.SQL 中的符号
    a. in,not in
    select * from students where id in(1,2,3,66,45);
    select * from students where id in(select pid from position)
    b. any some all 比较符号  <,>,=....
     any(条件)  只要满足其中的某一个条件 就可以查询出来结果
        select * from students where id      all(条件)  满足所有的条件,才能查询出来结果
         select * from students where id 4.DDL数据定义语言
     create  drop alter 
     添加字段  ADD 不能用not null;
     alter table students ADD(sAddress varchar2(100));
     更新字段  
     alter table students modify(sAddress varchar2(10));
     删除字段
     alter table students drop(address);
     扩展
     可以更改会话显示的宽度
     col <列名> format a10  字符类型的列
     col <列名> format 99999 数值类型的列
5.DML 数据操作语言
    insert update delete select 
    联合查询  
    内连接 
   <表名> inner jion <表名> on <条件>
     select * from <表名> a,<表名> a where a.<字段> = b.<字段>
    左外连接 
    <表名>  a  left outer join  <表名> b on  a.<字段> = b.<字段>
     select * from <表名>  a,<表名> b  where a.<字段> = b.<字段>(+);
    右外连接
    <表名>  a  right outer join  <表名> b on  a.<字段> = b.<字段>
     select * from <表名>  a,<表名> b  where  a.<字段>(+) = b.<字段>;
6.数据控制语言 
    系统权限  系统提供的权限 
      grant ... to  ...
      grant create any tale to demo;  
    对象权限  可以对Oracle的对象的操作权限
      select update delete insert all
     收回权限
      revoke ....from ...
7.事务控制语言 TCL
     事务?把处理事件的步骤在一个单元内执行,要么一起成功,要么一起失败。
     T-SQL SQL Server
     PL/SQL Oracle
     1.begin tansaction <名称>
       set @tran_error int;
       set @tran_error =  0 ;
      2.开始事务的操作
       update
      3.记录错误
       set @tran_error = @tran_error + @@error;
      4.开始下一个事务的操作
       update
      3.记录错误
       set @tran_error = @tran_error + @@error;
      if @tran_error <> 0
        begin
           rollbank transaction;
        end
     else 
        begin
          commit transction;
        end;
    Oracle
       savepiont 回滚点  rollback to 回滚点   commit;
        update account set acc = acc - 1000 where aid = 1;
        update account set acc = acc + 1000 where aid = 2;
8.伪表、伪列
    dual  为了保证数据查询的完整性
    select sysdate from dual; 
    ROWID  ROWNUM查看流水  
    level ???  
   
    

回顾
  1.服务
    linstener 监听会话的状态
    ServiceORCL
  2.实例 ORCL  完成操作Oracle数据库的过程
  3.SQLPLUS命令
    remark 
    show user;
    set linesize ;
    spool '<文件路径>'
    spool off;
    exit
    desc
    start ,@  用来执行SQL脚本
  4.表空间  tablespace 类似于 database
    create tablespace Demo
    datafile 'e:\Oracle\Demo.dbf'
    size 10m
    autoextend on;
  5.用户
    create user Demo identified by abc default tablespace demo temporary tablespace temp;
  6. 权限的管理
    
   系统权限:connect resource dba 
     grant connect to demo
    对象权限:insert delete update  select  all  
     
    收回权限 
     系统权限:
     revoke connect from demo
     对象权限
     revoke select on scott.emp from demo;


Lesson_2
1.数据类型
     a.数值型
     标准SQL 
     int  float double money byte
     number(p,s)
     p:精度 123456.7890000000000000000   38位 
     S:小数点后有效位数
     number (9,-4)
     123450.000
     兼容sql标准的数据类型
     b.字符型
     标准SQL 
      CHAR(10)  VARCHAR(10)  nvarchar(10)
     内存机制
      Oracle
       char(10)  varchar2(10)
     c.日期型
      SQL Server 
        datetime
      Oracle 
        date
     d.大对象
        SQL Server 
         Text
        Oracle
        CLOB BLOB
      long  2G  1024*1024*1024*2
     保留字 UID 
    TO_Date('1922-01-01','YYYY-MM-DD');
    To_char('1922-01-01','YYYY-MM-DD');
   
    理解会话: Session
    alter session set NLS_DATE_FORMAT='YYYY-MM-DD'
2.空类型 null
    ''的比较 
     
3.SQL 中的符号
    a. in,not in
    select * from students where id in(1,2,3,66,45);
    select * from students where id in(select pid from position)
    b. any some all 比较符号  <,>,=....
     any(条件)  只要满足其中的某一个条件 就可以查询出来结果
        select * from students where id      all(条件)  满足所有的条件,才能查询出来结果
         select * from students where id 4.DDL数据定义语言
     create  drop alter 
     添加字段  ADD 不能用not null;
     alter table students ADD(sAddress varchar2(100));
     更新字段  
     alter table students modify(sAddress varchar2(10));
     删除字段
     alter table students drop(address);
     扩展
     可以更改会话显示的宽度
     col <列名> format a10  字符类型的列
     col <列名> format 99999 数值类型的列
5.DML 数据操作语言
    insert update delete select 
    联合查询  
    内连接 
   <表名> inner jion <表名> on <条件>
     select * from <表名> a,<表名> a where a.<字段> = b.<字段>
    左外连接 
    <表名>  a  left outer join  <表名> b on  a.<字段> = b.<字段>
     select * from <表名>  a,<表名> b  where a.<字段> = b.<字段>(+);
    右外连接
    <表名>  a  right outer join  <表名> b on  a.<字段> = b.<字段>
     select * from <表名>  a,<表名> b  where  a.<字段>(+) = b.<字段>;
6.数据控制语言 
    系统权限  系统提供的权限 
      grant ... to  ...
      grant create any table to demo;  
    对象权限  可以对Oracle的对象的操作权限
      select update delete insert all
     收回权限
      revoke ....from ...
7.事务控制语言 TCL
     事务?把处理事件的步骤在一个单元内执行,要么一起成功,要么一起失败。
     T-SQL SQL Server
     PL/SQL Oracle
     1.begin tansaction <名称>
       set @tran_error int;
       set @tran_error =  0 ;
      2.开始事务的操作
       update
      3.记录错误
       set @tran_error = @tran_error + @@error;
      4.开始下一个事务的操作
       update
      3.记录错误
       set @tran_error = @tran_error + @@error;
      if @tran_error <> 0
        begin
           rollbank transaction;
        end
     else 
        begin
          commit transction;
        end;
    Oracle
       savepiont 回滚点  rollback to 回滚点   commit;
        update account set acc = acc - 1000 where aid = 1;
        update account set acc = acc + 1000 where aid = 2;
8.伪表、伪列
    dual  为了保证数据查询的完整性
    select sysdate from dual; 
    伪列:ROWID 记录每个数据行在硬盘上的位置的唯一标识;
          ROWNUM 标识查询结果集中记录序号;流水号
          LEVEL 查询数据所对应的层次;
      
        create table Position
(
         pid  number primary key,
         parentID number,
         posName varchar2(10)
        );
       insert into position values(1,null,'总经理');
       insert into position values(2,1,'项目经理');
       insert into position values(3,1,'财务总监');
       insert into position values(4,2,'程序员');
       insert into position values(5,3,'出纳');
      
  select level,pid,parentID,posName from position connect by prior pid = parentid start with pid = 1


9.集合运算
    union、union all  保持集合运算的两个表 要保持表结构一致。
    union 去除重复行
    union all 不去除重复行


    intersect  查询交集  
10.函数
   Lower ()   把字符变成小写
   upper ()   大写
   Trim()  去除空格  使用的场景  
   char(10)存储用户名或密码的时候,可能会存储空字符中,在读取的时候 要用到Trim()函数去除空格。
   round() 重点
   ceil()


   


11.分组函数
   MAX、count avg min sum


12.分析函数
  row_Number行号  rank dense_rank




----4.排序函数 ROW_NUMBER、RANK、DENSE_RANK


 create table stuMarks 
(
ID NUMBER ,
SName varchar2(10),
sMarks number
);




insert into stuMarks values (1,'aa',50);
insert into stuMarks values (2,'aa',60);
insert into stuMarks values (3,'bb',50);
insert into stuMarks values (4,'bb',60);
insert into stuMarks values (5,'cc',78);
insert into stuMarks values (6,'aa',42);
insert into stuMarks values (7,'vv',67);
insert into stuMarks values (8,'dd',45);
insert into stuMarks values (9,'ff',60);
insert into stuMarks values (10,'gg',56);




select row_number() over (partition by sname order by sMarks) as sMarks,id,sname,smarks from stumarks


select rank() over (partition by sname order by sMarks) as sMarks,id,sname,smarks from stumarks


select dense_rank() over (partition by sname order by sMarks) as sMarks,id,sname,smarks from stumarks




partition  by  分组


order by 排序




SQL Server


select ROW_NUMBER() OVER (ORDER BY stuScore desc) as 排名, a.sName,b.ID,b.stuScore,b.stuSubject  from StuInfo a,StuScore b 
where a.ID = b.stuID and b.stuSubject = 'SQL'  ----没有并列编号


select RANK() OVER (ORDER BY stuScore desc) as 排名, a.sName,b.ID,b.stuScore,b.stuSubject  from StuInfo a,StuScore b 
where a.ID = b.stuID and b.stuSubject = 'SQL'   ---有并列编号,且有跳空行




select DENSE_RANK() OVER (ORDER BY stuScore desc) as 排名, a.sName,b.ID,b.stuScore,b.stuSubject  from StuInfo a,StuScore b 
where a.ID = b.stuID and b.stuSubject = 'SQL'   ---有并列编号,连续


---5.PARTITION BY  对所有进行先分组后排序 替代 多个where子句
select DENSE_RANK() OVER (PARTITION BY stuSubject  ORDER BY stuScore desc) as 排名, a.sName,b.ID,b.stuScore,b.stuSubject  from StuInfo a,StuScore b 
where a.ID = b.stuID   
  
     


Lesson_3  分区表、锁
 
   分区表:按照一定的规则把表的数据进行分段存储,用于处理数据量大的情形
      来源:毛泽东选集
    范围分区  纵向比较
     1.为分区表建立相对应的表空间
     2.把一个完整的表进行按照一定的范围进行划分  
create table StuTab
 (
  sID number primary key,
  sname varchar2(10),
  sAge number
 )
 partition by range(sID)
 (
   partition p1 values less than (1001)  tablespace a,
   partition p2 values less than (2000)  tablespace b,
   partition p3 values less than (maxvalue)  tablespace c
 )


 list列表 横向比较
  create table MPhone
 (
   MID number(11)
   Mtype varchar(10),
   location varchar2(10)
 )
  partition by list(location)
  ( 
   patition p1 values('武汉','北京'),
   patition p2 values('香港','深圳','珠海'),
   patition p3 values('上海','苏州'),
   patition p3 values(default)
)


 
 散列Hash分区 


方法一:只关心分区的数量  保证性能的优化
 
create table Orders
  (
  oID number(10),
  nName varchar2(10),
  Odate date
 )
 partition by hash(oid)
 partition 8;
 


方法二:给定分区的名称
 create table Orders
  (
  oID number(10),
  nName varchar2(10),
  Odate date
 )
 partition by hash(oid)
(
  partition p1,
  partition p2,
  partition p3,
  partition p4
)
 
方法三:给定分区存储的表空间
 create table Orders
  (
  oID number(10),
  nName varchar2(10),
  Odate date
 )
 partition by hash(oid)
 partitions 4
  store in(a,b,c,d)




创建复合分区???(下次课讲)
 
分区表的维护
   1.查询分区 在查询语句后面 增加分区
    select * from <表名>  partirion(p1);
   2.增加分区
    alter table <表名>  ADD partition p5 values less then (3001) tablespace a;
   3.删除分区
    alter table <表名> drop partition  p3;





    1. 创建表空间
    create tablespace a
    datafile 'e:\Oracle\a.dbf'
    size 10m
    autoextend on
    2.创建范围分区
    create table students
   (
    stuid number primary key,
    sName varchar2(10),
    sAddress varchar2(10)
  )
   partition by range (stuid)
      subpartition by list (sAddress)
   (
    partition p1 values less than(1001) tablespace a
    (
       subpartition p11 values ('武汉','南京'),     
       subpartition p12 values ('北京','上海'),
       subpartition p13 values (default)
     ),
    partition p2 values less than(2001) tablespace b
    (
subpartition p21 values ('武汉','南京'),     
        subpartition p22 values ('北京','上海'),
subpartition p23 values (default)
     ),
    partition p3 values less than(maxvalue) tablespace c
    (
        subpartition p31 values ('武汉','南京'),     
        subpartition p32 values ('北京','上海'),
subpartition p33 values (default)
   )
 )


  第三题   
  select subStr(ename,1,1)||lower(substr(ename,2,length(ename)-1)) from scott.emp


**************Lesson_4  数据库对象 ****************
  
 ###  锁  ###


    用途:解决并发


    挂起:Oracle 自动提供了锁对正在被访问的表锁定,当其他用户访问的时候,不能访问的状态叫做挂起。
  
 ### 数据库对象 ###
   同义词、序列、视图、索引
  
 1.同义词
   猴哥 = 悟空 
   同义词:解决查询的数据库表名过长的问题,方便查询 
   
    1.私有同义词 synonym 
 
   让demo 用户给 Scott.emp创建一个 同义词
    1).给demo用户 create any synonym  的权限;
   grant create any synonym to demo;
    2).为scott.emp创建同义词
   create synonym <同义词名称> for scott.emp;


    2.公有同义词 public synonym 
     1).给demo用户 create public synonym 的权限
      grant create public synonym to demo;
     2).创建公有同义词
       create public synonym pubEMP for scott.emp;
    3.删除同义词
      drop synonym myEMP;
      drop public synonym pubEMP;


2.序列  自动增长列  sequence


 1.顺序增长   


   1).创建序列


   create sequence mySeq;
   2).显式使用序列
   insert into users values (mySeq.nextVAL,'demo');


 2.按照一定的间隔进行增长  
    create sequence mySeq1 increment by 2;


   ******** 掌握到此 即 OK *******


 3.按照开始的值进行序列往下
   create sequence mySeq2 increment by 1 start with 10;
 4.最大值的控制 
    create sequence mySeq2 increment by 1 start with 1 maxvalue 10  cycle chache 10;


5.删除序列
   drop sequence mySeq;
 


3.视图 简化查询
    1).简单视图:非链表查询
     create view vi_sal
     as
     查询语句
  
    复杂视图:链表查询
     create view vi_demo
as
select a.deptno,a.dname,b.empno,b.ename,b.sal,b.comm from dept a,emp b where a.deptno = b.deptno;
   
    2)键保留表(主键被保留)
     复杂视图有的字段可以修改,有的字段不能修改
     stuid的主键在视图中依然是主键,但classes的主键不再作为主键使用。因此students的主键叫做键保留表的主键,可以被修改。而classes 的主键是非键保留表的主键,不能被修改
    3)with check option 约束检查
      


4.索引 
   1.全表扫描
     select * from emp where sal<1500 
    2.通过索引扫描
      B树索引  位图索引 反向键索引
      在此基础上把数据排列一下,在内存中形成一种数据结构
          把第一个数字作为根节点,小的放左边,大的放右边。排列成树状结构
          只查询部分记录。 
  2.索引分类
    自动索引
       通过主键自动建立的索引,唯一索引
    手动索引
       
  3.建立索引原则                  
     
    a.在经常查询的字段上面建索引,不要在所有字段上建索引。
    b.只在上面update ,insert,delete 不用建索引,看数据结构
    c.用久了的索引,应该重新建索引。
    
 

        
     
   1.回顾
   数据库对象
1.同义词
   1).同义词 synonym 
    a.私有同义词 
    b.公有同义词 
   2).同义词权限
    grant create any synonym to demo
    grant create public synonym to demo
   3).删除
     drop synonym myEmp;
2.序列 
    1).sequence 自动增长列
    2).建序列
      create sequence mySeq;
    3).对象的属性
       mySeq.nextVAL;
    4).按照一定的间隔
      create sequence mySeq increment by 2;
3.视图
    view  
   1).create view vi_***
      as
      <查询语句>
   2).键保留表
      
4.索引
    index
   




1.office 


2.html  ---> b/s (网站) 


3.sql Server   +  asp.net 


  mySQL  + PHP  
                   + html + js(Jquery) + ps(网页设计)
  Oracle + jsp
   
4.   c/s winform + SQL Server  
         ??????   + Oracle


5.企业信息
   客户 + 原理 


      


Lesson_5  PL/SQL


1.什么是PL/SQL?
  数据库内部定义的语言
  SQL Server  Transaction-SQL
  Oracle      PL/SQL  


2.语言的数据类型,区别于字段的类型


    number(int,float), binary_interger,pls_interger


3.定义变量输出HelloWord
   1).输出Hello PL/SQL


   set serverpoutput on;  在客户端输出
   
    2).声明变量,并在begin 里面进行运算(方法体);
   declare 
     v_hello varchar2(10);
     v_plsql varchar2(10);
  begin 
    v_hello := 'hello';
    v_plsql := 'plsql';
    dbms_output.put_line(v_hello || v_plsql);
end;
    3).给默认值(初始值)
   declare 
   v_hello varchar(10) := 'Hello ';
   v_plsql varchar(10) default 'plsql';
   begin
     dbms_output.put_line(v_hello || ',今天学的是 :' || v_plsql);
   end;


************************* 注意 ********************
 
    4).(Oracle)利用%type定义变量 与 表中的数据保持一致 
    ***** 查询记录不能为多条;有且只有一行记录,不能返回空行或多行。 *****
     exact fetch returns more than requested number of rows
    ***** SQL Server查询多条记录的时候,给变量赋最后一个值  ****
     
   
4.
   1).利用查询语句进行赋值  %type 
   declare
      v_ename scott.emp.ename %type;
      v_sal   scott.emp.sal%type;
begin
    select scott.emp.ename into v_ename from scott.emp where scott.emp.empno = 7369;
  dbms_output.put_line(v_ename || v_sal);
end;
   2).利用查询语句进行赋多个值  %type 
   declare
   v_ename scott.emp.ename%type;
   v_sal scott.emp.sal%type;
 begin
   select scott.emp.ename, scott.emp.sal into v_ename,v_sal from scott.emp where    scott.emp.empno=7369;
  dbms_output.put_line('姓名:'||v_ename ||',薪水:'|| v_sal);
end;




5.%rowtype :赋整行的类型
declare
   v_row scott.dept%rowtype;
   v_dept scott.dept.deptno % type;
 begin
     v_dept := 10;
     v_row.deptno := 50;
     v_row.dname := 'demos';
     v_row.loc  := 'demos';
    v_dept := v_dept +  v_row.deptno;
    dbms_output.put_line(v_dept  || v_row.dname || v_row.loc);
 end;


   注意:null + 数字   仍然是 null
6.insert update delete 语句的使用
  step1:建表 
    create table test
    (
      tid number primary key,
      tname varchar2(10),
      tsal varchar2(10)
    );
    
  step2:建序列
    
     create sequence mySeq;
   
  step3:使用PL/SQL给表插入值


    declare 
      v_ename emp.ename%type := 'demo';
      v_sal   emp.sal%sal := 1200;
    begin 
      insert into test values(mySeq.nextval,v_ename,v_sal);
   end;


7.PL\SQL 控制语句
  1.  if 条件表达式 then
     执行语句
   end if;
   
   1).判断部门30的预算是否合理
  declare 
      sumsal emp.sal % type;
   begin 
     select sum(sal) into sumsal from emp group by deptno having deptno  = 30;
  if sumsal > 5000 then
     dbms_output.put_line('部门为30的工资总额超出预算,共'||sumsal);
  end if;
   end;
   2).条件判断
    if 条件表达式 then
      执行语句
    else
      执行语句
    end if ;
    end;
     
  declare 
      sumsal emp.sal%type;
      disSal number := 0;
     begin 
    select sum(sal) into sumsal from emp group by deptno having deptno =30;
    if (sumsal < 5000) then
      dbms_output.put_line('上月预算合理,此次批准拨款,上次预算为:'|| sumsal);
    else  
      disSal := sumsal- 5000;
      dbms_output.put_line('上月预算超支,此次审核后拨款,上次预算超额为:'|| disSal);
     end if;
   end;




    3).多从分支  
      if 条件 then
       执行语句
      elsif 条件 then
       执行语句
      else 
        执行语句
      end if;
      end;
       
     判断是否勤俭节约部门
     declare 
      sumsal emp.sal%type;
      disSal number := 0;
     begin 
      select sum(sal) into sumsal from emp group by deptno having deptno =30;
     if sumsal <= 3000 then
     dbms_output.put_line('最佳勤俭节约部门,花费预算为:'|| sumsal);
    elsif sumsal > 3000 and sumsal <= 5000 then   
     dbms_output.put_line('预算合理,花费预算为:'|| sumsal);
       else  
     disSal := sumsal- 5000;
      dbms_output.put_line('上月预算超支,此次审核后拨款,上次预算超额为:'|| disSal);
      end if;
      end;


  2.case  
       when 条件表达式1 then 
        执行语句;
       when 条件表达式2 then
        执行语句;
        else
        执行语句;
       end case;
       end;
   declare 
      sumsal emp.sal%type;
      disSal number := 0;
    begin
      select sum(sal) into sumsal from emp group by deptno having deptno = 30;
    case 
        when sumsal <= 3000 then 
         dbms_output.put_line('最佳勤俭节约部门');
        when sumsal > 3000 and sumsal <=5000
         dbms_output.put_line('预算合理');
        else  
        disSal := sumsal- 5000;
      dbms_output.put_line('上月预算超支,此次审核后拨款,上次预算超额为:'|| disSal);
    end;


8.循环控制 打印 1-10;
     语法: loop 
         exit when 条件表达式;
         执行语句
     end loop;
     
  declare 
     cou int := 1;
  begin 
     dbms_output.put_line('打印开始...');
  loop 
      exit when cou = 10;
       dbms_output.put_line('当前数字:'|| cou);
     cou:= cou +1;
   end loop;
 end;


9.  for 循环控制语句
     for 变量  in 起始值..结束值
     loop 
         执行语句
     end loop;
    
     declare 
         cou int := 1;
         result int := 0;
        begin 
        dbms_output.put_line('打印开始...');
      for cou in 1..10
        loop 
         dbms_output.put_line('当前数字:'|| cou);
          result := cou +1;
         end loop;
       end;


10.while 循环
     declare
     cou int := 0;
      begin
          dbms_output.put_line('打印开始...');
       while cou < 10
         loop
              cou := cou +1;
          dbms_output.put_line(cou);
         end loop;
         end;


11.跳转控制


  declare
      sumsal emp.sal % type;
  begin
      select sum(sal) into sumsal from emp where deptno = 30;
  if  sumsal > 2000 then
       goto first;
  elsif sumsal > 3000 then
       goto second;
  else goto third;
  end if;
 << first>>
   dbms_output.put_line('first:'||sumSal);
  return;
 <>
    dbms_output.put_line('second:'||sumSal);
  return;
 <>
    null;
end;


12.异常处理 
   1) 预定义异常
   declare 
     v_num number:= 0;
   begin 
     v_num := 2/v_num;
    dbms_output.put_line(v_num);
   exception 
      when others then
      dbms_output.put_line('error');
    end;




      


1.异常处理
   1) 预定义异常
   declare 
     v_num number:= 0;
   begin 
     v_num := 2/v_num;
    dbms_output.put_line(v_num);
   exception 
      when others then
      dbms_output.put_line('error');
    end;
   2).其他异常类型(略)
2.
  1).动态SQL
declare
   sqlstring varchar2(200);
   dept_id number(2) := 50;
   d_name varchar2(14) :='posal';
   location varchar2(10) :='develop';
  begin
  sqlstring :='insert into dept values (:1,:2,:3)';
  execute immediate sqlstring using dept_id,d_name,location;
end;


 
  2).动态SQL 把动态查询结果赋值给变量
declare
   sqlstring varchar2(200);
   emp_id number(4) := 7369;
   emp_rec emp%rowtype;
begin
 emp_id := &员工编号;
  sqlstring := 'select * from emp where empno = :id';
   execute immediate sqlstring into emp_rec using emp_id;
  dbms_output.put_line('员工编号:' || emp_rec.empno);
  dbms_output.put_line('员工姓名:' || emp_rec.ename);
end;


*******************  Lesson_5 游标 *****************




1.游标  显示游标


   为了暂存查询出来的多条结果。内存的引用


   1).提取emp中的所有数据
     declare
       --1.定义游标提取emp所有数据 
        cursor empcur 
         is 
         select * from scott.emp;
         emprow scott.emp%rowtype;
      begin
       --2.打开游标
       open empcur;
       --3.提取第一条记录数据;
      fetch empcur into emprow;
       --4.关闭游标;
         close empcur;
      end;


   2).循环提取所有的数据 ,有循环就需要有退出的条件   %notfound 游标检索数据表时,循环检测,直到不能被查询出来时。 %rowtype利用了面向对象的思想  一个%rowtype就是一个对象,
      读取与面向对象一样   students stu = new  students()   读取 stu.name  与  emprow.empno  一样  
     
       --1.定义游标提取emp所有数据 
        cursor empcur 
         is 
         select * from scott.emp;
         emprow scott.emp%rowtype;
      begin
       --2.打开游标
       open empcur;


       --3.提取所有记录数据;
      loop
      fetch empcur into emprow;
       exit when empcur%notfound;
      end loop;
       --4.关闭游标
         close empcur;
      end;
   3).定义多个变量去读取 
    declare
    cursor empcur
     is
    select empno,ename,sal from emp where deptno = 20;
    v_eno emp.empno%type;
    v_ename emp.ename%type;
    v_sal emp.sal%type;
   begin
     open empcur;
   loop
      fetch empcur into v_eno,v_ename,v_sal;
      exit when empcur%notfound;
      dbms_output.put_line('编号:'||v_eno ||',员工姓名:'|| v_ename || ',工资:' ||v_sal);
     end loop;
    close empcur;
  end;


2.游标的参数  empcur (形参)  ------> open empcur(实参) 


   declare
   t_dno emp.deptno%type;
   emprow emp%rowtype;
   --1.定义游标(参数)
   cursor empcur (dno emp.deptno%type) 
   is 
   select * from emp where deptno = dno;
  begin 
    --2.输入参数
    t_dno := &员工部门编号;
    --3.打开游标(带入参数)
    open empcur(t_dno);
    dbms_output.put_line('游标记录的条数:'|| empcur%rowcount);
     loop 
     --4.读取数据
          fetch empcur into emprow;
          exit when empcur%notfound;
          dbms_output.put_line('编号:'||emprow.empno ||',员工姓名:'|| emprow.ename || ',工资:' ||emprow.sal);
     end loop;
   dbms_output.put_line('游标记录的条数:'|| empcur%rowcount);
     --5.关闭游标
    close empcur;
 end;


3.循环游标  1.省略了open close  2.省略了行变量(对象)的定义
   declare 
     cursor empcur 
     is
     select * from emp where deptno = 10;
     begin 
       for emprow in curemp
       loop
         dbms_output.put_line('编号:'||emprow.empno ||',员工姓名:'|| emprow.ename || ',工资:' ||emprow.sal);
      end loop;
   end;


4.利用游标修改数据
   declare
     cursor empcur 
     is 
     select * from emp for update;
  begin 
     for emprow in empcur
      loop
         if emprow.deptno = 20 then
            dbms_output.put_line('进行修改的数据的编号为:' ||emprow.empno);
           update emp set ename = 'demo' where current of empcur;
          dbms_output.put_line('进行修改后的的数据为:' ||emprow.empno||',' || emprow.ename);
      end if;
     end loop;
 end; 


5.引用游标(动态游标)
   
 1).弱类型游标  (无规定的返回值) v_cur :可变的游标
   declare
--1.定义游标类型时,不控制游标的返回类型,。
   type empcur is ref cursor;
   v_cur empcur;
   command char(1);
   currow emp%rowtype;
   tname emp.ename%type;
 begin
      dbms_output.put_line('输入操作命令' || '1.查找dept = 30的员工姓名' || '查找job = manager的员工信息');
    command := &命令;
   if command = '1' then
            open v_cur for select empno from emp where deptno =30;
        loop
      fetch v_cur  into tname;
      exit when v_cur%notfound;
      dbms_output.put_line('部门为30的员工的姓名为:'||tname);
     end loop;
      close v_cur;
   else
     open v_cur  for select * from emp where job = 'manager';
      loop
        fetch v_cur into currow;
        exit when v_cur%notfound;
        dbms_output.put_line('编号:'||currow.empno||'姓名:'||currow.ename||'职位:'||currow.job);
      end loop;
     close v_cur;
   end if;
end;
   2).强类型游标 (规定返回的类型)
    declare 
  --1.定义游标类型时,控制游标的返回类型为对象类型%rowtype。
       type empcur is ref cursor 
       return emp%rowtype;
       v_cur empcur;
       command char(1);
       currow emp%rowtype;
 begin 
      dbms_output.put_line('输入操作命令' || '1.查找dept = 30的员工姓名' || '查找job = manager的员工信息');
       command := &命令;
     if command = '1' then
           open v_cur for select * from emp where deptno = 30;
        loop
        fetch v_cur into currow;
       exit when v_cur%notfound;
      dbms_output.put_line('编号...'|| currow.empno || '姓名...'||currow.ename ||'部门编号:'||currow.deptno);
      end loop;
    close v_cur;
   else 
      dbms_output.put_line('输入命令:2..');
      open v_cur for select * from emp where job = 'manager';
     loop
       fetch v_cur into currow;
        exit when v_cur%notfound;
   dbms_output.put_line('编号..'||currow.empno || '姓名:'||currow.ename ||'职位:' || currow.job);
end loop;
close v_cur;
end if;
end;




     
     *******************Lesson_7子程序和程序包*****************************


 PL/SQL程序单元
  
 1.是数据库中命名的PL/SQL块,作为数据对象保存在数据库中。
  
  什么是匿名函数?


  主要分类:
    1).存储过程(方法):执行特定的操作,无返回值;
    2).函数:进行复杂计算,有返回值;
    3).包:逻辑上相关的过程和函数组织在一起;
    4).触发器:事件触发,执行相关操作。


 create table StuInfos
 (
   stuid number PRIMARY KEY,
   sName varchar2(10) not null,
   sSex char(2) check(sSex= '男' or sSex = '女'),
   ClassID int
 )


 create sequence mySeq;


 insert into StuInfos values (mySeq.nextVAL,'喜洋洋','男',1);
 insert into StuInfos values (mySeq.nextVAL,'懒洋洋','女',2);


 


  2.存储过程的创建与执行
   create or replace procedure pro_demo
   is
   begin
     null;
   end;
 
     
   执行一:
   execute pro_demo;


   执行三:
   begin 
    pro_demo;
   end;
 
  
1.不带参数的存储过程
 1).
  create or replace procedure pro_InsertStu
  is
  begin
   insert into StuInfos values (mySeq.nextVAL,'美洋洋','女',2);
  end;
  
  begin
    pro_InsertStu;
  end;


 2).定义变量
   create or replace procedure pro_InStuInfos
   is
    v_name varchar2(10) := 'lauren';
    v_sex char(2) := '男';
    v_class int := 1;
  begin
       insert into StuInfos values (mySeq.nextVAL,v_name,v_sex,v_class);
  end;


   begin
     pro_InStuInfos;
   end;
  
2.带参数的存储过程 形参的变量 定义类型的时候只给类型不给长度
 
  用户从客户端输入数据,使用存储过程的方式为数据库添加数据,比用ado.net或JDBC的效率要高。


  create or replace procedure pro_InStuInfos(v_sname varchar2,v_sex char,v_class number)
   is
  begin 
     insert into stuinfos values (mySeq.nextval,v_sname,v_sex,v_class);
   end;


   带参的调用
  begin
    pro_InStuInfos('joana','女',1);
  end;




3.创建带输出参数的存储过程
create table StuMarks 
(
  stuMarkID number  primary key,
  sSubject varchar2(10) not null,
  sScore int not null,
  StuID number references StuInfos(stuid)
)


insert into StuMarks values (1,'JAVA',87,1);
insert into StuMarks values (2,'JAVA',72,2);


  
--查询喜洋洋、懒洋洋的java成绩  


create or replace procedure proc_GetStu(v_sName stuinfos.sname%type,v_score in out StuMarks.sScore%type)
as


begin


  select b.sScore into v_score from StuInfos a,StuMarks b where a.stuID  = b.StuID  and a.sName  = v_sName and b.sSubject = 'JAVA';


end;






 ---调用
declare
   theScore StuMarks.sScore%type;
begin 
   proc_GetStu('喜洋洋',theScore);
   dbms_output.put_line('喜洋洋的分数:'||theScore);
end;






4.结合游标的使用
 create or replace procedure upsal(theno emp.empno%type, per number)
   is
      cursor empcur (theEmpno emp.empno%type) 
       is 
       select * from emp where empno = theEmpno for update;
       emprow emp%rowtype;
  begin 
     open empcur(theno);
     fetch empcur into emprow;
     update emp set sal =  sal * (1+per) where current of empcur;
     dbms_output.put_line('数据修改完成');
    close empcur;
end;




begin
   UPSAL(7369,0.2);
end;




5.定义out 变量
  
  create or replace procedure upDateSal (theempno number,thesal in out number)
   is
     thejob emp.job%type;
     tempsal emp.sal%type;
 begin
     select job,sal into thejob,tempsal from emp where empno = theempno;
    if thejob  = 'manager' then
       thesal := thesal *1.2;
    end if;
     update emp set sal = thesal where empno = theempno;
end;


declare 
   thesal emp.sal%type;
 begin 
   thesal := 3000;
   upDateSal(7689,thesal);
   dbms_output.put_line(thesal);
end;




6.函数的定义


create or replace function myAdd(a int,b int) return int
as
 begin 
  return a + b;
end;




---1).在SQL 语句中调用;
select empno,ename,myAdd(sal,300),sal from emp where deptno = 30;


--2).在PL/SQL中调用


declare 
  result int := 100;
 begin
    result := myAdd(12,13);
 dbms_output.put_line('结果是:'|| result);
 end;




7.包的使用(相当于java中的类)


  包头
create or replace package pak_demo
is
  procedure mySub(n int);
  function myFun(n int) return int;
end pak_demo;


 包体
 
create or replace package body pak_demo
as


 procedure mySub(n int)
  is
 begin
    dbms_output.put_line(n*n); 
 end mySub;
 
 function myFUN(n int) return int
 is
 begin 
  return n+1;
 end myFun;
end pak_demo;


调用


begin
  pak_demo.mySub(5);
end;






1.回顾




2.包和作用域  




3.1).用一个方法a去调用b的方法;
 a()
{
   b();
}
 2).如果b()里面有一个操作是用来于a()里面修改的值一样,那么a()方法里面的操作失效


 3).自主事务处理就是用来解决方法之间的冲突问题。


  方法一
 create or replace procedure subProc
 as
   mysal number;
 begin
   select sal into mysal from emp where empno = 7369;
   dbms_output.put_line('儿子过程的mysal:' || mysal);
   rollback;
 end;
 
  方法二  方法体中调用 方法一 被方法一中的rollback 影响


 create or replace procedure parentProc
 as
   mysal number;
 begin
   select sal into mysal from emp where empno = 7369;
   dbms_output.put_line('调用前的mysal:' || mysal);
    update emp set sal = 5555 where empno = 7369;
    subProc();
    select sal into mySal from emp where empno = 7369;
    dbms_output.put_line('调用后的mysal:' || mysal);
 end;


  execute parentProc;




 解决方式:自主事务处理


 create or replace procedure subProc
 as
   mysal number;


   --自主事务处理关键字
   pragma autonomous_transaction;  
 begin
   select sal into mysal from emp where empno = 7369;
   dbms_output.put_line('儿子过程的mysal:' || mysal);
   rollback;
 end;




**************************   Lesson_8 触发器   ***************************


  1.触发器是一个特殊的存储过程
     
  2.与存储过程的区别
     1).存储过程需要调用,触发器无需调用,触发器会自动调用;
     2).触发器不带参数,存储过程可带参数可不带参数。
  
  3.触发器的类型
    1).DDL 触发器 (了解)  create drop 
    2).DML 触发器 (行级触发器(掌握),语句级触发器(理解))  insert update view 
    3).替代触发器 instead of 操作视图 (了解)


  4.创建简单触发器


   注意:主表的主键与从表外键的名称不能一样
    create table classes 
    (
      id number primary key,
      cname char(10)  
    );


     insert into classes values(1,'EIM1101');
     insert into classes values(2,'EIM1102');
     insert into classes values(3,'EIM1103');


    create table students
    (
     stuid number primary key,
     stuname char(10),
     sex char(2),
     cid number references classes(id)
    );


   insert into students values (1,'喜洋洋','男',1);
   insert into students values (2,'美洋洋','女',1);
   insert into students values (3,'小灰灰','男',1);
   insert into students values (4,'灰太狼','男',2);
   insert into students values (5,'红太狼','女',2);




1.触发机制   何时触发?  
  
DML触发器
 
  insert触发器的创建:语句级触发器 DDL
 
  create or replace trigger tg_insert
 
  before insert on student
 
  begin
 
     dbms_output.put_line('insert trigger is chufa le .....');
 
   end;


     insert into students values(201,'joana','女',1);




  update表级触发器的例子:
 
  create or replace trigger tg_updatestudent
 
  after update on students
 
  begin
 
    dbms_output.put_line('update trigger is chufale .....');
 
  end;




  库存表 


  出库表   




   删除班级表,班级的学生也删除     :old :new必须与行级触发器一起使用
   create or replace trigger tri_delStu
   before delete on classes
   for each row  --行级触发器:对每一行的每一条记录进行检查     
    begin 
       delete from students where cid = :old.id;
    end;


    delete from classes where id = 2;


    
     说明::old.id  = 2;


  执行删除操作前,建立一个old内存表,Old内存表和classes 表的结构完全一致。


  前置触发器(before)与后置触发器(after)  ---操作业务逻辑级别而言与主外键约束没有关系




 :new :old是内存的表保存数据的时机   insert 是先在内存中开辟空间然后 保存所以会使用到:new内存表 
                                     delete 是先删除表中的数据,然后在内存中缓存一段时间 会使用到 :old内存表


 For each row的意义是:在一次操作表的语句中,每操作成功一行就会触发一次;不写的话,表示是表级(语句)触发器,则无论操作多少行,都只触发一次;






:new 与: old:必须是针对行级触发器的,也就是说要使用这两个变量的触发器一定有for each row
 
这两个变量是系统自动提供的数组变量,:new用来记录新插入的值,old用来记录被删除的值;
 
使用insert的时候只有:new里有值;
 
使用delete的时候只有:old里有值;
 
使用update的时候:new和:old里都有值;




 4.创建行级插入触发器
       
    create or replace trigger tri_inStudent
    after insert on students
    for each row 
    begin 
      insert into classes values(:new.cid,'GIS1102');
    end;




    insert into students values (6,'村长','男',4)
     
  :new 当插入数据之前,会在内存中建立一个 new内存表,然后再插入到数据库中,与classes保持一致。 :new.cid = 4;






 5.更新班级ID  学生表中 cid 级联更新
   create or replace trigger tri_update
    after update on classes 
   for each row
  begin 
      update students set cid =:new.id,stuname =:new.stuname,sex = :new.sex,cid =:new.cid  where cid =:old.id;
  end;


  update classes  set id = 8 where id = 1;




 6.行级触发器带条件
   
   create table tritest
  (
    stuid int primary key,
    stuname char(8),
    sindex int
  );
  
  create sequence tSeq;


  create or replace trigger over_tri
  before insert on tritest
  for each row
  begin
    if :new.stuid >= 30 then 
      raise_application_error(-20001,'超出了一个班的范围');
    end if; 
  end;
  
  有条件的触发
  create or replace trigger tri_over
  before insert on tritest
  for each row
  when (new.stuid< 2000)  --注意作为条件的时候  :new前面不需要 “:”
  begin 
    if:new.stuid >= 30 then
       raise_application_error(-20001,'超出一个班的范围');
   end if;
 end;


7.创建混合触发器
  create table Demos
  (
  id number primary key,
  dname varchar2(10),
  dSex char(2)
  )


  create or replace trigger tir_Demos 
  before insert or update or delete
  on Demos
   for each row 
  begin 
    if inserting then 
     dbms_output.put_line('insert 被触发...');
   elsif updating then
     dbms_output.put_line('update 被触发...'); 
   elsif deleting then
     dbms_output.put_line('delete 被触发...');
   end if;
 end; 






8.语句级触发器 常用在 DDL上
  
  create or replace trigger tri_updateEMP
  before insert or update or delete
   on emp
   begin
      if user not in ('SCOTT') then
        raise_application_error(-20001,'该用户不能修改EMP表');
      end if;
   end;




9.替代触发器  instead of 用来操作视图  解决键保留表的问题
    
create view vi_student 
as
select c.id,c.cname,s.stuid,s.stuname,s.sex,s.cid from classes c,students s where c.id = s.cid;
  
更新视图


非键保留表不能被修改
update vi_student set cname = 'GIS1102' where id=1;


创建instead of 触发器可以解决此问题


create or replace trigger tri_vi_stu
instead of insert or update or delete
on vi_student
for each row
begin 
  if  inserting then 
      insert into students values (:new.stuid,:new.stuname,:new.sex,:new.cid);
      insert into classes values (:new.id,:new.cname);
 elsif updating then
      update students set stuname = :new.stuname,sex = :new.sex,cid = :new.cid where stuid = :old.stuid;
      update classes set cname =:new.cname where id = :old.id;
 elsif deleting then
      delete from classes where id = :old.id;
      delete from students where stuid =:old.stuid;
 end if;
end;








总结:1).掌握行级触发器;
      2).理解语句级触发器;
      4).前置before与后置对象after 
      3).理解内置对象的使用方法  :new , :old 





















 
       
   
     
  
   


      

  

你可能感兴趣的:(oracle)