Oracle的PL/SQL编程语言介绍、语法、循环、异常处理、游标、存储过程

目录

一、什么是PL/SQL

1、PL/SQL基本语法及实例用法:

2、PL/SQL 循环结构

3、PL/SQL 异常处理

二、游标

三、存储过程


一、什么是PL/SQL

结构化查询语言(Structured Query Language,简称SQL)是用来访问关系型数据库一种通用语言,其执行特点是过程化,即不用指明执行的具体方法和途径,而是简单的调用相应语句来直接取得结果即可。

有些复杂的业务流程又要求相应的程序来描述?
PL/SQL通过增加了用在其它过程性语言(java/python/...)中的结构来对SQL进行了扩展,使得它不仅是一个数据库查询语言,而且也是一个编程语言。

1、PL/SQL基本语法及实例用法:

/*PL/SQL语法:*******************************************************************/
 declare            --申明部分<可选>
    变量、常量、游标;
begin              --执行部分
    sql 语句;
    pl/sql 控制语句;
  exception        --异常处理部分<可选>
    错误发生异常时执行的动作;
end;
/*******************************************************************************/
-- PL/SQL 打印系统时间
declare
   sys_date date := sysdate;--申明变量sys_date 日期类型
begin --程序主题部分
   dbms_output.put_line(sys_date); --固定使用打印
   dbms_output.put_line('打印结束');
end;
/******************************************************************************/
-- PL/SQL 的%type和%rowtype
  
 -- 使用%type属性
 -- 定义变量的数据类型和长度与数据库表中的列保持一致。
 -- 例: 
declare 
   v_empName emp.ename%type;  
   
 -- 使用%rowtype属性
 -- 定义变量类型为记录变量,他表示和数据表一样类型的记录行。
 -- 例:
declare
  v_empRecord emp%rowtype; --复合型变量
 -- v_empRecord将与表EMP有相同的结构。如果表的定义改变了,则记录的类型也随之改变。
/******************************************************************************/  
-- 记录型变量赋值
declare
   v_empRecord scott.emp%rowtype;
begin
   select * into v_empRecord from scott.emp where empno=7369;
   dbms_output.put_line('empno='||v_empRecord.empno);
   dbms_output.put_line('ename='||v_empRecord.ename);
   dbms_output.put_line('job='||v_empRecord.job);
   dbms_output.put_line('sal='||v_empRecord.sal);
end;          
/******************************************************************************/

2、PL/SQL 循环结构

/******************************************************************************/
-- PL/SQL 循环结构 
   -- 基本循环
   LOOP
      语句序列
      exit when 布尔表达式为真退出循环;
   END LOOP; 
   -- while loop循环
   while 条件 loop
      语句序列
   end loop;
   --数值for loop循环
   for 计数器v_i in [reveres]低界.1..10.高界
   loop
       语句序列
   end loop;  
/******************************************************************************/     
-- 需求向部门表中插入10条数据,部门编号为41到50,部门名称都为loop.
declare
   v_counter number := 41;
-- v_counter scott.dept.deptno%type :=41;     
begin
  loop
     insert into scott.dept (deptno,dname)values(v_counter,'loop');
     exit when v_counter>=50;
     v_counter := v_counter + 1;   
  end loop;
end;

-- 需求向部门表中插入10条数据,部门编号为51到60,部门名称都为while loop.
declare
   v_cunter scott.dept.deptno%type := 51;
begin
  while v_cunter<=60 loop 
     insert into scott.dept(deptno,dname)values(v_cunter,'while loop');
     v_cunter := v_cunter+1;
  end loop;
end;
      
-- 需求向部门表中插入10条数据,部门编号为61到70,部门名称都为for loop.      
declare
   v_counter scott.dept.deptno%type := 61;  
begin
  for v_i in v_counter..v_counter+9 loop
     insert into scott.dept(deptno,dname)values(v_i,'for loop');  
  end loop;
end;
/******************************************************************************/

3、PL/SQL 异常处理

/******************************************************************************/
-- 异常处理
declare
   v_empno scott.emp.empno%type;
   v_sal scott.emp.sal%type := 1000;
begin
   select sal into v_sal from scott.emp where empno=v_empno;
   if v_sal<=2000 then update scott.emp set sal=sal+100 where empno=v_empno;
   end if;
exception
   when no_data_found then --固定用法:no_data_found 
        dbms_output.put_line(v_empno || ':不存在');
   when too_many_rows then --固定用法:too_many_rows
        dbms_output.put_line(v_empno || ':存在多个,请使用游标');
   when others then 
        dbms_output.put_line('存在其他未知错误');
end;     
/******************************************************************************/

二、游标

  • 用游标来指代一个DMLSQL操作返回的结果集。即当一个对数据库的查询操作返回一组结果集时,用游标来标注这组结果集,以后通过对游标的操作来获取结果集中的数据信息。
  • 游标(Cursor):用来查询数据库,获取记录集合(结果集)的指针可以让开发者一次访问一行结果集,在每条结果集上作操作。
  • 游标的过程:有明确的游标申明和操作过程;
  • 操作过程包括游标的申明,打开游标,取值,关闭游标
  1. cursor cursor_name is select_statement(select * from emp); -- 定义游标
  2. open cursor_name;  -- 打开游标
  3. fetch cursor_name into {variable_list | record_variable}; -- 提取游标数据:就是检索结果集合中的数据行,放入指定的输出变量中;对该记录进行处理,直到活动集合中没有记录
  4. close cursor_name; --关闭游标,以释放游标所占的系统资源
