oracle的学习Ⅴ(PL/SQL程序块)

一、什么是PL/SQL块

PL/SQL(Program Language / Structure Query Language)程序控制块是指具用一定功能sql程序,它可以复用,不过要注意的是语句的缩进以增强语句的可读性

例如:

set serveroutput on;		// 开启屏幕打印

begin 				// 块开始标志
  dbms_output.put_line('hello world!');	# 利用dbms_output包里面的put_line方法进行输出
end;				// 块结束标志

要注意的是

  • put_line()方法只能输出一个值,也就是说put_line(a, b)是不可以的,只能put_line(a || ‘ ’ || b)
  • 语句都要以分号结尾
  • = 比较运算符,而 :=赋值运算符

二、块的组成部分

整体框架

  • declare – 声明部分: 变量、常量、游标、数据类型等,该部分可以省略。
  • begin – 执行部分 : 这是块的开始标志,该部分不能省略。
  • exception – 异常处理部分,该部分可以省略。
  • end; – 结束标志 ,该部分不能省略。

变量声明

variable_name [constant] datatype[:=value1|default value2];

数据类型:

number,char,varchar2,date,boolean(true false null),lob (clob,blob)

标识符命名

  • 通常以字母开头,最长不超过30个字符。
  • v_(variable) c_ (constant) rec_ (record) cur_ (cursor)

%type

  • 声明一个变量与已有的变量或已有列数据类型一致,若要与已有列数据类型一致的话,就必须对列添加归属对象(如:emp.sal而不是sal)
  • 它是为了方便获得未知变量或列的数据类型

%rowtype

  • 声明一个变量与已有的记录或已有表结构保持一致,且声明出的这个变量是一个记录类型
  • 它是为了方便在不知道某个表需要输出多少列的时候使用
  • 它相当于加强的%type

例如1:

declare 
  v_bjxx varchar2(30); 		// 变量声明
  v_name varchar2(20); 
begin 				// 块开始
  v_bjxx:='abc';
  v_name:='a';
  dbms_output.put_line('班级信息:'||v_bjxx||'  '||'姓名:'||'  '||v_name);		// 输出结果
end;			// 块结束
/				// 反斜杠号执行代码块

例如2:

// 写一个PL/SQL程序,查询7788员工的姓名和工资。

declare 
  v_ename varchar2(10);
  v_sal   number(7,2);
begin 
  select ename,sal into v_ename,v_sal from emp where empno=7788;			// 把查询的结果赋给v_ename,v_sal变量
  dbms_output.put_line('7788姓名是:'||v_ename||'  '||v_sal);
end;
/			// 执行代码块

例如3:

// 写一个PL/SQL程序,查询7788员工的姓名和工资。

declare 
  v_ename emp.ename%type;			// 获取emp.ename的数据类型,下同
  v_sal   emp.sal%type;
begin 
  select ename,sal into v_ename,v_sal from emp where empno=7788;		// 查询的结果赋值给变量
  dbms_output.put_line('7788姓名是:'||v_ename||'  '||v_sal);
end;
/

例如4:

// 写一个PL/SQL程序,查询7788员工信息。

declare 
  rec_emp emp%rowtype;			// 获取emp.ename的数据类型,下同,注意这里的rec_emp为记录类型
begin 
  select * into rec_emp from emp where empno=7788;	// 查询的结果赋值给变量
  dbms_output.put_line('7788姓名是:'||rec_emp.ename||'  '||rec_emp.v_sal);		// 使用变量.原列名的方式获得数据
end;
/

三、哪些SQL语句可以用在PL/SQL 中使用呢

select – 一般在select中使用into将查询的指导入变量中
DML – 数据修改语言(insert、update、delete)
commit – DML的提交
rollback – DML的滚回

注意:DDL(create、alter、drop)是不可以在PL/SQL里面改使用的

四、流程控制语句(选择语句)

if语句

if 条件1 then 处理1;
elsif 条件2 then 处理2;

else 处理N;
end if;

注意这里是elsif,也要注意块的语句缩进
例子:

// 写一个PL/SQL程序,向 emp表中添加一条记录,若该记录存在,则提示记录已存在,否则添加该记录,并提示添加成功。

declare 			
  v_empno emp.empno%type;		// 变量声明
  v_count int;
begin 
  v_empno:=7700;			// 赋值
  select count(*) into v_count from emp where empno=v_empno;		// 判断emp表内是否有empno为7700的记录
  if v_count=1 then 	// 为1则已存在
     dbms_output.put_line(v_empno||'  '||'已存在');
  else					// 为0则不在,并将记录插入到表内
     insert into emp(empno) values(v_empno);
     commit;			// DML需要commit
     dbms_output.put_line(v_empno||' '||'记录添加成功 ');
  end if;
end;
/

case语句

简单case

case 表达式
when value1 then 处理1;

else 处理N;
end case;

搜索case

case
when 条件1 then 处理1;

else 处理N;
end case;

例子:

// 查询7788员工的工资,当工资超过3000,显示高工资,2000到3000之间,一般工资,否则低工资。

declare 
  v_sal emp.sal%type;
begin 
  select sal into v_sal from emp where empno=7788;
  case				// case语句,类似于if语句
  when v_sal>3000 then 
     dbms_output.put_line('高工资');
  when v_sal between 2000 and 3000 then 
     dbms_output.put_line('一般工资');
  else
     dbms_output.put_line('低工资');
  end case;
end;
/

这里的搜索case与上面的if和以前的case类似(只是结束符不同而已)

五、流程控制语句(循环语句)

简单循环

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

例如:

// 输出100以内偶数和。

declare
	v_sum number default 0;			// 定义变量并赋值
	v_i number := 2;
begin
	loop			// 开始循环
		v_sum := v_sum + v_i;
		v_i := v_i + 2;			// 增加
		exit when v_i > 100;	// 退出条件
	end loop;				// 循环结束标志
	dbms_output.put_line('结果为:' || v_sum);
end;
/

while循环

while 条件
loop
循环体
end loop;

例如:

// 输出100以内偶数和。

declare
	v_sum number default 0;			// 定义变量并赋值
	v_i number := 2;
begin
	while v_i <= 100				// 开始循环
		loop
			v_sum := v_sum + v_i;
			v_i := v_i + 2;			// 增加
		end loop;				// 循环结束标志
	dbms_output.put_line('结果为:' || v_sum);
end;
/

for 循环

for 循环控制变量 in [reverse] 下限…上限
loop
循环体
end loop;

例如:

// 输出100以内偶数和。

declare
	v_sum number default 0;
begin
	for v_i in 1..100				// 循环开始
		loop
			if mod(v_i, 2) = 0 then		// if判断是否为偶数
				v_sum := v_sum + v_i;
			end if;
		end loop;				// 循环结束
	dbms_output.put_line('结果为:' || v_sum);
end;
/

要注意的是:

  • 这里面没有取余符号,只能用**mod()**函数
  • for里面的循环控制变量不用声明的
  • for里面的下、上限包括临界值

六、游标

游标本质就是一个临时的内存块,用来存储某个查询的多条返回结果。它可以理解为多行的rowtype,且它分为隐式游标显式游标

隐式游标

当在PL/SQL块中执行SQL语句中时,隐式游标会在系统中自动生成,游标名 默认为SQL(sql)
隐式游标属性:

isopen: DML执行过程中为真,结束为假 。
rowcount: DML语句影响的行数。
found: SQL 语句执行成功为真,失败为假。
notfound: 成功为假,失败为真。

隐式游标用法: sql%属性名
例子:

// 向EMP表添加一条记录,判断该记录是否存在,不存在添加,存在则给出相应提示。

declare 
   v_empno emp.empno%type;
begin 
   v_empno:=&v_empno;
   insert into emp(empno) values(v_empno);
   if sql%found then 
      commit;
      dbms_output.put_line(v_empno||' '||'添加成功');
   else
      rollback;
      dbms_output.put_line(v_empno||' '||'已 存在 '); 
   end if;
end;

显式游标

显式游标是用户自定义的。使用显式游标有四个步骤

  • ①声明游标:cursor cursor_name is select;
  • ②打开游标:open cursor_name; --此时执行子查询,并读入内存缓冲区。
  • ③提取数据 :fetch cursor_name into 变量名1, 变量名2……;
  • ④关闭游标:close cursor_name;

显式游标属性

isopen: 游标打开为真,否则为假。
rowcount:当前提取的行数。
found: 提取成功为真,失败为假
notfound:提取失败为真,成功为假

显式游标用法: 游标名%属性名

例1:

// 查询所有员工的姓名和工资。

declare 			// 方法一
  cursor cur1 is select ename,sal from emp;
  v_ename emp.ename%type;
  v_sal emp.sal%type;
begin 
  open cur1;
  loop
    fetch cur1 into v_ename,v_sal;
     exit when cur1%notfound;
    dbms_output.put_line(v_ename||'   '||v_sal);
  end loop;
  close cur1;
end;

declare 				// 方法二
  cursor cur1 is select ename,sal from emp;
  v_ename emp.ename%type;
  v_sal emp.sal%type;
begin 
  open cur1;
  fetch cur1 into v_ename,v_sal;
  while cur1%found
  loop
     dbms_output.put_line(v_ename||'   '||v_sal);
     fetch cur1 into v_ename,v_sal;
  end loop;
  close cur1;
end;

例2:

// 查询所有员工的姓名,工资,工号,工龄,奖金。

declare 			// 方法一
  cursor cur1 is select ename,sal,empno,sysdate-hiredate a,hiredate,comm from emp;
  rec_cur1 cur1%rowtype;		// 这里可以是cursor类型的
begin 
  open cur1;
  fetch cur1 into rec_cur1;
  while cur1%found
  loop
     dbms_output.put_line(rec_cur1.ename||rec_cur1.sal);
     fetch cur1 into rec_cur1;
  end loop;
  close cur1;
