一、PL/SQL介绍

  1、概念

  PL/SQL也是一种程序语言,叫做过程化SQL语言(Procedural Language/SQL)。PL/SQL是Oracle数据库对SQL语句的扩展。在普通SQL语句的使用上增加了编程语言的特点,所以PL/SQL可以用来编写存储过程、存储函数、触发器等等。 PL/SQL是结构化SQL,就是在标准SQL中加入了IF...ELSE... For....等控制过程的SQL。

  2、学习必要性

  • 提高程序的运行性能
    传统的使用程序操作数据库的方式需要获得connection,然后程序传到数据库后还需要进行编译才能执行,而且执行结果还需要回调,这些过程都需要花费时间。而PL/SQL编程可以直接进行过程编程,这就节省了数据连接、语句传送和编译的时间,同时编程结果可以被外部程序调用。
  • 模块化的设计思想
    很多复杂的过程都需要传送和执行大量的sql语句,比如分页的过程、实现订单的过程、转账的过程等等,这些过程就可以通过PL/SQL进行模块化整理进而方便管理。
  • 减少网络传输量
  • 提高安全性

  PL/SQL的缺点在于移植性不好,如果项目不再使用Oracle来管理数据,那么需要重新编写语句。

二、开发工具

  1、Oracle自带的命令行工具sql*plus

  下面举一个运用PL/SQL语句的案列:编写一个存储过程,并执行。

  简单说一下,存储过程(Stored Procedure)的概念:在大型数据库系统中,一组为了完成特定功能的SQL语句集,存储在数据库中,经过一次编译后不需要再进行二次编译,用户直接通过指定该过程的名字,如果有参数并给出参数来执行它。类似编程里的函数的功能。

  • --1、创建一个表
    create table test(name varchar2(10),password varchar2(20));
    --2、创建一个存储过程
    create procedure proc1 is
    begin--开始
    insert into test values('tom','tom123');--执行过程
    end;--结束
    /--创建标志
    (注意:存储过程的命名需要唯一,如果重复需要更换一个名字或使用replace命令来替代已存在的存储过程)
    --3、调用过程
    exec 过程名(参数1,参数2...);(execute执行的缩写)
    call 过程名(参数1,参数2...);

    这只是存储过程使用的一个最基本案列,先简单体验一下。

  2、非官方工具:PL/SQL Developer

  我们首先要安装PL/SQL Developer工具,安装成功并配置相关文件后就可以使用了。使用同上面一样的案例(这里只是简单演示,后面会重点使用)

  

三、块(Block)

  块是PL/SQL的基本程序单元,编写PL/SQL其实就是编写PL/SQL块。一个块可以实现一个简单的功能,而复杂的功能可能需要在一个块中嵌套其他若干块。(感觉很像一个函数段)

  1、块的组成

  pl/sql 块由一般由三个部分构成:定义部分,执行部分,例外处理部分。

  • declare
    /*[可选]定义部分——定义常量、变量、游标、例外、复杂数据类型*/
    begin
    /*[必须]执行部分——要执行的pl/sql语句和sql语句*/
    exception
    /*[可选]例外处理部分——处理运行的各种错误*/
    end;

  注:定义部分是从declare开始的,该部分是可选的; 执行部分是从begin开始的,该部分是必须的; 例外处理部分是从exception开始的,该部分是可选的。

  2、PL/SQL的编写内容

  

  PL/SQL可以编写的主要内容有(注:Oracle中的数据对象包括:索引、表、视图、函数、包、过程、同义词、序列、触发器):

  • 过程(存储过程)
  • 函数
  • 触发器

  3、编写规范

  1. 注释

    --这是单行注释
    /*
    这是多行注释
    */
  2. 命名规范
    --变量命名规范:以v_作为前缀
    v_variable
    --常量命名规范:以c_作为前缀
    c_constant
    --游标命名规范:以_cursor作为后缀
    emp_cursor
    --例外命名规范:以e_作为前缀
    e_error

  4、pl/sql块示例

  • --示例1:只包括执行部分
    set serveroutput on --打开输出选项
    begin
    dbms_output.put_line('hello');
    end;
    --说明: dbms_output是oracle提供的包,类似Java的包,包中有若干过程,如put_line就是该包的过程,可以输出指定参数。
  • --示例2:包含定义部分和执行部分的pl/sql块
    declare
    v_ename varchar2(5); --定义字符串变量
    begin
    select ename into v_ename from emp where empno=&empno;
    dbms_output.put_line('雇员名:'||v_ename);
    end;
    --说明:into表示将查询的结果赋给变量v_ename;&表示需要从控制台输入变量;||表示字符串拼接,也可以使用concat函数来拼接。
  • 为了避免pl/sql程序的运行错误,提高pl/sql的健壮性,应该对可能的错误进行处理,这个很有必要。比如在实例2中,如果输入了不存在的雇员号,应当做例外处理。有时出现异常,希望用另外的逻辑处理。oracle事先预定义了一些例外,no_data_found就是找不到数据的例外。
    --示例3:包含declare、begin、exception三部分
    declare
    --定义变量
    v_ename varchar2(5);
    v_sal number(7,2);
    begin
    --执行部分
    select ename,sal into v_ename,v_sal from emp where empno=&empno;
    --在控制台显示用户名
    dbms_output.put_line('用户名是:'||v_ename||' 工资:'||v_sal);
    --异常处理
    exception
    when no_data_found then
    dbms_output.put_line('你的编号输入不符合规则!');
    end;
    /

