1.关系型数据库和结构化查询语言sql


2.Oracle,DB2,Sybase,MS SQL ,Mysql


3.实体,属性,关系 1521


4.oracle的服务:监听服务(远程访问需要)和数据库服务(要启动)


5.oracle的配置文件

listener.ora(监听器服务的配置文件)和
  tnsname.ora(监听器服务访问的配置文件)连接数据库的主机字符串(自定义:主机字符串包括远程IP
  和数据库名了)

6.测试远程连接

net manager(配置主机字符串和监听器)
    找安装路径的快捷方式:右击net manager打开文件
     plsql工具:字体设置和显示行号 关键字大写


7.oracle的物理文件

分为三类:数据文件(.dbf)、控制文件(.ctl)、日志文件(.log)


8.oracle系统表(数据字典)


9.表空间(对应一个物理的磁盘存储位置)
     

 CREATE TABLESPACE j1706
DATAFILE  'E:\oracle\product\10.2.0\oradata\orcl\j1706.dbf'  
SIZE 20M  
AUTOEXTEND ON ;  
   用户
  授权
   表


10.sql语句
     SQL语句主要可以划分为以下几类:
DDL(Data Definition Language):数据定义语言,定义对数据库对象(库、表、列、索引)的操作。
CREATE、DROP、ALTER、RENAME、 TRUNCATE等

DML(Data Manipulation Language): 数据操作语言,定义对数据库记录的操作。
INSERT、DELETE、UPDATE

DCL(Data Control Language): 数据控制语言,定义对数据库、表、字段、用户的访问权限和安全级别。
GRANT、REVOKE等

Transaction Control:事务控制
COMMIT、ROLLBACK、SAVEPOINT等

     (1)常用的数据类型   数值型(int、number)、字符型(char(固定长度)、varchar(可变长度)
           varchar2(可变长度))、日期型date

     (2)DDL(数据定义语言:表结构) 定义对数据库对象(库、表、列、索引)的操作
          

 建表:
         create table tb_person(
         id int,
         name varchar2(15),
         sex char(3),
         age int
         );
            查询表:
          select * from tb_person;
        删除表:
           drop table tb_person;
        修改表; 
           增加列:
          alter table tb_person add(phone varchar2(18),address varchar2(30));
            改变列长度:
          alter table tb_person modify(phone varchar2(20));
        删除列:
           alter table tb_person drop(phone,address);
        修改列名:
           alter table tb_person rename column phone to iphone7s;
        修改表名:
           rename tb_person to tb_people;
         截断表
       当表结构必须保留, 而表数据不再需要的时候
          TRUNCATE TABLE  tb_person


     (3)DML(数据操作语言) 定义对数据库记录的操作
        

插入:
         insert into tb_person(id,name,sex,age)
         values(1,'tom','男',20);
     删除数据:
          delete from tb_personn;或者DDL中的截断: truncate table tb_person;
     修改数据:
          update tb_person set age=21;
          update tb_person set age=21,id=2 where sex='男' and name='tom';

     sql语句删除数据有几种方式?分别是什么?

答:
    1. delete
          -- DML语句,delete语句最小单位是行,可以通过where选择删除,删除数据可以回滚,
      保留表结构。最慢
    2. truncate
          -- DDL语句,TRUNCATE是截断表的所有数据,删除数据不可以回滚,保留表结构。较快
    3. drop
          -- DDL语句,删除表结构和表所有数据,并且不能回滚,慎用。最快


      (4)事务控制
           transaction control:事务控制   commit(提交)、rollbck(回滚)
    (4)约束
        

 check 检查约束
        -- not null 非空约束(特殊的检查约束)
      unique 唯一约束
          primary key 主键约束(非空且唯一)
      foreign key   外键约束(解决数据冗余问题)
           列级约束:
         create table tb_person(
       id int primary key,
       name varchar2(18) not null,
       sex char(3) check(sex='男' or sex='女'),
       age int check(age>=18 and age<60),
       phone varchar2(20) unique,
       address varchar2(30),
       clazz_id int  references tb_clazz(id) on delete cascade 
     );
      create table tb_clazz(
       id int primary key,
       code varchar2(15),
       name varchar2(15),
       bzr varchar2(20)
      );
