Oracle学习笔记十 使用PL/SQL

PL/SQL 简介

PL/SQL 是过程语言(Procedural Language)与结构化查询语言(SQL)结合而成的编程语言,是对 SQL 的扩展,它支持多种数据类型,如大对象和集合类型,可使用条件和循环等控制结构,可用于创建存储过程、触发器和程序包,给SQL语句的执行添加程序逻辑,与 Oracle 服务器和 Oracle 工具紧密集成,具备可移植性、灵活性和安全性。

PL/SQL 的优点

  • 支持 SQL,在 PL/SQL 中可以使用:

  1.数据操纵命令

  2.事务控制命令

  3.游标控制

  4.SQL 函数和 SQL 运算符

  • 支持面向对象编程 (OOP)
  • 可移植性,可运行在任何操作系统和平台上的Oralce 数据库
  • 更佳的性能,PL/SQL 经过编译执行

  

  • 与 SQL 紧密集成,简化数据处理。

  1.支持所有 SQL 数据类型

  2.支持 NULL 值

  3.支持 %TYPE 和 %ROWTYPE 属性类型

  

  • 安全性,可以通过存储过程限制用户对数据的访问

PL/SQL 的体系结构

PL/SQL 引擎驻留在 Oracle 服务器中,该引擎接受 PL/SQL 块并对其进行编译执行。

PL/SQL基础

PL/SQL 块简介

PL/SQL 块是构成 PL/SQL 程序的基本单元,它将逻辑上相关的声明和语句组合在一起。

PL/SQL 分为三个部分,声明部分、可执行部分和异常处理部分。

[DECLARE
    declarations]   --声明部分定义变量、游标和自定义异常
    BEGIN
    executable statements  --包含 SQL 和 PL/SQL 语句的可执行部分
    [EXCEPTION
    handlers]  --指定出现错误时需要执行的操作
    END;
DECLARE
  qty_on_hand NUMBER(5);    --声明部分定义变量、游标和自定义异常
BEGIN     --begin到end 包含 SQL 和 PL/SQL 语句的可执行部分
  SELECT quantity INTO qty_on_hand
  FROM Products
  WHERE product = ‘芭比娃娃‘
  FOR UPDATE OF quantity;
  IF qty_on_hand > 0 THEN
    UPDATE Products SET quantity = quantity + 1
    WHERE product = ‘芭比娃娃‘;
    INSERT INTO purchase_record
    VALUES (‘已购买芭比娃娃‘, SYSDATE);
  END IF;
  COMMIT;
EXCEPTION  /* 异常处理语句 */  --指定出现错误时需要执行的操作
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE(‘出错:‘|| SQLERRM);
END;

PL/SQL中的复合符号

  :=        赋值操作符

  ||         连接操作符

  --        单行注释

  /**/      多行注释

  <<>>  标签分隔符

  ..         范围操作符

  **        求幂操作符

变量和常量

PL/SQL 块中可以使用变量和常量

  1.在声明部分声明,使用前必须先声明

  2.声明时必须指定数据类型,每行声明一个标识符

  3.在可执行部分的 SQL 语句和过程语句中使用

声明变量和常量的语法:

identifier [CONSTANT] datatype [NOT NULL]
        [:= | DEFAULT expr];

给变量赋值有两种方法:

1.使用赋值语句 :=

2.使用 SELECT INTO 语句

DECLARE
  icode VARCHAR2(6);
  p_catg VARCHAR2(20);
  p_rate NUMBER;
  c_rate CONSTANT NUMBER := 0.10;
BEGIN
  ...
  icode := ‘i205‘;
  SELECT p_category, itemrate * c_rate
  INTO  p_catg, p_rate
  FROM itemfile WHERE itemcode = icode;
  ...
END;

数据类型

PL/SQL 支持的内置数据类型

指定数值的存储格式

字符数据类型

字符数据类型包括:

1.CHAR

2.VARCHAR2

3.LONG

4.RAW

5.LONG RAW

PL/SQL 的数据类型与 SQL数据类型的比较


数据类型


SQL类型


PL/SQL类型


CHAR


1~2000


1~32767


LONG


1~2GB


1~32760


LONG RAW


1~2GB


1~32760


RAW


1~2000


1~32767


VARCHAR2


1~4000


1~32767

日期时间和布尔数据类型

日期时间类型

1.存储日期和时间数据

2.常用的两种日期时间类型

