Oracle PL/SQL (1) - 编程基础知识

PL/SQL概述

Oracle提供了在数据库服务器端编程的语言,即PL/SQL。而SQL只是一种声明式语言,是非过程性的,语句之间相互独立。在实际工作中,许多事务处理应用都是过程性的,前后语句之间存在一定关联。
PL/SQL是过程化SQL,可以弥补SQL语句的不足。可以编写过程、函数、触发器,而这些存放在oracle数据库中可以在java程序中调用就节省了传输量和解析时间,同时提高了性能。

在Oracle 中使用PL/SQL来扩展SQL的功能,PL/SQL可以通过IF和LOOP语句控制程序的执行流程;可以定义变量以便在语句之间传递数据信息。PL/SQL是对标准SQL语言的扩展, SQL语句完全可以嵌套在PL/SQL程序代码中,将SQL的数据处理能力和PL/SQL的过程处理能力结合在一起。使得SQL能够更加的灵活,功能更加强大,效率更高

本文主要讲述PL/SQL的基本语法、条件判断语句、循环语句。

1、PL/SQL变量的数据类型

number:数字类型,可以代表整数和浮点数。
int:整数型。
pls_integer:整数型,计算速度快(直接由cpu执行),占用较少的存储空间。但产生溢出时将触发异常。
binary_integer:带符号的整数型,不会出现溢出,但计算速度较慢(由oracle模拟执行)。
char:定长字符,最长255个字符。
varchar2:变长字符,最长2000个字符。
long:变长字符,最长2gb。
date:日期型。
boolean:布尔型(true或false)。

2、变量的声明和赋值

1)声明变量的语法
变量名 数据类型 := 初值 ;
变量名 数据类型 default 初值 ;
A.长度不能超过30个字符,不能有空格。
B.由字母、数字、下划线、美元符号$和#号组成,必须以字母开头。
C.不能使用PL/SQL或SQL的关键字。可以使用help reserved words 命令获得关键字列表。
D.变量默认值为null。
变量命名规范


image.png

2)使用%TYPE声明变量类型
%TYPE用来定义与数据表中指定字段数据类型相同的变量。如果表中字段的数据类型或长度发生变化,%TYPE变量会自动随之变化。这样用户不必查看表中各个字段的数据类型,就可以确保所定义的变量能够正确存储字段数据。
格式为:变量名 方案名.表名.字段名%type
如:var_username scott.emp.empname%type; --员工名称

3)使用%ROWTYPE声明变量类型
%ROWTYPE类型可以根据数据表的行结构定义数据类型,用于存储从数据表中检索到的一行完整的数据。如果数据库表的结构发生变化,记录变量中的结构也将随之改变。
格式为:变量名 方案名.表名%rowtype
例如:输入职工编号,输出其详细信息

declare
    var_emp  scott.emp%rowtype ; --数据行变量
    var_empno scott.emp.empno%type;
begin
    var_empno:=&var_empno;
    select * into var_emp from scott.emp where  empno=var_empno ;
    dbms_output.put (var_emp.ename) ;
    dbms_output.put_line(' '||var_emp.job) ; 
    dbms_output.put_line(' '||var_emp.sal) ;
end; 

4)自定义变量类型
自定义记录数据类型可以表示由多个字段值组成的一行数据。使用时首先要定义记录类型的结构,然后声明该类型的变量存储数据。

type 类型名称 is record (
     变量名称  数据类型 := 默认值 , 
     ……
     变量名称  数据类型 := 默认值 
) ;

例如:自定义员工姓名与工资类型,输入职工编号,输出其姓名与工资

declare
    type employee_type is record (  --声明自定义记录类型
         ename  scott.emp.ename%type, 
         sal  scott.emp.sal%type
);
    var_emp employee_type ; --声明自定义记录类型变量
    var_empno scott.emp.empno%type;
begin
    var_empno:=&var_empno;
    select ename, sal into var_emp from scott.emp where  empno=var_empno ; 
     dbms_output.put (var_emp.ename) ;
     dbms_output.put_line(' '||var_emp.sal) ; 
end; 

例如:允许同一记录类型的两个变量整体赋值。