外键中,当主表的记录被子表参照时,主表记录不允许被删除。
        解决方案:
           先删除字表数据,在删除父表数据。
           先将字表关联数据设为null,在删除父表数据
           先将子表数据修改,在删除父表数据。
        on delete cascade 当删除父表数据时,级联删除子表数据。
        on set null 当删除父表数据时,将关联的数据设置为null
 表级约束:
            create table tb_student(
          id int,
          name varchar2(18),
          sex char(3),
          age int,
          phone varchar2(18),
          email varchar2(18),
          address varchar2(18),
          clazz_id int,
          constraints tb_students_pk primary key(id),
          check(name is not null),
          check(sex='男' or sex='女'),
          check(age>18 and age<50),
          unique(phone),
          unique(email),
         constraints tb_students_fk foregin key(clazz_id) reference tb_clazz(id)
        );
        自定义约束名:(约束 约束名 约束类型)
        constraints tb_students_pk
        数据库建议建表:
          外键以表级约束,其他用列级约束。
           
         约束的维护(添加、删除):
         alter table tb_student add primary key(id);
         删除约束根据约束名删除:
         alter table tb_student drop constraints tb_students_pk;
         复合约束(只能在表级中定义):
         primary key(year,month)
     (5)nvl函数 nvl(第一个参数,第二个参数),
       如果第一个参数为null,则取第二个参数
       定义字段的别名as
       select empno as eID,ename,sal,sal*12 as yearsal from scott.emp;
       distinct关键字去除重复数据:
           select distinct deptno from scott.emp;
       比较运算符:
           select *from scott.emp where sal>=800 and sal<=1600;
           select * from scott.emp where sal between 800 and 1600;
           select * from scott.emp where deptno=20 or deptno=30;
           select * from scott.emp where deptno in(20,30);
      模糊查询like:
        %匹配所有  _匹配一个字符
        select * from scott.emp where ename like 's%';
        select * from scott.emp where ename like '%s';
        select * from scott.emp where ename like '%s%'; 
        select * from scott.emp where ename like '_s%';
     优先级规则:先and后or
         对结果排序 order by asc(升序 默认) desc(降序) 
     select * from scott.emp order by sal asc;
     select * from scott.emp order by sal desc;
      (6)多表连接
           内连接(等值连接)
           两个表(或连接)中某一数据项相等的连接称为内连接。
       SELECT FROM dept d INNER JOIN emp e ON d.deptno = e.deptno';
      外连接(非等值连接)