①DATE

②TIMESTAMP

布尔数据类型

1.此类别只有一种类型,即BOOLEAN类型

2.用于存储逻辑值(TRUE、FALSE和NULL)

3.不能向数据库中插入BOOLEAN数据

4.不能将列值保存到BOOLEAN变量中

5.只能对BOOLEAN变量执行逻辑操作

LOB  数据类型

用于存储大文本、图像、视频剪辑和声音剪辑等非结构化数据。

LOB 数据类型可存储最大 4GB的数据。

LOB 类型包括:

  1.BLOB   将大型二进制对象存储在数据库中

  2.CLOB   将大型字符数据存储在数据库中

  3.NCLOB   存储大型UNICODE字符数据

  4.BFILE     将大型二进制对象存储在操作系统文件中

LOB 类型的数据库列仅存储定位符,该定位符指向大型对象的存储位置

DBMS_LOB程序包用于操纵 LOB 数据

SET SERVEROUTPUT ON
DECLARE
  clob_var   CLOB;
  amount     INTEGER;
  offset     INTEGER;
  output_var VARCHAR2(100);
BEGIN
  SELECT chapter_text INTO clob_var   --从表中选择 CLOB 定位符到 clob_var变量中
  FROM my_book_text
  WHERE chapter_id=5;
  amount := 24;  -- 要读取的字符数
  offset := 1;   -- 起始位置
  DBMS_LOB.READ(clob_var,amount,offset,output_var);  --从CLOB数据中读取24个字符存储到 output_var 变量中
  DBMS_OUTPUT.PUT_LINE(output_var);  --显示读到的信息
END;

属性类型

用于引用数据库列的数据类型,以及表示表中一行的记录类型。

属性类型有两种:

1.%TYPE  -  引用变量和数据库列的数据类型

2.%ROWTYPE  -  提供表示表中一行的记录类型

使用属性类型的优点:

1.不需要知道被引用的表列的具体类型

2.如果被引用对象的数据类型发生改变,PL/SQL 变量的数据类型也随之改变

icode itemfile.itemcode%TYPE;
emp_rec scott.emp%ROWTYPE;

逻辑比较

逻辑比较用于比较变量和常量的值,这些表达式称为布尔表达式,布尔表达式由关系运算符与变量或常量组成。


关系运算符


说明


=


比较两个变量是否相等,如果值相当,则返回 True


<>, !=


比较两个变量,如果不相等,则返回 True


<


比较两个变量,检查值 1 是否小于值 2


>


比较两个变量,检查值 1 是否大于 值 2


<=


比较两个变量,检查变量 1 是否小于等于变量 2


>=


比较两个变量,检查变量 1 是否大于等于变量 2

布尔表达式的结果为TRUE、FALSE或NULL,通常由逻辑运算符AND、OR和NOT连接。

布尔表达式有三种类型:

  1.数字布尔型

  2.字符布尔型

  3.日期布尔型

控制结构

PL/SQL 支持的流程控制结构:

  条件控制

    1.IF 语句

    2.CASE 语句

  循环控制

    1.LOOP 循环

    2.WHILE 循环

    3.FOR 循环

  顺序控制

    1.GOTO 语句

    2.NULL 语句

条件控制

DECLARE
    icode VARCHAR2(4);
    irate NUMBER;
BEGIN
    icode := ‘i203‘;
  SELECT itemrate INTO irate FROM itemfile
  WHERE  itemcode = icode;
  IF irate > 200 THEN      --条件判断
    UPDATE itemfile SET itemrate = itemrate - 200
    WHERE itemcode = icode;
  ELSE
    UPDATE itemfile SET itemrate = itemrate - 50
    WHERE itemcode = icode;
  END IF;    --结束
  DBMS_OUTPUT.PUT_LINE(‘itemrate=‘|| irate);
END;

CASE 语句用于根据单个变量或表达式与多个值进行比较,执行 CASE 语句前,先计算选择器的值。

BEGIN
    CASE ‘&grade’
      WHEN ’A’ THEN DBMS_OUTPUT.PUT_LINE(’优异’);
      WHEN ’B’ THEN DBMS_OUTPUT.PUT_LINE (优秀’);
      WHEN ’C’ THEN DBMS_OUTPUT.PUT_LINE (’良好’);
      WHEN ’D’ THEN DBMS_OUTPUT.PUT_LINE (’一般’);
      WHEN ’F’ THEN DBMS_OUTPUT.PUT_LINE (’较差’);
      ELSE DBMS_OUTPUT.PUT_LINE (’没有此成绩’);
    END CASE;