四、过程(Procedure)

  1、概念

  存储过程(Stored Procedure)的概念:在大型数据库系统中,一组为了完成特定功能的SQL语句集,存储在数据库中,经过一次编译后不需要再进行二次编译,用户直接通过指定该过程的名字,如果有参数并给出参数来执行它。类似编程里的函数的功能,但是有区别,因为Oracle本身也具有函数。过程可以指定输入参数(in)将执行环境需要的数据传入,也可以指定输出数据(out)将执行环境中的数据导出到应用环境中。类似函数的参数和返回值。

  2、示例

  • --创建一个过程:为指定员工增加指定工资
    create or replace procedure pro_AddSal(v_ename varchar2,v_addsal number) is
    begin
    update emp set sal=sal+v_addsal where ename=v_ename;
    end;
    /
    --调用过程:为SCOTT增加1000元工资
    exec pro_AddSal('SCOTT',1000);

    我们可以也使用外部程序例如Java程序来执行:

     1 public static void main(String[] args){
    2 try{
    3 //1、使用jdbc加载驱动
    4 Class.forName("oracle.jdbc.driver.JdbcDriver");
    5 //2、获得连接
    6 Connection conn = DriverManager.getConnection("jdbc:oracle:thin:@192.168.183.1:1521:orcl","Scott","tiger");
    7 //3、创建存储过程的调用对象:CallableStatement
    8 CallableStatement cs = conn.prepareCall("{call pro_AddSal(?,?)}");
    9 //4、传入参数
    10 cs.setString(1,"SMITH");
    11 cs.setInt(2,500);
    12 //5、执行
    13 cs.excute();
    14 //6、关闭资源
    15 cs.close();
    16 conn.close();
    17 }catch(Exception e){
    18 e.printStackTrace();
    19 }
    20 }

五、函数(Function)

  1、概念

  函数用于返回特定的数据。当建立函数时,在函数头部必须包含return子句,而在函数体内必须包含return语句返回的数据。使用create function来建立函数。

  2、示例

  • --函数示例:输入雇员的姓名,返回该雇员的年薪
    --函数头:定义
    create function fun_showYearSal(v_ename varchar2)
    return number
    is yearSal number(7,2);
    begin
    --函数体:执行
    select sal*12+nvl(comm,0)*12 into yearSal from emp where ename=v_ename;
    return yearSal;
    end;
  • --调用函数
    var yearSal number;--定义一个变量用来接收返回值
    call fun_showYearSal('SCOTT') into:yearSal;--调用函数
    print yearSal;--显示返回值

六、包(Package)

  1、概念

  用于在逻辑上组合过程和函数。由包规范和包体两部分组成。使用create package命令来创建包。

  2、示例

  • --创建包Create Package
    --包规范:起到声明作用
    create package myPackage is
    procedure update_sal(name varchar2,newsal number);--过程
    function annual_income(name varchar2) return number;--函数
    end;
    /
  • --实现包体:create package body
    create or replace package body myPackage is
    --实现过程
    procedure update_sal(name varchar2,newsal number) is
    begin
    update emp set sal=newSal where ename=name;
    end;
    --实现函数
    function annual_income(name varchar2)
    return number
    is annual_salary number(7,2);
    begin
    select sal*12+nvl(comm,0) into annual_salary from emp where ename=name;
    return annual_salary;
    end;
    end;
    /
  • --调用包下的一个过程:call或exec
    call myPackage.update_sal('SCOTT',1500);

