PL/SQL基础

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;
... ...
<

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;

你可能感兴趣的:(PL/SQL基础)