END;

循环控制

循环控制用于重复执行一系列语句。

循环控制语句包括:

  1.LOOP、EXIT 和 EXIT WHEN

循环控制的三种类型:

  1.LOOP   -   无条件循环

LOOP
  sequence_of_statements
END LOOP;

  2.WHILE  -  根据条件循环

WHILE condition LOOP
  sequence_of_statements
END LOOP;

  3.FOR  -  循环固定的次数

FOR counter IN [REVERSE] value1..value2
LOOP
  sequence_of_statements
END LOOP;

loop...exit...when...end loop循环控制

采用loop...exit...when...end loop循环控制的语法结构如下所示:

loop
  循环体;
  exit when循环条件;
end loop

while...loop...end loop循环控制

这种循环控制的语法如下:

while 条件
loop
  执行语句段;
end loop;

循环例子:

--while循环
--循环输出Hello world
declare
    var_i int := 10;
begin
    loop
        dbms_output.put_line(‘Hello world‘);
        if var_i = 0 then
            exit;
        end if;
        var_i := var_i - 1;
    end loop;
end;

--loop输出1-10
declare
    var_i int := 1;
begin
    loop
        dbms_output.put_line(‘i = ‘ || var_i);
        exit when var_i = 10;
        var_i := var_i + 1;
    end loop;
End

--while循环1-5
Declare
    var_i int:=1;
Begin
    while var_i<=10 loop
        Dbms_output.put_line(‘I=‘||var_i);
        Var_i:=var_i+1;
    End loop;
End;

--for 循环 : for 变量 in 范围 loop
--1-10输出
begin
    for i in 1..10 loop
        dbms_output.put_line(‘i = ‘ || i);
    end loop;
end

--对员工的工资判断,如果少于2000则加50,直到工资满足为止!
declare
    var_sal int;
begin
    loop
        select sal into var_sal from emp where empno = 7499;
        exit when var_sal >= 2000;
        update emp set sal = sal + 50 where empno = 7499;
        dbms_output.put_line(‘加50‘);
    end loop;
end;

顺序控制

顺序控制用于按顺序执行语句。

顺序控制语句包括:

  1.GOTO 语句 -  无条件地转到标签指定的语句

  2.NULL 语句 -  什么也不做的空语句

DECLARE
  qtyhand itemfile.qty_hand%type;
  relevel itemfile.re_level%type;
BEGIN
  SELECT qty_hand,re_level INTO qtyhand,relevel
  FROM itemfile WHERE itemcode = ‘i201‘;
  IF qtyhand < relevel THEN
    GOTO updation;  --跳转到<<updation>>语句块
  ELSE
    GOTO quit;  --跳转到<<quit>>
  END IF;
  <<updation>>
  UPDATE itemfile SET qty_hand = qty_hand + re_level
  WHERE itemcode = ‘i201‘;
  <<quit>>
  NULL;
END;

动态 SQL

动态 SQL 是指要执行的SQL语句需要在执行的时候才能确定的SQL语句,是在PL/SQL程序执行时生成的 SQL 语句,编译程序对动态 SQL 不做处理,而是在程序运行时动态构造语句、对语句进行语法分析并执行。DDL 语句命令和会话控制语句不能在 PL/SQL 中直接使用,但是可以通过动态 SQL 来执行。

执行动态 SQL 的语法:

   EXECUTE IMMEDIATE dynamic_sql_string

      [INTO  define_variable_list]

      [USING bind_argument_list];

例:

DECLARE
  sql_stmt VARCHAR2(200);
  emp_id NUMBER(4) := 7566;
  emp_rec emp%ROWTYPE;
BEGIN
    EXECUTE IMMEDIATE
    ‘CREATE TABLE bonus1 (id NUMBER, amt NUMBER)‘;

    sql_stmt := ‘SELECT * FROM emp WHERE empno = :id‘;
    EXECUTE IMMEDIATE sql_stmt INTO emp_rec USING emp_id;
END;
--显示员工编号为7499的所有信息
declare
    Var_row emp%rowtype;
begin
    select * into var_row from emp where empno = 7499;
    dbms_output.put_line(‘编号=‘ || var_row.empno || ‘姓名=‘ || var_row.ename);