用于查询一张表在另一张表中没有关联数据的信息
外连接分为三种:
左外连接(LEFT OUTER JOIN)
右外连接(RIGHT OUTER JOIN)
全外连接(FULL OUTER JOIN)
-- 左外连接:+号在右边,左边的表的所有数据都要显示,如果右边表没有对应的数据,则补Null
-- 右外连接:+号在左边,右边的表的所有数据都要显示,如果左边表没有对应的数据,则补Null
-- 全外连接:两张表的所有数据都要全部显示
           备份一张表(只备份数据,不备份约束):
         create table tb_emp as select * from scott.emp;
         select e.empno,e.ename,e.mgr,t.ename
           from scott.emp e,tb_emp t
           where e.mgr=t.empno and  e.empno='7369';
             自连接:
            select e.empno,e.ename,e.mgr,t.ename
          from scott.emp e,scott.emp t
          where e.mgr=t.empno and e.empno='7369';
    (7)组函数:(组函数都会忽略NULL值)
        对一组值进行运算,并返回单个值,也叫聚合函数。
    count(*|列名) 统计行数:
      select count(*) from scott.emp;
      select count(comm) from scott.emp;
    sum(数值类型列名) 求和:
       select sum(sal) from scott.emp;
        avg(数值类型列名)  平均值:
       select avg(sal) from scott.emp;
    max(列名)  最大值:
       select max(sal) from scott.emp;
    min(列名) 最小值:
        select min(sal) from scott.emp;
   (8)分组 group by
      把该列具有相同值得多条记录当成一条记录处理,最后只输出一条记录。
       分组函数忽略空值。结果集隐式按升序排列,
       如果需要改变排序方式可以使用order by子句。
         按部门分组:
      select deptno from scott.emp group by deptnot;
      按工作岗位分组:
      select job from scott.emp group by job;
    group by子句的真正作用在于与各种组函数配合使用:
          select deptno,count(*),sum(sal),avg(sal),max(sal),min(sal)
        from scott.emp group by deptno;



       面试题:数据条件筛选时有几种方式?有什么区别?
        

 限定组的结果:having子句
      having子句用来对分组后的结果进行条件过滤。
      having和where的区别;
        where和having都是用于条件过滤。
        where在分组前进行条件过滤,having子句是在分组后进行条件过滤,
        where子句中不能使用聚合函数,having子句可以使用聚合函数。
            select deptno,count(*),sum(sal),avg(sal),max(sal),min(sal)
          from scott.emp group by deptno having sum(sal)>9000
          order by sum(sal) desc;
  (9)子查询
        子查询就是把多条语句写成一条,子查询执行的时候先执行子查询
    再执行主查询:
     select * from scott.emp where sal>(
      select sal from scott.emp where ename='allen'
     );
     子查询需要注意的问题:单行子查询返回多行
      多行比较运算符:
       In:与列表中的一个值相等(包含)
       any:与子查询返回的每一个值比较
       all:与子查询返回的所有值比较
         in:
          select * from scott.emp where sal in(
           select min(sal) from scott.emp group by deptno
          );
           any与子查询返回的每一个值比较 >any 大于最小的 <any 小于最大的
       select * from scott.emp where sal>any(
         select min(sal) from scott.emp group by deptno
       );
           all与子查询返回的所有值进行比较 >all 大于最大的 <all 小于最小的
       select * from scott.emp where sal>all(
        select min(sal) from scott.emp group by deptno
       );
    
     (10)集合运算:从多个结果集中提取数据
         union 把两个结果集的数据合起来,然后干掉重复的
       select deptno from scott.dept union 
       select deptno from scott.emp;
     union all:把两个结果集的数据合起来
       select deptno from scott.dept union all
       select deptno from scott.emp;
     intersect:把两个结果集的数据合起来,然后干掉重复的,
      再找两个查询中都出现的记录
        select deptno from scott.dept intersert
         slect deptno from scott.emp;
     minus:判断数据存在第一查询的结果集,而·不存在第二查询的数据集
        select deptno from scott.dept minus
         slect deptno from scott.emp;
        面试题:
         select r.id,r.R1,nvl(b.R2,'null') from r,b where r.id=b.id(+)
          union
          selet b.id,nvl(r.R1,'null'),b.R2 from r,b where r.id(+)=b.id;
       标准外连接:
         select r.id,r.R1,b.R2 from r left outer join b on r.id=b.id
         union
         select b.id,r.R1,b.R2 from r right outer join b on b.id=r.id;
       全外连接:
        select nvl(r.id,b.id) as id,r.R1,b.R2 from r full outer join b on 
        r.id=b.id;
     
    (11)rownum 伪列 ‘结果集’中产生的序列
       select rownum,deptno,dname,loc from scott.dept;
        只有存在rownum=1的记录,才可能存在rownum=2的记录
          利用rownum分页:
            select * from(
         select rownum as tempid,empno,ename from scott.emp
        )t1
        where t1.tempid between 6 and 10;
        
          rowid:一般来说每一行数据对应一个rowid,而且固定且唯一。
      在这一行存入数据库时就确定了。可以理解为java对象中的内存地址。
      可以利用rowid来查询记录,而且通过rowid查询速度最快的查询方法。
      rowid只有在表发生移动(比如表空间变化,数据导入/导出后)才会发生变化。
       面试题:
         删除重复数据(删除所有重复数据
     /删除重复数据但保留一条(保留最大rowid或者最小)):
      删除所有数据;
     delete from tb_test where name in(
      select name from tb_test group by name,age having count(*)>1
     );
       删除数据,保留一条数据(第一种方法);
        create table tb_tmp as select distinct name,age from tb_test;
       truncate table tb_test;
       insert into tb_test(name,age) select name,age from tb_tmp;
      删除数据,保留一条数据(方法二):
       delete from tb_test where rowid not in(
        select max(rowid) from tb_test group by name,age
       );
     (12)常用函数
        dual是oracle提供的一个虚表
    select length('hello') from dual;
     常用函数:
       lower把大写转成小写 upper把小写转大写:
        select upper('helloworld') from dual;
    select lower('HELLOWORLD') from dual;
    select * from scott.emp where ename='smith';
    select * from scott.emp where lower(ename)='smith';
   initcap使串中的所有单词首字母变成大写:
     select initcap('sql course') from dual;
   concat 连接两个字符串:
      select concat('Hello','World') from dual;
   substr 取字符串,从start开始,取count个:
      select substr('HelloWorld',1,5) from dual;
         从4开始取到末尾:
     select substr('Helloworld',4) from dual;
   length 返回字符串的长度:
         select length('HelloWorld') from dual;
   instr  在一个字符串中搜索指定的字符,返回发现指定的字符的位置,从1开始:
       select instr('HelloWorld','l') from dual;
   trim  删除首尾的空字符串
       select trim(' HelloWorld ') from dual;
   replace 替换:
     select replace('HelloWorld','ll','ff') from dual;
   round  四舍五入;
     select round(45.926,2) from dual;
   trunc  截断:
   select trunc(45.926,2) from dual;
   mod  取模:
     select mod(1600,300) from dual;
   decode函数:
     select ename,job,sal 基本工资,decode(job,
      'salesman', sal*0.9,
      'manager',sal*0.85,
      'clerk',sal+100,
      'pre
      sident',sal
     )as 实发工资 
     from scott.emp;
  面试题:
      select name,
        sum(decode(t.course,'JDBC',t.grade,0)) JDBC,
    sum(decode(t.course,'Hibernate',t.grade,0)) Hibernate,
    sum(decode(t.course,'Spring',t.grade,0)) Spring
     from tb_course t 
      group by t.name;