declare
    type employee_type is record ( 
         ename  scott.emp.ename%type, 
         sal  scott.emp.sal%type
);
    var_emp1 employee_type ;
    var_emp2 employee_type ; 
    var_empno scott.emp.empno%type;
begin
    var_empno:=&var_empno;
    select ename, sal into var_emp1 from scott.emp where empno=var_empno ;
    var_emp2:=var_emp1; 
    dbms_output.put (var_emp2.ename) ;
    dbms_output.put_line(' '||var_emp2.sal) ; 
end; 

3、PL/SQL的语法结构

    declare 
      //这部分用于声明变量
    begin
      //这部分用于处理业务逻辑
    exception
      //这部分用于处理例外也就是异常情况
    end;

例如:

 declare
        uname varchar2(10);
        hello varchar2(10) := 'helloworld'; --为变量赋值
        vsal emp.sal%type; --声明一个引用类型的变量
        pall emp%rowtype; --声明一个记录类型的变量
        digit number:=#---提示用户输入,然后根据用户输入执行相应的操作
        ...
      begin
        dbms_output.put_line(hello);
      exception
        when exception_name then
           //操作
      end;

例如:根据用户输入的员工编号获得其工资和奖金

declare
    var_empno number;  --员工编号
    var_sal number;    --工资
    var_comm number;   --奖金
begin
    --接收用户输入的员工编号
    var_empno:=&var_empno;
    --获得工资
    select sal,nvl(comm,0) into var_sal,var_comm from scott.emp where empno=var_empno;
    dbms_output.put_line('员工编号是'||var_empno||'的工资是'||var_sal||'奖金是'||var_comm);
end; 

4、PL/SQL的条件判断语句

if语句

 if 条件 then 
      语句;
 end if;

if...else语句

 if 条件 then 
      语句;
 else 
      语句;
 end if;

if...elseif...else语句

 if 条件 then 
      语句;
 elsif 条件then 
      语句;
 else 
      语句;
 end if;

例如:根据输入的数字判断大小

declare
   v_url VARCHAR(50):='www.baidu.com';
   v_num1 NUMBER:= 100;
   v_num2 NUMBER:=200;
   v_num3 NUMBER;
 begin
   dbms_output.put_line('请输入第三个数字:');
   v_num3 :=&num3;
   if v_num1 < v_num3 then
      dbms_output.put_line('第一个字符比第三个字符小');
   end if;
   if v_url like '%baidu%' then
      dbms_output.put_line('网址之中包含baidu单词');
   end if;
 end;

5、case语句

case语句语法为:

case 变量
    when <表达式1> then 语句块1;
    when <表达式2> then 语句块2;
      ……
    when <表达式n> then 语句块n;
   [ else 语句块 n+1 ]
end ;

例如:使用case语句判断数值

 declare
    v_choose NUMBER:=1;
 BEGIN
    case v_choose 
     when 0 then
          dbms_output.put_line('选择的是0');
     when 1 then
          dbms_output.put_line('选择的是1');
     else
          dbms_output.put_line('没有选项满足');
    end case;
 END;

6、PL/SQL的循环语句

在PL/SQL中有三种循环结构
1).loop循环
loop循环语法为:

loop
 语句块;
    exit when 循环结束条件;
 循环语句修改;
end loop;

例如:输出1-99的数。

      declare
        step number := 1;
      begin
        loop
          exit when step > 100;--当step>100退出循环
          dbms_output.put_line(step || ' ');
          step := step + 1;
        end loop;
      end;

2).while...loop循环
while...loop循环语法为:

while 循环结束条件 loop
            语句块;
    循环语句修改;
end loop;

例如:循环输出1-100的数。

      declare
        step number := 1;
      begin
        while step <= 100 loop
          dbms_output.put_line(step);
          step := step + 1;
        end loop;
      end;

3).for语句循环
for语句循环语法为:

 for 循环变量 in n..N loop
      语句块;
    end loop;

例如:输出1-100之间的数

    declare
    begin
      for i in 1.. 100 loop
      dbms_output.put_line(i);
    end loop;
    end;

7、异常处理