七、触发器(Trigger)

  触发器是在事件发生时隐式地自动运行的PL/SQL程序块,不能接收参数,不能被调用。当定义触发器时,必须指定触发的事件和触发的操作

  常用的触发事件包括:insert,update,delete语句。触发操作实际就是一个pl/sql块。可以使用create trigger来建立触发器。说明:触发器可以维护数据库的安全和一致性。

  触发器是很有用的数据对象,这里先简单了解。

八、变量

  1、类型

  • 标量类型(scalar)
  • 复合类型(composite)
  • 参照类型(reference)
  • lob(large object)

  2、标量类型(scalar)

  标量的定义:亦称“无向量”。有些物理量,只具有数值大小,而没有方向,部分有正负之分。物理学中,标量(或作纯量)指在坐标变换下保持不变的物理量。用通俗的说法,标量是只有大小,没有方向的量。

  1)语法

  • identifier:名称
  • constant:常量。需要制定初始值,而且不能够改变。
  • datatype:数据类型
  • not null:指定变量非空
  • : =    给变量或是常量指定初始值
  • default:指定初始值
  • expr:指定初始值的pl/sql表达式,可是文本值、其他变量、函数等

  2)案例

  • --定义一个变长字符串
    v_ename varchar2(10);
    --定义一个小数,范围-9999.99~9999.99
    v_sal number(6,2);
    --定义一个小树,并赋初始值为5.4
    v_sal2 number(6,2):=5.4;
    --定义一个日期类型的数据
    v_hiredate date;
    --定义一个布尔变量,不能为空,初始值为false;
    v_valid boolean not null default false;

  3)使用

  • --输入员工号,显示雇员姓名、工资、个人所得税(税率为0.03)
    declare
    c_tax_rate number(3,2):=0.03;--税率
    v_ename varchar2(5);--用户名
    v_sal number(7,2);--工资
    v_tax_sal number(7,2);--所得税
    begin
    --执行部分
    select ename,sal into v_ename,v_sal from emp where empno=&no;
    --计算所得税
    v_tax_sal:=v_sal*c_tax_rate;
    --输出
    dbms_output.put_line('姓名:'||v_ename||',工资:'||v_sal||',个人所得税为:'||v_tax_sal);
    end;
    /

  4)使用%type类型

  对于上面的pl/sql块:如果员工的姓名超过了5字符的话,就会有错误。为了降低pl/sql程序的维护工作量,可以使用%type属性定义变量。这样,可以按照数据库列来确定定义的变量的类型和长度。

  • --语法
    标识符名 表名.列名%type;
    --如
    v_ename varchar2(5); --用户名(上面的写法)
    v_ename emp.ename%type; --用户名(改进的写法)

  3、复合变量(composite)

  复合变量是用于存放多个值的变量。

  1)类型

  • pl/sql记录
  • pl/sql表
  • 嵌套表
  • varray(动态表)

   2)pl/sql记录

  相当于高级语言中的结构体、类

  注意:当引用pl/sql记录成员时,必须要加记录变量作为前缀(记录变量.记录成员)。

  • --pl/sql记录实例
    declare
    --定义一个pl/sql记录类型emp_record_type,类型包含三个数据name,salary,title
    type emp_record_type is record(
    name emp.ename%type,
    salary emp.sal%type,
    title emp.job%type);
    --定义了一个变量 sp_record ,类型是emp_record_type
    sp_record emp_record_type;
    begin
    select ename,sal,job into sp_record from emp where empno=7788;
    dbms_output.put_line('员工名:'||sp_record.name||',工资是:'||sp_record.salary||',工作是:'||sp_record.title);
    end;
    /

  3)pl/sql表

  相当于高级语言中的数组。注意:在高级语言中数组的下标不能为负数,而pl/sql的下标是可以为负数的,并且表元素的下标没有限制。

  • --pl/sql表实例
    declare
    --定义了一个pl/sql表类型sp_table_type,该类型是用于存放emp.ename%type
    --index by binary_integer表示下标为整数
    type sp_table_type is table of emp.ename%type index by binary_integer;
    --定义了变量sp_table,类型是sp_table_type
    sp_table sp_table_type;
    begin
    select ename into sp_table(0) from emp where empno=7788;
    dbms_output.put_line('员工名'||sp_table(0));
    end;
    /

  注:sp_table_type是pl/sql表类型;emp.ename%type制定了表的元素的类型和长度;sp_table为pl/sql表变量;sp_table(0)表示下表为0的元素。如果去掉where条件:

  • --pl/sql表实例
    declare
    --定义了一个pl/sql表类型sp_table_type,该类型是用于存放emp.ename%type
    --index by binary_integer表示下标为整数
    type sp_table_type is table of emp.ename%type index by binary_integer;
    --定义了变量sp_table,类型是sp_table_type
    sp_table sp_table_type;
    begin
    select ename into sp_table(0) from emp;
    dbms_output.put_line('员工名'||sp_table(0));
    end;
    /

  4、参照变量

  1)概念

  参照变量是用于存放数值指针的变量。是应用程序共享相同对象,从而降低占用的空间。分为:游标变量(ref cursor)和对象类型变量(ref obj_type)。

  2)游标变量(ref cursor)

  定义游标时,不需要指定相应的select语句。使用游标(open)时,需要制定select语句。

  实例:使用pl/sql编写一个块,可以输入部门号,并显示该部门所有员工姓名和工资。

  • --使用pl/sql编写一个块,可以输入部门号,并显示该部门所有员工姓名和工资。
    declare
    --定义游标类型
    type sp_emp_cursor is ref cursor;
    --定义一个游标变量
    test_cursor sp_emp_cursor;
    --定义变量
    v_ename emp.ename%type;
    v_sal emp.sal%type;
    begin
    --执行
    --把test_cursor和一个select结合
    open test_cursor for select ename,sal from emp where deptno=&no;
    --循环取出
    loop
    fetch test_cursor into v_ename,v_sal;
    --判断是否test_cursor为空
    exit when test_cursor%notfound;
    dbms_output.put_line('姓名:'||v_ename||',薪水:'||v_sal);
    end loop;
    end;
    /

    在上面的基础上,如果某个员工的工资低于200元,则增加100元。

  • --使用pl/sql编写一个块,可以输入部门号,并显示该部门所有员工姓名和工资。
    declare
    --定义游标类型
    type sp_emp_cursor is ref cursor;
    --定义一个游标变量
    test_cursor sp_emp_cursor;
    --定义变量
    v_ename emp.ename%type;
    v_sal emp.sal%type;
    begin
    --执行
    --把test_cursor和一个select结合
    open test_cursor for select ename,sal from emp where deptno=&no;
    --循环取出
    loop
    fetch test_cursor into v_ename,v_sal;
    --判断工资高低,决定是否更新
    if v_sal<200 then
    update emp set sal=sal+100 where ename=v_ename;
    end if;
    fetch test_cursor into v_ename,v_sal;
    --判断是否test_cursor为空
    exit when test_cursor%notfound;
    dbms_output.put_line('姓名:'||v_ename||',薪水:'||v_sal);
    end loop;
    end;
    /

