pl/sql编程基础知识篇

一、什么是pl/sql

pl/sql(procedural language/sql)是Oracle在标准的sql语言上的扩展,pl/sql不仅允许嵌入Sql语言,还可以定义变量和常量,允许使用条件语句和循环语句,允许使用例外处理各种错误,这样使得它的功能变得更加强大。

二、pl/sql学习的必要性

1、提高应用程序的运行性能。

2、模块化的设计思想。

3、减少网络传输量。

4、提高安全性。

解释:传统方法中每执行一个sql命令,都要传给数据库一次,然后数据库再编译,效率不高,相反程序中直接调用pl/sql模块,那么就会减少数据库的编译次数,所以也就能够提高程序运行效能.

三.缺点

  1. 移植性很差

四.简单分类

pl/sql编程基础知识篇_第1张图片
1. 所谓的块(block)是pl/sql的基本程序单元,编写pl/sql程序实际上就是写pl/sql块,要完成相对简单的应用功能,可以只编写一个pl/sql块或者多个块嵌套使用.
2. 块结构

declear(可选)
/*定义部分,定义常量,变量,游标,例外,复杂数据类型*/
begin(必须有)
/*执行部分,要执行的pl/sql语句或者sql语句 */
exception(可选)
/*例外处理部分,运行出错的解决方案 */

3.编程风格
(1).注释 –
eg: select * from emp;–取得emp表信息
多行注释用 /* …*/
(2).标识符号命名规范
1)当定义变量用v_作为前缀v_sal
2)定义常量用c_作为前缀c_rate
3)定义游标用_cursor作为后缀 emp_cursor
4)定义例外用e作为前缀e_error

五.简单案例

这里用oecale给建立的scott用户为例

--最简单的块
set serveroutput on;--打开输出选项
begin dbms_output.put_line('hello');
end;
---带声明的块
declare
    v_ename varchar2(5);--定义变量
    v_sal number(7,1);--定义变量
begin select ename,sal into v_ename,v_sal from emp where empno=&aa;--这个是输入的名字
   dbms_output.put_line('用户名'||v_ename||'工资'||v_sal);
 --异常处理
 exception
   when no_data_found then
     dbms_output.put_line('输入错误');
end;

pl/sql编程基础知识篇_第2张图片

--修改员工工资
create or replace procedure sp_prol(spname varchar2,spsal number) is --执行模块 begin UPDATE emp SET emp.sal=spsal WHERE emp.ename=spname ; 
   end;

pl/sql编程基础知识篇_第3张图片

六.java连接执行pl/sql

说明:这里主要用到CallableStatement类型变量,其他的和以前的jdbc没什么区别

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;

public class OracleTest {

    public static void main(String[] args){
        Connection ct = null;
        CallableStatement call = null;
        try {
            //加载驱动
            Class.forName("oracle.jdbc.driver.OracleDriver");
            //得到链接
            ct = DriverManager.getConnection("jdbc:oracle:thin:@127.0.0.1:1521:orcl", "SCOTT", "123456");
            //创建CallableStatemet
            call = ct.prepareCall("{call sp_prol(?,?)}");
            //给问号赋值
            call.setString(1, "SMITH");
            call.setInt(2, 500);
            //执行程序
            call.execute();
            System.out.println("执行完毕");
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        } catch (SQLException e) {
            e.printStackTrace();
        }finally{
            //关闭数据库资源
                try {
                    if(call!=null) call.close();
                    if(ct!=null) ct.close();
                } catch (SQLException e) {
                    e.printStackTrace();
                }
        }

    }

}

七.函数块

1.函数用于返回特定的数据,当建立函数时,在函数头部必须包含return子句,而在函数体必须包含return返回的数据,
2.EG:

--函数案例
--输入雇员姓名,返回雇员年薪
create or replace function sp_fun1(spname varchar2) return number is spyearsal number(7,2) ;
begin --执行部分 select sal*12+nvl(comm,0)*12 into spyearsal from emp where ename=spname;
  return spyearsal;
  end;

pl/sql编程基础知识篇_第4张图片
3.调用过程
1)在sql plus中调用

sql>var abc number--声明变量接收数据
    sql>call sp_fun1('SMITH') into abc;

2)在java中调用
select sp_fun1(‘SMITH’) from emp;
通过rs.getInt()取出数据即可

八,包的定义和包体的创建

包是逻辑上组合过程和函数,由包规范和包体两个部分组成
下面创建包

--创建包案例
create package sp_pac1 is 
--声明过程
  procedure update_sal(name varchar2,newsal number);
  --声明函数
  function annual_income (name varchar2) return number;
  end;

下面创建包体

--包体里面写具体的代码
--给sp_pac1实现包体
create or replace package body sp_pac1 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_sal number;
  begin select sal*12+nvl(comm,0)*12 into annual_sal from emp where ename=name;
    return annual_sal;
    end;
    end;

调用过程

sql>call sp_pac1.update_sal('SMITH',1500);

九.标量类型,复合类型,游标类型

标量类型就相当于普通变量
复合类型相当于高级语言中的数组
参照类型相当于一个指向select结果的指针

--输入员工号,显示雇员姓名,工资,个人所得税
--(税率0.03),说明变量使用
declare
c_tax_rate number(3,2):=0.03;--定义税率常量
--用户名
v_name emp.ename%type;--使字符大小和ename大小一样
v_sal emp.sal%type;
v_tax_sal number(7,2);
begin --执行 SELECT e.ename,e.sal into v_name,v_sal FROM emp e WHERE e.empno=&aa;
  --计算所得税
    v_tax_sal:=v_sal*c_tax_rate;
  --输出
    dbms_output.put_line('姓名'||v_name
                         ||'工资'||v_sal
                         ||'所得税'||v_tax_sal);
  end;