11.数据库对象
    (1)数据库对象包括: 表、序列、同义字、数据库链接、视图等。
       对象的特点:可以给其他对象使用,名字不能重复。
    (2)序列:自动生成的唯一序列号,常用在主键自动生成。
          创建序列:
         create seqeuence s_tb_student;
      删除序列:
          drop seqeuence s_tb_student;
      序列的两个属性currval,nextval:
         select s_tb_student.currval from dual;
         select s_tb_student.nextval from dual;
      使用序列:
          insert into tb_student(id)values(s_tb_student.nextval);
      序列不会随着rollback回滚,下面这些情况时sequence值可能产生间隙:
         回滚发生; 
         序列用于多个表(不建议),建议一张表使用一个序列;
          系统宕机。
    (3)索引
         面试:如何优化你的数据库查询?
        1.数据库的查询方式?
          --全表扫描  select * from tb_student 慢
          --利用索引扫描   快
          --共享语句   最快(oracle有个回滚段,临时表空间)
      
    索引 index
      作用:在数据库中用来加速对表的查询
      原理:通过使用快速路径访问方法快速定位数据,减少了磁盘的I/O
      特点:与表独立存放,但不能独立存在,必须属于某个表
             由数据库自动维护,表被删除时,该表上的索引自动被删除。
        
          索引的创建:
           自动:当在表上定义一个primary key或者unique约束1条件时,数据库会
             自动创建一个对应的索引。
           手动:用户可以创建索引以加速查询。
           create index i_tb_student_name on tb_student(name);
           查询的时候使用索引:
             select * from tb_student where name='Alice';
           删除索引:
              drop index i_tb_student_name;
      当创建索引的时候,oracle会默认创建一个和当前表相关的索引页,
      而索引页中保存了索引字段和真实的磁盘地址,当用户发送sql语句带了索引时,
      oracle会到索引页中查询索引字段,直接定位磁盘IO,提取数据。
      所以索引数据快于全表扫描。
    索引的维护
       1.建立索引后,查询的时候需要在where条件中带索引字段才可以使用索引。
       2.在经常查询的字段上面建立索引。不要在所有字段上建立索引。
       3.因为索引是用来加速查询速度的,如果一张表经常做insert,delete,
        update ,而很少做select,不建议建立索引
     如果一张表字段很少,不建议建立索引。
       4.索引是由oracle自动维护的。索引使用久了会产生索引碎片
        (磁盘碎片),影响查询效果,所以使用久了需要手动进行维护(删除在重建)
   sql语句的优化:
     多使用共享语句,尽量使你的sql语句能够使用索引。
     怎样使sql语句能够使用到索引呢?
      当sql语句中包含not in,<>,is null,is not null,like'%%'的时候
      不会使用索引。
      in:可以使用索引。
      优化方案: a<>0  改为a>0 or a<0
                 a is not null改为 a>0 或a>''
         is null 用一个缺省值代替空值
         like'%%'不能使用索引
         like'001%'可以使用索引
   (4)同义字 :通过创建同义字(对象的另外的一个名字)简化访问对象的操作。
      create synonym tb_emp for scott.emp;
      select * from tb_emp;
      删除:drop synonym tb_emp;
     数据库链接--database link
   (5)视图
     创建用户时通过dba角色赋予权限,而不是手动赋予权限,则会创建
     视图会报:没有权限
      解决方案:使用system用户登录,在给j1703赋予权限
      grant create any table to j1703 with admin option;
      grant create any view to j1703 with admin option;
      grant select any table to j1703 with admin option;
      所有数据字典都是视图:
       select * from User_Tables;
       视图可以使复杂的查询变得简单
       创建简单视图(一个表):
         create view v_deptinfo as
     select deptno as 部门,count(*) 人数,sum(sal) 总工资,avg(sal)
     平均工资,max(sal) 最高工资,min(sal) 最低工资
     from scott.emp group by deptno;
