PL/SQL 基础(变量,条件语句,光标, 异常)

简介

PL/SQL(Procedure Language/SQL)是Oracle对SQL语言的过程化扩展,在SQL命令语言中增加了过程处理语句(如分支、循环等),使SQL语言具有处理过程的能力。所以PL/SQL是面向过程的语言。对于其他的数据库也有其对应的过程扩展语言,例如DB2的SQL/PL,SQL Server的Transac-SQL(T-SQL)。

程序结构

declare 
	说明部分(变量说明、光标说明、例外申明)
begin
	语句序列(DML语句)
exception
	例外处理语句
end;
/

如果没有说明部分,declare可以不需要。

变量

变量可以分为基本类型变量,引用型变量和记录型变量。变量的赋值使用“:=”或者在SQL语句中使用“into”。
基本变量类型有char, varchar2, date, number, boolean, long。

pnumber   number(7,2)  //定义一个number类型变量,7表示小数点前保留7位,2表示保留两位小数
pname    varchar2(20)   //定义一个长度为20的varchar2类型变量
pdate   date   //定义一个date类型变量
pnumber := 1;   //赋值
pdate := sysdate;   //赋值
select ename into pname from emp where empno = 7839;   //使用into赋值ename, empno为字段名, emp为表名

引用型变量为引用表中的字段的类型,如

pname   emp.ename%TYPE;   //定义一个引用型变量

这表示定义了一个变量“pname”,这个变量的类型和emp表中ename字段的数据类型是一样的。

记录型变量记录表中的一行数据

emp_rec   emp%rowtype;    //定义一个记录型变量 
emp_rec.ename := 'ADAMS';     //引用记录型变量,并把ADMS赋值给记录中的ename字段
select * into emp_rec from emp where empno=7839;   //使用into给emp_rec赋值

“emp_rec”代表变量名,emp为表的名字,“ename”为emp表中的一个字段。

条件语句

if语句

  1. IF 条件 THEN 执行语句;
    END IF;

  2. IF 条件 THEN 执行语句;
    ELSE 执行语句;
    END IF;

  3. IF 条件 THEN 执行语句;
    ELSIF 条件 THEN 执行语句;
    ELSE 执行语句;
    END IF;

循环语句

  1. WHILE 条件 LOOP
    执行语句;
    END LOOP;
  2. LOOP
    EXIT [WHEN 条件];
    执行语句;
    END LOOP;
  3. FOR 变量 IN 范围(如1…3) LOOP
    执行语句;
    END LOOP;

光标

光标(cursor),也称游标,作为集合存储多个值。
光标属性: %found, %notfound,%isopen,%rowcount(影响的行数,而不是总行数,如取到第十行的值时,rowcount即为10)
光标的数量限制:oracle数据库只允许同一个会话中,默认有限个数的光标被打开,一般为300。可在SYS用户下使用show parameter cursor 看到cursor相关的参数,open_cursors即为默认打开的光标数。“alter system set_open_cursors=400 scope=both;”可以更改默认光标数,这里改为了400。

光标的定义:
CURSOR 光标名 [(参数名 数据类型[, 参数名 数据类型]…)] IS SELECT 语句

cursor c1 is select ename from emp;
open c1;   //打开光标执行语句
	fetch c1 into pename;    //取一行数据到变量中, 嵌入循环中可取每一行数据
close c1;   //关闭光标释放资源

cursor c2 is select ename, sal from emp;   //不带参数的光标的声明
cursor cemp(dno number) is select ename from emp where deptno = dno;   //带参数的光标的声明
open cemp(10);   //打开带参数的光标时传递参数进去
	...
close cemp;

异常(exception)

异常分为系统异常和用户自定义异常。系统异常包括:

No_data_found 没有找到数据
Too_many_rows select…into语句匹配多个行
Zero_Divide 被零除
Value_error 算术或类型转换错误
Timeout_on_resource 在等待资源时发生超时

异常处理语句结构

exception
	when 异常(no_data_found) then 异常处理语句;
	when others(其他异常) then 异常处理语句;

尽量捕获并处理所有的异常,否则直接抛给系统的话,会增加系统负担。
自定义异常:在declare部分定义一个变量,其类型为exception,在执行语句中使用raise关键字抛出自定义异常,并在exception部分处理该异常。

简单例子

/*
以SCOTT用户下的表为例
统计每年入职的员工人数,即1980,1981,1982,1987四年每年的入职人数
*/
set serveroutput on;

declare
  --每一位员工入职的年份
  cursor cemp is select to_char(hiredate, 'yyyy') from emp;
  --年份
  phiredate varchar2(5);
  --员工入职人数
  count80 number := 0;
  count81 number := 0;
  count82 number := 0;
  count87 number := 0;

begin
--打开光标
open cemp;
loop
  --取员工入职年份
  fetch cemp into phiredate;
  --退出条件,这里使用了光标的notfound属性
  exit when cemp%notfound; 
  
  --根据年份计算数量
  if phiredate = '1980' then count80 := count80 + 1;
  elsif phiredate = '1981' then count81 := count81 + 1;
  elsif phiredate = '1982' then count82 := count82 + 1;
  else count87 := count87 + 1;
  end if;

end loop;
--关闭光标
close cemp;
--输出结果
dbms_output.put_line('四年总入职人数:' || (count80 + count81 + count82 + count87));
dbms_output.put_line('1980: ' || count80);
dbms_output.put_line('1981: ' || count81);
dbms_output.put_line('1982: ' || count82);
dbms_output.put_line('1987: ' || count87);
end;
/

输出结果为:

	四年总入职人数:14
	1980: 1
	1981: 10
	1982: 1
	1987: 2

你可能感兴趣的:(Oracle,数据库)