--游标定义实例
declare
  v_empno number(4);
  v_ename varchar(20); 
  cursor c_emp is select empno,ename from scott.emp;
begin
  open c_emp;
  loop     
       fetch c_emp into v_empno,v_ename;
       exit when c_emp%notfound;
       dbms_output.put_line(v_empno || '-' || v_ename);
  end loop; 
  close c_emp;
end;
      
-- 删除scott.dept表中dname 相同的数据,但需要保留deptno最大的一条记录
declare
   v_dn scott.dept.dname%type;
   v_dno scott.dept.deptno%type;
   cursor c_dept is select dname,max(deptno) dno from scott.dept group by dname having count(*)>1;
begin
   open c_dept;
   loop  
     fetch c_dept into v_dn,v_dno; 
     delete from scott.dept t where t.dname=v_dn and t.deptno <> v_dno;
     exit when c_dept%notfound;
   end loop;
   close c_dept;
end;

三、存储过程

存储过程是一种PL/SQL块,以命名的数据库对象形式存储于数据库当中
--可以传递参数给存储过程;--存储过程可以有返回值,也可以没有返回值;--存储过程的返回值必须通过参数带回。

为什么要写存储过程?

1.效率高:  存储过程编译一次后,就会存到数据库,每次调用时都直接执行。

2.降低网络流量:存储过程编译好会放在数据库,我们在远程调用时,不会传输大量的字符串类型的sql语句。

3.复用性高:存储过程往往是针对一个特定的功能编写的,当再需要完成这个特定的功能时,可以再次调用该存储过程。

4.可维护性高:当功能要求发生小的变化时,修改之前的存储过程比较容易,花费精力少。

5.安全性高:完成某个特定功能的存储过程一般只有特定的用户可以使用,具有使用身份限制,更安全。

语法:

-- 创建存储过程的语法结构
create [or replace] procedure p_name<存储过程名称> [(parameter list)]
is | as 
<local variable declaration>
begin
<executable statement>
[exception]
<exception handlers>
[commit;] --提交
end [p_name<存储过程名称>];

--创建带参数的存储过程时,有三种模式:in(输入)、out(输出)、in out(输入和输出)
--默认参数是属于输入模式in可以省略不写
--参数需要申明类型,但不指定长度

-- 执行存储过程的两种方式
   --(1)在命令窗口执行
   SQL> execute procedure p_name<存储过程名称>;
   -- (2) 用PL/SQL 调用
   begin 
   procedure p_name<存储过程名称>;
   end;

--注意:
--(1)没有参数的时候不需要加括号。即第1条语句不能这样写:
    CREATE [OR REPLACE] PROCEDURE MYPROC()--错误写法
--(2)如果有INSERT,UPDATE,DELETE语句,则一定要有COMMIT语句。
--(3)or replace 尽量不要用,把原有的存储过程删除了就不好啦。
/*****************************************************************************/
-- 创建不带参数的存储过程案例
create procedure a_pd 
as
begin
  delete from scott.dept where deptno in(80,81);
  insert into scott.dept (deptno,dname)values(80,'信息部');
  insert into scott.dept (deptno,dname)values(81,'运营部');
  commit;
end;  
-- 执行存储过程
begin
a_pd;
end; 
-- 查询验证      
select * from scott.dept;     
/****************************************************************************/      
--创建带参数的存储过程时,有三种模式:in(输入)、out(输出)、in out(输入和输出)
--默认参数是属于输入模式in可以省略不写
--参数需要申明类型,但不指定长度
--走,案例:根据输入的员工编号,打印员工姓名
/****************************************************************************/
--创建包含输入参数的存储过程
create or replace procedure a_pd_1 (p_empno in number)--in 可以不写
as
v_ename varchar(40);
begin
   select ename into v_ename from scott.emp where empno=p_empno;
   dbms_output.put_line(v_ename); 
exception 
   when no_data_found then 
   dbms_output.put_line('不存在');
end;  
--调用存储过程
begin
   a_pd_1(73690);
end;
-- 输出结果:SMITH 
/**************************************************************************/
--创建包含一个输入参数和一个输出参数的存储过程
create procedure a_pd_2(eno in number,ename out varchar)
as
ename_temp varchar(50);
begin
   select ename into ename_temp from scott.emp
   where empno=eno;
   ename := ename_temp;
exception
   when no_data_found then
   dbms_output.put_line('未找到!');
end;
-- 调用存储过程的输出参数
declare
   v_a varchar(50);
begin
a_pd_2(7369 ,v_a);
dbms_output.put_line(v_a);
end;
/**************************************************************************/
-- 创建一个包含即可以做输入又可以做输出的参数,交换两个参数的位置
create procedure a_pd_3(x1 in out number,x2 in out number)
as
v_temp number;
begin
  v_temp := x1;
  x1 := x2;
  x2 := v_temp;
end;

--调用含输出参数的存储过程
declare
 num1 number := 10;
 num2 number := 20;
begin
 a_pd_3(num1,num2);
 dbms_output.put_line(num1);
 dbms_output.put_line(num2);
end;
/****************************************************************************/
发布了103 篇原创文章 · 获赞 75 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/weixin_41685388/article/details/103547946