end;

declare 				// 方法二
  cursor cur1 is select ename,sal,empno,sysdate-hiredate a,hiredate,comm from emp;
  rec_cur1 cur1%rowtype;
begin 
  for rec_cur1 in cur1
  loop 
         dbms_output.put_line(rec_cur1.ename||rec_cur1.sal);
  end loop;
end;


begin 					// 方法三,注意这里的cursor的四步都在for里面自动执行了
  for rec_cur1 in (select ename,sal,empno,sysdate-hiredate a,hiredate,comm from emp)
  loop 
         dbms_output.put_line(rec_cur1.ename||rec_cur1.sal);
  end loop;
end;

七、异常处理

系统预定义异常

类型有no_data_found、too_many_rows、invalid_cursor、zero_divide、others,注意这里的others类型要放在异常处理的最后面。不过这里有两个函数sqlcode()、sqlerrm(),它们分别为错误编号错误信息
例如:

// 查询特定员工的工资(使用姓名查询)。

declare 
    v_empno emp.empno%type;
    v_sal emp.sal%type;
    v_ename emp.ename%type;
begin 
    v_empno:=&v_empno;
    select ename,sal into v_ename,v_sal from emp where empno=v_empno;
    dbms_output.put_line(v_empno||'的工资是:'||v_sal);
exception
   when no_data_found then 
       dbms_output.put_line('数据不存在');
   when too_many_rows then 
       dbms_output.put_line('数据过多');
    when others then 
       dbms_output.put_line('发生错误:'||'错误代码: '||sqlcode()||'  '||'错误信息'||sqlerrm());
end;

用户自定义异常

方法一

用户自定义异常分为步骤: ①声明异常 (异常名 exception;)②激活异常 (raise 异常名;)③处理异常 (when 异常名 then 处理;)

// 写一个用户自定义异常,实现与异常zero_divide同样的处理。

declare 
    v_a number;
    v_b number;
    zero_divide1 exception;			// 异常名定义
begin 
    v_a:=&v_a;			// 获得输入
    v_b:=&v_b;
    if v_b=0 then 			// 激活条件
        raise zero_divide1;		// 激活异常
    else 
    dbms_output.put_line(v_a/v_b);
    end if;
exception
    when zero_divide1 then 			// 处理异常
        dbms_output.put_line('v_b'||'不能为0');
end;

方法二
函数: raise_application_error(-a,b), a代表// 写一个用户自定义异常,实现与异常zero_divide同样的处理。,范围为20000-20999, b代表错误信息。但是该函数有时会无法捕获错误

// 写一个用户自定义异常,实现与异常zero_divide同样的处理。

declare 
  v_a number;
  v_b number;
begin 
  v_a:=&v_a;
  v_b:=&v_b;
  if v_b=0 then 
    raise_application_error(-20001,'除数不能为0');	// 函数处理异常
  else
    dbms_output.put_line(v_a/v_b);
  end if;
end;

八、其他

开启屏幕的打印,该语句不能出现的PL/SQL块里面

set serveroutput on/off; 		// 开关屏幕输出

从键盘输入获得内容,注意如果要输入的内容为字符串或者日期类型的话就必须使用引号把输入内容括起来

v_names := '&v_name'				// v_name为变量名,这里的v_names是字符串类型的

// 例如:
select * from emp where empno = &empno;			// 不要加引号
select * from emp where ename =&ename’;		// 要加引号

本文只用于学习与记录

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Oracle PL/SQLOracle数据库的编程语言,它允许开发人员编写存储过程、触发器、函数和包等数据库对象,以实现更高效、安全和可靠的应用程序。以下是一些Oracle PL/SQL必知必会的知识点: 1. PL/SQL基础语法:包括变量定义、控制结构、循环语句、异常处理等。 2. 存储过程:存储过程是一组SQL语句的集合,可以在其中定义变量、使用控制结构、调用其他存储过程等。 3. 触发器:触发器是一种特殊的存储过程,它会在数据库表上的特定事件发生时自动执行一些操作。 4. 函数:函数是一种可以接受输入参数并返回结果的代码,它可以用于处理数据、计算等操作。 5. 包:包是一种可以封装存储过程、函数和变量的方式,它可以提供更好的代码管理和组织。 6. 游标:游标是一种可以遍历查询结果集的机制,它可以用于在PL/SQL中处理大量数据。 7. 动态SQL:动态SQL是一种可以在运行时构建和执行SQL语句的机制,它可以提供更大的灵活性和自由度。 8. 性能优化:在编写PL/SQL代码时需要注意性能问题,如尽量避免使用循环、减少数据库访问次数等。 9. 安全性:在编写PL/SQL代码时需要注意安全问题,如避免SQL注入攻击、对敏感数据进行加密等。 以上是Oracle PL/SQL必知必会的一些知识点,掌握它们可以帮助开发人员更好地使用Oracle数据库进行应用程序开发。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值