Oracle实战笔记(第六天)之PL/SQL基础的更多相关文章

  1. Oracle学习笔记十 使用PL/SQL

    PL/SQL 简介 PL/SQL 是过程语言(Procedural Language)与结构化查询语言(SQL)结合而成的编程语言,是对 SQL 的扩展,它支持多种数据类型,如大对象和集合类型,可使用 ...

  2. oracle学习笔记4:PL/SQL

    PL/SQL是没命名的存储过程,函数,触发器,PL/SQL块的语法格式如下: [declare] --声明部分,可选 begin --执行部分,必须 [exception] --异常处理部分,可选 e ...

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

    程序异常是在操作期间正常,出现在节目的准备过程是不可避免的例外.但是,必须有一个相应的异常处理机 制,以保证程序的正常运行.PL/SQL程序运行过程中出现的错误.称为异常. 一个优秀的程序都应该可以正 ...

  4. oracle学习(二)pl/sql基础

    pl/sql组成:DDL DML DCL pl/sql特点: SQL&PL/SQL编译器集成PL/SQL,支持SQL所有范围的语法 支持CASE语句和表达式 继承和动态方法释放 类型进化.属性 ...

  5. Oracle实战笔记(第七天)之PL/SQL进阶

    一.控制结构 控制结构包括:判断语句(条件分支语句).循环语句.顺序控制语句三种. 1.条件分支语句 if--then:简单条件判断 --编写一个过程,可以输入一个雇员名,如果该雇员名的工资低于200 ...

  6. ORACLE PATCH 版本的查询 PL/SQL

    --ORACLE PATCH 版本的查询 PL/SQL SELECT DD.PATCH_NAME,        PP.CREATION_DATE,        PP.DRIVER_FILE_NAM ...

  7. 慕课网笔记之oracle开发利器-PL/SQL基础

    实例1--if语句 /* 慕课网Oracle数据库开发必备之PL/SQL_2-3 判断用户从键盘输入的数字 1.如何使用if语句 2.接收一个键盘的输入(字符串) */ set serveroutpu ...

  8. Oracle数据库之PL/SQL基础

    介绍PL/SQL之前,先介绍一个图像化工具:Oracle SQL Developer 在oracle的开发过程中, 我们难免会使用第三方开发的软件来辅助我们书写SQL, pl/sql是一个不错的sql ...

  9. PL/SQL基础2(笔记)

    1 第一个PL/SQL的程序 DECLARE BEGIN DBMS_OUTPUT.PUT_LINE('Hello World!'); END; / --2一个简单的PL/SQL程序 DECLARE v ...

