Oracle-PL/SQL编程语言

Oracle-PL/SQL编程语言

  1. 变量定义

    declare
       定义变量
    begin
       处理业务逻辑
    end;
    
    
    
    
    -- 案例
    -- 声明方法
    -- 赋值操作可以使用:=也可以使用into查询语句赋值 
    declare
       -- 定义一个i 类型为number(数字或小数)长度为2 赋值为10
       i number(2) := 10;
       
       -- 定义一个s 类型varchar2(字符串)长度为10 赋值为'小明'
       s varchar2(10) := '小明';
       
       -- 定义一个ena 类型是emp表下的ename列的类型长度也是
       ena emp.ename%type; -- 引用型变量
       
       -- 存放emp表中的一行记录
       emprow emp%rowtype; -- 记录型变量 
    begin
       -- 输出i的值
       dbms_output.put_line(i);
       
       -- 输出s的值
       dbms_output.put_line(s);
       
       -- 把查询出来的结果 赋值给ena (into 变量名)
       select ename into ena from emp where empno = 7788;
       
       -- 输出ena的值
       dbms_output.put_line(ena);
       
       -- 把查询出来的结果 赋值给emprow (into 变量名)
       select * into emprow from emp where empno = 7788;
       
       -- 输出emprow哪一行中的数据 (|| 输出多个值得连接符)
       dbms_output.put_line(emprow.ename || '的工作为: ' || emprow.job);
    end;
    
  2. if判断

    declare
       定义变量 
    begin
       if 判断 then
       		逻辑代码块
       elsif 判断 then
       		逻辑代码块
       else
       		逻辑代码块
       end if;
    end;
    
    
    -- 案例
    
    -- 输入小于18的数字, 输出未成年
    -- 输入大于18小于40的数字, 输出中年人
    -- 输入大于40的数字, 输出老年人
    declare
       -- i的值是输入的 (&后面随便写个字母单词都行)
       i number(3) := &i;
    begin
       if i < 18 then
          dbms_output.put_line('未成年');
       elsif i < 40 then
          dbms_output.put_line('中年人');   
       else
          dbms_output.put_line('老年人');  
       end if;
    end;
    
  3. loop循环

    -- while循环
    declare
       定义变量
    begin
       while 判断 loop
            逻辑
       end loop;
    end;
    
    
    -- exit循环
    declare
       定义变量
    begin
       loop
         exit when 判断;
         	逻辑
       end loop;
    end;
    
    
    -- for循环
    declare
       
    begin
       for 变量 in 范围 loop
           逻辑
       end loop;
    end;
    
    
    
    
    -- 案例
    
    -- 用三种方式输出110的数字
    -- where循环
    declare
       i number(2) := 1;
    begin
       -- i 大于 10 时 退出循环
       while i < 11 loop
            dbms_output.put_line(i); 
            i := i + 1;
       end loop;
    end;
    
    -- exit循环
    declare
       i number(2) := 1;
    begin
       loop
         -- i 大于 10 时 退出循环
         exit when i > 10;
         dbms_output.put_line(i); 
         i := i + 1;
       end loop;
    end;
    
    -- for循环
    declare
       
    begin
       -- 循环110的值
       for i in 1..10 loop
           dbms_output.put_line(i); 
       end loop;
    end;
    
  4. 游标

    declare
    
       cursor 游标名称 is 结果集;
       
       定义一个记录型变量
    begin
       open 游标名称;
       
          loop
            fetch 游标名称 into 记录型变量;
          
            exit when 游标名称%notfound;
          
          	业务逻辑
          
          end loop;
       
       close 游标名称;
    end;
    
    
    
    -- 案例
    
    
    -- 游标: 可以存放多个对象, 多行记录.
    -- 输出emp表中所有员工的姓名
    declare
       -- 把emp表中的全部记录, 存储到c1游标中
       cursor c1 is select * from emp;
       
       -- 定义一个记录型变量
       emprow emp%rowtype;
    begin
       -- 打开游标
       open c1;
       
          loop
            -- 把c1中遍历的每一行 都 赋值给emprow
            fetch c1 into emprow;
          
            -- 当它查不到的时候退出
            exit when c1%notfound;
            
            -- 输出名称
            dbms_output.put_line(emprow.ename);
          
          end loop;
       
       -- 关闭游标
       close c1;
    end;
    
    
    
    
    -- 给指定部门员工涨工资
    declare
       -- 定义一个带参数的游标, 参数作为条件
       cursor c2(eno emp.deptno%type) is select empno from emp where deptno = eno;
       
       -- 定义一个引用型变量
       en emp.empno%type;
    begin
       -- 注意:打开的时候, 必须赋值
       open c2(10);
            loop
               -- 把c2中遍历的每一行 都 赋值给en
               fetch c2 into en;
               
               -- 当它查不到的时候退出
               exit when c2%notfound;
            
               -- 执行更新语句
               update emp set sal = sal + 100 where empno = en;
               
               -- 提交事务
               commit;
            
            end loop;
       
       close c2;
    
    end;
    
  5. 存储过程的使用

    -- 存储过程
    -- 存储过程: 存储过程就是提前已经编译好的一段pl/sql语言, 放置在数据库端, 
    -- 可以直接被调用. 这一段pl/sql一般都是固定步骤的业务.
    create or replace procedure 方法名(参数) 
    
    is
    
    begin
    	业务逻辑
    end;
    
    
    
    
    -- 案例
    
    -- 给指定员工涨100块钱
    create or replace procedure p1(eno emp.empno%type) -- 参数不写in 或者 out 默认是in
    
    is
    
    begin
    
       update emp set sal = sal + 100 where empno = eno;
       commit;
    end;
    
    -- 测试p1
    declare
    
    begin
       -- 调用方法 传递参数
       p1(7788);
    end;
    
  6. 存储函数

    create or replace function f_yearsal(参数) return 返回值类型
    
    is
    
      定义变量
    
    begin
           
       逻辑
       
       return 返回值;
    
    end;
    
    
    
    
    -- 案例
    
    -- 通过存储函数实现计算指定员工的年薪
    -- 存储过程和存储函数的参数都不能带长度
    -- 存储函数的返回值类型不能带长度
    create or replace function f_yearsal(eno emp.empno%type) return number
    
    is
    
      s number(10);
    
    begin
           
       select sal * 12 + nvl(comm, 0) into s from emp where empno = eno;
       
       return s;
    
    end;
    
    -- 测试f_yearsal
    -- 存储函数在调用的时候, 返回值需要接收.
    declare
       s number(10);
    begin
       s := f_yearsal(7788);
       dbms_output.put_line(s);
    end;
    
  7. out类型参数的讲解

    -- out类型参数如何使用
    -- 使用存储过程来算年薪
    create or replace procedure p_yearsal(eno emp.empno%type, yearsal out number)
    is
    
       s number(10);
       c emp.comm%type;
    
    begin
    
       select sal * 12, nvl(comm, 0) into s, c from emp where empno = eno;
    
       yearsal := s + c;
       
    end;
    
    
    -- 测试p_yearsal
    declare
       yearsal number(10);
    begin
       p_yearsal(7788, yearsal);
       dbms_output.put_line(yearsal);
    end;
    
    
    -- in和out类型参数的区别是什么?
    -- 凡是涉及到into查询语句赋值或者:=赋值操作的参数, 都必须使用out来修饰.
    
    
  8. 存储过程和存储函数的区别

    /*
     存储过程和存储函数的区别
     语法区别: 关键字不一样.
           存储函数比存储过程多了两个return.
     本质区别: 存储函数有返回值, 存储过程没有返回值.
           如果存储过程想实现由返回值的业务, 我们就必须使用out类型的参数.
           即便是存储过程使用了out类型的参数, 其本质也不是真的有了返回值.
           而是在存储过程内部给out类型参数赋值, 在执行完毕后, 我们直接拿到输出类型参数的值.
    */
    -- 我们可以使用存储函数有返回值的特性, 来自定义函数.
    -- 而存储过程不能用来自定义函数.
    -- 案例需求: 查询出员工姓名, 员工所在部门名称.
    -- 使用传统方式来实现案例需求
    select 
       e.ename,
       d.dname
    from
       emp e,
       dept d
    where
       e.deptno = d.deptno;
       
    -- 使用存储函数来实现提供一个部门编号, 输出一个部门名称.
    create or replace function fdna(dno dept.deptno%type) return dept.dname%type
    is
       dna dept.dname%type;
    begin
       select dept.dname into dna from dept where deptno = dno;    
       return dna;
    end;
    
    -- 使用fdna存储函数来实现案例需求: 查询出员工姓名, 员工所在部门名称.
    select e.ename, fdna(e.deptno)
    from emp e;
    
  9. 触发器案例

    /*
      触发器, 就是制定一个规则, 在我们做增删改操作的时候, 
           只需要满足该规则, 自动触发, 无需调用.
           语句级触发器: 不包含for each row的触发器.
           行级触发器: 包含for each row的就是行级触发器.
                     加for each row是为了使用:old或者:new对象或者一行记录.
    */
    
    -- 语句触发器
    create or replace trigger 触发器名称
    after  -- 执行后触发
    操作
    on 表名称 
    declare
    
    begin
       逻辑
    end;
    
    
    -- 行级触发器
    create or replace trigger 触发器名称
    before -- 执行前触发
    操作
    on 表名称
    for each row
    declare
    
    begin
        逻辑
    end;
    
    
    
    
    -- 案例
    -- 语句触发器
    -- 插入一条记录, 输出一个新员工入职
    create or replace trigger t1
    after  -- 执行后触发
    insert -- insert操作
    on person 
    declare
    
    begin
       dbms_output.put_line('一个新员工入职');
    end;
    
    -- 触发t1
    insert into person values(1, '小红');
    commit;
    
    
    
    -- 行级触发器
    -- 不能给员工降薪
    -- raise_application_error(-20001~-20999之间, '错误提示信息');
    create or replace trigger t2
    before -- 执行前触发
    update -- update操作
    on emp
    for each row
    declare
    
    begin
        -- 修改前的工资 大于 修改后的工资
        if :old.sal > :new.sal then 
           -- 抛异常
           raise_application_error(-20001, '不能给员工降薪');
        end if;
    end;
    
    
    -- 触发t2
    update emp set sal = sal - 1 where empno = 7788;
    commit;
    
  10. 使用触发器实现主键自增

    -- 触发器实现主键自增. [行级触发器]
    -- 分析: 在用户做插入操作之前, 拿到即将插入的数据.
    -- 给该数据中的主键列赋值.
    create or replace trigger auid
    before
    insert
    on person
    for each row
    declare
    
    begin
       select s_person.nextval into :new.pid from dual;
    end;
    
    -- 使用auid实现主键自增
    insert into person (pname) values ('小明');
    commit;
    
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章