PL/SQL程序运行时出现的错误称为异常。可以分为两类:
预定义异常: 当 PL/SQL 程序违反 Oracle 规则或超越系统限制时隐式引发
用户自定义异常:用户可以声明自定义异常,自定义的异常通过 raise 语句手动引发
系统预定义异常

begin
     过程及sql语句;
exception
     when 异常名称then
          过程及sql语句;
     when others then
          过程及sql语句;
end;
image.png

例如:当在程序中使用0作为除数进行运算时,将触发该异常。

DECLARE
v_test1 NUMBER := 100;
v_test2 NUMBER := 0;
v_test3 NUMBER := 0;
BEGIN
v_test3 := v_test1 / v_test2;
dbms_output.put_line(v_test3);
EXCEPTION
WHEN zero_divide THEN
dbms_output.put_line('0不能作为除数.');
END;
/

例如:当程序中的对象还没有先进行对象初始化的操作,就直接为对象的属性赋值,将触发该异常。

DECLARE
v_test test_type;
BEGIN
v_test.v_name := 'test';
EXCEPTION
WHEN access_into_null THEN
dbms_output.put_line('首先初始化对象v_test');
END;
/

例外函数1: SQLCODE,SQLERRM 在PL/SQL块中出现Oracle错误时,通过使用例外函数可以取得错误号以及相关的错误消息。
SQLCODE 返回Oracle错误号。
SQLERRM 返回错误号对应的错误消息。

begin
  insert into scott.emp(empno , ename , job , sal , deptno)
  values('7999','ATG','CLERK',1500,'ABC');
exception
  when dup_val_on_index then
    dbms_output.put_line('捕获dup_val_on_index异常');
    dbms_output.put_line('该主键值已经存在');
  when others then  -- others子句必须放在各种异常处理的最后
    dbms_output.put_line( '错误号:' || sqlcode );
    dbms_output.put_line( '错误描述:' ||sqlerrm );
end;

备注:others可以捕获所有异常,如果使了其它具体异常则others子句必须放在这些异常处理的最后。

例外函数2:RAISE_APPLICATION_ERROR在存储过程,函数和包中使用RAISE_APPLICATION_ERROR可以自定义错误号和消息。
raise_application_error:用于自定义错误消息(用于程序段中)

语法:
raise_application_error(error_number,message[,{TRUE | FALSE}]);
error_number : 错误号,范围是: -20000 ~ -20999之间的负整数;
message : 错误消息,长度不能超过2048字节;
第三个可靠选参数,如果TRUE,该错误会被放在先前错误堆栈中;如果FALSE(默认),则替换先前所有错误.
例如:

CREATE OR REPLACE PROCEDURE raise_comm
(
eno NUMBER,
commission NUMBER
) IS
v_comm emp.comm%TYPE;
BEGIN
SELECT comm INTO v_comm FROM emp WHERE emp = eno;
IF v_comm IS NULL THEN
raise_application_error(-20001, '该员工无补助.');
END IF;
EXCEPTION
WHEN NO_DATA_FOUND THEN
dbms_output.put_line('该雇员不存在.');
END;
/

用户自定义异常
自定义异常使用预定义异常和非预定义异常,程序可以捕获Oracle错误,并且在出现Oracle错误时自动触发对应的异常。但是在实际应用中,可能还会 遇到其它错误,这时可以为特定的情况自定义异常,不过需要显示触发该异常:通过定义异常,然后关联异常和错误,显示触发异常,最后在EXCEPTION 中处理该异常。
自定义异常的处理步骤:
定义异常处理:异常名 exception ;
触发异常处理:raise 异常名
例如:

--自定义异常  
declare  
        e_wage EXCEPTION;  
        v_wage teachers.wage%type;  
    begin  
            v_wage:=&wage;  
            insert into teachers values (10111,'王彤','教授','01-9月-1990',1000,v_wage,101);  
            if v_wage <0 then   
             raise e_wage;  
            end if;  
            exception   
                when e_wage then  
                dbms_output.put_line('教师工资不能为负');  
                rollback;  
                when others then  
                    dbms_output.put_line('未知异常');  
    end;  
/  

你可能感兴趣的:(Oracle PL/SQL (1) - 编程基础知识)