Oracle_Day06

pl/sql
1、什么是pl/sql
pl/sql就是对sql语言的拓展,在之前所学的sql基础上又添加了一些编程语言的特性。所以pl/sql是把数据操作和查询组织在过程化单元里面,通过逻辑判断、循环等实现复杂的功能或者计算。

例子:对员工表涨工资。ios工种涨500,Android涨300,其余涨1000。
例子:通过每个人的身份证号知道每个人的生日。

2、为什么要学习pl/sql
1、可以更高效地操作数据库
2、想学习后面的触发器、过程、函数,pl/sql是基础

3、pl/sql怎样去学习
3.1、pl/sql的基本语法
declare
--说明部分(定义变量,若没有说明部分,那么declare可以不写。)
begin
--执行部分
end;
/
--执行结束

  --案例1:通过pl/sql输出helloword
  declare
        
  begin
      --执行部分
      dbms_output.put_line('HelloWorld');
  expection
      --处理例外

  end;
  /

3.2、pl/sql中的变量定义
1、基本变量
java:int a=10;
pl/sql:a number:= 1000;

-- 案例:适用基本数据类型
    declare
        pname varchar2(20);
        pnumber number;
    begin
        pname:='李四';
        pnumber:='1000';
        dbms_output.put_line(pname||''||pnumber);
     end;
      /

2、引用型变量
      举例:pname emp.ename%type;
      说明:将emp表中的ename字段的数据类型作为ename的数据类型。
      
    --案例:查询员工表中编号为1的员工的姓名和工资
      declare
        pname emp.ename%type;
        psal emp.sal%type;
      begin
        select ename,sal into pname,psal from emp where empno=1;
        --将查到的ename与sal放到pname与psal中
        dbms_output.put_line(pname||'的工资是'||psal);
      end;
      /

3、记录型变量
    举例:emp_res  emp%rowtype
     --新建一个变量emp_res 使其等于emp表的第一行数据类型
    --案例:查询员工表中编号为1的员工的所有信息
    declare
        emp_res emp%rowtype;
    begin
        select * into emp_res from emp where empno=1;
        dbms_output.put_line('编号为'||emp_res.empno||'的'||emp_res.ename||'工资是'||emp_res.sal||'工种是'||emp_res.job);
     end;
      /

3.3、pl/sql中的循环和if else
if else

      1、if 条件 then 执行语句1,执行语句2,执行语句3,执行语句4;
            end if;
      2、if 条件1 then 执行语句;
            else 执行语句;
            end if;
      3、if 条件1 then 执行语句;
            elsif 条件2 then 执行语句;
            elsif 条件3 then 执行语句;
            else 执行语句;
            end if;
      
      --案例:让用户通过键盘录入数据
        accept num prompt('请输入一个数字');
        declare
            pnumber number:=#
        begin
            if pnumber=1 then dbms_output.put_line('输入的数字是1');
            elsif pnumber =2 then dbms_output.put_line('输入的数字是2');
            else dbms_output.put_line('输入的是其他数字');
            end if;
         end;
         /
         
       循环:while
        while 循环的条件 loop
            循环体
        end loop;
      --案例:通过while循环打印数字1到10
        declare 
          i number:=1;
        begin
          while i<=10 loop
            dbms_output.put_line(i);
            i:=i+1;  --plsql中没有++与--
          end loop;
        end;
        /

       循环:for
          for i in 1..10 loop  --i的取值从1开始到10结束
            循环体
           end loop;
      --案例:通过for循环打印数字1到10
        begin   
           for i in 1..10 loop
             dbms_output.put_line(i);
             end loop;
          end;
          / 

       循环:loop
          loop
          exit when 退出条件;
            循环体
          end loop;
      --案例:通过loop循环打印数字1到10
          declare 
             i number :=1;
          begin
              loop exit when i>10;
                dbms_output.put_line(i);
                 i:=i+1;
              end loop;
          end;
          /

3.4、pl/sql中的游标(光标,cursor,结果集(ResultSet))就是个结果集;

       定义:cursor 光标的名字;(注意对比基本数据类型的顺序)
       光标的名字 is select * from emp;
       fecth把指针指向的数据返回,并将指针指向下一条数据

        --案例:查看员工表中所有员工的姓名和工资
          declare
              pname emp.ename%type;
              psal emp.sal%type;
              --定义一个光标
              cursor cemp is select ename sal from emp;
           begin
              --开启光标
              open cemp;
              --对光标的取值
              loop
                --循环体  
                fetch cemp into pname,psal;
              exit when cemp%notfound; --循环结束的条件:循环到没有下一条数据
                dbms_output.put_line(pname||'工资是'||psal);
              end loop;
              --关闭游标
             close cemp;
             end;
            /

        案例:供员工涨工资,ios的工种涨500,android的工种涨1000,其余涨2000;
             alter table briup_emp modify (sal number (7,2));
              declare
              pempno briup_emp.empno%type;
              psal briup_emp.sal%type;
              pjob briup_emp.job%type;
              cursor cemp is select empno,job,sal from briup_emp;
           begin
              open cemp;
              loop
                fetch cemp into pempno,pjob,psal;
              exit when cemp%notfound; 
                if pjob='ios' then update briup_emp set sal = psal+500 where empno=pempno;
                elsif pjob='android' then update briup_emp set sal = psal+1000 where empno=pempno;
                else update briup_emp set sal = psal+2000 where empno=pempno;
                 end if;
              end loop;
              --关闭游标
             close cemp;
             end;
            /
            commit;