使用视图:select *from v_deptinfo;
     复杂视图(多个表)
      删除视图:drop view v_deptinfo;
   (6)数据建模(试规范题)
   软件开发过程:
1. 需求调研,与客户进行沟通
2. 需求分析,将现实工作中的动作模拟到计算机
   数据建模
3. 开发
4. 测试
5. 上线部署
从关系数据库的表中删除冗余信息的过程称为规范化,
是得到高效的关系型数据库表的逻辑结构最好和最容易的方法。
规范化数据时:应执行以下操作:
将数据库的结构精简为最简单的形式
从表中删除冗余值
标识所有依赖与其他数据的数据
     获得数据化的三种方法:三范式
       步骤1:
         第一范式:必须要有主键,并且每个属性值都是不可分的最小数据单元
     ,则称为是第一范式。
     第二范式:所有非主关键字都完全依赖于主关键字(通常用于联合主键)
     第三范式:非主关键字不能依赖于其他非主关键字(通常用于一个主键)
     数据建模
      1.根据三个范式
      2.分析实体之间的关系
        1对1:一个人只有一个××× 唯一外键关联或者主键关联
    一对多:一个班级可以有多个学生  一个学生只属于一个班级
            关联:一对多使用主外键关联,通常在多方建立外键
        多对多:一个学生可以选择多门课程 一门课程可以被多个学生选修
           关联:多对多通常使用中间表(再多建一张表存储)关联数据
               通常中间表会有两张表的id作为联合主键,并且
           作为外键指向关联表
        订单和用户之间的关系是多对一:
       create table tb_order(
        id int primary key,
        code varchar2(50),
        user_id int,
        foregin key(user_id) references tb_user(id)
       );
     订单和书籍是多对多关系:
       create table tb_item(
        order_id int,
        book_id int,
        count int,
        primary key(order_id,book_id),
        foregin key(order_id) references tb_order(id),
        foregin key(book_id) references tb_book(id)
       );
       select * from tb_user u,tb_book b,tb_order o,tb_item i
        where u.id=o.user_id 
        and o.id=i.order_id,
        and b.id=i.book_id
 and u.name='jack';