end;
--动态执行
declare
    var_row emp%rowtype;
    var_sql varchar(100);
    var_empno int;
begin
    var_sql := ‘select * from emp where empno = :num‘ ;
    execute immediate var_sql into var_row using var_empno;
    dbms_output.put_line(‘编号=‘ || var_row.empno || ‘姓名=‘ || var_row.ename);
end;
--用动态SQL来实现分页
begin
    execute immediate ‘select * from (select rownum rn, d.* from (select * from :tableName order by sal desc) d) where rn > :min and rn <= :max‘ using ‘emp‘ , 1, 5;
End;

错误处理

在运行程序时出现的错误叫做异常,发生异常后,语句将停止执行,控制权转移到 PL/SQL 块的异常处理部分。

异常有两种类型:

1.预定义异常 -  当 PL/SQL 程序违反 Oracle 规则或超越系统限制时隐式引发

2.用户定义异常  -  用户可以在 PL/SQL 块的声明部分定义异常,自定义的异常通过 RAISE 语句显式引发

处理预定义异常

access_into_null   --在未初化对象时出现
case_not_found    --在CASE语句中的选项与用户输入的数据不匹配时出现
collection_is_null    --在给尚未初始化的表或数组赋值时出现
cursor_already_open    --在用户试图打开已经打开的游标时出现
dup_val_on_index    --在用户试图将重复的值存在使用唯一索引的数据库列中时出现
invalid_cursor        --在执行非法游标运算(如打开一个尚未打开的游标)时出现
invalid_number     --在将字符串转换为数字时出现
login_denied        --在输入的用户名或密码无效时出现
no_data_found     --在表中不存在的请求的行时出现,此外,当程序引用已经删除的元素时
storage_error       --在内存损坏或PL/SQL耗尽内存时出现
too_many_rows    --在执行SELECT INTO语句后返回多行时出现
value_error    --在产生大小限制错误时出现
zero_divide    --以零作除数时出现
Others          --针对所有异常

处理用户定义异常

DECLARE
  invalidCATEGORY EXCEPTION;
  category VARCHAR2(10);
BEGIN
  category := ‘&Category‘;
  IF category NOT IN (‘附件‘,‘顶盖‘,‘备件‘) THEN
    RAISE invalidCATEGORY;
  ELSE
    DBMS_OUTPUT.PUT_LINE(‘您输入的类别是‘|| category);
  END IF;
EXCEPTION
  WHEN invalidCATEGORY THEN
    DBMS_OUTPUT.PUT_LINE(‘无法识别该类别‘);
END;

引发应用程序错误

DECLARE
  rate itemfile.itemrate%TYPE;
  rate_exception EXCEPTION;  --定义异常
BEGIN
  SELECT NVL(itemrate,0) INTO rate FROM itemfile
  WHERE  itemcode = ‘i207‘;
  IF rate = 0 THEN
    RAISE rate_exception;  --引发异常
  ELSE
    DBMS_OUTPUT.PUT_LINE(‘项费率为:‘ || rate);
  END IF;
EXCEPTION
  WHEN rate_exception THEN  --扑捉异常
    RAISE_APPLICATION_ERROR(-20001, ‘未指定项费率‘);
END;

引发系统级错误

begin
    if 10 > 5 then
        raise_application_error(-20001, ‘这个是自定义错误显示‘);
    end if;
end; 
时间: 2024-12-19 07:12:40

Oracle学习笔记十 使用PL/SQL的相关文章

Oracle 学习笔记 17 -- 异常处理(PL/SQL)

程序在执行过程中出现异常是正常的,在程序的编写过程中出现异常也是不可避免的.但是要有相应的异常处理的机 制,来保证程序的正常执行.PL/SQL程序执行过程中出现的错误,称为异常.一个优秀的程序都应该能够正确处理 各种出错的情况,并尽可能的从错误中恢复.PL/SQL提供了异常处理机制. 概念: 异常处理(exception)是用来处理正常执行过程中未预料的事件,程序块的异常处理定义的错误和自定义的错误, 由于PL/SQL程序块一旦产生异常而没有指出如何处理时,程序就会异常的终止. 有三种类型的错误

Oracle 学习笔记 16 -- 游标(PL/SQL)