3.5、pl/sql中的例外
oracle 中的例外即语法错误
预定义例外:
no_data_found(没有找到数据)
too_many_rows(匹配了多个行)
zero_divide(除数为0)
value_error(数据类型转换失败)
timeout_on_resource(资源连接超时)
案例:模拟no_data_found例外
declare
pname briup_emp.ename%type;
begin
select ename from briup_emp where empno=100;
expection ---例外处理情况
when no_data_found(错误名称) then dbms_output.put_line(‘没有找到这个员工’);(错误之后该怎么做)
when others then dbms_output.put_line('出现了其他情况');
end;
/

       案例:模拟too_many_rows例外
             declare
                pname briup_emp.ename%type;
             begin
                select ename into pname from briup_emp where empno=1;
             expection    ---例外处理情况
                 when too_many_rows(错误名称) then dbms_output.put_line(‘匹配了多行数据’);(错误之后该怎么做) 
                 when others then dbms_output.put_line('出现了其他情况');
             end;
             /

3.6、pl/sql中的过程(存储过程,没有返回值)
指存储在数据库中共所有用户调用的子程序
概念:过程是一种命名的pl/sql代码块,它既可以没有参数,也可以有参数,既可以有In参数,也可以有out参数,但他没有返回值。过程一旦被创建好,就会储存到数据库中,过程不能被普通的sql语句调用的,第一个调用方式通过execute或者在pl/sql代码块中调用,因为过程是提前编译好的代码,所以执行效率很高。

                过程该如何创建(用法):
                create [or replace] procedure_pro_name[(参数列表:参数名 参数类型(输入/输出参数) 数据类型)] is | as(说明部分)begin..........end;/

                案例:通过过程打印helloword
                  create or replace procedure dbms_helloword
                  is
                  begin
                          dbms_output.put_line('helloword');
                   end;
                    /

                    调用:execute dbms_helloworld;
                    内部调用:begin
                                      dbms_helloword;
                                      dbms_helloword;
                                      end;
                                      /

                案例:通过过程向员工表中添加一条数据
                  create or replace procedure insert_emp
                  is
                  begin
                          insert into birup_emp(ename) value('yxx');
                          --commit;不应该写在过程中,因为是否提交应该由调用者来处理。
                   end;
                    /



                 案例:向过程中添加输入参数(通过员工编号查询员工的名字)
                  create or replace procedure select_emp_by_empno(eno in number)
                  is
                  pname briup_emp.ename%type;
                  begin
                          select ename into pname from briup_emp where empno=eno;
                          dbms_output.put_line(enp||'员工名字为'||ename)
                   end;
                    /
                    内部调用:begin
                                      select_emp_by_empno(2);
                                      end;
                                      /

                 案例:向过程中添加输出参数,好比过程抛出的结果(通过员工编号查询工种和工资)
                  create or replace procedure select_emp_by_empno
                  (eno in number,--通过这个输入参数指定查询的员工号
                   ejob out varchar2,
                   esal out number
                  )
                  is
                  pjob briup_emp.job%type;
                  psal briup_emp.sal%type;
                  begin
                          select job,sal into pjob,psal from briup_emp where empno=eno;      
                  exception    ---例外处理情况
                             when no_date_found then dbms_output.put_line('没有这个员工’);
                             when others then dbms_output.put_line('出现了其他情况');
                   end;
                    /
                    内部调用:
                        declare
                            pjob briup_emp.job%type;
                            psal briup_emp.sal%type;                
                         begin
                         select_emp_by_empno(2,pjob,psal);
                         dbms_output.put_line('工种是'||pjob||'工资是'||psal)
                         
                         end;
                         /

                    删除过程:drop procedure procedure_name

3.7、pl/sql中的函数(存储函数)
指存储在数据库中共所有用户调用的子程序

        共同点:都是执行某个功能的代码块
        不同点:是否有return返回值
        概念:函数一般用于计算或者返回一个值,函数在创建的时候和过程很相似调用时完全不同,函数调用时需要表达式,pnmuber:=函数,函数必须有返回值。
        create or relpace function fun_name(参数列表)
        return 返回值类型
        is/as
        ...................

        --案例:计算一个员工的年工资
        create or replace function years_salary(eno in number)
        return number
        is
        pys number(10);
        begin
          select sal*12 into pys from briup_emp where empno=eno;
           return pys;
        end;
        /

        declare
          pyear_sal number(10);
        begin
           pyear_sal:=year_salary(1);
           dbms_output.put_line('年薪是'||pyear_sal);

      删除函数:drop function fun_name;

3.8、通过pl/sql编写触发器
结合一些案例
概念
触发器是一个与表关联的pl/sql程序,insert update delete 会在指定的表上发出时,Oracle会在佛那个执行触发器中的相关逻辑。
作用
1、可以实现安全性检查,2、数据确认,3、审计功能,4、数据备份或同步
分类
语句级触发器:
行级触发器:
写法
create trigger tri_name
after | before insert | update | delete [of 字段名]
on table_name
[for each row 行级/不写的话为语句级]
......................
案例
案例1:第一个触发器(如果向员工表中新增了一个数据,那就在屏幕上打印一句“添加了一个员工”)
create trigger insert_briup_emp
after insert --插入成功后触发
on briup_emp
begin
dbms_output.put_line('添加了一个员工');
end;
/

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,544评论 6 501
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,430评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,764评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,193评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,216评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,182评论 1 299
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,063评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,917评论 0 274
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,329评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,543评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,722评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,425评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,019评论 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,671评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,825评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,729评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,614评论 2 353

推荐阅读更多精彩内容