zoukankan      html  css  js  c++  java
  • 【Oracle11g】18_PL/SQL基础

    1.PL/SQL简介

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

    2.PL/SQL的优点

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

    • 数据操纵命令
    • 事务控制命令
    • 游标控制
    • SQL 函数和 SQL 运算符

    2)用户把PL/SQL块整个发送到服务器端,oracle服务器端编译、运行,再把结果返回给用户
    3)可移植性,可运行在任何操作系统和平台上的Oralce 数据库
    4)更佳的性能,PL/SQL 经过编译执行
    5)安全性,可以通过存储过程限制用户对数据的访问
    6)与 SQL 紧密集成,简化数据处理。

    • 支持所有 SQL 数据类型
    • 支持 NULL 值
    • 支持 %TYPE 和 %ROWTYPE 属性类型

    3.PL/SQL的体系结构

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

    4.PL/SQL块简介

    1)PL/SQL 块是构成 PL/SQL 程序的基本单元
    2)将逻辑上相关的声明和语句组合在一起
    3)PL/SQL 分为三个部分,声明部分、可执行部分和异常处理部分

       [DECLARE declarations]
       BEGIN
           executable statements
           [EXCEPTION handlers]
       END;
    

    5.变量和常量

    • PL/SQL 块中可以使用变量和常量
      • 在声明部分声明,使用前必须先声明
      • 声明时必须指定数据类型,每行声明一个标识符
      • 在可执行部分的 SQL 语句和过程语句中使用
    • 声明变量和常量的语法:
    identifier [CONSTANT] datatype [NOT NULL]   
    		[:= | DEFAULT expr];
    
    • 给变量赋值有两种方法:
      • 使用赋值语句 :=
      • 使用 SELECT INTO 语句

    实战案例

    -- 建表准备环境
    create table student(id number,name varchar2(40),age number);
    insert into student values(1,'Jack',23);
    insert into student values(2,'Tom',25);
    insert into student values(3,'Alice',30);
    
    -- 查询表记录数的PL/SQL块
    declare 
        total_row number;
    begin
        select count(1) into total_row from student;
        dbms_output.put_line('一共有'|| total_row ||'记录');
    end;
    /
    

    执行PL/SQL块后结果如下图:

    6.PL/SQL数据类型

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

    6.1.1 数字数据类型

    BINARY_INTEGER:存储有符号整数,所需存储空间少于NUMBER类型值
    NUMBER:存储整数、实数和浮点数
    PLS_INTEGER:存储有符号整数,可使算术计算快速而有效

    Oracle11g推出了一个新的数据类型SIMPLE_INTEGER,这种数据类型的取值范围为–2147483 648~+2147483647,数据类型不为空。对于此数据类型,Oracle可以将这个数据类型的操作直接作用于硬件,从而提高性能。

    6.1.2 字符数据类型

    数据类型 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字节

    6.1.3 日期数据类型

    日期时间类型:存储日期和时间数据
    常用的两种日期时间类型

    • DATE
    • TIMESTAMP

    6.1.4 布尔数据类型

    布尔数据类型:此类别只有一种类型,即BOOLEAN类型

    • 用于存储逻辑值(TRUE、FALSE和NULL)
    • 不能向数据库中插入BOOLEAN数据
    • 不能将列值保存到BOOLEAN变量中
    • 只能对BOOLEAN变量执行逻辑操作

    6.1.5 LOB数据类型

    用于存储大文本、图像、视频剪辑和声音剪辑等非结构化数据。
    LOB 数据类型可存储最大 4GB的数据。
    LOB 类型包括:

    • BLOB 将大型二进制对象存储在数据库中
    • CLOB 将大型字符数据存储在数据库中
    • NCLOB 存储大型UNICODE字符数据
    • BFILE 将大型二进制对象存储在操作系统文件中

    LOB 类型的数据库列仅存储定位符,该定位符指向大型对象的存储位置
    DBMS_LOB程序包用于操纵 LOB 数据。

    实战演练:clob

    -- 创建表
    create table testclob(id number primary key,content clob);
    -- 插入数据
    insert into testclob values(1,'道不尽红尘奢恋 诉不完人间恩怨,世世代代都是缘,流着相同的血 喝着相同的水,这条路漫漫又长远,红花当然配绿叶 这一辈子谁来陪,渺渺茫茫来又回,往日情景再浮现 藕虽断了丝还连,,爱江山 更爱美人,哪个英雄好汉宁愿孤单,好儿郎 浑身是胆,壮志豪情四海远名扬,人生短短几个秋啊 不醉不罢休,东边儿我度的美人哪 西边儿黄河流,来呀来个酒啊 不醉不罢休,愁情烦事别放心头。');
    
    -- 查询
    select * from testclob;
    

    查询结果:

    从查询结果我们可以看到,通过普通的select只能查出部分数据。,所以下边使用PL/SQL来获取

    declare 
        clob_var   clob;
        amount     integer;
        offset     integer;
        output_var varchar2(10000);
    begin
        select content into clob_var from testclob where id=1;
        amount := 2000;
        offset := 1;
        dbms_lob.read(clob_var, amount, offset,  output_var);
        dbms_output.put_line(output_var) ;
    end;
    /
    

    运行结果:

    实战演练:blob

    -- 首先在c盘下创建文件夹photo,并且保存一张图片到该目录,例如:a.jpg
    
    -- 创建目录(使用system用户授权)
    grant read, write on directory PHOTO to scott;
    create directory PHOTO as 'c:/photo';
    
    -- 创建表
    create table testblob(id number primary key,photo blob);
    
    -- 创建存储过程
    create or replace procedure insertBlob(id varchar2, imgFile varchar2)
    is
        img_file bfile;
        img_blob blob;
        lob_length number;
    begin
        -- 先插入一个空值
        insert into testblob values(id, empty_blob() );
        select photo into img_blob from testblob where id = id;
    
        -- 读取img_file中的内容
        img_file := bfilename('PHOTO', imgFile);
        dbms_lob.open(img_file);
        lob_length := dbms_lob.getlength(img_file);
    
        -- 修改表中列photo的内容
        dbms_lob.loadfromfile(img_blob, img_file, lob_length);
        dbms_lob.close(img_file);
    end;
    /
    

    执行该存储过程

    exec insertBlob(1,'a.jpg');
    

    查询结果,发现已经保存成功

    7.属性类型

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

    属性类型有两种:

    • %TYPE - 引用变量和数据库列的数据类型
    • %ROWTYPE - 提供表示表中一行的记录类型

    使用属性类型的优点:

    • 不需要知道被引用的表列的具体类型
    • 如果被引用对象的数据类型发生改变,PL/SQL 变量的数据类型也随之改变,健壮性。

    8.PL/SQL块中取序列的值

    -- 创建序列
    create sequence seq1 start with 1 increment by 1;
    
    -- 取值的PL/SQL块
    SQL> set serveroutput on -- 设置允许显示输出类似dbms_output
    
    declare
        num int;
    begin
        num := seq1.nextval; -- 11g新特性
        -- 11g之前:select seq1.nextval into num from dual;
        dbms_output.put_line('num的值是:' || num);
    end;
    /
    

    9.逻辑比较

    逻辑比较用于比较变量和常量的值,这些表达式称为布尔表达式
    布尔表达式由关系运算符与变量或常量组成
    布尔表达式的结果为TRUE、FALSE或NULL,通常由逻辑运算符AND、OR和NOT连接
    布尔表达式有三种类型:

    • 数字布尔型
    • 字符布尔型
    • 日期布尔型

    10.控制结构

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

    • 条件控制
      • IF 语句
      • CASE 语句
    • 循环控制
      • LOOP 循环
      • WHILE 循环
      • FOR 循环
    • 顺序控制
      • GOTO 语句
      • NULL 语句

    10.1 IF语句

    IF 语句根据条件执行一系列语句,有三种形式:IF-THEN、IF-THEN-ELSE 和 IF-THEN-ELSIF

    案例:

    -- 建表并插入数据
    create table t1(id number,name varchar2(10),age number);
    insert into t1 values(1,'Jack',19);
    insert into t1 values(2,'Tom',22);
    insert into t1 values(3,'Alice',11);
    commit;
    
    -----PL/SQ块:判断Jack的年龄是否大于18岁
    SQL> set serveroutput on -- 设置允许显示输出类似dbms_output
    declare
        v_age t1.age%type;
    begin
        select age into v_age from t1 where id=1;
        if v_age > 18 then
            dbms_output.put_line('Jack的年龄大于18岁');
        else
            dbms_output.put_line('Jack的年龄小于等于18岁');
        end if;
    end;
    /
    
    

    10.2 CASE语句

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

    案例

    --&grade表示从键盘输入值赋给变量grade
    declare 
        outgrade varchar2(20);
    begin
        outgrade := CASE &grade 
            WHEN 'A' THEN '优秀'
            WHEN 'B' THEN '良好'
            WHEN 'C' THEN '中等'
            WHEN 'D' THEN '及格'
            WHEN 'E' THEN '不及格'
            ELSE '没有此成绩'
        END;
        dbms_output.put_line(outgrade );
    end;    
    /    
    

    执行结果:

    10.3 循环控制

    循环控制用于重复执行一系列语句
    循环控制语句包括:

    • LOOP、EXIT 和 EXIT WHEN 、FOR 、WHILE

    循环控制的三种类型:

    • LOOP - 无条件循环
    • WHILE - 根据条件循环
    • FOR - 循环固定的次数
    -- LOOP循环
    LOOP 
      sequence_of_statements
    END LOOP;
    
    -- WHILE循环
    WHILE condition LOOP 
      sequence_of_statements
    END LOOP;
    
    -- FOR循环
    FOR counter IN [REVERSE] value1..value2
    LOOP 
      sequence_of_statements
    END LOOP;
    
    

    实战演练:按要求打印1~8的数字

    -- LOOP实现
    declare
        num number := 0;
    begin
        num := 1;
        loop
            dbms_output.put_line(num || '******');
            exit when num > 7;
            num := num + 1;
        end loop;
        dbms_output.put_line( '结束');
    end;
    /
    
    -- WHILE实现
    declare
        num number := 0;
    begin
        num := 1;
        while num <=8
        loop
            dbms_output.put_line(num || '******');
            num := num + 1;
        end loop;
        dbms_output.put_line( '结束');
    end;
    /
    
    -- FOR实现
    
    begin
        for num in 1..8
        loop
            dbms_output.put_line(num || '******');
        end loop;
        dbms_output.put_line( '结束');
    end;
    /
    

    10.4 continue语句

    continue表示本次循环结束,下次循序继续
    实战演练

    declare
        num number := 0;
    begin
        num := 1;
        loop
            num := num + 1;
            exit when num > 8;
            continue when num > 4;
            dbms_output.put_line(num || '******');     
        end loop;
        dbms_output.put_line( '结束');
    end;
    /
    

    执行结果:
    2******
    3******
    4******
    结束

    10.5 goto语句

    顺序控制用于按顺序执行语句
    顺序控制语句包括:

    • GOTO 语句 - 无条件地转到标签指定的语句
    • NULL 语句 - 什么也不做的空语句

    实战演练:按要求打印1~8

    -- null表示什么都不做,CPU停一下
    declare
        num number := 0;
    begin
        num := 1;
        <<aa>>
            dbms_output.put_line(num || '******');     
            num := num+1;
            if num <= 8 then goto aa;end if;
            if num > 8 then goto bb;end if;
        <<bb>> null;
        dbms_output.put_line( '结束');
    end;
    /
    

    11.动态SQL

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

    EXECUTE IMMEDIATE dynamic_sql_string
          [INTO  define_variable_list]
          [USING bind_argument_list];
    

    实战演练

    begin
        execute immediate 'create table t2(id number)';
    end;
    /
    

    12.错误处理

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

    • 预定义异常 - 当 PL/SQL 程序违反 Oracle 规则或超越系统限制时隐式引发。
    • 用户定义异常 - 用户可以在 PL/SQL 块的声明部分定义异常,自定义的异常通过 RAISE 语句显式引发。

    12.1 预定义异常

    实战演练:预定义异常

    declare 
        v_name t1.name%type;
    begin
        select name into v_name from t1 where id=99;
        dbms_output.put_line(v_name);
    exception
        when no_data_found then
           dbms_output.put_line('没有这个人的信息存在!'); 
    end;
    /
    

    12.2 用户定义异常

    实战演练:用户定义异常

    -- 往表t1插入记录
    insert into t1 values(4,'Lucy',-12);
    
    SQL> select * from t1;
    
            ID NAME              AGE
    ---------- ---------- ----------
             1 Jack               19
             2 Tom                22
             3 Alice              11
             4 Lucy              -12
    
    -- 此时Lucy的年龄是异常的,在PL/SQL块做异常处理
    declare
        v_age t1.age%type;
        invalid_age exception;
    begin
        select age into v_age from t1 where id=4;
        if v_age < 0 then
            raise invalid_age ;
        else
            dbms_output.put_line('年龄正常');
        end if;
    exception
        when invalid_age then
            dbms_output.put_line('年龄错粗了,怎么可能是负数?');
    end;
    /
    

    13.引发应用程序错误

    RAISE_APPLICATION_ERROR 过程

    • 用于创建用户定义的错误信息
    • 可以在可执行部分和异常处理部分使用
    • 错误编号必须介于 –20000 和 –20999 之间
    • 错误消息的长度可长达 2048 个字节

    引发应用程序错误的语法:

    RAISE_APPLICATION_ERROR(error_number, error_message);
    

    实战演练

    declare
        v_age t1.age%type;
        invalid_age exception;
    begin
        select age into v_age from t1 where id=4;
        if v_age < 0 then
            raise invalid_age ;
        else
            dbms_output.put_line('年龄正常');
        end if;
    exception
        when invalid_age then
            dbms_output.put_line('年龄错粗了,怎么可能是负数?');
            RAISE_APPLICATION_ERROR(-20996, '年龄异常');
    end;
    /
    

  • 相关阅读:
    Web API 强势入门指南
    毫秒必争,前端网页性能最佳实践
    Windbg Extension NetExt 使用指南 【3】 ---- 挖掘你想要的数据 Managed Heap
    Windbg Extension NetExt 使用指南 【2】 ---- NetExt 的基本命令介绍
    Windbg Extension NetExt 使用指南 【1】 ---- NetExt 介绍
    WCF : 修复 Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service 问题
    透过WinDBG的视角看String
    Microsoft Azure Web Sites应用与实践【4】—— Microsoft Azure网站的“后门”
    企业IT管理员IE11升级指南【17】—— F12 开发者工具
    WCF : 如何将NetTcpBinding寄宿在IIS7上
  • 原文地址:https://www.cnblogs.com/OliverQin/p/12771415.html
Copyright © 2011-2022 走看看