12.plsql(数据库编程语言)
    PL/SQL=传统SQL+结构化流程控制
      好处:1.有结构化的流程控制,可以完成复杂的操作
            2.性能高于sql
   sql:页面输入信息 -- servlet接收数据,调用持久层生成sql - sql语句发送到数据库(DBMS),数据库编译 -- 执行sql。
   plsql:页面输入信息 -- servlet接收数据,调用持久层传入参数(调用存储过程) -  执行sql。
        3.可以对程序中的异常进行处理
        PL/SQL程序由三个块组成。
(1) 声明部分: 在此声明PL/SQL用到的变量,类型及游标,以及局部的存储过程和函数 
 (2)执行部分: 过程及SQL 语句  , 即程序的主要部分 
 (3)  异常处理部分: 错误处理  
    语法:declare --声明部分,用来定义变量等
           begin--可以理解成java的花括号,编写代码的地方
           exception--处理程序抛出异常
           end;
      
       第一个plsql,在控制台输出HelloWorld
        BEGIN
       --包名.过程('参数')
       dbms_output.put_line('HelloWorld!');
     END;
       定义变量,变量初始值都是null
       常量constant
       declare
          v_id int;
      v_name varchar2(18):='jack';
      v_clazz constant varchar2(5):='j1703';
    begin
       v_id:=100;
       dbms_output.put_line('v_id='||v_id);
       dbms_output.put_line('v_name='||v_name);
    end;
    复合变量(数据类型) record
    1.包含多个内部组件,用于存放多个值
    2.需要先定义类型,然后用该类型可重复定义多个变量
     注意:复合变量属于数据类型,定义时前面要加TYPE
           TYPE是不能直接使用的,使用前需要定义变量引用
      declare 
          type r_tb_clazz is record
          (
            id int,
        code varchar2(18)
           );
            v_clazz r_tb_clazz;
         begin
           v_clazz.id:=1;
           v_clazz.code:='j1703';
      end;
    plsql分两大类:匿名块,带名块 
    begin 
      insert into tb_clazz(id,code) values(3,'j1703');
      commit;
    end;
     select
         1.缺少into子句,plsql目的是操作数据,需要定义变量
     2.实际返回行数超过请求行数(只能查询一条数据,如果需要查询
        多条数据,使用游标)
     3.未找到数据
    declare  
        v_id int;
    v_code varchar2(18);
    begin
        select id,code into v_id,v_code from tb_clazz where id=1;
    dbms_output.put_link(v_id || '' || v_code);
    end;
      %type属性:
       定义某个变量的数据类型与已经存在的变量数据类型,
        某个列的数据类型相同。
       declare
          v_id tb_clazzz.id%type;
      v_code tb_clazz.code%type;
    begin
       select id,code into v_id,v_code from tb_clazz where id=1;
         dems_output.put_line(v_id || '' || v_code);
    end;
     %rowtype属性:
        用于定义不确定的类型的变量
    当数据库中表字段的个数和数据类型会在运行中改变,
     程序中的变量也会自动随之改变。
      rt_tb_clazz tb_clazz%rowtype
      rt_tb_clazz 变量和tb_clazz表结构一致,相当于表结构的副本。
     declare
        v_tb_clazz tb_clazz%rowtype;
      begin
         select id,code into v_tb_clazz.id,v_tb_clazz.code from 
           tb_clazz where id=1;
           dbms_output.put_line(v_tb_clazz.id || '' || v_tb_clazz.code);
      end; 
      declare
        v_tb_clazz tb_clazz%rowtype;
      begin
         select * into v_tb_clazz from tb_clalzz where id=1;
         dbms output.put_line(v_tb_clazz.id || '' || v_tb_clazz.code);
         end;
     使用recode
     declare
         type r_tb_clazzz is recode
         (
           id tb_clazz.id%type,
           code tb_clazz.code%type;
          );
          v_tb_clazz r_tb_clazz;
       begin
         select * into v_tb_clazz from tb_clazz where id=1;
         dbms_output.putline(v_tb_clazz.id || '' || v_tb_clazz.code);
       end;
     循环和判断
          if分支
         declare
            v_i number:=10;
              begin 
             if(v_i=10)then
           dbms_output.putline('进入if块');
               end if;
          end;
       
      if else分支
         if ()then...else ...end if
      if elsif else分支
           if() then...elsif()then ...else ...end if
    plsql的循环有三种:loop for while
       loop循环:
           loop
          v_i:=v_i+1;--自增
          exit when v_i=5;
        end loop;
         第二种结束方法:
         loop 
           v_i:=v_i+1;
           if(v_i=5) then
              exit;
          end if;
          end loop;
       for循环
           for v_i in 1..5
       loop
        end loop;
     --重点 项目当中最常用的异常处理
     --实际开发中异常的处理  重点
      create table tb_error(
        id int primary key,
    errorObj varchar2(18),--抛出异常的对象
    sqlcode varchar(50),--异常编码
    sqlerrm varchar(200),--异常信息
    currdate date    --发生时间
      );
       create sequence s_tb_error;
     --重点掌握
     --orale当抛出异常时会将异常编码存储到sqlcode函数,异常信息
     -- 存储到sqlerrm 
       declare
          v_id tb_clazz.id%type;
      v_code tb_clazz.code%type;
       begin
          select id,code into v_id,v_code from tb_clazz;
      dbms_output.put_line(v_id || '' || v_code );
    exception
        when others then
      v_sqlcode :=sqlcode;
      v_sqlerrm:=sqlerrm;
      insert into tb_error(id,errorobj,sqlcode,sqlerrm,currdate)
      values(s_tb_error.nextval,'default',v_sqlcode,v_sqlerrm,sysdate);
      commit;
     end;
     --游标:用来提取多行数据
     --oracle打开一个工作区(缓存)来保存多行查询的结果集,
     -- 游标就是给这个工作区命的名称,并能用于处理由多行查询而返回的