在PL/SQL程序中,对于处理多行记录的事务经常使用游标来实现.当执行查询语句或者数据操纵语句是,一般可能会产生或者处理一组记录.游标是为了处理这些记录而分配的一段内存区. 游标分为:显示游标和隐示游标.当记录集中只有单行数据时,系统自动的进行定义右边,称为隐示游标.记录集中含有多行数据时,需要用户自己定义游标,称为显示游标.下面分别进行介绍. 显示游标 显示游标的处理需四个使用步骤: 1.定义游标: 就是定义一个游标名,以及与其对应的select 语句. 格式: CURSOR cursor_n

Oracle学习笔记(十二)

十三.存储过程和存储函数1.掌握存储过程(相当于建立一个函数或者方法体,然后通过外部对其调用) 指存储在数据库中供所有程序调用的子程序叫做存储过程或存储函数. 相同点: 完成特定功能的程序 区别: 是否用return语句返回值 (1)创建和使用存储过程 用create procedure命令建立存储过程和存储函数 语法: create or replace procedure 过程名(参数列表) as PL/SQL 子程序体(说明部分); 事例: (a)打印一个存储过程:打印HelloWorld

Oracle学习笔记十二 子程序(存储过程、自定函数)和程序包

子程序 子程序:命名的 PL/SQL 块,编译并存储在数据库中. 子程序的各个部分: 1.声明部分 2.可执行部分 3.异常处理部分(可选) 子程序的分类: 1.过程 - 执行某些操作 2.函数 - 执行操作并返回值 子程序的优点: 模块化 将程序分解为逻辑模块 可重用性 可以被任意数目的程序调用 可维护性 简化维护操作 安全性 通过设置权限,使数据更安全 存储过程 过程是用于完成特定任务的子程序. 例如: 一个购票过程可以分为很多个子过程,分别完成. 创建存储过程 创建过程的语法: CREAT

Oracle学习笔记十四 内置程序包

扩展数据库的功能 为 PL/SQL 提供对 SQL 功能的访问 用户 SYS 拥有所有程序包 是公有同义词 可以由任何用户访问 一些内置程序包 程序包名称 说明 STANDARD和DBMS_STANDARD 定义和扩展PL/SQL语言环境 DBMS_LOB 提供对 LOB数据类型进行操作的功能 DBMS_OUTPUT 处理PL/SQL块和子程序输出调试信息 DBMS_RANDOM 提供随机数生成器 DBMS_SQL 允许用户使用动态 SQL DBMS_XMLDOM 用DOM模型读写XML类型的数

Oracle笔记 十、PL/SQL存储过程

--create or replace 创建或替换,如果存在就替换,不存在就创建 create or replace procedure p is cursor c is select * from dept2 for update; begin for row_record in c loop if (row_record.deptno = 30) then update dept2 set dname = substr(dname, 0, length(dname) - 3) where c

Oracle学习笔记(十)

光标(游标)概念引入 就是一个结果集(查询或者其他操作返回的结果是多个时使用)定义一个光标 cursor c1 is select ename from emp: 从光标中取值 打开光标: --open c1;(打开光标执行查询) 关闭光标: --close c1;(关闭游标释放资源)取一行光标的值: --fetch c1 into pename;(取一行到变量中) fetch的作用: --把当前指针指向的记录返回 --将指针指向下一条记录 使用光标查询员工姓名和工资,并打印 declare -

Oracle学习笔记之第八节sql语句(开发课学生指南051)

开发课 做练习 学生指南051 les01 ppt oracle经常两表连接,叫第三范式,如带有ID性质的东西 以下是sql语句的命令 select * from departments; 部门表 select * from employees; 员工表 select employee_id,rowid,rownum from employees where employee_id>=200;  64进制内部运算 rownum本质查询第几行 select employee_id,rowid,ro

Oracle 学习笔记 18 -- 存储函数和存储过程(PL/SQL子程序)

PL/SQL子程序 包括函数和过程.这里的函数指的是用户自己定义的函数,和系统函数是不同的.子程序一般是完成特定功能的PL/SQL程序块,并且具有一定的通用性,可以被不同的应用程序多次调用.Oracle提供可以把PL/SQL程序存储在数据库中,并可以再任何地方来运行它.这样就叫做存储过程或者是函数.过程和函数的唯一区别就是函数总是向调用者返回数据,而过程则不返回数据. 函数 如果用户要经常执行某些操作,并且需要返回特定的数据,那么就可以将这些操作构造成一个函数. 可以使用SQL语句定义函数. 基