pl/sql编程基础知识篇_第5张图片

 --复合变量的创建
 declare
 --定义复合变量
 type emp_record_type is record (
 ename emp.ename%type,
 sal emp.sal%type,
 job emp.job%type);
 --创建复合变量
 record1 emp_record_type ;
 begin
   --执行过程
 SELECT e.ename,e.sal,e.job into record1 
 FROM emp e 
 WHERE empno=7499;
 dbms_output.put_line('员工姓名'||record1.ename);
 end;

pl/sql编程基础知识篇_第6张图片

--pl/sql表的实例
 declare
 ---定义一个存放ename字段的表,也就是数组
 type sp_table_type is table of 
   emp.ename%type index by binary_integer;--以十进制下标排序
   --定义表实例
   sp_table sp_table_type;
   begin select ename into sp_table(0) from emp where emp.empno=7499;
     --这个只能单行赋值,如果需要多行要用到参照变量
    dbms_output.put_line('员工姓名'||sp_table(0));
 end; 

--游标使用
 declare
 --定义游标
 type sp_emp_cursor is ref cursor;
 --定义游标变量
 test_cursor sp_emp_cursor;
 --定义普通变量
 v_ename emp.ename%type;
 v_sal emp.sal%type;
 begin
   --执行
   --把游标和select结合,查询后游标指向第一条记录
   open test_cursor for select ename,sal from emp;
   --循环取出
   loop
     fetch test_cursor into v_ename,v_sal;---取出游标
     --判断游标是否为空
     exit when test_cursor%notfound;
     dbms_output.put_line('员工姓名'||v_ename||'薪水'||v_sal);
   end loop;

   end; 

pl/sql编程基础知识篇_第7张图片

十,分支语句

1.单分分支

--单分支
--输入雇员名,如果该雇员的工资低于2000则
--增加10%的金额
create or replace procedure sp_prol(spname varchar2) is --定义,这里不需要declare声明 v_sal emp.sal%type;
 --执行部分
 begin
   select sal into v_sal from emp where ename=spname;
   --开始判断
   if v_sal<2000 
     then update emp set sal=sal*1.1 where ename=spname;
     end if;--结束标识
 end;

2.双分支

--双重分支
 --输入雇员名,如果补助不为0,则把补助调为200,否则增加100
 create or replace procedure sp_prol(spname varchar2) is --定义,这里不需要declare声明 v_comm emp.comm%type;
 --执行部分
 begin
   select comm into v_comm from emp where ename=spname;
   --开始判断
   if v_comm<>0--不等于0 
     then update emp set comm=comm+100 where ename=spname;
     --未定义或者等于0
     else update emp set comm=200 where ename=spname;
     end if;--结束标识
 end;

3.多分支

--多重分支
 --输入雇员编号,如果职位是PRESIDENT给工资加1000,
 --如果是MANANGER则增加500,其他职位增加200
  create or replace procedure sp_prol(sppno number) is --定义,这里不需要declare声明 v_job emp.job%type;
 v_sal emp.sal%type;
 --执行部分
 begin select job,sal into v_job,v_sal from emp where emp.empno=sppno;
   --开始判断
   if v_job='PRESIDENT'--是董事长
     then update emp set sal=sal+1000 where emp.empno=sppno;
     elsif v_job='MANAGER'--这里没有e哈
     then update emp set sal=sal+500 where emp.empno=sppno;
     --其他职位
     else update emp set sal=sal+200 where emp.empno=sppno;
     end if;--结束标识
 end;

十一.循环控制

1,loop循环,至少会执行一次

--循环控制loop(至少执行一次)
 --输入用户名,循环添加3个用户到测试表
 create or replace procedure sp_prol(sppname varchar2) is --定义计数器 v_num number:=1;
 --执行部分
 begin
   --开始循环
   loop
     insert into test values(v_num,sppname);
     --判断是否结束循环
     exit when v_num=3;
     --自增
     v_num := v_num+1;
     end loop;
  end;

2.while循环,条件为真才执行

--while循环
  --输入用户名,编号从4开始,添加3create or replace procedure sp_prol(sppname varchar2) is --定义计数器 v_num number:=4;
 --执行部分
 begin
   --开始循环
  while v_num <= 6--条件为真则执行
    loop
      insert into test values(v_num,sppname);
      --自增
      v_num := v_num+1;
      end loop;
  end;

3.for循环不经常使用,以上两种即可完成日常任务

--for循环   结构不太符合常规,不常使用
 --输入用户名,编号从4开始,添加3create or replace procedure sp_prol(sppname varchar2) is begin --开始循环 for i in reverse 4..6 --倒过来执行的,插入顺序6,5,4 loop insert into test values(i,sppname);
      end loop;
  end;

十二,综合案例

--判断输入的子串是否是数字,是返回1,不是返回0
create or replace function isNumber(MyStr varchar2) return number is v_str varchar2(400);
v_isnum number;
v_num number;
begin --返回值为0不是数字,1则是数字 v_isnum:=0;
  v_str:=trim(MyStr);
  --如果输入值为空就不是数字
  if v_str is not null then
    begin v_num:=TO_NUMBER(v_str);
      v_isnum:=1;
      exception
        when INVALID_NUMBER then
          null;
        when OTHERS then
          null;
     end;
     end if;
     return v_isnum;
 end;

你可能感兴趣的:(oracle,plsql)