记录行
    --隐式游标:默认的DML语句和select语句都有隐式游标
    --显示游标:开发中给工作区命名,并且可以进行操作
    --%isopen  boolean 游标打开,则返回true
    --%nofound  boolean  如果最近抓取没有获得记录,返回true
    --%found  boolean  如果最近抓取获得记录,返回true
    --%rowcount  number 返回到目前为止获取的记录数
    --使用游标的步骤
    --1.定义游标  cursor c_tb_clazz is select * from tb_clazz;
    --2.打开游标  open c_tb_clazz;
    --3.fetch游标  fetch c_tb_clazz into r_tb_clazz;
    -- 游标有个指针,默认指向第一行之上,fetch将指针向下移动,指向第n
      行数据,如果有数据,notfound 返回false,found返回true
       如果到末尾,抓取不到数据,一直显示最后一条数据
    --4.关闭游标 close c_tb_clazz;
    --第一个例子  ;使用游标提取tb_clazz的所有数据
      declare 
           cursor c_tb_clazz is select * from tb_clazz;
       r_tb_clazz tb_clazz%rowtype;
      begin
         open c_tb_clazz;
        loop
           fetch c_tb_clazz into r_tb_clazz;
            dbms_output.put_line(r_tb_clazz.id || '' || r_ tb_clazz.code);
         end loop;
        close c_tb_clazz;
     end;
    --带参数的游标
      第二个例子:使用游标提取tb_clazz的所有数据,同时提取每个班级的学生数据
    --注意:传递是形参,形参是不用长度的
     declare 
        --班级游标
    cursor c_tb_clazz is select * from tb_clazz;
     r_tb_clazz tb_clazz%rowtype;
     --学生游标
     cursor c_tb_student(v_clazz_id tb_clazz.id%type)
      is select * from tb_student where clazz_id=v_clazz_id;
         r_tb_student tb_student%rowtype;
      begin
         open c_tb_clazz;
         loop
            fetch c_tb_clazz into r_tb_clazz;
        exit when c_tb_clazz%notfound;
        dbms_output.put_.line('班级' || r_tb_clazz.id || '' || r_tb_clazz.code);
              --当前班级的学生数据
          --打开学生游标,参数是班级id
               open c_tb_student(r_tb_clazz.id);
                loop
              fetch c_tb_student into r_tb_student;
              exit when c_tb_student%nofound;
              dbms_output.putline(r_tb_student.id || '' || r_tb_student.name);
           end loop;
               close c_tb_student;
       end loop;
     close c_tb_clazz;
      end;
    --游标for循环
      1.不需要显式打开游标
      2.for循环自动隐式地定义recode变量
      3.不需要使用fetch抓取数据
      4.循环结束后,不需要使用close来关闭游标
       declare
           cursor c_dept is select * from scott.dept;
       begin
            for re_dept in c_dept
          loop
             dbms_output.put_line();
          end loop;
      end;
      --带名块(declare  begin end; 就是匿名块)
      是数据库中命名的PL/SQL块,作为数据库对象保存在数据库里。
        主要四类:
      存储过程:执行特定操作,无返回值
       函数:进行复杂计算,有返回值
        包:逻辑上相关的过程和函数组织在一起
        触发器:事件触发,执行相应操作
         
     过程和函数统称为PL/SQL子程序,过程和函数的唯一区别是函数总向调用者返回数据,
     而过程则不返回数据。 
    --存储过程
    语法:(直接创建)
       procedure name
        [(parameters)形参]
          is
           局部变量声明
         begin
           语句;
          [exception]
         end;
       --建立存储过程,可以被多个程序调用(java或者c++),可以向
       --存储过程传递参数,也可以让存储过程传出参数
       --参数:
       --in:默认,值被传递给子程序。子程序不能改变参数值。
       --out:值被返回调用环境(java或者c++),子程序会改变参数值。
       --调用存储过程
          begin 
            insertclazz();--存储过程名
          end;
       --调用存储过程通过带参数传给存储过程
     --函数与过程语法差异:
         (1)在函数的声明中,必须包含一个带有数据类型的return字句,
       返回值表示的类型,在函数体中必须有一个有效的return语句。
      (2)只能使用in模式参数传入参数值
      --语法:
           function name
       [(parameters)形参]
        return datatype
        is 
          局部变量声明
            begin
          语句;
          return value;
          [exception]
          end;
        
        包类似于C++和Java语言中的类,其中变量相当于类中的成员变量,过程和函数相当于类方法。把相关的程序单元归纳到包里
