PL/SQL基础

作者: 404er | 来源:发表于2017-09-16 10:15 被阅读115次

    1.PL/SQL

    • pl/sql (procedural language/sql) 是 Oracle 在标准的 sql 语言上的扩展。pl/sql不仅允许嵌入sql语言,还可以定义变量和常量,允许使用条件语句和循环语句,允许使用例外处理各种错误。
    • pl/sql developer 是用于开发pl/sql块的集成开发环境(ide),它是一个独立的产品,而不是oracle的一个附带品。
    • pl/sql 优点
        1. 提高应用程序的运行性能
        2. 模块化的设计思想【分页的过程,订单的过程,转账的过程。。】
        3. 减少网络传输量
        4. 提高安全性(sql会包括表名,有时还可能有密码,传输的时候会泄露。PL/SQL 就不会)

    2.PL/SQL基本的语法格式

    1.PL/SQL块

    declare
      -- 声明部分:在此声明PL/SQL用到的变量、类型及游标,以及局部的存储过程和函数
      variable_name  –变量名称  
      [CONSTANT]  –是否为常量  
      datatype  –变量的数据类型 
      [NOT NULL]  –是否为空 
      [:=value | default expr];  –变量初始化   
                 -- := 是pl/sql赋值符号
                 -- => 是命名参数,指定某个参数的值
                 -- expr是指定初始值的pl/sql 表达式,可以是文本值、其它变量、函数等
    begin
      -- 执行部分:过程及sql语句(类似java里的main方法)
    exception
      -- 异常处理部分:错误处理
      -- when...then...
    end;
    

    声明部分是可选的;执行部分是必须的;异常处理部分是可选的。

    2.命名规则

    标识符 命名规则 例子
    程序变量 V_name V_name
    程序常量 C_name C_company_name
    游标变量 Name_cursor Emp_cursor
    异常标识 E_name E_too_many
    表类型 Name_table_type Emp_record_type
    Name_table Emp
    记录类型 Name_record Emp_record
    SQL Plus 替代变量 P_name P_sal
    绑定变量 G_name G_year_sal

    3. 常用代码

    PL/SQL可用的SQL语句:
    insert,update,delete,select...into,commit,rollback,savepoint
    
    set timing on -- 打开时间(没有分号)
    
    set serveroutput on -- 打开控制台输出(没有分号)
    
    dbms_output.put_line ('hello'); -- 输出字符串
          -- 注:dbms_output是oracle所提供的包,put_line就是dbms_output包的一个过程
    
    show error; -- 查看错误信息
    
     v_sal employees.salary%type;
    -- 其数据类型与已经定义的某个数据变量的类型相同,或者与数据库表的某个列的数据类型相同
    
    v_emp_record employees%rowtype;
    -- 其数据类型和数据库表的数据结构相一致
    
    &:从键盘读取一个值
    

    3.记录类型

    记录类型是把互不相同但逻辑相关的数据作为一个单元存储起来

    declare
        --声明一个记录类型
        type emp_record is record(
        v_sal emp.sal%type,
        v_email emp.email%type
        );
        --定义一个记录类型的成员变量
        v_emp_record emp_record;
    begin
        select sal,email into v_emp_record from emp where employee_id=100;
        --打印
        dbms_output.put_line(v_emp_record.v_sal||','||v_emp_record.v_email);
    end;
    

    4.流程控制

    1.控制语句

    1.IF语句
    IF<布尔表达式> THEN
       PL/SQL和SQL语句;
    ELSIF<其他布尔表达式> THEN  
      其他语句;
    ELSE
      其他语句;
    END IF;
    

    注:ELSIF不能写成ELSEIF

    2.CASE表达式
    CASE selector
      WHEN expression THEN result1
      ELSE resultN
    END;
    

    2.循环语句

    1.简单循环
    LOOP
      要执行的语句;
      EXIT WHEN<条件语句>;    -- 条件满足,退出循环语句
    END LOOP;
    
    2.WHILE循环
    WHILE<布尔表达式> LOOP
      要执行的语句;
    END LOOP;
    
    3.FOR循环
    FOR num IN[REVERSE] 下限 .. 上限 LOOP
        要执行的语句;
    END LOOP;
    

    注:每循环一次,循环变量自动加1;使用关键字REVERSE,循环变量自动减1;
      下限必须小于上限,且必须是整数,不能是变量或表达式,可使用EXIT退出。

    3.顺序语句

    1.GOTO语句

    无条件跳转到指定的标号去

    GOTO label;
    ... ...
    <<label>>
    

    5.游标的使用(类似java中的Iterator)

    • 在PL/SQL程序中,对于处理多行记录的事务经常使用游标来实现
    • 游标是一个指向上下文的句柄或指针

    1.游标属性

    %FOUND:布尔型属性,当最近一次读记录时成功返回则值为TRUE;
    %NOTFOUND:布尔型属性,与%FOUND相反;
    %ISOPEN:布尔型属性,当游标已打开时返回TRUE;
    %ROWCOUNT:数字型属性,返回已从游标中读取的记录数。

    2.显式游标处理(四步)

    • 定义游标:
    CURSOR cursor_name(参数名 数据类型) IS select_satement;
    -- 定义游标不能有INTO
    -- 游标参数可以没有,若有只能为输入参数
    -- 指定数据类型时不能使用长度约束
    
    • 打开游标
      OPEN cursor_name; -- 不能用OPEN语句重复打开一个游标
    • 提取游标数据
      FETCH cursor_name INTO v_list | record_v;
    • 关闭游标
      CLOSE cursor_name;

    3.游标的FOR循环

    自动执行游标的OPEN、FETCH、CLOSE语句和循环语句的功能

    FOR index_variable IN cursor_name LOOP   
      游标数据处理代码
    END LOOP;
    
    • index_variable变量为记录类型
    • 如果游标查询语句的选择列表中存在计算列,则必须为其指定别名才能通过游标FOR循环访问

    4.隐式游标

    BEGIN
      UPDATE employees
      SET salary=salary+10
      WHERE employee_id=1001;
      
      IF sql%notfound THEN dbms_output.putline('查无此人');
      END IF;
    END;
    

    5.参照游标

    • 用于存放数值指针的变量,通过使用参照变量可以使应用程序共享相同对象,从而降低占用的空间
    • 定义游标不需要指定相应的select语句,但是当使用游标时(open时)需要指定select语句
    declare 
      type emp_cursor is REF CURSOR;
      emp_infor_cursor emp_cursor;
      e_name emp.ename%type;
      e_sal emp.sal%type;
    begin 
      open emp_infor_cursor for select ename,sal from emp where deptno=10;
      loop
        exit when emp_infor_cursor%notfound;
        fetch emp_infor_cursor into  e_name,e_sal;
        dbms_output.put_line('姓名:'||e_name||' 薪水:'||e_sal);
      end loop;
      close emp_infor_cursor;
    end;
    

    6.异常的处理(三种方式)

    EXCEPTION
      WHEN first_exception THEN 处理语句
      WHEN OTHERS THEN 处理语句
    END;
    
    • 异常处理可以按任意次序排列,但 OTHERS 必须放在最后
    • 出现异常则异常之后的语句不执行,直接执行处理异常语句

    1.预定义错误

    无需在程序中定义,由ORACLE自动将其引发

    2.非预定义错误

    需要用户在程序中定义,然后由ORACLE自动将其引发

    DECLARE
      e_deleteid_exception exception;
      PRAGMA EXCEPTION_INIT(e_deleteid_exception,错误代码);
    

    3.用户定义的错误

    需要用户在程序中定义,然后显式地在程序中将其引发

    DECLARE
      e_too_high_sal exception;
      ...
    BEGIN
      ...
      IF v_sal>10000 THEN RASIE e_too_high_sal;
      END IF;
    EXCEPTION
      WHEN e_too_high_sal THEN dbms_output.put_line('工资太高了!');
    END;
    

    7.包

    package 是一个能够将相关对象存储在一起的PLSQL结构,Package包括两个分量的组成部分:specification(包声明),body(声明中的程序实现,包体)。每一个部分都单独的存储在数据字典中。包声明是可见的;包体是黑盒,隐藏了实现的细节。

    1.创建包

    -- 包头声明:
    create or replace package pkg_name  is | as 
      
      公共变量(varibale)的定义;
    
      公共类型(type)的定义;
    
      公共游标(cursor)的定义;
    
      函数说明;
      function fun1(p_1 number) return number;
      过程说明;
      procedure proc1;
    
    end package_name;
    
    -- 包体声明;
    create or replace package body pkg_name  is | as 
    
      --  函数实现
      function fun1(p_1 number) return number is
        begin
    
        return p_1
        end;
    
      -- 过程实现
      procedure proc1 is
        begin         
        
        end;
    
      -- 初始化代码
      begin
      
      end;
    
    end package_name;
    

    2.调用包

    declare 
      e_name varchar2(20);
    begin 
      package_test.pro_1(7839,e_name);
      dbms_output.put_line(e_name);
    end; 
    

    8.编写存储过程和存储函数

    • Oracle 提供可以把 PL/SQL 程序存储在数据库中,并可以在任何地方来运行它,这样就叫存储过程或函数

    1.存储过程与存储函数的区别

    存储过程 存储函数
    头部声明:procedure 头部声明:function
    没有返回值 有返回值
    可作为独立的PL/SQL语句来执行 不能独立执行,必须作为表达式的一部分调用
    SQL语句中不可调用 SQL语句中可以调用

    2.存储函数的格式

    -- 函数的声明
    create or replace function func_name(v_param varchar2) 
    -- 返回值的类型
    return varchar2
    is
      -- PL/SQL块变量,记录类型,游标的声明(类似于前面的declare的部分)
    begin
      -- 函数体(可以实现增删改查等操作,返回值需要return)
      return 'helloworld';
    end;
    

    3.说明

    1. 函数名后面是一个可选的参数列表,包括 IN,OUT,INOUT 标记,参数之间用逗号隔开。若省略标记则参数隐含为 IN。没有参数则不写括号。
    2. 调用是先输出返回值,打印是按顺序输出
    3. 函数只能有一个返回值,OUT型参数实现多个返回值

    9.编写触发器

    1.触发器(Trigger):

    当某个事件发生时自动地隐式运行,不能接收参数

    2.触发器的组成:

    • 触发事件:即在何种情况下触发TRIGGER;例如:INSERT,UPDATE,DELETE。

    • 触发时间:即该TRIGGER是在触发事件发生之前(BEFORE)还是之后(AFTER)触发,也就是触发事件和该TRIGGER的操作顺序。

    • 触发器本身:即该TRIGGER被除法之后的目的和意图,正是触发器本身要做的事情。例如:PL/SQL块。

    • 触发频率:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。
      语句级触发器:是指当某触发事件发生时,该触发器只执行一次;
      行级触发器:是指当某触发事件发生时,对该操作影响的每一行数据,触发器都单独执行一次

    3.示例

    create or replace trigger update_emp_trigger
    after
      update on emp
    for each row
    begin
      dbms_output.put_line('hello world'||:old.sal||:new.sal);
    end;
    

    相关文章

      网友评论

      • 王梦琦_674c:循环显示春夏秋冬,条件怎么写?
      • 404er:触发器调用自增长
        select sequence1.nextval into:new.id from dual;
      • 404er:oracle 游标在取出一行数据后修改这行数据,返回的游标里面不会同时更新值
      • 404er:exec和call的区别:
        1. 但是exec是sqlplus命令,只能在sqlplus中使用;call为sql命令,没有限制.
        2. 存储过程没有参数时,exec可以直接跟过程名(可以省略()),但call则必须带上().

      本文标题:PL/SQL基础

      本文链接:https://www.haomeiwen.com/subject/dpdesxtx.html