随机推荐

  1. while100以内的偶数

    #显示100以内的偶数 #声明i i = 1 #开始循环条件为i不等于100,执行while代码块 while i != 100: #给i加1 i +=1 #如果循环到此时i的取余运算为0则打印i i ...

  2. MySQL 5.7 InnoDB缓冲池NUMA功能支持——但是别高兴的太早

    当前CPU都已是NUMA架构,相信除了历史遗留系统,很少会有数据库跑在SMP的CPU上了.NUMA架构带来的优势无言而语,CPU更快的内存访问速度,但是带来的问题也不言而喻,特别是对于数据库的影响.M ...

  3. Mycat 配置

    前言 Mycat 是一个数据库分库分表中间件 MyCAT 是作为通用代理设计的,后端是以 Mysql协议 和 JDBC 的方式连接数据库,可以支持 Oracle.DB2.SQL Server . mo ...

  4. selenium之 驱动环境配置chrome、firefox、IE

    讲起动态网页获取我们一定会用到selenium,至于selenium在各种语言的开发代码很多,但是在我们兴致勃勃找了很多代码,要运行的时候,编译器只会给我们抛出异常,因为我们没有配置好环境.下面我将为 ...

  5. 使用 GStreamer appsrc 等插件实现视频音频混流,录制和推流

    目前在做的在线直播教室,需要将老师分享的屏幕和老师的声音.学生的声音录制为一个视频文件,以便学生上课后还可以再看回放. 直播服务我们采用的是腾讯的视频服务,有现成的 SDK 可以用.但 SDK 自带的 ...

  6. Java入门篇(二)——Java语言基础(下)

    上篇说到Java中的变量与常量,接下来就是简单的计算了,首先需要了解一下Java中的运算符. 六.运算符 1. 赋值运算符 赋值运算符即"=",是一个二元运算符(即对两个操作数进行 ...

  7. BZOJ 2463: [中山市选2009]谁能赢呢?(新生必做的水题)

    2463: [中山市选2009]谁能赢呢? Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2372  Solved: 1750[Submit][Sta ...

  8. [bzoj1594] [Usaco2008 Jan]猜数游戏

    二分答案(二分没冲突的前Q-1个问题),用并查集判定(用法同bzoj 1576) 假设一个询问区间[l,r],最小干草堆数目是A,我们可以得出[l,r]上的干草堆数目都>=A. 二分出mid后, ...

  9. 电铸3D18K硬金 电铸易熔合金 电铸中空硬金饰品合金

        俊霖电铸3DK金易熔合金是要求相互关连,互为条件,缺一不可,是产品完整性和完美性的重要体现.    第一.适用性:电铸3DK金易熔合金的性能应适用于电铸.首饰.K金饰品.摆件等工艺品的易熔合金 ...

  10. mysql按照天统计报表,当天没有数据,填0

    1.问题复现: 按照天数统计每天的总数,如果其中有几天没有数据,那么group by 返回会忽略那几天,如何填充0?如下图,统计的10-3~10-10 7天的数据,其中只有8号和10号有数据,这样返回 ...