通过使用包,可使开发人员利用面向对象的方法进行存储过程的开发,从而提高系统性能。
      --触发器
      --触发器是当某个事件发生时自动隐式运行。而且,触发器不能
      接收参数。
      --触发器最主要作用:提供更灵活的完整性校验规则。
      --语法:
        trigger name
        after|berfore
        is 
          局部变量声明;
        begin
           语句;
           [exception]
            end;
    --触发器的组成成分:
       触发事件:在任何情况下触发trigger(insert,undate,delete等)
       触发时间:before或者after
       触发器本身:该trigger被触发后的执行体
       触发频率:动作被执行的次数(主要行级触发器)
       
          当行级触发器被触发时,如果要访问插入,更新或删除的记录的值,
      可以使用:
         :new  访问操作完成后的值
         :old 访问操作前的数据
         --特性  insert   update   delete
            :old    Null      有效    有效
          :new    有效      有效     null
      当删除tb_tran的数据时,将数据备份到tb_back:
  
         create  or  replace trigger t_del_tran
           before delete
           on tb_tran
           for  each row
         declare
             begin
             insert into tb_back(id,accout,amount,currdate)
         values(:old.id,:old.Accout,:old.Amount,:old:Currdate);
             end t_del_tran;
            触发器还可以用来维护数据完整性:
          create or replace trigger t_del_clazz
            before delete
        on  tb_clazz
                for each row
      declarer
          begin
              delete from tb_student_course
          where student_id in
          (
             select id from tb_student where clazz_id=:old.id
          );
                  delete from tb_student where clazz_id=:old.id;
    end  t_del_clazz;