zoukankan      html  css  js  c++  java
  • 【PL/SQL】匿名块、存储过程、函数、触发器

    名词解释

    子程序:PL/SQL的过程和函数统称为子程序。

    匿名块:以DECLARE或BEGIN开始,每次提交都被编译。匿名块因为没有名称,所以不能在数据库中存储并且不能直接从其他PL/SQL块中调用。

    命名块:除匿名块之外的其他块。包括过程、函数、包和触发器。可以在数据库中存储并在适当的使用运行。

    子程序的优点:

    1)具有扩展性

    可以自定义PL/SQL语言以满足实际应用

    2)高可用和可维护性

    子程序的调用不受调用者数目的影响,只要有效就可被调用。

    如果定义被更改以后,只有子程序受到影响,简化了维护、优化过程。

     

    匿名块、过程、函数的执行过程基本相似,不同之处在于:匿名块在DECLARE后面声明变量,而过程和函数在IS后面声明。

    函数也可以称为过程,特殊之处为:函数总是有一个返回值(RETURN)。

    匿名块

    [DECLARE]

    BEGIN

      --statements

    [EXCEPTION]

    END;

    过程

    PROCEDURE name

    IS

    BEGIN

      --statements

    [EXCEPTION]

    END;

    函数

    FUNCTION name

    RETURN datatype

    IS

    BEGIN

      --statements

      RETURN value;

    [EXCEPTION]

    END;

    1、 创建存储过程

    1)语法

    CREATE [OR REPLACE] PROCEDURE procedure_name

    [argument[{IN|OUT|IN OUT}] TYPE]

    {IS|AS}

      <类型、变量的说明>

    BEGIN

      <执行部分>

    EXCEPTION

      <可选的异常错误处理程序>

    END;

    2)示例

    ①要求:记录登录数据的userid和logdate。

     

    ##创建表,用来存储userid和logdate

    SQL> create table logtable (userid varchar2(10),logdate date);

     

    Table created.

     

    ##创建存储过程

    SQL> create or replace procedure logexecution is

      2  begin

      3    insert into logtable (userid, logdate) values (user, sysdate);

      4  end;

      5  /

     

    Procedure created.

     

    ##执行存储过程

     

    SQL>  exec logexecution;    

     

    PL/SQL procedure successfully completed.

     

    ##验证执行结果

     

    SQL> select * from logtable;

     

    USERID     LOGDATE

    ---------- -------------------

    SYS        2017-03-12 01:18:28

     

    ② 要求:删除表中记录

    ##创建过程

    SQL> create or replace procedure delemp(v_empno in emp.empno%type) is

      2    no_result exception;

      3  begin

      4    delete from emp where empno = v_empno;

      5    if sql%notfound then

      6      raise no_result;

      7    end if;

      8    dbms_output.put_line('employee number' || v_empno || 'was deleted!');

      9  exception

     10    when no_result then

     11      dbms_output.put_line('no row found!');

     12    when others then

     13      dbms_output.put_line('other error!');

     14  end delemp;

     15  /

     

    Procedure created.

     

    ##执行过程

    SQL> exec delemp(999);

    no row found!

     

    PL/SQL procedure successfully completed.

     

    SQL> exec delemp(7499);

    employee number7499was deleted!

     

    PL/SQL procedure successfully completed.

     

    2、 创建函数

    1)语法

    CREATE [OR REPLACE] FUNCTION function_name

    [(argument[{IN|OUT|IN OUT}] TYPE,

    ...

    argument[{IN|OUT|IN OUT}] TYPE)]

    RETURN return_type {IS|AS}

    function_body

     

    2)示例

    ##创建函数

    SQL> create or replace function get_salary(dept_no number, v_num out number)

      2    return number is

      3    v_sum number;

      4  begin

      5    select sum(sal), count(*)

      6      into v_sum, v_num

      7      from emp

      8     where deptno = dept_no;

      9    return v_sum;

     10  exception

     11    when no_data_found then

     12      dbms_output.put_line('你需要的数据不存在!');

     13    when too_many_rows then

     14      dbms_output.put_line('程序运行错误!请使用游标');

     15    when others then

     16      dbms_output.put_line('发生其他错误!');

     17  end get_salary;

     18  /

     

    Function created.

     

    ##调用函数(注:函数不能单独调用,只能在语句中调用)

    SQL> declare

      2    v_num number;

      3    v_sum number;

      4  begin

      5    v_sum := get_salary(30,v_num);

      6    dbms_output.put_line('30 department sum salary is '||v_sum||' employee: '||v_num);

      7  end;

      8  /

    30 department sum salary is 9400 employee: 6

     

    PL/SQL procedure successfully completed.

     

    3、 触发器

    触发器:在数据库中以独立的对象存储,它与存储过程不同的是,存储过程通过其他程序来启动运行或者直接启动运行,而触发器是由一个事件来启动运行。即触发器是当某个事件发生时自动地隐式运行。并且触发器不能接收参数,不能commit。

    触发器类型:

    DML触发器:Oracle可以在DML语句进行触发,可以在DML操作前或操作后进行触发,并且可以对每个行或语句操作上进行触发。

    替代触发器:由于在Oracle里,不能对复杂视图进行操作。所以给出了替代触发器。它就是Oracle专门为进行视图操作的一种处理方法。

    系统触发器:它可以在Oracle数据库系统的事件中进行触发,如Oracle系统的启动与关闭等。

    触发器组成:

    触发事件:即在何种情况下触发TRIGGER。

    触发事件:即该TRIGGER是在触发事件发生之前(BEFORE)还是之后(AFTER)触发。

    触发器本身:即该TRIGGER被触发之后的目的和意图。

    触发类型:说明触发器内定义的动作被执行的次数。即语句级(STATEMENT)触发器和行级(ROW)触发器。

    语句级(STATEMENT)触发器:指当某触发事件发生时,该触发器只执行一次。

    行级(ROW)触发器:指当某触发器事件发生时,对收到该操作影响的每一行数据,触发器都单独执行一次。

    1)示例

    ①创建DML触发器

    要求:当职工表emp被删除一条记录时,把被删除记录写到职工表删除日志表中。

    ##建立删除日志表

    SQL> create table emp_his as select * from emp where 1=2;

     

    Table created.

    ##创建触发器

    SQL> create or replace trigger del_emp

      2    before update or delete on scott.emp

      3    for each row

      4  begin

      5    insert into emp_his

      6      (deptno, empno, ename, job, mgr, sal, comm, hiredate)

      7    values

      8      (:old.deptno,

      9       :old.empno,

     10       :old.ename,

     11       :old.job,

     12       :old.mgr,

     13       :old.sal,

     14       :old.comm,

     15       :old.hiredate);

     16  end del_emp;

     17  /

     

    Trigger created.

     

    ##验证触发器

    SQL> delete from emp where empno=7844;

     

    1 row deleted.

     

    SQL> select count(*) from emp_his;

     

      COUNT(*)

    ----------

             1

     

    ②创建替代触发器

     

    ##创建复杂视图

    SQL> create or replace view emp_view as

      2  select deptno,count(*) total_employeer,sum(sal) total_salary

      3  from emp group by deptno;

     

    View created.

     

    ##对视图进行DML会报错,因为复杂视图不能直接进行DML操作

    SQL> delete from emp_view where deptno=10;

    delete from emp_view where deptno=10

                *

    ERROR at line 1:

    ORA-01732: data manipulation operation not legal on this view

    ##创建触发器

    SQL> create or replace trigger emp_view_delete

      2    instead of delete on emp_view

      3    for each row

      4  begin

      5    delete from emp where deptno = :old.deptno;

      6  end emp_view_delete;

      7  /

     

    Trigger created.

    ##再次删除,发现执行成功

    SQL> delete from emp_view where deptno=10;

     

    1 row deleted.

     

    ③ 创建系统事件触发器

    注意:系统时间触发器要以sys用户运行

    ##登录sys用户

    SQL> conn / as sysdba

    Connected.

    ##创建表

    SQL> create table logtable (name varchar2(20),log_time date);

     

    Table created.

    ##创建触发器

    SQL> create or replace trigger login_his

      2    after logon on database

      3  begin

      4    insert into logtable values (user, sysdate);

      5  end;

      6  /

     

    Trigger created.

    ##验证触发器

    SQL> select * from logtable;

     

    NAME                 LOG_TIME

    -------------------- -------------------

    SYS                  2017-03-12 00:15:29


  • 相关阅读:
    TCP粘包,产生的原因以及解决方案
    php判断变量是否为正整数
    php函数trim中文编码问题解决
    win10设置开机自动启动vagrant虚拟机
    Can't connect to local MySQL server through socket '/var/lib/mysql/mysql.sock' (2)
    git push 时 fatal: Unable to create 'D:/phpStudy/WWW/green_tree/.git/index.lock': File exists.解决办法
    git push 提示 Everything up-to-date
    Allowed memory size of 134217728 bytes exhausted (tried to allocate 2 bytes)
    访问远程mysql数据库,出现报错,显示“1130
    改变网页选中文本的颜色
  • 原文地址:https://www.cnblogs.com/NextAction/p/7366636.html
Copyright © 2011-2022 走看看